def test_write_no_sourcemap(self): root = mktemp() definitions = { 'Node': ( Attr(attr='left'), Attr(attr='op'), Attr(attr='right'), ) } # the program node; attributes are assigned to mimic a real one program = Node() program.left, program.op, program.right = ('foo', '=', 'true') program.sourcepath = join(root, 'original.js') program._token_map = { 'foo': [(0, 1, 1)], '=': [(4, 1, 5)], 'true': [(6, 1, 7)], } output_stream = StringIO() output_stream.name = join(root, 'processed.js') unparser = BaseUnparser(definitions) io.write(unparser, program, output_stream) self.assertEqual('foo=true', output_stream.getvalue())
def test_write_wrong_type(self): stream = StringIO() unparser = BaseUnparser({}) with self.assertRaises(TypeError): io.write(unparser, [], stream) with self.assertRaises(TypeError): io.write(unparser, '', stream)
def readwrite(self, source): unparser = convert_dynamic_require_unparser() original = StringIO(source) original.name = 'source.js' output = StringIO() output.name = 'output.js' srcmap = StringIO() srcmap.name = 'output.js.map' io.write(unparser, io.read(es5, original), output, srcmap) return output, srcmap
def test_write_multiple(self): root = mktemp() definitions = { 'Node': ( Attr(attr='left'), Text(value=' '), Attr(attr='op'), Text(value=' '), Attr(attr='right'), Text(value=';'), ) } # the program node; attributes are assigned to mimic a real one program1 = Node() program1.left, program1.op, program1.right = ('foo', '=', 'true') program1.sourcepath = join(root, 'program1.js') program1._token_map = { 'foo': [(0, 1, 1)], '=': [(4, 1, 5)], 'true': [(6, 1, 7)], } program2 = Node() program2.left, program2.op, program2.right = ('bar', '=', 'false') program2.sourcepath = join(root, 'program2.js') program2._token_map = { 'bar': [(0, 1, 1)], '=': [(4, 1, 5)], 'false': [(6, 1, 7)], } # streams output_stream = StringIO() output_stream.name = join(root, 'packed.js') sourcemap_stream = StringIO() sourcemap_stream.name = join(root, 'packed.js.map') unparser = BaseUnparser(definitions) io.write(unparser, [program1, program2], output_stream, sourcemap_stream, source_mapping_url=None) self.assertEqual('foo = true;bar = false;', output_stream.getvalue()) sourcemap = json.loads(sourcemap_stream.getvalue()) self.assertEqual( { "version": 3, "sources": ["program1.js", "program2.js"], "names": [], "mappings": "AAAA,WCAA", "file": "packed.js" }, sourcemap)
def test_write_same_stream_callable(self): # streams root = mktemp() output_stream = StringIO() output_stream.name = join(root, 'packed.js') called = [] closed = [] def close(): closed.append(True) output_stream.close = close def f_output_stream(): called.append(True) return output_stream definitions = { 'Node': ( Attr(attr='text'), Text(value=';'), ) } # the program node; attributes are assigned to mimic a real one program = Node() program.text = 'hello' program.sourcepath = join(root, 'program.js') program._token_map = {'hello': [(0, 1, 1)]} unparser = BaseUnparser(definitions) io.write(unparser, [program], f_output_stream, f_output_stream) self.assertEqual(1, len(called)) self.assertEqual(1, len(closed)) output = output_stream.getvalue() self.assertIn('hello', output) self.assertNotIn('program.js', output) # since output stream is a StringIO, default to utf8 encoding self.assertIn('data:application/json;base64;charset=utf8', output) # decode the base64 string self.assertEqual( { "version": 3, "sources": ["program.js"], "names": [], "mappings": "AAAA", "file": "packed.js" }, json.loads( base64.b64decode(output.splitlines()[-1].split(',')[-1].encode( 'utf8')).decode('utf8')))
def test_write_sourcemap_omitted(self): root = mktemp() definitions = { 'Node': ( Attr(attr='left'), Attr(attr='op'), Attr(attr='right'), ) } # the program node; attributes are assigned to mimic a real one program = Node() program.left, program.op, program.right = ('foo', '=', 'true') program.sourcepath = join(root, 'original.js') program._token_map = { 'foo': [(0, 1, 1)], '=': [(4, 1, 5)], 'true': [(6, 1, 7)], } # streams output_stream = StringIO() output_stream.name = join(root, 'processed.js') sourcemap_stream = StringIO() sourcemap_stream.name = join(root, 'processed.js.map') unparser = BaseUnparser(definitions) io.write(unparser, program, output_stream, sourcemap_stream, source_mapping_url=None) sourcemap = json.loads(sourcemap_stream.getvalue()) self.assertEqual( { "version": 3, "sources": ["original.js"], "names": [], "mappings": "AAAA,GAAI,CAAE", "file": "processed.js" }, sourcemap) self.assertEqual('foo=true', output_stream.getvalue())
def test_write_error_handled_callable_closed(self): # streams root = mktemp() output_stream = StringIO() output_stream.name = join(root, 'packed.js') closed = [] def close(): closed.append(True) output_stream.close = close def f_output_stream(): return output_stream def f_error(): raise IOError('some error happened') definitions = { 'Node': ( Attr(attr='text'), Text(value=';'), ) } # the program node; attributes are assigned to mimic a real one program = Node() program.text = 'hello' program.sourcepath = join(root, 'program.js') program._token_map = {'hello': [(0, 1, 1)]} unparser = BaseUnparser(definitions) with self.assertRaises(IOError): io.write(unparser, [program], f_output_stream, f_error) self.assertEqual(1, len(closed)) self.assertEqual('hello;', output_stream.getvalue()) self.assertNotIn('program.js', output_stream.getvalue())
def _finalize_test_path(toolchain, spec, modname, path): """ Process the path as a test file and bring it to a finalized location if necessary. Current condition for the relocation is usage of dynamic imports within the provided ES5 source file. """ if not exists(path): # nothing to do. return path with codecs.open(path, encoding='utf8') as fd: try: tree = io.read(parse, fd) imports = yield_module_imports_nodes(tree) except Exception: # can't do anything. return path # if there are not any nodes that are not strings if not any(node for node in imports if not isinstance(node, asttypes.String)): return path # generate the new target using the toolchain instance. rel_target = toolchain.modname_source_to_target(spec, modname, path) target = join(spec[BUILD_DIR], normpath(rel_target)) target_map = target + '.map' makedirs(dirname(target)) with codecs.open(target, 'w', encoding='utf8') as ss: with codecs.open(target_map, 'w', encoding='utf8') as sm: io.write(convert_dynamic_require_unparser(), tree, ss, sm) return target
def run(inputs, output, mangle, obfuscate, pretty, source_map, indent_width, drop_semi, encoding, version): """ Not a general use method, as sys.exit is called. """ def stdin(): return ( sys.stdin if isinstance(sys.stdin, (StringIO, TextIOWrapper)) else codecs.getreader(sys.stdin.encoding or encoding)(sys.stdin) ) def stdout(): return ( sys.stdout if isinstance(sys.stdout, (StringIO, TextIOWrapper)) else codecs.getwriter(sys.stdout.encoding or encoding)(sys.stdout) ) abs_output = abspath(output) if output else output abs_source_map = abspath(source_map) if source_map else source_map input_streams = ( [partial(codecs.open, abspath(p), encoding=encoding) for p in inputs] if inputs else [stdin] ) output_stream = ( partial(codecs.open, abs_output, 'w', encoding=encoding) if abs_output else stdout ) # if source_map is flagged (from empty string, in the const), if # no further name is supplied, use the output to build the path, # if it is also not stdout. source_map_path = ( abs_output + '.map' if source_map == '' and output_stream is not stdout else abs_source_map ) if source_map and abs_source_map == abs_output: # if a source_map was specified and the absolute paths of that # and the output is equal, use the output_stream that was # already created. sourcemap_stream = output_stream else: # no source map if source_map path is actually None, and only # generate a callable if the source_map_path is not an empty # string. sourcemap_stream = None if source_map_path is None else ( partial(codecs.open, source_map_path, 'w', encoding=encoding) if source_map_path else stdout ) enabled_rules = [rules.minify(drop_semi=drop_semi or mangle)] if obfuscate or mangle: enabled_rules.append(rules.obfuscate( reserved_keywords=Lexer.keywords_dict.keys() )) if pretty: enabled_rules.append(rules.indent(indent_str=' ' * indent_width)) printer = Unparser(rules=enabled_rules) try: io.write( printer, (io.read(parse, f) for f in input_streams), output_stream, sourcemap_stream, ) except ECMASyntaxError as e: logger.error('%s', e) sys.exit(1) except (IOError, OSError) as e: logger.error('%s', e) if e.args and isinstance(e.args[0], int): sys.exit(e.args[0]) sys.exit(5) # EIO except UnicodeDecodeError as e: logger.error('read error: %s', e) sys.exit(1) except UnicodeEncodeError as e: logger.error('write error: %s', e) sys.exit(1) except KeyboardInterrupt: sys.exit(130) # no need to close any streams as they are callables and that the io # read/write functions take care of that. sys.exit(0)
def test_write_callables(self): closed = [] class Stream(StringIO): # don't actually close the stream so it can be read later by # the tests def close(self): closed.append(self) # streams root = mktemp() output_stream = Stream() output_stream.name = join(root, 'packed.js') sourcemap_stream = Stream() sourcemap_stream.name = join(root, 'packed.js.map') def f_output_stream(): return output_stream def f_sourcemap_stream(): return sourcemap_stream definitions = { 'Node': ( Attr(attr='left'), Text(value=' '), Attr(attr='op'), Text(value=' '), Attr(attr='right'), Text(value=';'), ) } # the program node; attributes are assigned to mimic a real one program1 = Node() program1.left, program1.op, program1.right = ('foo', '=', 'true') program1.sourcepath = join(root, 'program1.js') program1._token_map = { 'foo': [(0, 1, 1)], '=': [(4, 1, 5)], 'true': [(6, 1, 7)], } program2 = Node() program2.left, program2.op, program2.right = ('bar', '=', 'false') program2.sourcepath = join(root, 'program2.js') program2._token_map = { 'bar': [(0, 1, 1)], '=': [(4, 1, 5)], 'false': [(6, 1, 7)], } unparser = BaseUnparser(definitions) io.write(unparser, [program1, program2], f_output_stream, f_sourcemap_stream, source_mapping_url=None) self.assertIn(output_stream, closed) self.assertIn(sourcemap_stream, closed) self.assertEqual('foo = true;bar = false;', output_stream.getvalue()) sourcemap = json.loads(sourcemap_stream.getvalue()) self.assertEqual( { "version": 3, "sources": ["program1.js", "program2.js"], "names": [], "mappings": "AAAA,WCAA", "file": "packed.js" }, sourcemap)