├── requirements.txt ├── tests ├── __init__.py ├── modules │ ├── __init__.py │ ├── without_all.py │ └── with_all.py ├── simple_print.py ├── simple_lambda.py ├── chain.py ├── compare.py ├── future_braces.py ├── lambda.py ├── dictionary.py ├── if.py ├── simple_slice.py ├── simple_state.py ├── division.py ├── function.py ├── function_name.py ├── future_division.py ├── importdot.py ├── set.py ├── tuple.py ├── class_free.py ├── genexp.py ├── nullary.py ├── scope.py ├── imports.py ├── ifelse.py ├── while.py ├── for_return.py ├── future_unicode_literals.py ├── global.py ├── importfrom.py ├── override_builtin.py ├── 1line.py ├── boring_try.py ├── future_division_inplace.py ├── future_print_function.py ├── num_repr.py ├── return_exec_defined_variable.py ├── unimplemented │ ├── class_doc_scope.py │ ├── argument_named_print.py │ ├── softspace.py │ ├── exec_local_return_behavior.py │ ├── print_eval_order.py │ ├── 9lines.py │ ├── 20lines.py │ └── reraise_bug.py ├── binding_indeterminate.py ├── future_absolute_import.py ├── aug.py ├── ifelifelse.py ├── name_main.py ├── return_none.py ├── slice.py ├── aug_coerce.py ├── closing_over.py ├── reassignment.py ├── 2lines.py ├── reraise.py ├── exec.py ├── call.py ├── closing_over_2.py ├── fibonacci.py ├── if_comprehensive.py ├── future_braces_as_division.py ├── future_division_as_braces.py ├── html_module.py ├── ifelse_comprehensive.py ├── 5lines.py ├── count_vowels.py ├── list_comprehension.py ├── try_finally_except.py ├── decorated_function_name.py ├── finally_return_swallows_exception.py ├── try_try_again.py ├── 3lines.py ├── 4lines.py ├── old_style_class.py ├── decorator_order.py ├── import_specific.py ├── closure.py ├── decorator.py ├── aug_getattr.py ├── 8lines.py ├── class_function_scope.py ├── 6lines.py ├── future_division_eval.py ├── relative_import.py ├── metaclass.py ├── 7lines.py ├── print.py ├── ifelifelse_comprehensive.py ├── del.py ├── for.py ├── 11lines.py ├── while_break_continue_else.py ├── aug_getattribute.py ├── for_break_continue_else.py ├── 14lines.py ├── 12lines.py ├── closure_mutate.py ├── 13lines.py ├── 15lines.py ├── exec_scope.py ├── 10lines.py ├── guess_my_number.py ├── slice_getattribute.py ├── mangle.py ├── exec_del.py ├── 18lines.py ├── 16lines.py ├── try_finally.py ├── 33lines.py ├── prime_tester.py ├── 28lines.py ├── 21lines.py ├── scope_comprehension.py ├── try_except.py ├── slice_torture.py ├── doc.py ├── eval_order.py └── symtable_torture.py ├── onelinerizer ├── __init__.py ├── runtests.py ├── __main__.py ├── template.py └── onelinerizer.py ├── .gitignore ├── .travis.yml ├── talks ├── presentation-pycon-2016.pdf ├── presentation-wecode-2017.pdf └── oneliner-bostonpython-presentation.pdf ├── setup.py ├── .setup.py ├── LICENSE.md ├── README.md └── main_ol.py /requirements.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/simple_print.py: -------------------------------------------------------------------------------- 1 | print 42 2 | -------------------------------------------------------------------------------- /tests/simple_lambda.py: -------------------------------------------------------------------------------- 1 | print (lambda x: 8*x)(4) 2 | -------------------------------------------------------------------------------- /tests/chain.py: -------------------------------------------------------------------------------- 1 | d = {} 2 | i = d[i] = 1 3 | print d 4 | -------------------------------------------------------------------------------- /tests/compare.py: -------------------------------------------------------------------------------- 1 | x = 3 2 | y = 4 3 | print (x < y < 5) 4 | -------------------------------------------------------------------------------- /tests/future_braces.py: -------------------------------------------------------------------------------- 1 | from __future__ import braces 2 | -------------------------------------------------------------------------------- /tests/lambda.py: -------------------------------------------------------------------------------- 1 | f = lambda x: x * 4 2 | print f(f(8)) 3 | -------------------------------------------------------------------------------- /tests/dictionary.py: -------------------------------------------------------------------------------- 1 | print {'1':'2', 3:4, "stringy":2+2*8} 2 | -------------------------------------------------------------------------------- /tests/if.py: -------------------------------------------------------------------------------- 1 | x = 7 2 | if True: 3 | x = 5 4 | print x 5 | -------------------------------------------------------------------------------- /tests/simple_slice.py: -------------------------------------------------------------------------------- 1 | print 'meow'[:2] 2 | print 'meow'[2:] 3 | -------------------------------------------------------------------------------- /onelinerizer/__init__.py: -------------------------------------------------------------------------------- 1 | from .onelinerizer import onelinerize 2 | -------------------------------------------------------------------------------- /tests/simple_state.py: -------------------------------------------------------------------------------- 1 | x = 5 2 | y = x + x 3 | print y, x+(x+x) 4 | -------------------------------------------------------------------------------- /tests/division.py: -------------------------------------------------------------------------------- 1 | print 10/3 2 | print 10./3 3 | print int(10./3) 4 | -------------------------------------------------------------------------------- /tests/function.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | return x+5 3 | 4 | print f(13) 5 | -------------------------------------------------------------------------------- /tests/function_name.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | pass 3 | print foo.__name__ 4 | -------------------------------------------------------------------------------- /tests/future_division.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | print 1/2 3 | -------------------------------------------------------------------------------- /tests/importdot.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | print os.path.join('hello', 'world') 3 | -------------------------------------------------------------------------------- /tests/set.py: -------------------------------------------------------------------------------- 1 | print {} # (not a set) 2 | print {0} 3 | print {0, 1, 2} 4 | -------------------------------------------------------------------------------- /tests/tuple.py: -------------------------------------------------------------------------------- 1 | x = (2,3,4,5) 2 | (y,z) = (6,7) 3 | print x, y, x, (), (4,) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | stocks.csv 3 | *.egg-info 4 | build/ 5 | dist/ 6 | .ve 7 | -------------------------------------------------------------------------------- /tests/class_free.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | class c: 3 | print x 4 | f(3) 5 | -------------------------------------------------------------------------------- /tests/genexp.py: -------------------------------------------------------------------------------- 1 | def p(x): 2 | print x 3 | map(p, (10*x for x in [1,2,3])) 4 | -------------------------------------------------------------------------------- /tests/modules/without_all.py: -------------------------------------------------------------------------------- 1 | a = 2 2 | b = 2 3 | c = 2 4 | _d = 2 5 | __e = 2 6 | -------------------------------------------------------------------------------- /tests/nullary.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | print 'hi' 3 | f() 4 | 5 | (lambda: None)() 6 | -------------------------------------------------------------------------------- /tests/scope.py: -------------------------------------------------------------------------------- 1 | x = 2 2 | def foo(): 3 | x = 1 4 | 5 | foo() 6 | print x 7 | -------------------------------------------------------------------------------- /tests/imports.py: -------------------------------------------------------------------------------- 1 | import re, string as s 2 | print re.sub('abc','zxy',s.lowercase) 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | script: python setup.py test 5 | -------------------------------------------------------------------------------- /tests/ifelse.py: -------------------------------------------------------------------------------- 1 | x = 7 2 | if x > 8: 3 | x = 5 4 | else: 5 | x = 10 6 | print x 7 | -------------------------------------------------------------------------------- /tests/while.py: -------------------------------------------------------------------------------- 1 | x = 5 2 | while x > 0: 3 | x = x - 1 4 | print x 5 | print "Done!" 6 | -------------------------------------------------------------------------------- /tests/for_return.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | for i in [1, 2, 3]: 3 | return i 4 | print f(0) 5 | -------------------------------------------------------------------------------- /tests/future_unicode_literals.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | print(type('')) 3 | -------------------------------------------------------------------------------- /tests/global.py: -------------------------------------------------------------------------------- 1 | x = 2 2 | def foo(): 3 | global x 4 | x = 1 5 | 6 | foo() 7 | print x 8 | -------------------------------------------------------------------------------- /tests/importfrom.py: -------------------------------------------------------------------------------- 1 | from os.path import join, split as s 2 | print join(*s('hello/world')) 3 | -------------------------------------------------------------------------------- /tests/override_builtin.py: -------------------------------------------------------------------------------- 1 | False = True 2 | while False: 3 | print False 4 | del False 5 | -------------------------------------------------------------------------------- /tests/1line.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | print "Hello, world!" 3 | -------------------------------------------------------------------------------- /tests/boring_try.py: -------------------------------------------------------------------------------- 1 | try: 2 | print "Hello!" 3 | except: 4 | print "Something went wrong." 5 | -------------------------------------------------------------------------------- /tests/future_division_inplace.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | x = 1 3 | x /= 2 4 | print x 5 | -------------------------------------------------------------------------------- /tests/future_print_function.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | print('hello', 'world') 3 | -------------------------------------------------------------------------------- /tests/num_repr.py: -------------------------------------------------------------------------------- 1 | print repr(123) 2 | print repr(123.0) 3 | print repr(123L) 4 | print repr(123j) 5 | -------------------------------------------------------------------------------- /tests/return_exec_defined_variable.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | exec('a = 5') 3 | return a 4 | print f() 5 | -------------------------------------------------------------------------------- /tests/modules/with_all.py: -------------------------------------------------------------------------------- 1 | a = 1 2 | b = 1 3 | c = 1 4 | _d = 1 5 | __e = 1 6 | 7 | __all__ = ['a', 'b'] 8 | -------------------------------------------------------------------------------- /tests/unimplemented/class_doc_scope.py: -------------------------------------------------------------------------------- 1 | '''foo''' 2 | class C: 3 | '''bar''' 4 | print __doc__ 5 | -------------------------------------------------------------------------------- /tests/binding_indeterminate.py: -------------------------------------------------------------------------------- 1 | def f(y): 2 | if y > 0.5: x = 'x' 3 | return x 4 | 5 | print f(0) 6 | -------------------------------------------------------------------------------- /tests/future_absolute_import.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | __package__ = 'os' 3 | import path 4 | -------------------------------------------------------------------------------- /talks/presentation-pycon-2016.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csvoss/onelinerizer/HEAD/talks/presentation-pycon-2016.pdf -------------------------------------------------------------------------------- /talks/presentation-wecode-2017.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csvoss/onelinerizer/HEAD/talks/presentation-wecode-2017.pdf -------------------------------------------------------------------------------- /tests/aug.py: -------------------------------------------------------------------------------- 1 | x = [1] 2 | y = x 3 | y += [2] 4 | print x, y 5 | 6 | x = 1 7 | y = x 8 | y += 2 9 | print x, y 10 | -------------------------------------------------------------------------------- /tests/ifelifelse.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | if False: 3 | x = 2 4 | elif True: 5 | x = 6 6 | else: 7 | x = 7 8 | print x 9 | -------------------------------------------------------------------------------- /tests/name_main.py: -------------------------------------------------------------------------------- 1 | ## Does __name__ == '__main__' check pass? 2 | 3 | if __name__ == '__main__': 4 | print "Pass!" 5 | -------------------------------------------------------------------------------- /tests/return_none.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | print 1 3 | return 4 | print 2 5 | 6 | print 3 7 | print f() 8 | print 4 9 | -------------------------------------------------------------------------------- /tests/slice.py: -------------------------------------------------------------------------------- 1 | print "meow"[:], "meow"[:2], "meow"[2:] 2 | print "meow"[::], "meow"[::-1], "meow"[:2:], "meow"[2::] 3 | -------------------------------------------------------------------------------- /tests/aug_coerce.py: -------------------------------------------------------------------------------- 1 | class C: 2 | def __coerce__(self, other): 3 | return 2, 2 4 | o = C() 5 | o += C() 6 | print o 7 | -------------------------------------------------------------------------------- /tests/closing_over.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | x = 'closed-over' 3 | def g(): 4 | return x 5 | return g 6 | print f()() 7 | -------------------------------------------------------------------------------- /tests/reassignment.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | x = 'local' 3 | x = 'reassigned' 4 | x = 'reassigned again' 5 | 6 | print f() 7 | -------------------------------------------------------------------------------- /talks/oneliner-bostonpython-presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csvoss/onelinerizer/HEAD/talks/oneliner-bostonpython-presentation.pdf -------------------------------------------------------------------------------- /tests/2lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | name = raw_input("Enter your name: ") 3 | print "Hi, %s." % name 4 | -------------------------------------------------------------------------------- /tests/reraise.py: -------------------------------------------------------------------------------- 1 | try: 2 | try: 3 | 0/0 4 | except Exception: 5 | raise 6 | except Exception as e: 7 | print repr(e) 8 | -------------------------------------------------------------------------------- /tests/exec.py: -------------------------------------------------------------------------------- 1 | exec "print s" in {}, {'s': 'Hello, world!'} 2 | exec "print s" in {'s': 'Hello, world!'} 3 | s = 'Hello, world!' 4 | exec "print s" 5 | -------------------------------------------------------------------------------- /tests/unimplemented/argument_named_print.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | def f(print): 3 | return print 4 | print(f(**{'print': 1})) 5 | -------------------------------------------------------------------------------- /tests/call.py: -------------------------------------------------------------------------------- 1 | def function_call(x, y, *args, **kwargs): 2 | print x,y,args,kwargs 3 | 4 | function_call(42, "stringy\n\"", 5, 6, 7, foo=43+4, bar=22) 5 | -------------------------------------------------------------------------------- /tests/closing_over_2.py: -------------------------------------------------------------------------------- 1 | def g(): 2 | x = 'outer' 3 | def h(): 4 | x = 'inner' 5 | return x 6 | return (h(), x) 7 | print g() 8 | -------------------------------------------------------------------------------- /tests/fibonacci.py: -------------------------------------------------------------------------------- 1 | x = 0 2 | y = 1 3 | 4 | counter = 0 5 | 6 | while counter < 15: 7 | counter += 1 8 | x, y = y, x + y 9 | print x 10 | -------------------------------------------------------------------------------- /tests/if_comprehensive.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | if True: 3 | x = 2 4 | else: 5 | x = 3 6 | print x 7 | if False: 8 | x = 4 9 | else: 10 | x = 5 11 | print x -------------------------------------------------------------------------------- /tests/future_braces_as_division.py: -------------------------------------------------------------------------------- 1 | from __future__ import braces as division 2 | 3 | # These ought not to execute. 4 | print 3/5 5 | print division 6 | print braces 7 | -------------------------------------------------------------------------------- /tests/future_division_as_braces.py: -------------------------------------------------------------------------------- 1 | from __future__ import division as braces 2 | 3 | print 3/5 4 | print braces 5 | 6 | # This one ought to error. 7 | print division 8 | -------------------------------------------------------------------------------- /tests/html_module.py: -------------------------------------------------------------------------------- 1 | ## Minimized version of a bug that appeared in 21lines.py 2 | import xml.etree.ElementTree as etree 3 | print etree.fromstring("").tag 4 | -------------------------------------------------------------------------------- /tests/ifelse_comprehensive.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | if True: 3 | x = 2 4 | else: 5 | x = 3 6 | print x 7 | if False: 8 | x = 4 9 | else: 10 | x = 5 11 | print x 12 | -------------------------------------------------------------------------------- /tests/5lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | def greet(name): 3 | print 'Hello', name 4 | greet('Jack') 5 | greet('Jill') 6 | greet('Bob') 7 | -------------------------------------------------------------------------------- /tests/count_vowels.py: -------------------------------------------------------------------------------- 1 | def count_vowels(x): 2 | return sum([1 if i in "aeiou" else 0 for i in x.lower()]) 3 | 4 | print count_vowels("Supercalifragilisticexpialidocious!") 5 | -------------------------------------------------------------------------------- /tests/list_comprehension.py: -------------------------------------------------------------------------------- 1 | print [i for i in range(5) if i%2==0] 2 | print [i for j in range(5) for i in range(j)] 3 | print [i for j in range(5) if j%2==0 for i in range(j) if i%2==0] 4 | -------------------------------------------------------------------------------- /tests/try_finally_except.py: -------------------------------------------------------------------------------- 1 | try: 2 | try: 3 | print 'try 1' 4 | assert False 5 | finally: 6 | print 'finally 1' 7 | except AssertionError: 8 | print 'except 1' 9 | -------------------------------------------------------------------------------- /tests/decorated_function_name.py: -------------------------------------------------------------------------------- 1 | def decorator(f): 2 | print f.__name__ 3 | def bar(): 4 | return f() 5 | return bar 6 | 7 | @decorator 8 | def foo(): 9 | pass 10 | print foo.__name__ 11 | -------------------------------------------------------------------------------- /tests/finally_return_swallows_exception.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | try: 3 | print 'try f' 4 | assert False 5 | finally: 6 | print 'finally f' 7 | return 'returned' 8 | 9 | print 'f: ' + f() 10 | -------------------------------------------------------------------------------- /tests/unimplemented/softspace.py: -------------------------------------------------------------------------------- 1 | # The output should have a trailing newline and no spaces. 2 | print '\t', 0 3 | print '\n', 1 4 | print '\x0b', 2 5 | print '\x0c', 3 6 | print '\r', 4 7 | print 5, 8 | print 9 | print 6, 10 | -------------------------------------------------------------------------------- /tests/try_try_again.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | try: 3 | try: 4 | return 'returned' 5 | except AssertionError: 6 | pass 7 | except AssertionError: 8 | pass 9 | 10 | print 'f: ' + f() 11 | -------------------------------------------------------------------------------- /tests/3lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | friends = ['john', 'pat', 'gary', 'michael'] 3 | for i, name in enumerate(friends): 4 | print "iteration {iteration} is {name}".format(iteration=i, name=name) 5 | -------------------------------------------------------------------------------- /tests/4lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | parents, babies = (1, 1) 3 | while babies < 100: 4 | print 'This generation has {0} babies'.format(babies) 5 | parents, babies = (babies, parents + babies) 6 | -------------------------------------------------------------------------------- /tests/old_style_class.py: -------------------------------------------------------------------------------- 1 | class C: 2 | def __getattr__(self, name): 3 | if name == '__str__': 4 | return lambda: 'foo' 5 | raise AttributeError 6 | print C() 7 | 8 | class D(C): 9 | pass 10 | print D() 11 | -------------------------------------------------------------------------------- /tests/unimplemented/exec_local_return_behavior.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | exec "" 3 | locals()['a'] = 6 4 | return a 5 | 6 | def g(): 7 | locals()['a'] = 6 8 | return a 9 | 10 | a = 5 11 | print f() 12 | 13 | a = 5 14 | print g() 15 | -------------------------------------------------------------------------------- /tests/decorator_order.py: -------------------------------------------------------------------------------- 1 | def f0(g0): 2 | print 0 3 | return lambda: [0] + g0() 4 | 5 | def f1(g1): 6 | print 1 7 | return lambda: [1] + g1() 8 | 9 | @f0 10 | @f1 11 | def g(): 12 | print 2 13 | return [2] 14 | 15 | print g() 16 | -------------------------------------------------------------------------------- /tests/import_specific.py: -------------------------------------------------------------------------------- 1 | a = 0 2 | b = 0 3 | c = 0 4 | _d = 0 5 | __e = 0 6 | print a, b, c, _d, __e 7 | 8 | from tests.modules.with_all import a 9 | print a, b, c, _d, __e 10 | 11 | from tests.modules.without_all import b 12 | print a, b, c, _d, __e 13 | -------------------------------------------------------------------------------- /tests/closure.py: -------------------------------------------------------------------------------- 1 | a = 1 2 | print a 3 | def outer(b): 4 | c = 3 5 | print a, b, c 6 | def inner(d): 7 | e = 5 8 | print a, b, c, d, e 9 | return lambda f: (a, b, c, d, e, f) 10 | return inner 11 | print outer(2)(4)(6) 12 | -------------------------------------------------------------------------------- /tests/decorator.py: -------------------------------------------------------------------------------- 1 | def print_decorator(f): 2 | def g(*args, **kwargs): 3 | print "Calling the function!" 4 | return f(*args, **kwargs) 5 | return g 6 | 7 | @print_decorator 8 | def add_numbers(x,y): 9 | print x+y 10 | 11 | add_numbers(42, 56) 12 | -------------------------------------------------------------------------------- /tests/aug_getattr.py: -------------------------------------------------------------------------------- 1 | class C: 2 | def __getattr__(self, name): 3 | global o 4 | if name == '__iadd__': 5 | o = None 6 | elif name == '__add__': 7 | return lambda other: None 8 | raise AttributeError 9 | 10 | o = C() 11 | o += 1 12 | -------------------------------------------------------------------------------- /tests/8lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | # This program adds up integers in the command line 3 | import sys 4 | try: 5 | total = sum(int(arg) for arg in sys.argv[1:]) 6 | print 'sum =', total 7 | except ValueError: 8 | print 'Please supply integer arguments' 9 | -------------------------------------------------------------------------------- /tests/class_function_scope.py: -------------------------------------------------------------------------------- 1 | def f(x, y): 2 | print x 3 | print y 4 | class c: 5 | x = 4 6 | print x 7 | print y 8 | def g(self): 9 | print x 10 | print y 11 | print c 12 | return c 13 | print f("x", "y")().g() 14 | -------------------------------------------------------------------------------- /tests/6lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | import re 3 | for test_string in ['555-1212', 'ILL-EGAL']: 4 | if re.match(r'^\d{3}-\d{4}$', test_string): 5 | print test_string, 'is a valid US local phone number' 6 | else: 7 | print test_string, 'rejected' 8 | -------------------------------------------------------------------------------- /tests/future_division_eval.py: -------------------------------------------------------------------------------- 1 | from __future__ import division 2 | print eval('1/2') 3 | exec('print 1/2') 4 | eval(compile('print 1/2', 'wat.py', 'exec')) 5 | print eval(compile('1/2', 'wat.py', 'eval')) 6 | print eval(compile('1/2', 'wat.py', 'eval', 0, 0)) 7 | print eval(compile('1/2', 'wat.py', 'eval', 0, ~0)) 8 | -------------------------------------------------------------------------------- /tests/relative_import.py: -------------------------------------------------------------------------------- 1 | __package__ = 'os' 2 | import path 3 | print path.join(*path.split('hello/world')) 4 | 5 | __package__ = 'os.path' 6 | from . import join 7 | from ..path import split 8 | print join(*split('hello/world')) 9 | 10 | from .. import path 11 | print path.join(*path.split('hello/world')) 12 | -------------------------------------------------------------------------------- /tests/metaclass.py: -------------------------------------------------------------------------------- 1 | class M(type): 2 | def __init__(cls, name, bases, dct): 3 | print 'metaclass' 4 | super(M, cls).__init__(name, bases, dct) 5 | 6 | class C: 7 | __metaclass__ = M 8 | 9 | class C(object): 10 | __metaclass__ = M 11 | 12 | __metaclass__ = M 13 | 14 | class C: 15 | pass 16 | -------------------------------------------------------------------------------- /tests/7lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | prices = {'apple': 0.40, 'banana': 0.50} 3 | my_purchase = { 4 | 'apple': 1, 5 | 'banana': 6} 6 | grocery_bill = sum(prices[fruit] * my_purchase[fruit] 7 | for fruit in my_purchase) 8 | print 'I owe the grocer $%.2f' % grocery_bill 9 | -------------------------------------------------------------------------------- /tests/print.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import StringIO 3 | 4 | print 5 | print 1, 6 | print 2 7 | 8 | s = StringIO.StringIO() 9 | print >>s, 3, 10 | print >>s, 4 11 | print repr(s.getvalue()) 12 | 13 | def f(): 14 | print 'f' 15 | return sys.stdout 16 | def g(): 17 | print 'g' 18 | return 'hello' 19 | print >>f(), g() 20 | -------------------------------------------------------------------------------- /tests/ifelifelse_comprehensive.py: -------------------------------------------------------------------------------- 1 | x = 1 2 | if True: 3 | x = 2 4 | elif False: 5 | x = 3 6 | else: 7 | x = 4 8 | print x 9 | if False: 10 | x = 5 11 | elif True: 12 | x = 6 13 | else: 14 | x = 7 15 | print x 16 | if False: 17 | x = 8 18 | elif False: 19 | x = 9 20 | else: 21 | x = 10 22 | print x 23 | -------------------------------------------------------------------------------- /tests/del.py: -------------------------------------------------------------------------------- 1 | i = 17 2 | del i 3 | 4 | class dummy(object): 5 | def __init__(self): 6 | self.foo = 1 7 | print getattr(self, 'foo', 'missing') 8 | del self.foo 9 | print getattr(self, 'foo', 'missing') 10 | 11 | dummy() 12 | 13 | a = range(15) 14 | del (a[4:6], [a[::2], a[4]]), a[0] 15 | print a 16 | 17 | del [] 18 | del [], [] 19 | -------------------------------------------------------------------------------- /tests/for.py: -------------------------------------------------------------------------------- 1 | x = 5 2 | for i in range(5): 3 | x = x + i 4 | print x 5 | 6 | # inner loop takes in d, returns a modified d? 7 | # list: a list of i 8 | # function: takes in i, d; spits out d 9 | # for loop: takes in d, spits out d 10 | # reduce: function, sequence, initial 11 | # (lambda d.x: (lambda d: print(d.x))(reduce((lambda d, i: (lambda d.x: d)(d.x+i)), range(5), d)))(5) 12 | -------------------------------------------------------------------------------- /tests/11lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | REFRAIN = ''' 3 | %d bottles of beer on the wall, 4 | %d bottles of beer, 5 | take one down, pass it around, 6 | %d bottles of beer on the wall! 7 | ''' 8 | bottles_of_beer = 99 9 | while bottles_of_beer > 1: 10 | print REFRAIN % (bottles_of_beer, bottles_of_beer, 11 | bottles_of_beer - 1) 12 | bottles_of_beer -= 1 13 | -------------------------------------------------------------------------------- /tests/while_break_continue_else.py: -------------------------------------------------------------------------------- 1 | out = '' 2 | f = True 3 | while True: 4 | out += 'a' 5 | g = True 6 | while g: 7 | g = False 8 | out += 'b' 9 | continue 10 | else: 11 | out += 'c' 12 | if f: 13 | f = False 14 | continue 15 | else: 16 | break 17 | out += 'd' 18 | else: 19 | out += 'e' 20 | print out 21 | -------------------------------------------------------------------------------- /tests/aug_getattribute.py: -------------------------------------------------------------------------------- 1 | class M(type): 2 | __getattribute__ = None 3 | 4 | class G(object): 5 | __metaclass__ = M 6 | __getattribute__ = None 7 | def __get__(self, instance, owner): 8 | return lambda other: 'pass' 9 | 10 | class C(object): 11 | __metaclass__ = M 12 | __getattribute__ = None 13 | __iadd__ = G() 14 | 15 | o = C() 16 | o.__iadd__ = None 17 | o += 1 18 | print o 19 | -------------------------------------------------------------------------------- /tests/for_break_continue_else.py: -------------------------------------------------------------------------------- 1 | out = '' 2 | for i in [1,2,3,4]: 3 | print i 4 | out += 'a' 5 | for j in [5,6,7,8]: 6 | print j 7 | out += 'b' 8 | continue 9 | else: 10 | print j 11 | out += 'c' 12 | if i == 2: 13 | continue 14 | elif i == 3: 15 | break 16 | out += 'd' 17 | else: 18 | out += 'e' 19 | print i, out 20 | -------------------------------------------------------------------------------- /tests/unimplemented/print_eval_order.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def trace(msg, value): 4 | print msg 5 | return value 6 | 7 | print trace('print arg 0', 0), trace('print arg 1', 1), 8 | print trace('print arg 2', 2), trace('print arg 3', 3) 9 | print >>trace('print file 0', sys.stdout), trace('print arg 4', 4), trace('print arg 5', 5), 10 | print >>trace('print file 1', sys.stdout), trace('print arg 6', 6), trace('print arg 7', 7) 11 | -------------------------------------------------------------------------------- /tests/unimplemented/9lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | # indent your Python code to put into an email 3 | import glob 4 | # glob supports Unix style pathname extensions 5 | python_files = glob.glob('*.py') 6 | for file_name in sorted(python_files): 7 | print ' ------' + file_name 8 | 9 | with open(file_name) as f: 10 | for line in f: 11 | print ' ' + line.rstrip() 12 | 13 | print 14 | -------------------------------------------------------------------------------- /tests/14lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | def median(pool): 3 | '''Statistical median to demonstrate doctest. 4 | >>> median([2, 9, 9, 7, 9, 2, 4, 5, 8]) 5 | 7 6 | ''' 7 | copy = sorted(pool) 8 | size = len(copy) 9 | if size % 2 == 1: 10 | return copy[(size - 1) / 2] 11 | else: 12 | return (copy[size/2 - 1] + copy[size/2]) / 2 13 | 14 | print median([2, 9, 9, 7, 9, 2, 4, 5, 8]) 15 | -------------------------------------------------------------------------------- /tests/12lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | class BankAccount(object): 3 | def __init__(self, initial_balance=0): 4 | self.balance = initial_balance 5 | def deposit(self, amount): 6 | self.balance += amount 7 | def withdraw(self, amount): 8 | self.balance -= amount 9 | def overdrawn(self): 10 | return self.balance < 0 11 | my_account = BankAccount(15) 12 | my_account.withdraw(5) 13 | print my_account.balance 14 | -------------------------------------------------------------------------------- /tests/closure_mutate.py: -------------------------------------------------------------------------------- 1 | def f(): 2 | x = 1 3 | a = lambda: x 4 | b = (lambda: lambda: x)() 5 | c = (lambda: lambda: lambda: x)()() 6 | x = 2 7 | print a(), b(), c() 8 | f() 9 | 10 | def g(): 11 | print [f() for f in [lambda: x for x in range(5)]] 12 | print [f() for f in [(lambda: lambda: x)() for x in range(5)]] 13 | print [f() for f in [(lambda x: lambda: x)(x) for x in range(5)]] 14 | print [f() for f in map(lambda x: lambda: x, range(5))] 15 | g() 16 | -------------------------------------------------------------------------------- /tests/13lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | import unittest 3 | def median(pool): 4 | copy = sorted(pool) 5 | size = len(copy) 6 | if size % 2 == 1: 7 | return copy[(size - 1) / 2] 8 | else: 9 | return (copy[size/2 - 1] + copy[size/2]) / 2 10 | class TestMedian(unittest.TestCase): 11 | def testMedian(self): 12 | self.failUnlessEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7) 13 | if __name__ == '__main__': 14 | unittest.main() 15 | -------------------------------------------------------------------------------- /tests/15lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | from itertools import groupby 3 | lines = ''' 4 | This is the 5 | first paragraph. 6 | 7 | This is the second. 8 | '''.splitlines() 9 | # Use itertools.groupby and bool to return groups of 10 | # consecutive lines that either have content or don't. 11 | for has_chars, frags in groupby(lines, bool): 12 | if has_chars: 13 | print ' '.join(frags) 14 | # PRINTS: 15 | # This is the first paragraph. 16 | # This is the second. 17 | -------------------------------------------------------------------------------- /tests/exec_scope.py: -------------------------------------------------------------------------------- 1 | g = 0 2 | def f(): 3 | global g 4 | l = 0 5 | exec 'global g; g = 1; l = 1' 6 | print g, l 7 | exec 'global g; g = 2; l = 2' in None 8 | print g, l 9 | exec 'global g; g = 3; l = 3' in {} 10 | print g, l 11 | exec 'global g; g = 4; l = 4' in None, None 12 | print g, l 13 | exec 'global g; g = 5; l = 5' in None, {} 14 | print g, l 15 | exec 'global g; g = 6; l = 6' in {}, None 16 | print g, l 17 | exec 'global g; g = 7; l = 7' in {}, {} 18 | print g, l 19 | f() 20 | -------------------------------------------------------------------------------- /tests/10lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | from time import localtime 3 | 4 | activities = {8: 'Sleeping', 5 | 9: 'Commuting', 6 | 17: 'Working', 7 | 18: 'Commuting', 8 | 20: 'Eating', 9 | 22: 'Resting' } 10 | 11 | time_now = localtime() 12 | hour = time_now.tm_hour 13 | 14 | for activity_time in sorted(activities.keys()): 15 | if hour < activity_time: 16 | print activities[activity_time] 17 | break 18 | else: 19 | print 'Unknown, AFK or sleeping!' 20 | -------------------------------------------------------------------------------- /tests/guess_my_number.py: -------------------------------------------------------------------------------- 1 | def guess_my_number(n): 2 | while True: 3 | user_input = raw_input("Enter a positive integer to guess: ") 4 | if len(user_input)==0 or not user_input.isdigit(): 5 | print "Not a positive integer!" 6 | else: 7 | user_input = int(user_input) 8 | if user_input > n: 9 | print "Too big! Try again!" 10 | elif user_input < n: 11 | print "Too small! Try again!" 12 | else: 13 | print "You win!" 14 | return True 15 | guess_my_number(42) 16 | -------------------------------------------------------------------------------- /tests/slice_getattribute.py: -------------------------------------------------------------------------------- 1 | class M(type): 2 | __getattribute__ = None 3 | 4 | class G(object): 5 | __metaclass__ = M 6 | __getattribute__ = None 7 | def __get__(self, instance, owner): 8 | def f(*args): 9 | print args 10 | return f 11 | 12 | class C(object): 13 | __metaclass__ = M 14 | __getattribute__ = None 15 | __getitem__ = G() 16 | __setitem__ = G() 17 | __delitem__ = G() 18 | 19 | o = C() 20 | o.__getitem__ = None 21 | o.__setitem__ = None 22 | o.__delitem__ = None 23 | o[:] 24 | o[::] 25 | o[:] = [] 26 | o[::] = [] 27 | del o[:] 28 | del o[::] 29 | -------------------------------------------------------------------------------- /tests/mangle.py: -------------------------------------------------------------------------------- 1 | __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c = 0, 1, 2, 3, 4, 5, 6, 7, 8 2 | print __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c 3 | class A(object): 4 | __a = 9 5 | print __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c 6 | def f(self): 7 | print __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c 8 | class B(object): 9 | __b = 10 10 | print __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c 11 | def f(self): 12 | print __a, _A__a, _B__a, __b, _A__b, _B__b, __c, _A__c, _B__c 13 | 14 | A().f() 15 | A().B().f() 16 | -------------------------------------------------------------------------------- /tests/exec_del.py: -------------------------------------------------------------------------------- 1 | a = 0 2 | 3 | def f(): 4 | a = 1 5 | exec 'g = lambda: a; print a, g()' 6 | print a, g() 7 | exec 'a = 2; print a, g()' 8 | exec 'print a, g()' 9 | print a, g() 10 | exec 'del a; print a, g()' 11 | exec 'print a, g()' 12 | print a, g() 13 | a = 3 14 | exec 'print a, g()' 15 | print a, g() 16 | 17 | f() 18 | 19 | a = 4 20 | exec 'g = lambda: a; print a, g()' 21 | print a, g() 22 | exec 'a = 5; print a, g()' 23 | exec 'print a, g()' 24 | print a, g() 25 | exec 'del a; print a, g()' 26 | exec 'print a, g()' 27 | print a, g() 28 | a = 6 29 | exec 'print a, g()' 30 | print a, g() 31 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | (lambda __g: (lambda __mod: [(setup(name='onelinerizer', version='1.0.4', author='Chelsea Voss', author_email='csvoss@mit.edu', maintainer='Chelsea Voss and Anders Kaseorg', maintainer_email='onelinerizer@mit.edu', url='https://github.com/csvoss/onelinerizer', description='Convert any Python file into a single line of code.', long_description=open('README.md', 'r').read(), long_description_content_type='text/markdown', packages=['onelinerizer'], entry_points={'console_scripts': ['onelinerizer=onelinerizer.__main__:main']}, test_suite='onelinerizer.runtests'), None)[1] for __g['setup'] in [(__mod.setup)]][0])(__import__('setuptools', __g, __g, ('setup',), 0)))(globals()) 2 | -------------------------------------------------------------------------------- /tests/18lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | BOARD_SIZE = 8 3 | 4 | def under_attack(col, queens): 5 | left = right = col 6 | 7 | for r, c in reversed(queens): 8 | left, right = left - 1, right + 1 9 | 10 | if c in (left, col, right): 11 | return True 12 | return False 13 | 14 | def solve(n): 15 | if n == 0: 16 | return [[]] 17 | 18 | smaller_solutions = solve(n - 1) 19 | 20 | return [solution+[(n,i+1)] 21 | for i in xrange(BOARD_SIZE) 22 | for solution in smaller_solutions 23 | if not under_attack(i+1, solution)] 24 | for answer in solve(BOARD_SIZE): 25 | print answer 26 | -------------------------------------------------------------------------------- /tests/unimplemented/20lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | import itertools 3 | 4 | def iter_primes(): 5 | # an iterator of all numbers between 2 and +infinity 6 | numbers = itertools.count(2) 7 | 8 | # generate primes forever 9 | while True: 10 | # get the first number from the iterator (always a prime) 11 | prime = numbers.next() 12 | yield prime 13 | 14 | # this code iteratively builds up a chain of 15 | # filters...slightly tricky, but ponder it a bit 16 | numbers = itertools.ifilter(prime.__rmod__, numbers) 17 | 18 | for p in iter_primes(): 19 | if p > 1000: 20 | break 21 | print p 22 | -------------------------------------------------------------------------------- /.setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name="onelinerizer", 5 | version="1.0.4", 6 | author="Chelsea Voss", 7 | author_email="csvoss@mit.edu", 8 | maintainer="Chelsea Voss and Anders Kaseorg", 9 | maintainer_email="onelinerizer@mit.edu", 10 | url='https://github.com/csvoss/onelinerizer', 11 | description='Convert any Python file into a single line of code.', 12 | long_description=open('README.md', 'r').read(), 13 | long_description_content_type='text/markdown', 14 | packages=['onelinerizer'], 15 | entry_points={ 16 | 'console_scripts': ['onelinerizer=onelinerizer.__main__:main'], 17 | }, 18 | test_suite='onelinerizer.runtests', 19 | ) 20 | -------------------------------------------------------------------------------- /tests/16lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | import csv 3 | 4 | # write stocks data as comma-separated values 5 | writer = csv.writer(open('stocks.csv', 'wb', buffering=0)) 6 | writer.writerows([ 7 | ('GOOG', 'Google, Inc.', 505.24, 0.47, 0.09), 8 | ('YHOO', 'Yahoo! Inc.', 27.38, 0.33, 1.22), 9 | ('CNET', 'CNET Networks, Inc.', 8.62, -0.13, -1.49) 10 | ]) 11 | 12 | # read stocks data, print status messages 13 | stocks = csv.reader(open('stocks.csv', 'rb')) 14 | status_labels = {-1: 'down', 0: 'unchanged', 1: 'up'} 15 | for ticker, name, price, change, pct in stocks: 16 | status = status_labels[cmp(float(change), 0.0)] 17 | print '%s is %s (%s%%)' % (name, status, pct) 18 | -------------------------------------------------------------------------------- /tests/try_finally.py: -------------------------------------------------------------------------------- 1 | try: 2 | print 'try 0' 3 | finally: 4 | print 'finally 0' 5 | 6 | def f(): 7 | try: 8 | print 'try f' 9 | finally: 10 | print 'finally f' 11 | return 'returned' 12 | 13 | print 'f: ' + f() 14 | 15 | def g(): 16 | try: 17 | print 'try g' 18 | return 'returned' 19 | finally: 20 | print 'finally g' 21 | 22 | print 'g: ' + g() 23 | 24 | def h(): 25 | try: 26 | print 'try h' 27 | finally: 28 | print 'finally h' 29 | return 'returned' 30 | 31 | print 'h: ' + h() 32 | 33 | def i(): 34 | try: 35 | print 'try i' 36 | return 'returned' 37 | finally: 38 | print 'finally i' 39 | return 'returned harder' 40 | 41 | print 'i: ' + i() 42 | -------------------------------------------------------------------------------- /tests/33lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | import random 3 | 4 | guesses_made = 0 5 | 6 | name = raw_input('Hello! What is your name?\n') 7 | 8 | number = random.randint(1, 20) 9 | print 'Well, {0}, I am thinking of a number between 1 and 20.'.format(name) 10 | 11 | while guesses_made < 6: 12 | 13 | guess = int(raw_input('Take a guess: ')) 14 | 15 | guesses_made += 1 16 | 17 | if guess < number: 18 | print 'Your guess is too low.' 19 | 20 | if guess > number: 21 | print 'Your guess is too high.' 22 | 23 | if guess == number: 24 | break 25 | 26 | if guess == number: 27 | print 'Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made) 28 | else: 29 | print 'Nope. The number I was thinking of was {0}'.format(number) 30 | -------------------------------------------------------------------------------- /tests/prime_tester.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def is_prime(n): 4 | if n < 2: 5 | return False 6 | if n == 2: 7 | return True 8 | n = int(n) 9 | factors = range(2, int(math.ceil(math.sqrt(n))+1)) 10 | i = 0 11 | while i < len(factors): 12 | factor = factors[i] 13 | if n % factor == 0: 14 | return False 15 | i = i + 1 16 | return True 17 | 18 | def smallest_prime_larger_than(x): 19 | while True: 20 | x = x + 1 21 | if is_prime(x): 22 | return x 23 | 24 | print is_prime(1) 25 | print is_prime(2) 26 | print is_prime(3) 27 | print is_prime(4) 28 | print is_prime(5) 29 | print is_prime(45) 30 | print is_prime(91) 31 | print is_prime(89) 32 | 33 | print smallest_prime_larger_than(1) 34 | print smallest_prime_larger_than(91) 35 | print smallest_prime_larger_than(1000) 36 | -------------------------------------------------------------------------------- /tests/28lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | BOARD_SIZE = 8 3 | 4 | class BailOut(Exception): 5 | pass 6 | 7 | def validate(queens): 8 | left = right = col = queens[-1] 9 | for r in reversed(queens[:-1]): 10 | left, right = left-1, right+1 11 | if r in (left, col, right): 12 | raise BailOut 13 | 14 | def add_queen(queens): 15 | for i in range(BOARD_SIZE): 16 | test_queens = queens + [i] 17 | try: 18 | validate(test_queens) 19 | if len(test_queens) == BOARD_SIZE: 20 | return test_queens 21 | else: 22 | return add_queen(test_queens) 23 | except BailOut: 24 | pass 25 | raise BailOut 26 | 27 | queens = add_queen([]) 28 | print queens 29 | print "\n".join(". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens) 30 | -------------------------------------------------------------------------------- /tests/21lines.py: -------------------------------------------------------------------------------- 1 | ## inspired by https://wiki.python.org/moin/SimplePrograms 2 | dinner_recipe = ''' 3 | 4 | 5 | 6 | 7 | 8 |
amtunititem
24slicesbaguette
2+tbspolive oil
1cuptomatoes
1jarpesto
''' 9 | 10 | # In Python 2.5 or from http://effbot.org/zone/element-index.htm 11 | import xml.etree.ElementTree as etree 12 | tree = etree.fromstring(dinner_recipe) 13 | 14 | # For invalid HTML use http://effbot.org/zone/element-soup.htm 15 | # import ElementSoup, StringIO 16 | # tree = ElementSoup.parse(StringIO.StringIO(dinner_recipe)) 17 | 18 | pantry = set(['olive oil', 'pesto']) 19 | for ingredient in tree.getiterator('tr'): 20 | amt, unit, item = ingredient 21 | if item.tag == "td" and item.text not in pantry: 22 | print "%s: %s %s" % (item.text, amt.text, unit.text) 23 | -------------------------------------------------------------------------------- /tests/unimplemented/reraise_bug.py: -------------------------------------------------------------------------------- 1 | # https://bugs.python.org/issue23556 2 | 3 | try: 4 | try: 5 | raise Exception('foo') 6 | except Exception: 7 | try: 8 | raise Exception('bar') 9 | except Exception: 10 | pass 11 | 12 | # In Python 3, this reraises the caught Exception('foo'), like 13 | # you'd expect. In Python 2, this reraises the ignored 14 | # Exception('bar'). 15 | raise 16 | 17 | except Exception as e: 18 | print(repr(e)) 19 | 20 | try: 21 | try: 22 | raise Exception('foo') 23 | except Exception: 24 | def f(): 25 | try: 26 | raise Exception('bar') 27 | except Exception: 28 | pass 29 | f() 30 | 31 | # If we move the inner exception handler into a function, we 32 | # get the expected Exception('foo') in all versions. 33 | raise 34 | 35 | except Exception as e: 36 | print(repr(e)) 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2015 Chelsea Voss and Anders Kaseorg 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | “Software”), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /tests/scope_comprehension.py: -------------------------------------------------------------------------------- 1 | x = 4 2 | 3 | a = lambda: x 4 | 5 | # Perhaps it once made sense to someone why c and d see the inner x 6 | # but a and b do not. 7 | 8 | print(''.join( 9 | # generator expression 10 | '{}{}{} {}{}{}{}\n'.format(i, j, k, a(), b(), c(), d()) 11 | for i, b in enumerate([a, lambda: x, a]) 12 | for j, c in enumerate([b, lambda: x, b]) 13 | for k, d in enumerate([c, lambda: x, c]) 14 | for x in [5])) 15 | 16 | print(''.join(sorted({ 17 | # set comprehension 18 | '{}{}{} {}{}{}{}\n'.format(i, j, k, a(), b(), c(), d()) 19 | for i, b in enumerate([a, lambda: x, a]) 20 | for j, c in enumerate([b, lambda: x, b]) 21 | for k, d in enumerate([c, lambda: x, c]) 22 | for x in [6]}))) 23 | 24 | print(''.join(sorted({ 25 | # dict comprehension 26 | '{}{}{} {}{}{}{}\n'.format(i, j, k, a(), b(), c(), d()): 1 27 | for i, b in enumerate([a, lambda: x, a]) 28 | for j, c in enumerate([b, lambda: x, b]) 29 | for k, d in enumerate([c, lambda: x, c]) 30 | for x in [7]}.keys()))) 31 | 32 | # Except in list comprehensions. 33 | 34 | print(''.join([ 35 | # list comprehension 36 | '{}{}{} {}{}{}{}\n'.format(i, j, k, a(), b(), c(), d()) 37 | for i, b in enumerate([a, lambda: x, a]) 38 | for j, c in enumerate([b, lambda: x, b]) 39 | for k, d in enumerate([c, lambda: x, c]) 40 | for x in [8]])) 41 | -------------------------------------------------------------------------------- /tests/try_except.py: -------------------------------------------------------------------------------- 1 | try: 2 | print 'try 0' 3 | except AssertionError: 4 | print 'except 0' 5 | else: 6 | print 'else 0' 7 | 8 | try: 9 | print 'try 1' 10 | assert False 11 | except AssertionError: 12 | print 'except 1' 13 | else: 14 | print 'else 1' 15 | 16 | try: 17 | try: 18 | print 'try 2' 19 | assert False 20 | except ZeroDivisionError: 21 | print 'wrong except 2' 22 | else: 23 | print 'else 2' 24 | except AssertionError: 25 | print 'right except 2' 26 | else: 27 | print 'else 2' 28 | 29 | try: 30 | print 'try 3' 31 | assert False 32 | except ZeroDivisionError: 33 | print 'wrong except 3' 34 | except AssertionError: 35 | print 'right except 3' 36 | else: 37 | print 'else 3' 38 | 39 | try: 40 | print 'try 4' 41 | assert False 42 | except: 43 | print 'except 4' 44 | else: 45 | print 'else 4' 46 | 47 | def f(): 48 | try: 49 | print 'try f' 50 | return 'returned' 51 | except AssertionError: 52 | print 'except f' 53 | else: 54 | print 'else f' 55 | 56 | print 'f: ' + f() 57 | 58 | def g(): 59 | try: 60 | print 'try g' 61 | assert False 62 | except AssertionError: 63 | print 'except g' 64 | return 'returned' 65 | else: 66 | print 'else g' 67 | 68 | print 'g: ' + g() 69 | 70 | def f(): 71 | try: 72 | print 'try h' 73 | except: 74 | print 'except h' 75 | else: 76 | print 'else h' 77 | return 'returned' 78 | 79 | print 'h: ' + f() 80 | -------------------------------------------------------------------------------- /onelinerizer/runtests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | import random 4 | import sys 5 | from StringIO import StringIO 6 | 7 | from .onelinerizer import onelinerize 8 | 9 | TEST_DIRECTORY = 'tests' 10 | 11 | DEBUG = False 12 | 13 | class TestOneLine(unittest.TestCase): 14 | def runTest(self): 15 | pass 16 | 17 | def make_test(filename): 18 | """Return a function that verifies that the file and its onelinerized 19 | version both output the same.""" 20 | 21 | def new_test(self): 22 | with open(filename, 'r') as fi: 23 | self.longMessage = True 24 | original = fi.read().strip() 25 | onelinerized = onelinerize(original) 26 | self.assertEqual(capture_exec(original), 27 | capture_exec(onelinerized), 28 | msg="\n\nOnelined: " + onelinerized) 29 | return new_test 30 | 31 | class FakeStdin(object): 32 | """Sometimes tests use raw_input; this feeds those deterministically.""" 33 | def __init__(self): 34 | self.counter = 0 35 | def readline(self): 36 | self.counter += 1 37 | return str(self.counter) 38 | 39 | def capture_exec(code_string): 40 | """Run the code with FakeStdin as stdin, return its stdout.""" 41 | random.seed(4) # for RFC 1149.5 compliance 42 | new_stdout = StringIO() 43 | old_stdout = sys.stdout 44 | old_stdin = sys.stdin 45 | sys.stdout = new_stdout 46 | sys.stdin = FakeStdin() 47 | namespace = {} 48 | try: 49 | exec code_string in namespace 50 | except Exception as e: 51 | import traceback 52 | exc = traceback.format_exc() 53 | if DEBUG: 54 | old_stdout.write("\nFYI: test threw error %s\n" % str(type(e)(code_string + ', ' + exc))) 55 | new_stdout.write("Error thrown.") 56 | sys.stdout = old_stdout 57 | sys.stdin = old_stdin 58 | return new_stdout.getvalue() 59 | 60 | # Monkey-patch 61 | for subdir, dirs, files in os.walk(TEST_DIRECTORY): 62 | for filename in files: 63 | root, ext = os.path.splitext(filename) 64 | if ext == '.py' and 'unimplemented' not in subdir: 65 | setattr(TestOneLine, 66 | 'test_%s' % root, 67 | make_test(os.path.join(subdir, filename))) 68 | 69 | if __name__ == '__main__': 70 | unittest.main() 71 | -------------------------------------------------------------------------------- /onelinerizer/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | import traceback 4 | 5 | from .onelinerizer import onelinerize 6 | 7 | def main(): 8 | usage = ['onelinerizer --help', 9 | 'onelinerizer [--debug] [infile.py [outfile.py]]', 10 | ] 11 | parser = argparse.ArgumentParser(usage='\n '.join(usage), 12 | description=("if infile is given and outfile is not, outfile will be " 13 | "infile_ol.py")) 14 | parser.add_argument('infile', nargs='?') 15 | parser.add_argument('outfile', nargs='?') 16 | parser.add_argument('--debug', action='store_true') 17 | args = parser.parse_args() 18 | original = None 19 | if args.infile is None: 20 | # I have gotten no arguments. Look at sys.stdin 21 | original = sys.stdin.read() 22 | outfilename = None 23 | elif args.outfile is None: 24 | # I have gotten one argument. If there's something to read from 25 | # sys.stdin, read from there. 26 | if args.infile.endswith('.py'): 27 | outfilename = '_ol.py'.join(args.infile.rsplit(".py", 1)) 28 | else: 29 | outfilename = args.infile + '_ol.py' 30 | else: 31 | outfilename = args.outfile 32 | 33 | if original is None: 34 | infile = open(args.infile) 35 | original = infile.read().strip() 36 | infile.close() 37 | onelinerized = onelinerize(original) 38 | if outfilename is None: 39 | print onelinerized 40 | else: 41 | outfi = open(outfilename, 'w') 42 | outfi.write(onelinerized + '\n') 43 | outfi.close() 44 | 45 | if args.debug: 46 | if outfilename is None: 47 | # redirect to sys.stderr if I'm writing outfile to sys.stdout 48 | sys.stdout = sys.stderr 49 | print '--- ORIGINAL ---------------------------------' 50 | print original 51 | print '----------------------------------------------' 52 | scope = {} 53 | try: 54 | exec(original, scope) 55 | except Exception as e: 56 | traceback.print_exc(e) 57 | print '--- ONELINERIZED -----------------------------' 58 | print onelinerized 59 | print '----------------------------------------------' 60 | scope = {} 61 | try: 62 | exec(onelinerized, scope) 63 | except Exception as e: 64 | traceback.print_exc(e) 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /tests/slice_torture.py: -------------------------------------------------------------------------------- 1 | import types 2 | 3 | def trace(name): 4 | def f(self, *args): 5 | print name, repr(args) 6 | return 0 7 | return f 8 | 9 | def get(a, s): 10 | a[1*s] 11 | a[...] 12 | a[:] 13 | a[2*s:] 14 | a[:3*s] 15 | a[4*s:5*s] 16 | a[::] 17 | a[6*s::] 18 | a[:7*s:] 19 | a[::8*s] 20 | a[9*s:10*s:] 21 | a[11*s::12*s] 22 | a[:13*s:14*s] 23 | a[15*s:16*s:17*s] 24 | a[18*s, 19*s:20*s, 21*s:22*s:23*s, :, ::, ...] 25 | a[24*s,] 26 | a[25*s:26*s,] 27 | a[27*s:28*s:29*s,] 28 | a[...,] 29 | a[:,] 30 | a[::,] 31 | 32 | def set(a, s): 33 | a[1*s] = 0 34 | a[...] = 0 35 | a[:] = 0 36 | a[2*s:] = 0 37 | a[:3*s] = 0 38 | a[4*s:5*s] = 0 39 | a[::] = 0 40 | a[6*s::] = 0 41 | a[:7*s:] = 0 42 | a[::8*s] = 0 43 | a[9*s:10*s:] = 0 44 | a[11*s::12*s] = 0 45 | a[:13*s:14*s] = 0 46 | a[15*s:16*s:17*s] = 0 47 | a[18*s, 19*s:20*s, 21*s:22*s:23*s, :, ::, ...] = 0 48 | a[24*s,] = 0 49 | a[25*s:26*s,] = 0 50 | a[27*s:28*s:29*s,] = 0 51 | a[...,] = 0 52 | a[:,] = 0 53 | a[::,] = 0 54 | 55 | def aug(a, s): 56 | a[1*s] += 0 57 | a[...] += 0 58 | a[:] += 0 59 | a[2*s:] += 0 60 | a[:3*s] += 0 61 | a[4*s:5*s] += 0 62 | a[::] += 0 63 | a[6*s::] += 0 64 | a[:7*s:] += 0 65 | a[::8*s] += 0 66 | a[9*s:10*s:] += 0 67 | a[11*s::12*s] += 0 68 | a[:13*s:14*s] += 0 69 | a[15*s:16*s:17*s] += 0 70 | a[18*s, 19*s:20*s, 21*s:22*s:23*s, :, ::, ...] += 0 71 | a[24*s,] += 0 72 | a[25*s:26*s,] += 0 73 | a[27*s:28*s:29*s,] += 0 74 | a[...,] += 0 75 | a[:,] += 0 76 | a[::,] += 0 77 | 78 | def delete(a, s): 79 | del a[1*s] 80 | del a[...] 81 | del a[:] 82 | del a[2*s:] 83 | del a[:3*s] 84 | del a[4*s:5*s] 85 | del a[::] 86 | del a[6*s::] 87 | del a[:7*s:] 88 | del a[::8*s] 89 | del a[9*s:10*s:] 90 | del a[11*s::12*s] 91 | del a[:13*s:14*s] 92 | del a[15*s:16*s:17*s] 93 | del a[18*s, 19*s:20*s, 21*s:22*s:23*s, :, ::, ...] 94 | del a[24*s,] 95 | del a[25*s:26*s,] 96 | del a[27*s:28*s:29*s,] 97 | del a[...,] 98 | del a[:,] 99 | del a[::,] 100 | 101 | def g(e): 102 | def __getattr__(self, name): 103 | print '__getattr__', repr(name) 104 | if name == '__len__': 105 | return lambda: 100 106 | if name in e: 107 | return e[name].__get__(self) 108 | raise AttributeError 109 | return {'__getattr__': __getattr__} 110 | 111 | for ns in [['__%sitem__'], ['__%sitem__', '__%sslice__']]: 112 | e = {n % a: trace(n % a) for a in ['get', 'set', 'del'] for n in ns} 113 | for meta, d in [ 114 | (type, e), 115 | (type, dict(e, __len__=lambda self: 100)), 116 | (types.ClassType, dict(e, __len__=lambda self: 100)), 117 | (types.ClassType, g(e))]: 118 | a = meta('dummy', (), d)() 119 | for s in [1, -1]: 120 | get(a, s) 121 | set(a, s) 122 | aug(a, s) 123 | delete(a, s) 124 | -------------------------------------------------------------------------------- /tests/doc.py: -------------------------------------------------------------------------------- 1 | """Lorem ipsum dolor sit amet, consectetur adipiscing elit. 2 | 3 | Curabitur egestas aliquam eros, et luctus felis accumsan a. Mauris 4 | scelerisque sapien non mi vehicula facilisis. Cum sociis natoque 5 | penatibus et magnis dis parturient montes, nascetur ridiculus mus. 6 | Vivamus eget purus ac arcu aliquam vulputate vitae et diam. Nullam sit 7 | amet diam condimentum, laoreet turpis nec, venenatis sem. Morbi mi 8 | tortor, vestibulum sit amet nisi non, euismod suscipit lectus. Ut 9 | vitae est nisi. Quisque et posuere tortor. Maecenas suscipit ut leo 10 | vitae hendrerit. 11 | """ 12 | 13 | def aenean_interdum(f): 14 | """Cras ut convallis sapien. 15 | 16 | Aliquam suscipit, enim lacinia lacinia rhoncus, sapien est feugiat 17 | nulla, ac dictum orci magna tincidunt ipsum. Quisque posuere 18 | sodales turpis sit amet tincidunt. Nam tincidunt dolor volutpat 19 | sapien auctor fringilla. Pellentesque arcu turpis, tincidunt 20 | ultrices dignissim in, vestibulum id urna. Curabitur congue 21 | pulvinar arcu ac iaculis. Pellentesque habitant morbi tristique 22 | senectus et netus et malesuada fames ac turpis egestas. Fusce enim 23 | nisi, porta sed ligula ut, fermentum hendrerit sapien. Sed 24 | imperdiet eu quam faucibus faucibus. 25 | """ 26 | 27 | print f.__doc__ 28 | f.__doc__ += '\nNullam id feugiat orci, nec bibendum lacus.\n' 29 | return f 30 | 31 | @aenean_interdum 32 | def donec_porttitor(whats_up): 33 | """Nulla nec venenatis turpis, fermentum tristique dolor. 34 | 35 | Morbi sodales risus at purus commodo, et pellentesque orci 36 | blandit. Donec lacinia tortor eu mi maximus, sed suscipit ipsum 37 | lobortis. Sed id sollicitudin enim, id feugiat eros. Aenean 38 | accumsan felis ac neque dapibus fringilla. Nam et posuere erat, in 39 | pulvinar metus. Donec vitae maximus tellus, non feugiat nisl. Ut 40 | efficitur mattis lacus vitae feugiat. In rutrum ligula ut erat 41 | viverra interdum. Pellentesque vulputate commodo ligula, in 42 | euismod velit dapibus at. Pellentesque eget posuere mauris. Donec 43 | dictum maximus lacus, eu rutrum massa. 44 | """ 45 | 46 | print whats_up.__doc__ 47 | return whats_up 48 | 49 | @donec_porttitor 50 | class vestibulum_ante(object): 51 | """Pellentesque habitant morbi tristique senectus et netus et 52 | malesuada fames ac turpis egestas. 53 | 54 | Nunc id risus tellus. Nulla ullamcorper dui a urna sollicitudin 55 | sodales. Ut diam augue, sollicitudin maximus euismod eu, cursus a 56 | dolor. Integer tempor iaculis dignissim. Etiam pulvinar quis nulla 57 | eu molestie. In maximus, justo in congue lobortis, libero enim 58 | pulvinar dolor, non hendrerit lorem magna sit amet 59 | tellus. Suspendisse in tempus est. Nam congue scelerisque diam, 60 | quis consequat orci aliquam ut. Donec sed mauris in leo ultrices 61 | maximus ullamcorper eget arcu. Donec ac urna in dui efficitur 62 | suscipit ac eu ipsum. Aenean ac facilisis nisi. Etiam elit libero, 63 | vulputate at orci accumsan, dignissim volutpat nibh. Aliquam 64 | bibendum felis a erat iaculis, auctor hendrerit felis luctus. Duis 65 | nec hendrerit nisi. 66 | """ 67 | 68 | pass 69 | 70 | print __doc__ 71 | print aenean_interdum.__doc__ 72 | print donec_porttitor.__doc__ 73 | print vestibulum_ante.__doc__ 74 | -------------------------------------------------------------------------------- /tests/eval_order.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def trace(msg, value): 4 | print msg 5 | return value 6 | 7 | @trace('function decorator 0', lambda f: f) 8 | @trace('function decorator 1', lambda f: f) 9 | def function_def( 10 | arg0=trace('function default 0', None), 11 | arg1=trace('function default 1', None)): 12 | trace('function body', None) 13 | 14 | class base0: pass 15 | class base1: pass 16 | 17 | @trace('class decorator 0', lambda cls: cls) 18 | @trace('class decorator 1', lambda cls: cls) 19 | class class_def(trace('class base 0', base0), trace('class base 1', base1)): 20 | trace('class body', None) 21 | 22 | o = base0() 23 | o.attr0 = o.attr1 = o.attr2 = o.attr3 = o.attr4 = 0 24 | l = [0, 0] 25 | d = {(0, 0): 0, (1, 1): 1} 26 | 27 | del trace('del value 0', o).attr0, \ 28 | trace('del value 1', l)[trace('del index', 0)], \ 29 | trace('del value 2', l)[trace('del lower', 0):trace('del upper', 0):trace('del step', 1)], \ 30 | trace('del value 3', d)[trace('del index 0', 0), trace('del index 1', 0)], \ 31 | [trace('del value 4', o).attr1, trace('del value 5', o).attr2], \ 32 | (trace('del value 6', o).attr3, trace('del value 7', o).attr4) 33 | 34 | trace('assign target 0', o).attr, trace('assign target 1', o).attr = \ 35 | trace('assign target 2', o).attr, trace('assign target 3', o).attr = \ 36 | trace('assign value', (0, 0)) 37 | trace('aug assign target 0', o).attr += trace('aug assign value 0', 0) 38 | trace('aug assign target 1', l)[trace('aug assign index', 0)] += trace('aug assign value 1', 0) 39 | trace('aug assign target 2', l)[trace('aug assign lower 2', 0):trace('aug assign upper 2', 0)] += trace('aug assign value 2', []) 40 | trace('aug assign target 3', l)[trace('aug assign lower 3', 0):trace('aug assign upper 3', 0):trace('aug assign step 3', 1)] += trace('aug assign value 2', []) 41 | 42 | print >>trace('print file', sys.stdout), trace('print arg', 0) 43 | 44 | for trace('for target', o).attr in trace('for iter', [0]): 45 | trace('for body', None) 46 | else: 47 | trace('for else', None) 48 | 49 | b = True 50 | while trace('while test', b): 51 | trace('while body', None) 52 | b = False 53 | else: 54 | trace('while else', None) 55 | 56 | for b in [True, False]: 57 | if trace('if test', b): 58 | trace('if body', None) 59 | else: 60 | trace('if orelse', None) 61 | 62 | # TODO: with 63 | 64 | # TODO: raise 65 | 66 | # TODO: try 67 | 68 | assert trace('assert test', True), trace('assert message', '') 69 | 70 | exec trace('exec body', '') 71 | exec trace('exec body', '') in trace('exec globals', {}) 72 | exec trace('exec body', '') in trace('exec globals', {}), trace('exec locals', {}) 73 | 74 | trace('bool op left', True) or trace('bool op right', True) 75 | trace('bin op left', 0) + trace('bin op right', 0) 76 | not trace('unary op operand', True) 77 | lam = lambda lambda_arg0=trace('lambda default 0', None), \ 78 | lambda_arg1=trace('lambda default 1', None), \ 79 | *lambda_args, **lambda_kwargs: \ 80 | trace('lambda body', None) 81 | for b in [True, False]: 82 | trace('if exp body', None) if trace('if exp test', b) else trace('if exp orelse', None) 83 | {trace('dict key 0', 0): trace('dict value 0', 0), trace('dict key 1', 1): trace('dict value 1', 1)} 84 | {trace('set elt 0', 0), trace('set elt 1', 1)} 85 | 86 | [trace('list comp elt', 0) 87 | for trace('list comp target 0', o).attr in trace('list comp iter 0', [0]) 88 | if trace('list comp test 0', True) if trace('list comp test 1', True) 89 | for trace('list comp target 1', o).attr in trace('list comp iter 1', [0]) 90 | if trace('list comp test 2', True) if trace('list comp test 3', True)] 91 | 92 | {trace('set comp elt', 0) 93 | for trace('set comp target 0', o).attr in trace('set comp iter 0', [0]) 94 | if trace('set comp test 0', True) if trace('set comp test 1', True) 95 | for trace('set comp target 1', o).attr in trace('set comp iter 1', [0]) 96 | if trace('set comp test 2', True) if trace('set comp test 3', True)} 97 | 98 | {trace('dict comp key', 0): trace('dict comp value', 0) 99 | for trace('dict comp target 0', o).attr in trace('dict comp iter 0', [0]) 100 | if trace('dict comp test 0', True) if trace('dict comp test 1', True) 101 | for trace('dict comp target 1', o).attr in trace('dict comp iter 1', [0]) 102 | if trace('dict comp test 2', True) if trace('dict comp test 3', True)} 103 | 104 | next(trace('generator exp elt', 0) 105 | for trace('generator exp target 0', o).attr in trace('generator exp iter 0', [0]) 106 | if trace('generator exp test 0', True) if trace('generator exp test 1', True) 107 | for trace('generator exp target 1', o).attr in trace('generator exp iter 1', [0]) 108 | if trace('generator exp test 2', True) if trace('generator exp test 3', True)) 109 | 110 | # TODO: yield 111 | 112 | trace('compare left', 0) < trace('compare middle', 1) < trace('compare right', 2) 113 | 114 | trace('lambda func', lam)( 115 | trace('lambda arg 0', 0), 116 | trace('lambda arg 1', 1), 117 | kwarg=trace('lambda kwarg', 0), 118 | *trace('lambda args', []), 119 | **trace('lambda kwargs', {})) 120 | 121 | `trace('repr value', 0)` 122 | 123 | trace('attribute value', o).attr 124 | trace('slice2 value', l)[trace('slice2 lower', 0):trace('slice2 upper', 0)] 125 | trace('slice3 value', l)[trace('slice3 lower', 0):trace('slice3 upper', 0):trace('slice3 step', 1)] 126 | trace('subscript value', l)[trace('subscript index', 0)] 127 | trace('extslice value', d)[trace('extslice index 0', 1), trace('extslice index 1', 1)] 128 | 129 | [trace('list elt 0', 0), trace('list elt 1', 1)] 130 | (trace('tuple elt 0', 0), trace('tuple elt 1', 1)) 131 | -------------------------------------------------------------------------------- /tests/symtable_torture.py: -------------------------------------------------------------------------------- 1 | # This test is designed to complain about any deviation from the 2 | # traversal order used by symtable. 3 | 4 | def only_for_parsing(): 5 | 6 | @decorator0(lambda: decorator_arg0) 7 | @decorator1(lambda: decorator_arg1) 8 | def function_def( 9 | function_arg0=lambda: function_default0, 10 | function_arg1=lambda: function_default1, 11 | *function_args, **function_kwargs): 12 | lambda: function_body 13 | return lambda: return_value 14 | 15 | @class_decorator0(lambda: class_decorator_arg0) 16 | @class_decorator1(lambda: class_decorator_arg1) 17 | class class_def(lambda: class_base0, lambda: class_base1): 18 | lambda: class_body 19 | 20 | del (lambda: del_value0).attr, \ 21 | (lambda: del_value1)[lambda: del_index], \ 22 | (lambda: del_value2)[lambda: del_lower:lambda: del_upper:lambda: del_step], \ 23 | (lambda: del_value3)[lambda: del_index0, lambda: del_index1], \ 24 | ((lambda: del_value4).attr, (lambda: del_value5).attr), \ 25 | [(lambda: del_value6).attr, (lambda: del_value7).attr] 26 | 27 | (lambda: assign_target0).attr, (lambda: assign_target1).attr \ 28 | = (lambda: assign_target2).attr, (lambda: assign_target3).attr \ 29 | = lambda: assign_value 30 | 31 | (lambda: aug_assign_target0).attr += lambda: aug_assign_value0 32 | (lambda: aug_assign_target1)[lambda: aug_assign_index] += lambda: aug_assign_value1 33 | (lambda: aug_assign_target2)[lambda: aug_assign_lower2:lambda: slice_upper2] += lambda: aug_assign_value2 34 | (lambda: aug_assign_target3)[lambda: aug_assign_lower3:lambda: slice_upper3:lambda: slice_upper3] += lambda: aug_assign_value3 35 | 36 | print lambda: print_arg0, lambda: print_arg1, 37 | print lambda: print_arg2, lambda: print_arg3 38 | print >>lambda: print_file0, lambda: print_arg4, lambda: print_arg5, 39 | print >>lambda: print_file1, lambda: print_arg6, lambda: print_arg7 40 | 41 | for (lambda: for_target).attr in lambda: for_iter: 42 | lambda: for_body 43 | break 44 | else: 45 | lambda: for_orelse 46 | 47 | while lambda: while_test: 48 | lambda: while_body 49 | continue 50 | else: 51 | lambda: while_orelse 52 | 53 | if lambda: if_test: 54 | lambda: if_body 55 | else: 56 | lambda: if_orelse 57 | 58 | # TODO: with 59 | 60 | raise lambda: raise_type, lambda: raise_inst, lambda: raise_tback 61 | 62 | try: 63 | lambda: body 64 | except lambda: handler_type0 as (lambda: handler_name0).attr: 65 | lambda: handler_body0 66 | except lambda: handler_type1 as (lambda: handler_name1).attr: 67 | lambda: handler_body1 68 | else: 69 | lambda: orelse_body 70 | 71 | try: 72 | lambda: body 73 | finally: 74 | lambda: finalbody 75 | 76 | assert lambda: assert_test, lambda: assert_msg 77 | 78 | import import_name0, import_name1 as import_asname1 79 | from import_from_module import import_from_name0, import_from_name1 as import_from_asname1 80 | 81 | exec (lambda: exec_body) in lambda: exec_globals, lambda: exec_locals 82 | 83 | global global_name 84 | 85 | pass 86 | 87 | (lambda: bool_op_left) or (lambda: bool_op_right) 88 | (lambda: bin_op_left) + (lambda: bin_op_right) 89 | not (lambda: unary_op_operand) 90 | lambda lambda_arg0=lambda: lambda_default0, \ 91 | lambda_arg1=lambda: lambda_default1, \ 92 | *lambda_args, **lambda_kwargs: \ 93 | lambda: lambda_body 94 | (lambda: if_exp_body) if (lambda: if_exp_test) else lambda: if_exp_orelse 95 | {lambda: dict_key0: lambda: dict_value0, lambda: dict_key1: lambda: dict_value1} 96 | {lambda: set_elt0, lambda: set_elt1} 97 | 98 | [lambda: list_comp_elt 99 | for (lambda: list_comp_target0).attr in lambda: list_comp_iter0 100 | if lambda: list_comp_test0 if lambda: list_comp_test1 101 | for (lambda: list_comp_target1).attr in lambda: list_comp_iter1 102 | if lambda: list_comp_test2 if lambda: list_comp_test3] 103 | 104 | {lambda: set_comp_elt 105 | for (lambda: set_comp_target0).attr in (lambda: set_comp_iter0) 106 | if lambda: set_comp_test0 if lambda: set_comp_test1 107 | for (lambda: set_comp_target1).attr in (lambda: set_comp_iter1) 108 | if lambda: set_comp_test2 if lambda: set_comp_test3} 109 | 110 | {lambda: dict_comp_key: lambda: dict_comp_value 111 | for (lambda: dict_comp_target0).attr in (lambda: dict_comp_iter0) 112 | if lambda: dict_comp_test0 if lambda: dict_comp_test1 113 | for (lambda: dict_comp_target1).attr in (lambda: dict_comp_iter1) 114 | if lambda: dict_comp_test2 if lambda: dict_comp_test3} 115 | 116 | (lambda: generator_exp_elt 117 | for (lambda: generator_exp_target0).attr in (lambda: generator_exp_iter0) 118 | if lambda: generator_exp_test0 if lambda: generator_exp_test1 119 | for (lambda: generator_exp_target1).attr in (lambda: generator_exp_iter1) 120 | if lambda: generator_exp_test2 if lambda: generator_exp_test3) 121 | 122 | # TODO: yield 123 | 124 | (lambda: compare_left) < (lambda: compare_middle) < (lambda: compare_right) 125 | 126 | (lambda: lambda_func)( 127 | lambda: lambda_arg0, 128 | lambda: lambda_arg1, 129 | kwarg=lambda: lambda_value, 130 | *lambda: lambda_args, 131 | **lambda: lambda_kwargs) 132 | 133 | `lambda: repr_value` 134 | 17 135 | "string" 136 | 137 | (lambda: attribute_value).attr 138 | (lambda: slice2_value)[lambda: slice2_lower:lambda: slice2_upper] 139 | (lambda: slice3_value)[lambda: slice3_lower:lambda: slice3_upper:lambda: slice3_step] 140 | (lambda: subscript_value)[lambda: subscript_index] 141 | (lambda: extslice_value)[lambda: extslice_index0, lambda: extslice_index1] 142 | 143 | name 144 | [lambda: list_elt0, lambda: list_elt1] 145 | (lambda: tuple_elt0, lambda: tuple_elt1) 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Oneliner-izer 2 | ========= 3 | 4 | [![Build Status](https://travis-ci.org/csvoss/onelinerizer.svg?branch=master)](https://travis-ci.org/csvoss/onelinerizer) 5 | 6 | 7 | Convert any Python 2 script into a single line of code. 8 | 9 | No newlines allowed. No semicolons, either. No silly file I/O tricks, or eval or exec. Just good, old-fashioned λ. 10 | 11 | Play with a live demo at [onelinerizer.com](http://www.onelinerizer.com/)! Watch the [presentation at PyCon 2016](https://www.youtube.com/watch?v=DsUxuz_Rt8g), or peruse the [slide deck](https://speakerdeck.com/pycon2016/chelsea-voss-oneliner-izer-an-exercise-in-constrained-coding). 12 | 13 | 14 | User Installation and Usage 15 | --- 16 | 17 | Install via `pip` from PyPI: 18 | 19 | ```sh 20 | $ pip install onelinerizer 21 | ``` 22 | 23 | Use either the command line function or the Python module: 24 | 25 | ```sh 26 | $ echo "def f(x):\n print x\nf(4)" > sandbox.py 27 | $ onelinerizer sandbox.py --debug 28 | $ onelinerizer sandbox_ol.py 29 | ``` 30 | 31 | ```python 32 | from onelinerizer import onelinerize 33 | onelinerize("def f(x):\n print x\nf(4)") 34 | ``` 35 | 36 | Examples 37 | -------- 38 | 39 | **Before:** 40 | 41 | ```python 42 | x = 3 43 | y = 4 44 | print (x < y < 5) 45 | ``` 46 | 47 | **After:** 48 | 49 | ```python 50 | (lambda __builtin__: (lambda __print, __y, d: [[__print(d.x n: 90 | print "Too big! Try again!" 91 | elif user_input < n: 92 | print "Too small! Try again!" 93 | else: 94 | print "You win!" 95 | return True 96 | guess_my_number(42) 97 | ``` 98 | 99 | **After:** 100 | 101 | ```python 102 | (lambda __builtin__: (lambda __print, __y, d: [(lambda ___: None)(d.guess_my_number(42)) for d.guess_my_number in [(lambda n:[(__y(lambda __this: (lambda d: (lambda __after: [(lambda __after: (lambda ___: __after(d))(__print('Not a positive integer!')) if (d.len(d.user_input)==0 or (not d.user_input.isdigit())) else [(lambda __after: (lambda ___: __after(d))(__print('Too big! Try again!')) if d.user_input>d.n else (lambda __after: (lambda ___: __after(d))(__print('Too small! Try again!')) if d.user_input=3 else (lambda __after: [__after(__d) for __d.outfilename in [('.ol.py'.join(__d.infilename.rsplit('.py',1)))]][0] if '.py' in __d.infilename else [__after(__d) for __d.outfilename in [((__d.infilename+'.ol.py'))]][0])(lambda __d: (lambda ___: __after(__d))(__print(('Writing to %s'%__d.outfilename)))))(lambda __d: [[[[(lambda ___: (lambda __after: (lambda ___: (lambda ___: (lambda ___: (lambda ___: __after(__d))(__print(__d.onelined)))(__print('--- ONELINED ---------------------------------')))(__print(__d.original)))(__print('--- ORIGINAL ---------------------------------')) if __d.VERBOSE else __after(__d))(lambda __d: __after(__d)))(__d.outfi.write((__d.onelined+'\n'))) for __d.onelined in [(__d.to_one_line(__d.original))]][0] for __d.original in [(__d.infi.read().strip())]][0] for __d.outfi in [(__d.open(__d.outfilename,'w'))]][0] for __d.infi in [(__d.open(__d.infilename,'r'))]][0]) for __d.infilename in [(__d.sys.argv[1])]][0])(lambda __d: __after(__d)) if __d.True else __after(__d))(lambda __d: None) for __d.VERBOSE in [(__d.True)]][0] for __d.to_one_line in [(lambda original:[[(lambda __after: __d.original if __d.len(__d.original.splitlines())==1 else __after(__d))(lambda __d: [__d.code(__d.t) for __d.t in [(__d.ast.parse(__d.original))]][0]) for __d.original in [(__d.original.strip())]][0] for __d.original in [(original)]][0])]][0] for __d.code_with_after in [(lambda tree,after:[(lambda __after: '+' if __d.type(__d.tree) is __d.ast.Add else (lambda __after: ' and ' if __d.type(__d.tree) is __d.ast.And else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Assert else (lambda __after: [[[('[%s for %s in [(%s)]][0]'%(__d.after,__d.targets,__d.value)) for __d.targets in [(','.join(__d.targets))]][0] for __d.value in [(__d.code(__d.tree.value))]][0] for __d.targets in [([__d.code(__d.target) for __d.target in __d.tree.targets])]][0] if __d.type(__d.tree) is __d.ast.Assign else (lambda __after: ('%s.%s'%(__d.code(__d.tree.value),__d.tree.attr)) if __d.type(__d.tree) is __d.ast.Attribute else (lambda __after: [[[('[%s for %s in [%s%s%s]][0]'%(__d.after,__d.target,__d.target,__d.op,__d.value)) for __d.value in [(__d.code(__d.tree.value))]][0] for __d.op in [(__d.code(__d.tree.op))]][0] for __d.target in [(__d.code(__d.tree.target))]][0] if __d.type(__d.tree) is __d.ast.AugAssign else (lambda __after: ('(%s%s%s)'%(__d.code(__d.tree.left),__d.code(__d.tree.op),__d.code(__d.tree.right))) if __d.type(__d.tree) is __d.ast.BinOp else (lambda __after: '&' if __d.type(__d.tree) is __d.ast.BitAnd else (lambda __after: '|' if __d.type(__d.tree) is __d.ast.BitOr else (lambda __after: '^' if __d.type(__d.tree) is __d.ast.BitXor else (lambda __after: ('(%s)'%__d.code(__d.tree.op).join([__d.code(__d.val) for __d.val in __d.tree.values])) if __d.type(__d.tree) is __d.ast.BoolOp else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Break else (lambda __after: [[[(lambda __after: [__after(__d) for __d.starargs in [([])]][0] if __d.tree.starargs is __d.None else [__after(__d) for __d.starargs in [([('*'+__d.code(__d.tree.starargs))])]][0])(lambda __d: (lambda __after: [__after(__d) for __d.kwargs in [([])]][0] if __d.tree.kwargs is __d.None else [__after(__d) for __d.kwargs in [([('**'+__d.code(__d.tree.kwargs))])]][0])(lambda __d: [[('%s(%s)'%(__d.func,__d.comma_sep_elems)) for __d.comma_sep_elems in [(','.join(__d.elems))]][0] for __d.elems in [((((__d.args+__d.keywords)+__d.starargs)+__d.kwargs))]][0])) for __d.keywords in [([__d.code(__d.kw) for __d.kw in __d.tree.keywords])]][0] for __d.args in [([__d.code(__d.arg) for __d.arg in __d.tree.args])]][0] for __d.func in [(__d.code(__d.tree.func))]][0] if __d.type(__d.tree) is __d.ast.Call else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.ClassDef else (lambda __after: None if __d.type(__d.tree) is __d.ast.Compare else (lambda __after: (('for %s in %s'%(__d.code(__d.tree.target),__d.code(__d.tree.iter)))+''.join([(' if '+__d.code(__d.i)) for __d.i in __d.tree.ifs])) if __d.type(__d.tree) is __d.ast.comprehension else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Continue else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Delete else (lambda __after: ('{%s}'%','.join([('%s:%s'%(__d.code(__d.k),__d.code(__d.v))) for (__d.k,__d.v) in __d.zip(__d.tree.keys,__d.tree.values)])) if __d.type(__d.tree) is __d.ast.Dict else (lambda __after: ('{%s}'%' '.join(([((__d.code(__d.tree.key)+':')+__d.code(__d.tree.value))]+[__d.code(__d.gen) for __d.gen in __d.tree.generators]))) if __d.type(__d.tree) is __d.ast.DictComp else (lambda __after: '/' if __d.type(__d.tree) is __d.ast.Div else (lambda __after: '...' if __d.type(__d.tree) is __d.ast.Ellipsis else (lambda __after: '==' if __d.type(__d.tree) is __d.ast.Eq else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.ExceptHandler else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Exec else (lambda __after: [('(lambda ___: %s)(%s)'%(__d.after,__d.code_to_exec)) for __d.code_to_exec in [(__d.code(__d.tree.value))]][0] if __d.type(__d.tree) is __d.ast.Expr else (lambda __after: __d.code(__d.tree.body) if __d.type(__d.tree) is __d.ast.Expression else (lambda __after: ', '.join([__d.code(__d.dim) for __d.dim in __d.tree.dims]) if __d.type(__d.tree) is __d.ast.ExtSlice else (lambda __after: '//' if __d.type(__d.tree) is __d.ast.FloorDiv else (lambda __after: [[[(lambda __after: __after(__d) if __d.len(__d.tree.orelse) is not 0 else __after(__d))(lambda __d: ('(lambda __d: %s)(reduce((lambda __d, __i:[%s for %s in [__i]][0]),%s,__d))'%(__d.after,__d.body,__d.item,__d.items))) for __d.items in [(__d.code(__d.tree.iter))]][0] for __d.body in [(__d.many_to_one(__d.tree.body,after='__d'))]][0] for __d.item in [(__d.code(__d.tree.target))]][0] if __d.type(__d.tree) is __d.ast.For else (lambda __after: [[[[(lambda __after: (lambda __d: __after(__d))(reduce((lambda __d, __i:[[__d for __d.function_code in [(('%s(%s)'%(__d.code(__d.decorator),__d.function_code)))]][0] for __d.decorator in [__i]][0]),__d.tree.decorator_list,__d)) if __d.len(__d.tree.decorator_list)>0 else __after(__d))(lambda __d: ('[%s for __d.%s in [(%s)]][0]'%(__d.after,__d.tree.name,__d.function_code))) for __d.function_code in [((__d.args+__d.body))]][0] for __d.body in [(('[%s for %s in [(%s)]][0]'%(__d.body,('__d.'+',__d.'.join(__d.arg_names)),','.join(__d.arg_names))))]][0] for __d.body in [(__d.many_to_one(__d.tree.body))]][0] for (__d.args,__d.arg_names) in [(__d.code(__d.tree.args))]][0] if __d.type(__d.tree) is __d.ast.FunctionDef else (lambda __after: [[[[(lambda __after: [[__after(__d) for __d.arg_names in [__d.arg_names+[__d.tree.vararg]]][0] for __d.args in [__d.args+[('*'+__d.tree.vararg)]]][0] if __d.tree.vararg is not __d.None else __after(__d))(lambda __d: (lambda __after: [[__after(__d) for __d.arg_names in [__d.arg_names+[__d.tree.kwarg]]][0] for __d.args in [__d.args+[('**'+__d.tree.kwarg)]]][0] if __d.tree.kwarg is not __d.None else __after(__d))(lambda __d: [(('lambda %s:'%__d.args),__d.arg_names) for __d.args in [(','.join(__d.args))]][0])) for __d.args in [([(__d.a.id if __d.d is __d.None else ((__d.a.id+'=')+__d.code(__d.d))) for (__d.d,__d.a) in __d.args])]][0] for __d.args in [(__d.zip(__d.padded_defaults,__d.tree.args))]][0] for __d.arg_names in [([__d.arg.id for __d.arg in __d.tree.args])]][0] for __d.padded_defaults in [((([__d.None]*(__d.len(__d.tree.args)-__d.len(__d.tree.defaults)))+__d.tree.defaults))]][0] if __d.type(__d.tree) is __d.ast.arguments else (lambda __after: ('%s'%' '.join(([__d.code(__d.tree.elt)]+[__d.code(__d.gen) for __d.gen in __d.tree.generators]))) if __d.type(__d.tree) is __d.ast.GeneratorExp else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Global else (lambda __after: '>' if __d.type(__d.tree) is __d.ast.Gt else (lambda __after: '>=' if __d.type(__d.tree) is __d.ast.GtE else (lambda __after: [[[('(lambda __after: %s if %s else %s)(lambda __d: %s)'%(__d.body,__d.test,__d.orelse,__d.after)) for __d.orelse in [(__d.many_to_one(__d.tree.orelse,after='__after(__d)'))]][0] for __d.body in [(__d.many_to_one(__d.tree.body,after='__after(__d)'))]][0] for __d.test in [(__d.code(__d.tree.test))]][0] if __d.type(__d.tree) is __d.ast.If else (lambda __after: ('(%s if %s else %s)'%(__d.code(__d.tree.body),__d.code(__d.tree.test),__d.code(__d.tree.orelse))) if __d.type(__d.tree) is __d.ast.IfExp else (lambda __after: (lambda __d: __d.after)(reduce((lambda __d, __i:[(lambda __after: [__after(__d) for __d.alias.asname in [(__d.alias.name)]][0] if __d.alias.asname is __d.None else __after(__d))(lambda __d: [__d for __d.after in [(("[%s for __d.%s in [__import__('%s')]][0]"%(__d.after,__d.alias.asname,__d.alias.name)))]][0]) for __d.alias in [__i]][0]),__d.tree.names,__d)) if __d.type(__d.tree) is __d.ast.Import else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.ImportFrom else (lambda __after: ' in ' if __d.type(__d.tree) is __d.ast.In else (lambda __after: ('%s'%__d.code(__d.tree.value)) if __d.type(__d.tree) is __d.ast.Index else (lambda __after: (__d.INIT_CODE%__d.many_to_one(__d.child_nodes(__d.tree))) if __d.type(__d.tree) is __d.ast.Interactive else (lambda __after: '~' if __d.type(__d.tree) is __d.ast.Invert else (lambda __after: ' is ' if __d.type(__d.tree) is __d.ast.Is else (lambda __after: ' is not ' if __d.type(__d.tree) is __d.ast.IsNot else (lambda __after: '<<' if __d.type(__d.tree) is __d.ast.LShift else (lambda __after: ('%s=%s'%(__d.tree.arg,__d.code(__d.tree.value))) if __d.type(__d.tree) is __d.ast.keyword else (lambda __after: [[[((('('+__d.args)+__d.body)+')') for __d.body in [(('[%s for %s in [(%s)]][0]'%(__d.body,('__d.'+',__d.'.join(__d.arg_names)),','.join(__d.arg_names))))]][0] for __d.body in [(__d.code(__d.tree.body))]][0] for (__d.args,__d.arg_names) in [(__d.code(__d.tree.args))]][0] if __d.type(__d.tree) is __d.ast.Lambda else (lambda __after: [('[%s]'%','.join(__d.elts)) for __d.elts in [([__d.code(__d.elt) for __d.elt in __d.tree.elts])]][0] if __d.type(__d.tree) is __d.ast.List else (lambda __after: ('[%s]'%' '.join(([__d.code(__d.tree.elt)]+[__d.code(__d.gen) for __d.gen in __d.tree.generators]))) if __d.type(__d.tree) is __d.ast.ListComp else (lambda __after: '<' if __d.type(__d.tree) is __d.ast.Lt else (lambda __after: '<=' if __d.type(__d.tree) is __d.ast.LtE else (lambda __after: '%' if __d.type(__d.tree) is __d.ast.Mod else (lambda __after: (__d.INIT_CODE%__d.many_to_one(__d.child_nodes(__d.tree))) if __d.type(__d.tree) is __d.ast.Module else (lambda __after: '*' if __d.type(__d.tree) is __d.ast.Mult else (lambda __after: ('__d.'+__d.tree.id) if __d.type(__d.tree) is __d.ast.Name else (lambda __after: 'not ' if __d.type(__d.tree) is __d.ast.Not else (lambda __after: '!=' if __d.type(__d.tree) is __d.ast.NotEq else (lambda __after: ' not in ' if __d.type(__d.tree) is __d.ast.NotIn else (lambda __after: __d.str(__d.tree.n) if __d.type(__d.tree) is __d.ast.Num else (lambda __after: ' or ' if __d.type(__d.tree) is __d.ast.Or else (lambda __after: __d.after if __d.type(__d.tree) is __d.ast.Pass else (lambda __after: '**' if __d.type(__d.tree) is __d.ast.Pow else (lambda __after: [(lambda __after: ('(lambda ___: %s)(__print(%s))'%(__d.after,__d.to_print)) if __d.after is not 'None' else ('__print(%s)'%__d.to_print))(lambda __d: __after(__d)) for __d.to_print in [(','.join([__d.code(__d.x) for __d.x in __d.tree.values]))]][0] if __d.type(__d.tree) is __d.ast.Print else (lambda __after: '>>' if __d.type(__d.tree) is __d.ast.RShift else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Raise else (lambda __after: ('repr(%s)'%__d.code(__d.tree.value)) if __d.type(__d.tree) is __d.ast.Repr else (lambda __after: __d.code(__d.tree.value) if __d.type(__d.tree) is __d.ast.Return else (lambda __after: ('set(%s)'%__d.tree.elts) if __d.type(__d.tree) is __d.ast.Set else (lambda __after: ('{%s}'%' '.join(([__d.code(__d.tree.elt)]+[__d.code(__d.gen) for __d.gen in __d.tree.generators]))) if __d.type(__d.tree) is __d.ast.SetComp else (lambda __after: (lambda __after: ('%s:%s'%(__d.code(__d.tree.lower),__d.code(__d.tree.upper))) if __d.tree.step is __d.None else ('%s:%s:%s'%(__d.code(__d.tree.lower),__d.code(__d.tree.upper),__d.code(__d.tree.step))))(lambda __d: __after(__d)) if __d.type(__d.tree) is __d.ast.Slice else (lambda __after: __d.repr(__d.tree.s) if __d.type(__d.tree) is __d.ast.Str else (lambda __after: '-' if __d.type(__d.tree) is __d.ast.Sub else (lambda __after: ('%s[%s]'%(__d.code(__d.tree.value),__d.code(__d.tree.slice))) if __d.type(__d.tree) is __d.ast.Subscript else (lambda __after: (__d.INIT_CODE%__d.many_to_one(__d.child_nodes(__d.tree))) if __d.type(__d.tree) is __d.ast.Suite else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.TryExcept else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.TryFinally else (lambda __after: [(lambda __after: '()' if __d.len(__d.elts) is 0 else (lambda __after: ('(%s,)'%__d.elts[0]) if __d.len(__d.elts) is 1 else ('(%s)'%','.join(__d.elts)))(lambda __d: __after(__d)))(lambda __d: __after(__d)) for __d.elts in [([__d.code(__d.elt) for __d.elt in __d.tree.elts])]][0] if __d.type(__d.tree) is __d.ast.Tuple else (lambda __after: '+' if __d.type(__d.tree) is __d.ast.UAdd else (lambda __after: '-' if __d.type(__d.tree) is __d.ast.USub else (lambda __after: ('(%s%s)'%(__d.code(__d.tree.op),__d.code(__d.tree.operand))) if __d.type(__d.tree) is __d.ast.UnaryOp else (lambda __after: [[[('(__y(lambda __this: (lambda __d: (lambda __after: %s if %s else %s)(lambda __d: %s))))(__d)'%(__d.body,__d.test,__d.orelse,__d.after)) for __d.orelse in [(__d.many_to_one(__d.tree.orelse,after='__after(__d)'))]][0] for __d.body in [(__d.many_to_one(__d.tree.body,after='__this(__d)'))]][0] for __d.test in [(__d.code(__d.tree.test))]][0] if __d.type(__d.tree) is __d.ast.While else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.With else (lambda __after: __after(__d) if __d.type(__d.tree) is __d.ast.Yield else __after(__d))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: __after(__d)))(lambda __d: None) for __d.tree,__d.after in [(tree,after)]][0])]][0] for __d.code in [(lambda tree:[__d.code_with_after(__d.tree,'None') for __d.tree in [(tree)]][0])]][0] for __d.many_to_one in [(lambda trees,after='None':[None for __d.trees,__d.after in [(trees,after)]][0])]][0] for __d.child_nodes in [(lambda tree:[__d.list(__d.ast.iter_child_nodes(__d.tree)) for __d.tree in [(tree)]][0])]][0] for __d.fields in [(lambda tree:[__d.dict(__d.list(__d.ast.iter_fields(__d.tree))) for __d.tree in [(tree)]][0])]][0] for __d.INIT_CODE in [("(lambda __builtin__: (lambda __print, __y, __d: %s)(__builtin__.__dict__['print'],(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))),type('StateDict',(),__builtin__.__dict__)()))(__import__('__builtin__'))")]][0] for __d.sys in [__import__('sys')]][0] for __d.ast in [__import__('ast')]][0])(__builtin__.__dict__['print'],(lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))),type('StateDict',(),__builtin__.__dict__)()))(__import__('__builtin__')) 2 | -------------------------------------------------------------------------------- /onelinerizer/onelinerizer.py: -------------------------------------------------------------------------------- 1 | """Convert any Python file into a single line of code. 2 | 3 | Usage via the command line: 4 | 5 | $ python main.py --help 6 | print usages 7 | $ python main.py infile.py 8 | one-line infile.py, put the result in infile.ol.py 9 | $ python main.py infile.py outfile.py 10 | one-line infile.py, put the result in outfile.py 11 | """ 12 | 13 | import ast 14 | import symtable 15 | 16 | from .template import T 17 | 18 | 19 | def lambda_function(arguments_to_values): 20 | """ 21 | Arguments: 22 | arguments_to_values: {string: string | T} - e.g. {'a': '47'} 23 | 24 | Returns: 25 | T - e.g. (lambda a: {})(47) 26 | """ 27 | return T('(lambda {}: {})({})').format( 28 | T(', ').join(arguments_to_values.keys()), 29 | T('{}'), 30 | T(', ').join(arguments_to_values.values())) 31 | 32 | def provide(body, **subs): 33 | """ 34 | Provide the variables in subs to the code in `body`, by wrapping 35 | `body` in a lambda function if needed. 36 | 37 | Arguments: 38 | body: string | T, e.g. '__print(42)' 39 | subs: {string: string | T}, e.g. {'__print': 'f'} 40 | 41 | Returns: 42 | T - e.g. (lambda __print: __print(42))(f) 43 | """ 44 | body = T('{}').format(body) 45 | needed = set(body.free()).intersection(subs) 46 | if needed: 47 | return lambda_function({k: subs[k] for k in needed}).format( 48 | body.format(**{k: k for k in needed})) 49 | else: 50 | return body 51 | 52 | 53 | def get_init_code(tree, table): 54 | """Get one-lined code from `tree` and `table. 55 | 56 | Calculate the helper variables that we will need, and wrap the output 57 | code (computed from `tree`) with definitions of those variables. 58 | 59 | TODO: Short-circuit to something far simpler if the program has only one 60 | print statement. 61 | 62 | Arguments: 63 | tree: Python AST node 64 | table: symtable.symtable 65 | 66 | Returns: 67 | string - valid one-line code 68 | """ 69 | output = Namespace(table).many_to_one(tree.body) 70 | 71 | doc = ast.get_docstring(tree, clean=False) 72 | if doc is not None: 73 | output = assignment_component(output, T("{__g}['__doc__']"), repr(doc)) 74 | 75 | output = provide( 76 | output.format(__l=T('{__g}')), 77 | __print=T("__import__('__builtin__', level=0).__dict__['print']"), 78 | __y="(lambda f: (lambda x: x(x))(lambda y:" 79 | " f(lambda: y(y)())))", 80 | __g=T("globals()"), 81 | __contextlib="__import__('contextlib', level=0)", 82 | __operator="__import__('operator', level=0)", 83 | __sys="__import__('sys', level=0)", 84 | __types="__import__('types', level=0)") 85 | 86 | return output.close() 87 | 88 | 89 | boolop_code = { 90 | ast.And: ' and ', 91 | ast.Or: ' or ', 92 | } 93 | 94 | operator_code = { 95 | ast.Add: '+', 96 | ast.Sub: '-', 97 | ast.Mult: '*', 98 | ast.Div: '/', 99 | ast.Mod: '%', 100 | ast.Pow: '**', 101 | ast.LShift: '<<', 102 | ast.RShift: '>>', 103 | ast.BitOr: '|', 104 | ast.BitXor: '^', 105 | ast.BitAnd: '&', 106 | ast.FloorDiv: '//', 107 | } 108 | 109 | unaryop_code = { 110 | ast.Invert: '~', 111 | ast.Not: 'not ', 112 | ast.UAdd: '+', 113 | ast.USub: '-', 114 | } 115 | 116 | cmpop_code = { 117 | ast.Eq: ' == ', 118 | ast.NotEq: ' != ', 119 | ast.Lt: ' < ', 120 | ast.LtE: ' <= ', 121 | ast.Gt: ' > ', 122 | ast.GtE: ' >= ', 123 | ast.Is: ' is ', 124 | ast.IsNot: ' is not ', 125 | ast.In: ' in ', 126 | ast.NotIn: ' not in ', 127 | } 128 | 129 | 130 | def assignment_component(after, targets, value): 131 | """ 132 | Assign `targets` to `value` in the code `after`. 133 | 134 | Arguments: 135 | after: string, e.g. 'x+42' 136 | targets: string, e.g. 'x,y,z' 137 | value: string, e.g. '(1,2,3)' 138 | 139 | Returns: 140 | T, e.g. T('[x+42 for x,y,z in [((1,2,3))]]') 141 | """ 142 | # Old way: 143 | # return T('(lambda {}: {})({})').format(targets, after, value) 144 | return T('[{} for {} in [({})]][0]').format(after, targets, value) 145 | 146 | 147 | class Namespace(ast.NodeVisitor): 148 | """ 149 | AST visitor. 150 | """ 151 | def __init__(self, table, private=''): 152 | self.table = table 153 | self.subtables = iter(table.get_children()) 154 | self.private = '_' + table.get_name() if table.get_type() == 'class' \ 155 | else private 156 | self.futures = set() 157 | 158 | def next_child(self): 159 | return Namespace(next(self.subtables), private=self.private) 160 | 161 | def mangle(self, name): 162 | return self.private + name if name.startswith('__') and \ 163 | not name.endswith('__') else name 164 | 165 | def var(self, name): 166 | name = self.mangle(name) 167 | sym = self.table.lookup(name) 168 | if self.table.get_type() == 'module' or (sym.is_global() and self.table.is_optimized()) or name == 'None': 169 | return T('{__print}') if name == 'print' else T('{}').format(name) 170 | elif sym.is_global(): 171 | return T('({__l}[{!r}] if {!r} in __l else {})').format( 172 | name, name, T('{__print}') if name == 'print' else name) 173 | elif sym.is_local(): 174 | return T('{__l}[{!r}]').format(name) 175 | elif sym.is_free(): 176 | return T('{___f_' + name + '}()').format(name) 177 | else: 178 | raise SyntaxError('confusing symbol {!r}'.format(name)) 179 | 180 | def store_var(self, name): 181 | name = self.mangle(name) 182 | sym = self.table.lookup(name) 183 | if sym.is_global(): 184 | return T('{__g}[{!r}]').format(name) 185 | elif sym.is_local(): 186 | return T('{__l}[{!r}]').format(name) 187 | elif sym.is_free(): 188 | raise SyntaxError('storing free variable {!r}'.format(name)) 189 | else: 190 | raise SyntaxError('confusing symbol {!r}'.format(name)) 191 | 192 | def delete_var(self, name): 193 | name = self.mangle(name) 194 | sym = self.table.lookup(name) 195 | if sym.is_global(): 196 | return T('{__g}.pop({!r})').format(name) 197 | elif sym.is_local(): 198 | return T('{__l}.pop({!r})').format(name) 199 | elif sym.is_free(): 200 | raise SyntaxError('deleting free variable {!r}'.format(name)) 201 | else: 202 | raise SyntaxError('confusing symbol {!r}'.format(name)) 203 | 204 | def close(self, ns, local, body, **subs): 205 | if self.table.get_type() == 'function': 206 | subs = dict(subs, **{'___f_' + v: T('lambda: {}').format(self.var(v)) 207 | for v in self.table.get_locals()}) 208 | return provide(body, __l=local, **subs) 209 | 210 | def many_to_one(self, trees, after='None'): 211 | # trees :: [Tree] 212 | # return :: string 213 | return reduce( 214 | lambda ctx, tree: ctx.format(after=self.visit(tree)), 215 | trees, 216 | T('{after}')).format(after=after) 217 | 218 | def slice_repr(self, slice): 219 | if type(slice) is ast.Ellipsis: 220 | return T('Ellipsis') 221 | elif type(slice) is ast.Slice: 222 | return T('slice({}, {}, {})').format( 223 | 'None' if slice.lower is None else self.visit(slice.lower), 224 | 'None' if slice.upper is None else self.visit(slice.upper), 225 | 'None' if slice.step is None else self.visit(slice.step)) 226 | elif type(slice) is ast.ExtSlice: 227 | return T('({})').format(T(', ').join(map(self.slice_repr, slice.dims)) + 228 | ','*(len(slice.dims) == 1)) 229 | elif type(slice) is ast.Index: 230 | return self.visit(slice.value) 231 | else: 232 | raise NotImplementedError('Case not caught: %s' % str(type(slice))) 233 | 234 | def delete_code(self, target): 235 | if type(target) is ast.Attribute: 236 | return [T('delattr({}, {!r})').format(self.visit(target.value), target.attr)] 237 | elif type(target) is ast.Subscript: 238 | if type(target.slice) is ast.Slice and target.slice.step is None: 239 | return [T("(lambda o, **t: type('translator', (), {{t[m]: " 240 | "staticmethod(object.__getattribute__(d[m], '__get__'" 241 | ")(o, type(o))) for d in [object.__getattribute__(" 242 | "type(o), '__dict__')] for m in t if m in d}})())({}," 243 | " __delitem__='__getitem__', __delslice__=" 244 | "'__getslice__', __len__='__len__')[{}]").format( 245 | self.visit(target.value), 246 | self.visit(target.slice))] 247 | else: 248 | return [T("{__operator}.delitem({}, {})").format( 249 | self.visit(target.value), 250 | self.slice_repr(target.slice))] 251 | elif type(target) is ast.Name: 252 | return [self.delete_var(target.id)] 253 | elif type(target) in (ast.List, ast.Tuple): 254 | return [c for elt in target.elts for c in self.delete_code(elt)] 255 | else: 256 | raise NotImplementedError('Case not caught: %s' % str(type(target))) 257 | 258 | def visit_Assert(self, tree): 259 | return T('({after} if {} else ([] for [] in []).throw(AssertionError{}))').format( 260 | self.visit(tree.test), 261 | '' if tree.msg is None else T('({})').format(self.visit(tree.msg))) 262 | 263 | def visit_Assign(self, tree): 264 | targets = [self.visit(target) for target in tree.targets] 265 | value = self.visit(tree.value) 266 | targets = T(', ').join(targets) 267 | return assignment_component(T('{after}'), targets, 268 | value if len(tree.targets) == 1 269 | else T('[{}]*{}').format(value, len(tree.targets))) 270 | 271 | def visit_Attribute(self, tree): 272 | return T('{}.{}').format(self.visit(tree.value), tree.attr) 273 | 274 | def visit_AugAssign(self, tree): 275 | if type(tree.target) is ast.Attribute: 276 | target_params = ['__target'] 277 | target_args = [self.visit(tree.target.value)] 278 | target_value = T('__target.{}').format(tree.target.attr) 279 | elif type(tree.target) is ast.Subscript: 280 | if type(tree.target.slice) is ast.Slice and tree.target.slice.step is None: 281 | target_params = ['__target'] 282 | target_args = [self.visit(tree.target.value)] 283 | if tree.target.slice.lower is not None: 284 | target_params.append('__lower') 285 | target_args.append(self.visit(tree.target.slice.lower)) 286 | if tree.target.slice.upper is not None: 287 | target_params.append('__upper') 288 | target_args.append(self.visit(tree.target.slice.upper)) 289 | target_value = T('__target[{}:{}]').format( 290 | '' if tree.target.slice.lower is None else '__lower', 291 | '' if tree.target.slice.upper is None else '__upper') 292 | else: 293 | target_params = ['__target', '__slice'] 294 | target_args = [self.visit(tree.target.value), self.slice_repr(tree.target.slice)] 295 | target_value = '__target[__slice]' 296 | elif type(tree.target) is ast.Name: 297 | target_params = [] 298 | target_args = [] 299 | target_value = self.store_var(tree.target.id) 300 | else: 301 | raise SyntaxError('illegal expression for augmented assignment') 302 | 303 | iop = type(tree.op).__name__.lower() 304 | if iop.startswith('bit'): 305 | iop = iop[len('bit'):] 306 | if 'division' in self.futures and isinstance(tree.op, ast.Div): 307 | iop = 'truediv' 308 | value = self.visit(tree.value) 309 | assign = assignment_component( 310 | T('{after}'), target_value, 311 | T("{__operator}.i{}({}, {})").format(iop, target_value, value)) 312 | if target_params: 313 | assign = T('(lambda {}: {})({})').format( 314 | T(', ').join(target_params), 315 | assign, 316 | T(', ').join(target_args)) 317 | return assign 318 | 319 | def visit_BinOp(self, tree): 320 | if 'division' in self.futures and isinstance(tree.op, ast.Div): 321 | return T('{__operator}.truediv({}, {})').format(self.visit(tree.left), self.visit(tree.right)) 322 | return T('({} {} {})').format(self.visit(tree.left), operator_code[type(tree.op)], self.visit(tree.right)) 323 | 324 | def visit_BoolOp(self, tree): 325 | return T('({})').format(T(boolop_code[type(tree.op)]).join(map(self.visit, tree.values))) 326 | 327 | def visit_Break(self, tree): 328 | return T('{__break}()') 329 | 330 | def visit_Call(self, tree): 331 | func = self.visit(tree.func) 332 | args = [self.visit(arg) for arg in tree.args] 333 | keywords = [self.visit(kw) for kw in tree.keywords] 334 | if tree.starargs is None: 335 | starargs = [] 336 | else: 337 | starargs = ["*" + self.visit(tree.starargs)] 338 | if tree.kwargs is None: 339 | kwargs = [] 340 | else: 341 | kwargs = ["**" + self.visit(tree.kwargs)] 342 | elems = args + keywords + starargs + kwargs 343 | comma_sep_elems = T(', ').join(elems) 344 | return T('{}({})').format(func, comma_sep_elems) 345 | 346 | def visit_ClassDef(self, tree): 347 | bases = (T(', ').join(map(self.visit, tree.bases)) + 348 | ','*(len(tree.bases) == 1)) 349 | decoration = T('{}') 350 | for decorator in tree.decorator_list: 351 | decoration = decoration.format(T('{}({})').format(self.visit(decorator), T('{}'))) 352 | ns = self.next_child() 353 | body = ns.many_to_one(tree.body, after=T('{__l}')) 354 | doc = ast.get_docstring(tree, clean=False) 355 | body = self.close(ns, "{{'__module__': __name__{}}}".format( 356 | '' if doc is None else ", '__doc__': {!r}".format(doc)), body) 357 | if tree.bases: 358 | class_code = T("(lambda b, d: d.get('__metaclass__', getattr(b[0], " 359 | "'__class__', type(b[0])))({!r}, b, d))(({}), " 360 | "{})").format(tree.name, bases, body) 361 | else: 362 | class_code = T("(lambda d: d.get('__metaclass__', {__g}.get(" 363 | "'__metaclass__', {__types}.ClassType))({!r}, (), " 364 | "d))({})").format(tree.name, body) 365 | class_code = decoration.format(class_code) 366 | return assignment_component(T('{after}'), self.store_var(tree.name), class_code) 367 | 368 | def visit_Compare(self, tree): 369 | assert len(tree.ops) == len(tree.comparators) 370 | return T('({})').format(self.visit(tree.left) + T('').join( 371 | [cmpop_code[type(tree.ops[i])] + self.visit(tree.comparators[i]) 372 | for i in range(len(tree.ops))])) 373 | 374 | def visit_comprehension(self, tree): 375 | return (T('for {} in {}').format(self.visit(tree.target), self.visit(tree.iter)) + 376 | T('').join(' if ' + self.visit(i) for i in tree.ifs)) 377 | 378 | def comprehension_code(self, generators, wrap): 379 | iter0 = self.visit(generators[0].iter) 380 | ns = self.next_child() 381 | return self.close( 382 | ns, '{}', 383 | wrap(ns, T(' ').join( 384 | [T('for {} in {__iter}').format(ns.visit(generators[0].target))] + 385 | ['if ' + ns.visit(i) for i in generators[0].ifs] + 386 | map(ns.visit, generators[1:]))), 387 | __iter=iter0) 388 | 389 | def visit_Continue(self, tree): 390 | return T('{__continue}()') 391 | 392 | def visit_Delete(self, tree): 393 | cs = [c for target in tree.targets for c in self.delete_code(target)] 394 | if cs: 395 | return T('({}, {after})[-1]').format(T(', ').join(cs)) 396 | else: 397 | return T('{after}') 398 | 399 | def visit_Dict(self, tree): 400 | return T('{{{}}}').format(T(', ').join( 401 | T('{}: {}').format(k, v) 402 | for k, v in zip(map(self.visit, tree.keys), map(self.visit, tree.values)))) 403 | 404 | def visit_DictComp(self, tree): 405 | return self.comprehension_code( 406 | tree.generators, 407 | lambda ns, g: T('{{{}: {} {}}}').format( 408 | T('{}'), ns.visit(tree.value), g).format(ns.visit(tree.key))) 409 | 410 | def visit_Ellipsis(self, tree): 411 | return T('...') 412 | 413 | def visit_ExceptHandler(self, tree): 414 | raise NotImplementedError('Open problem: except') 415 | 416 | def visit_Exec(self, tree): 417 | body = self.visit(tree.body) 418 | if tree.globals is None and self.table.get_type() == 'module': 419 | exec_code = T( 420 | "eval(compile({}, '', 'exec'), " 421 | "None, {__l})").format(body) 422 | elif tree.globals is None: 423 | exec_code = T( 424 | "(lambda b, c: (eval(compile(b, '', 'exec'), " 425 | "None, c), {__l}.update(c)))({}, {__l}.copy())").format(body) 426 | elif tree.locals is None and self.table.get_type() == 'module': 427 | exec_code = T( 428 | "(lambda b, g: eval(compile(b, '', 'exec'), g, " 429 | "{__l} if g is None else g))({}, {})").format( 430 | body, self.visit(tree.globals)) 431 | elif tree.locals is None: 432 | exec_code = T( 433 | "(lambda b, g, c: (eval(compile(b, '', 'exec'), g, " 434 | "c if g is None else g), " 435 | "{__l}.update(c)))({}, {}, {__l}.copy())").format( 436 | body, self.visit(tree.globals)) 437 | elif self.table.get_type() == 'module': 438 | exec_code = T( 439 | "(lambda b, g, l: eval(compile(b, '', 'exec'), g, " 440 | "({__l} if g is None else g) if l is None " 441 | "else l))({}, {}, {})").format( 442 | body, self.visit(tree.globals), self.visit(tree.locals)) 443 | else: 444 | exec_code = T( 445 | "(lambda b, g, l, c: (eval(compile(b, '', 'exec'), g, " 446 | "(c if g is None else g) if l is None else l), " 447 | "{__l}.update(c)))({}, {}, {}, {__l}.copy())").format( 448 | body, self.visit(tree.globals), self.visit(tree.locals)) 449 | return T('({}, {after})[1]').format(exec_code) 450 | 451 | def visit_Expr(self, tree): 452 | return T('({}, {after})[1]').format(self.visit(tree.value)) 453 | 454 | def visit_Expression(self, tree): 455 | return self.visit(tree.body) 456 | 457 | def visit_ExtSlice(self, tree): 458 | return (T(', ').join(map(self.visit, tree.dims)) + 459 | ','*(len(tree.dims) == 1)) 460 | 461 | def visit_For(self, tree): 462 | item = self.visit(tree.target) 463 | items = self.visit(tree.iter) 464 | body = self.many_to_one(tree.body, after='__this()') 465 | orelse = self.many_to_one(tree.orelse, after='__after()') 466 | return lambda_function({'__items': T('iter({})').format(items), '__sentinel': 467 | '[]', '__after': T('lambda: {after}')}).format( 468 | T('{__y}(lambda __this: lambda: {})()').format( 469 | lambda_function({'__i': 'next(__items, __sentinel)'}).format( 470 | T('{} if __i is not __sentinel else {}').format( 471 | provide( 472 | assignment_component(body, item, '__i'), 473 | __break='__after', __continue='__this'), 474 | orelse)))) 475 | 476 | def visit_FunctionDef(self, tree): 477 | # self.visit() returns something of the form 478 | # ('lambda x, y, z=5, *args: ', ['x', 'y', 'z', 'args']) 479 | args, arg_names = self.visit(tree.args) 480 | decoration = T('{}') 481 | for decorator in tree.decorator_list: 482 | decoration = decoration.format(T('{}({})').format(self.visit(decorator), T('{}'))) 483 | ns = self.next_child() 484 | body = ns.many_to_one(tree.body).format(pre_return='', post_return='') 485 | if arg_names: 486 | body = assignment_component(body, 487 | T(', ').join(ns.var(name) for name in arg_names), 488 | T(', ').join(arg_names)) 489 | body = self.close(ns, '{}', body) 490 | function_code = args + body 491 | doc = ast.get_docstring(tree, clean=False) 492 | if tree.decorator_list: 493 | return assignment_component( 494 | T('{after}'), 495 | self.store_var(tree.name), 496 | decoration.format(assignment_component( 497 | '__func', 498 | '__func, __func.__name__' + ('' if doc is None else ', __func.__doc__'), 499 | T('{}, {!r}' + ('' if doc is None else ', {!r}')).format( 500 | function_code, tree.name, doc)))) 501 | else: 502 | return assignment_component( 503 | T('{after}'), 504 | T('{}, {}.__name__' + ('' if doc is None else ', {}.__doc__')).format( 505 | self.store_var(tree.name), self.var(tree.name), self.var(tree.name)), 506 | T('{}, {!r}' + ('' if doc is None else ', {!r}')).format( 507 | function_code, tree.name, doc)) 508 | 509 | def visit_arguments(self, tree): 510 | # this should return something of the form 511 | # ('lambda x, y, z=5, *args: ', ['x', 'y', 'z', 'args']) 512 | padded_defaults = [None] * (len(tree.args) - 513 | len(tree.defaults)) + tree.defaults 514 | arg_names = [arg.id for arg in tree.args] 515 | args = zip(padded_defaults, tree.args) 516 | args = [a.id if d is None else a.id + "=" + self.visit(d) for (d, a) in args] 517 | if tree.vararg is not None: 518 | args += ["*" + tree.vararg] 519 | arg_names += [tree.vararg] 520 | if tree.kwarg is not None: 521 | args += ["**" + tree.kwarg] 522 | arg_names += [tree.kwarg] 523 | args = T(', ').join(args) 524 | return (T('lambda {}: ').format(args), arg_names) 525 | 526 | def visit_GeneratorExp(self, tree): 527 | return self.comprehension_code( 528 | tree.generators, 529 | lambda ns, g: T('({} {})').format(ns.visit(tree.elt), g)) 530 | 531 | def visit_Global(self, tree): 532 | return T('{after}') 533 | 534 | def visit_If(self, tree): 535 | test = self.visit(tree.test) 536 | body = self.many_to_one(tree.body, after='__after()') 537 | orelse = self.many_to_one(tree.orelse, after='__after()') 538 | return T('(lambda __after: {} if {} else {})(lambda: {after})').format( 539 | body, test, orelse) 540 | 541 | def visit_IfExp(self, tree): 542 | test = self.visit(tree.test) 543 | body = self.visit(tree.body) 544 | orelse = self.visit(tree.orelse) 545 | return T('({} if {} else {})').format(body, test, orelse) 546 | 547 | def visit_Import(self, tree): 548 | after = T('{after}') 549 | level_arg = ', level=0' if 'absolute_import' in self.futures else '' 550 | for alias in tree.names: 551 | ids = alias.name.split('.') 552 | if alias.asname is None: 553 | after = assignment_component(after, self.store_var(ids[0]), 554 | T('__import__({!r}, {__g}, {__l}{})').format( 555 | alias.name, level_arg)) 556 | else: 557 | after = assignment_component(after, self.store_var(alias.asname), 558 | T('.').join([T('__import__({!r}, {__g}, {__l}{})').format( 559 | alias.name, level_arg)] + ids[1:])) 560 | return after 561 | 562 | def visit_ImportFrom(self, tree): 563 | body = assignment_component( 564 | T('{after}'), 565 | T(', ').join(self.store_var(alias.name if alias.asname is None 566 | else alias.asname) for alias in tree.names), 567 | T(', ').join('__mod.' + alias.name for alias in tree.names)) 568 | if tree.module == '__future__': 569 | self.futures |= set(alias.name for alias in tree.names) 570 | body = T( 571 | '(lambda __f: type(__f)(type(__f.func_code)(' 572 | '__f.func_code.co_argcount, ' 573 | '__f.func_code.co_nlocals, ' 574 | '__f.func_code.co_stacksize, ' 575 | '__f.func_code.co_flags{}, ' 576 | '__f.func_code.co_code, ' 577 | '__f.func_code.co_consts, ' 578 | '__f.func_code.co_names, ' 579 | '__f.func_code.co_varnames, ' 580 | '__f.func_code.co_filename, ' 581 | '__f.func_code.co_name, ' 582 | '__f.func_code.co_firstlineno, ' 583 | '__f.func_code.co_lnotab, ' 584 | '__f.func_code.co_freevars, ' 585 | '__f.func_code.co_cellvars), ' 586 | '__f.func_globals, ' 587 | '__f.func_name, ' 588 | '__f.func_defaults, ' 589 | '__f.func_closure)())(lambda: {})' 590 | ).format( 591 | ''.join(' | __mod.' + alias.name + '.compiler_flag' 592 | for alias in tree.names), 593 | body) 594 | return T('(lambda __mod: {})(__import__({!r}, {__g}, {__l},' 595 | ' {!r}, {!r}))').format( 596 | body, 597 | '' if tree.module is None else tree.module, 598 | tuple(alias.name for alias in tree.names), 599 | tree.level) 600 | 601 | def visit_Index(self, tree): 602 | return self.visit(tree.value) 603 | 604 | def visit_keyword(self, tree): 605 | return T('{}={}').format(tree.arg, self.visit(tree.value)) 606 | 607 | def visit_Lambda(self, tree): 608 | args, arg_names = self.visit(tree.args) 609 | ns = self.next_child() 610 | body = ns.visit(tree.body) 611 | if arg_names: 612 | body = assignment_component(body, T(', ').join(ns.store_var(name) 613 | for name in arg_names), T(', ').join(arg_names)) 614 | body = self.close(ns, '{}', body) 615 | return '(' + args + body + ')' 616 | 617 | def visit_List(self, tree): 618 | elts = [self.visit(elt) for elt in tree.elts] 619 | return T('[{}]').format(T(', ').join(elts)) 620 | 621 | def visit_ListComp(self, tree): 622 | return T('[{}]').format(T(' ').join([self.visit(tree.elt)] + 623 | map(self.visit, tree.generators))) 624 | 625 | def visit_Name(self, tree): 626 | if isinstance(tree.ctx, (ast.Store, ast.AugStore)): 627 | return self.store_var(tree.id) 628 | else: 629 | return self.var(tree.id) 630 | 631 | def visit_Num(self, tree): 632 | return T('{!r}').format(tree.n) 633 | 634 | def visit_Pass(self, tree): 635 | return T('{after}') 636 | 637 | def visit_Print(self, tree): 638 | to_print = T('{}') 639 | if tree.dest is not None: 640 | # Abuse varargs to get the right evaluation order 641 | to_print = T('file={}, *[{}]').format(self.visit(tree.dest), to_print) 642 | to_print = to_print.format(T(', ').join(self.visit(x) for x in tree.values)) 643 | if not tree.nl: 644 | # TODO: This is apparently good enough for 2to3, but gets 645 | # many cases wrong (tests/unimplemented/softspace.py). 646 | to_print += ", end=' '" 647 | return T('({__print}({}), {after})[1]').format(to_print) 648 | 649 | def visit_Raise(self, tree): 650 | if tree.type is None: 651 | return T('([] for [] in []).throw(*{__sys}.exc_info())') 652 | else: 653 | return T('([] for [] in []).throw({}{}{})').format( 654 | self.visit(tree.type), 655 | '' if tree.inst is None else ', ' + self.visit(tree.inst), 656 | '' if tree.tback is None else ', ' + self.visit(tree.tback)) 657 | 658 | def visit_Repr(self, tree): 659 | return T('`{}`').format(self.visit(tree.value)) 660 | 661 | def visit_Return(self, tree): 662 | return T('{pre_return}{}{post_return}').format( 663 | 'None' if tree.value is None else self.visit(tree.value)) 664 | 665 | def visit_Set(self, tree): 666 | assert tree.elts, '{} is a dict' 667 | return T('{{{}}}').format(T(', ').join(self.visit(elt) for elt in tree.elts)) 668 | 669 | def visit_SetComp(self, tree): 670 | return self.comprehension_code( 671 | tree.generators, 672 | lambda ns, g: T('{{{} {}}}').format(ns.visit(tree.elt), g)) 673 | 674 | def visit_Slice(self, tree): 675 | return T('{}:{}{}').format( 676 | '' if tree.lower is None else self.visit(tree.lower), 677 | '' if tree.upper is None else self.visit(tree.upper), 678 | '' if tree.step is None else ':' + self.visit(tree.step)) 679 | 680 | def visit_Str(self, tree): 681 | return T('{!r}').format(tree.s) 682 | 683 | def visit_Subscript(self, tree): 684 | return T('{}[{}]').format(self.visit(tree.value), self.visit(tree.slice)) 685 | 686 | def visit_TryExcept(self, tree): 687 | body = self.many_to_one( 688 | tree.body, after=T('(lambda __after: {orelse})')).format( 689 | orelse=self.many_to_one(tree.orelse, after='__after()'), 690 | pre_return=T('(lambda ret: lambda after: ret)({pre_return}'), 691 | post_return=T('{post_return})')) 692 | handlers = [] 693 | for handler in tree.handlers: 694 | if handler.type is None: 695 | code = T('{body}') 696 | else: 697 | code = T('issubclass(__exctype, {type}) and {body}').format( 698 | type=self.visit(handler.type)) 699 | if handler.name is not None: 700 | code = code.format(body=assignment_component( 701 | T('{body}'), self.visit(handler.name), '__value')) 702 | handlers.append(code.format( 703 | body=assignment_component( 704 | 'True', 705 | '__out[0]', 706 | self.many_to_one(handler.body, after='lambda after: after()').format( 707 | pre_return=T('(lambda ret: lambda after: ret)({pre_return}'), 708 | post_return=T('{post_return})'))))) 709 | return \ 710 | lambda_function({'__out': '[None]'}).format( 711 | lambda_function({ 712 | '__ctx': T( 713 | "{__contextlib}.nested(type('except', (), {{" 714 | "'__enter__': lambda self: None, " 715 | "'__exit__': lambda __self, __exctype, __value, __traceback: " 716 | "__exctype is not None and ({handlers})}})(), " 717 | "type('try', (), {{" 718 | "'__enter__': lambda self: None, " 719 | "'__exit__': lambda __self, __exctype, __value, __traceback: " 720 | "{body}}})())").format( 721 | body=assignment_component('False', '__out[0]', body), 722 | handlers=T(' or ').join(handlers)) 723 | }).format( 724 | T('[__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: {after})][2]'))) 725 | 726 | def visit_TryFinally(self, tree): 727 | body = self.many_to_one( 728 | tree.body, after=T('(lambda after: after())')).format( 729 | pre_return=T('(lambda ret: lambda after: ret)({pre_return}'), 730 | post_return=T('{post_return})')) 731 | 732 | finalbody = self.many_to_one(tree.finalbody, after=T('{after}')) 733 | if 'pre_return' in finalbody.free(): 734 | finalbody = T('({})(lambda ret: {})').format( 735 | finalbody.format( 736 | after='lambda change_ret: False', 737 | pre_return=T('(lambda ret: lambda change_ret: change_ret(ret))({pre_return}'), 738 | post_return=T('{post_return})')), 739 | assignment_component('True', '__out[0]', 'lambda after: ret')) 740 | else: 741 | finalbody = finalbody.format(after='False') 742 | 743 | return \ 744 | lambda_function({'__out': '[None]'}).format( 745 | lambda_function({ 746 | '__ctx': T( 747 | "{__contextlib}.nested(type('except', (), {{" 748 | "'__enter__': lambda self: None, " 749 | "'__exit__': lambda __self, __exctype, __value, __traceback: " 750 | "{finalbody}}})(), " 751 | "type('try', (), {{" 752 | "'__enter__': lambda self: None, " 753 | "'__exit__': lambda __self, __exctype, __value, __traceback: " 754 | "{body}}})())").format( 755 | body=assignment_component('False', '__out[0]', body), 756 | finalbody=finalbody) 757 | }).format( 758 | T('[__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: {after})][2]'))) 759 | 760 | def visit_Tuple(self, tree): 761 | return T('({})').format(T(', ').join(map(self.visit, tree.elts)) + 762 | ','*(len(tree.elts) == 1)) 763 | 764 | def visit_UnaryOp(self, tree): 765 | return T('({}{})').format(unaryop_code[type(tree.op)], self.visit(tree.operand)) 766 | 767 | def visit_While(self, tree): 768 | test = self.visit(tree.test) 769 | body = self.many_to_one(tree.body, after='__this()') 770 | orelse = self.many_to_one(tree.orelse, after='__after()') 771 | return lambda_function({'__after': T('lambda: {after}')}).format( 772 | T('{__y}(lambda __this: lambda: {} if {} else {})()').format( 773 | provide(body, __break='__after', __continue='__this'), 774 | test, orelse)) 775 | 776 | def visit_With(self, tree): 777 | raise NotImplementedError('Open problem: with') 778 | 779 | def visit_Yield(self, tree): 780 | raise NotImplementedError('Open problem: yield') 781 | 782 | def generic_visit(self, tree): 783 | raise NotImplementedError('Case not caught: %s' % str(type(tree))) 784 | 785 | 786 | # The entry point for everything. 787 | def onelinerize(original): 788 | # original :: string 789 | # :: string 790 | t = ast.parse(original) 791 | table = symtable.symtable(original, '', 'exec') 792 | 793 | original = original.strip() 794 | 795 | # If there's only one line anyways, be lazy 796 | if len(original.splitlines()) == 1 and \ 797 | len(t.body) == 1 and \ 798 | type(t.body[0]) in (ast.Delete, ast.Assign, ast.AugAssign, ast.Print, 799 | ast.Raise, ast.Assert, ast.Import, ast.ImportFrom, 800 | ast.Exec, ast.Global, ast.Expr, ast.Pass): 801 | return original 802 | 803 | return get_init_code(t, table) 804 | --------------------------------------------------------------------------------