рдмрд╡рдВрдбрд░ v2, рдпрд╛ рдПрдПрд╕рдЯреА рдкреИрдЪ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХреЙрд▓ рдХрд╛ рд╕рдмрд╕реЗ рдЫреЛрдЯрд╛ рд░рд┐рдХреЙрд░реНрдб

рдореБрдЭреЗ рд▓реЗрдЦ рдореЗрдВ рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдкреА рдереА рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ рдмрд╡рдВрдбрд░ рдпрд╛ рдкреИрдЪ рдмрд╛рдЗрдЯрдХреЛрдб рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХреЙрд▓ рдХреА рд╕рдмрд╕реЗ рдЫреЛрдЯреА рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ , рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗред
рдлрд┐рд░ рднреА, рд░рдирдЯрд╛рдЗрдо рдореЗрдВ рдмрд╛рдпрдЯреЗрдХреЛрдб рдХрд╛ рд╕рдВрд╢реЛрдзрди рдмрд╣реБрдд рдЦрддрд░рдирд╛рдХ рдФрд░ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╕рдВрдЪрд╛рд▓рди рд╣реИред рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкрд╛рдпрдерди рджреБрднрд╛рд╖рд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИред

рдЖрдЗрдП рдЗрд╕ рдХрдореА рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдЬреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ рдФрд░ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд╕рдорд╛рди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдореИрдВ рдЕрднреА рд▓рд┐рд╕реНрдк рдпрд╛ рдПрд░реНрд▓рд╛рдВрдЧ рдореЗрдВ рдорд┐рд▓рд╛ рдерд╛)ред рдпрд╣ рд╡рд┐рдзрд┐ рдЕрдореВрд░реНрдд рд╕рд┐рдВрдЯреЗрдХреНрд╕ рдЯреНрд░реА (рдПрдПрд╕рдЯреА) рдХрд╛рд░реНрдпрдХреНрд░рдо рдХрд╛ рдПрдХ рд╕рдВрд╢реЛрдзрди рд╣реИред

рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП - рдПрдПрд╕рдЯреА рдХреНрдпрд╛ рд╣реИ? рдПрдПрд╕рдЯреА рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛрдб рдХрд╛ рдПрдХ рдордзреНрдпрд╡рд░реНрддреА рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╣реИ, рдЬреЛ рдкрд╛рд░реНрд╕рд░ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдкрд░ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдХреЛрдб
def func(who): print "Hello, %s!" % who func() 

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдПрд╕рдЯреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:
 FunctionDef( name='func', #   args=arguments( #   args=[Name(id='who', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[ #   Print(dest=None, values=[ BinOp(left=Str(s='Hello %s!'), op=Mod(), right=Name(id='who', ctx=Load()))], nl=True)], decorator_list=[]), #  Expr(value=Call( #   func=Name(id='func', ctx=Load()), #   args=[], #   keywords=[], # kv  starargs=None, # *args  kwargs=None)) # **kwargs  

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдХреБрдЫ рднреА рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдмрд╛рд░реАрдХреА рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕ рдкреЗрдбрд╝ рдХреЗ рдХрд┐рд╕реА рднреА рддрддреНрд╡ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдПрдПрд╕рдЯреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрддреНрд╡реЛрдВ рдФрд░ рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдкреВрд░реНрдг рдкреНрд░рд▓реЗрдЦрди (рдорд╛рдирдХ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ)ред

рддреЛ, рд╡рд╛рдкрд╕ рдмрд╡рдВрдбрд░ рдХреЗ рд▓рд┐рдПред рдЖрдЗрдП рдореВрд▓ рд▓реЗрдЦ рдореЗрдВ рдЙрд╕реА рд╕рдВрдХреЗрддрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ, рдЕрд░реНрдерд╛рддреНред @shortgen рдирд╛рдордХ рдПрдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рдФрд░ рдПрдХ рдмрд╛рдЗрдирд░реА рд╢рд┐рдлреНрдЯ рдСрдкрд░реЗрдЯрд░ << ред
рд╣рдо рдореВрд▓ рд▓реЗрдЦ рдореЗрдВ рдЙрд╕реА рдХреЛрдб рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

рдЯреНрд░реЗрдирд┐рдВрдЧ



рдмрд╡рдВрдбрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ
 mkdir tornado-shortgen cd tornado-shortgen/ virtualenv .env source .env/bin/activate pip install tornado 


рдЪрд▓реЛ рдмрд╡рдВрдбрд░ рд▓рд┐рдЦрддреЗ рд╣реИрдВ - рдЖрд╡реЗрджрди

 import tornado.ioloop import tornado.web import tornado.gen import os class Handler(web.RequestHandler): @asynchronous @gen.engine @shortgen def get_short(self): (result, status) << self.db.posts.find_e({'name': 'post'}) @asynchronous @gen.engine def get(self): (result, status) = yield gen.Task(self.db.posts.find_e, {'name': 'post'}) application = tornado.web.Application([ (r"/", Handler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start() 

Shortgen_test.py рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВ

рдкрд░рд┐рд╡рд░реНрддрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдЖрдЗрдП рд╣рдорд╛рд░реЗ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдПрдПрд╕рдЯреА рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред

 $ python >>> import ast >>> print ast.dump(ast.parse(open("shortgen_test.py").read())) 

рд╣рдореЗрдВ рдкрд╛рда рдХрд╛ рдПрдХ рд▓рдВрдмрд╛ рдлрд╝реБрдЯрдкрд╛рде рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рд╣рдо рдХреЗрд╡рд▓ get_short рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдп get рдХрд░рддреЗ рд╣реИрдВ

get_short - рдмрд╛рдЗрдирд░реА рд╢рд┐рдлреНрдЯ рдФрд░ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд╕рд╛рде рд╕реНрд░реЛрдд рдлрд╝рдВрдХреНрд╢рди
 FunctionDef( name='get_short', args=arguments(args=[Name(id='self', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[ Expr(value=BinOp( #   2-  left=Tuple( #   -   elts=[Name(id='result', ctx=Load()), Name(id='status', ctx=Load())], ctx=Load()), op=LShift(), #    right=Call( #   -   self.db.posts.find_e func=Attribute( value=Attribute( value=Attribute( value=Name(id='self', ctx=Load()), attr='db', ctx=Load()), attr='posts', ctx=Load()), attr='find_e', ctx=Load()), args=[Dict(keys=[Str(s='name')], values=[Str(s='post')])], #       keywords=[], starargs=None, kwargs=None)))], decorator_list=[ #   Attribute(value=Name(id='web', ctx=Load()), attr='asynchronous', ctx=Load()), Attribute(value=Name(id='gen', ctx=Load()), attr='engine', ctx=Load()), Name(id='shortgen', ctx=Load())]) #     ! 


рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ
 FunctionDef( name='get', args=arguments(args=[Name(id='self', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[ Assign( #   targets=[ Tuple(elts=[ #     =  - tuple,  ctx   Store() Name(id='result', ctx=Store()), Name(id='status', ctx=Store())], ctx=Store())], value=Yield( #   - yield    value=Call( #  gen.Task func=Attribute( value=Name(id='gen', ctx=Load()), attr='Task', ctx=Load()), args=[Attribute( #   -   self.db.posts.find_e value=Attribute( value=Attribute( value=Name(id='self', ctx=Load()), attr='db', ctx=Load()), attr='posts', ctx=Load()), attr='find_e', ctx=Load()), Dict(keys=[Str(s='name')], values=[Str(s='post')])], keywords=[], #     starargs=None, kwargs=None)))], decorator_list=[ Name(id='asynchronous', ctx=Load()), Attribute(value=Name(id='gen', ctx=Load()), attr='engine', ctx=Load())]) #  shortgen  

рдпрд╣ рд░рд╛рдХреНрд╖рд╕реА рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд┐рддрдирд╛ рд▓рдЪреАрд▓рд╛! рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИред
рдЖрдЗрдП рдорддрднреЗрджреЛрдВ рдХреЛ рджреЗрдЦреЗрдВ:
  1. рдкреВрд░реА рддрд░рд╣ рд╕реЗ Expr рдЪрд▓рд╛ рдЧрдпрд╛
  2. BinOp(left, op, right) рдмрдЬрд╛рдп рдЕрдм Assign(targets, value)
  3. Load рд╕реЗ Store рд░рд╛рдЗрдЯ рдСрдкрд░реЗрдВрдб ctx рд╡реИрд▓реНрдпреВ рдмрджрд▓ рдЧрдпрд╛
  4. рдХреЙрд▓ self.db.posts.find_e(...) gen.Task(self.db.posts.find_e, ...) self.db.posts.find_e(...) рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
  5. рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛
  6. рдорд┐рд╕рд┐рдВрдЧ рдбреЗрдХреЛрд░реЗрдЯрд░ @shortgen

рддрджрдиреБрд╕рд╛рд░, рдкрд╣рд▓реЗ рджреВрд╕рд░реЗ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЬрд╝рд░реВрд░рдд рд╣реИ
  1. рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЦреЛрдЬреЗрдВ, @shortgen decorator_list рдореЗрдВ @shortgen decorator_list рд╣реИ
  2. рдЗрд╕ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рд╣рдЯрд╛рдПрдВ
  3. рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдореЗрдВ рдмрд╛рдЗрдирд░реА рд╢рд┐рдлреНрдЯ рдСрдкрд░реЗрдЯрд░ BinOp рдкрддрд╛ рд▓рдЧрд╛рдПрдВ
  4. рдмрд╛рдПрдВ рдФрд░ рджрд╛рдПрдВ рдСрдкрд░реЗрдВрдб рдХреЛ рд╕рд╣реЗрдЬреЗрдВред рдмрд╛рдИрдВ рдУрд░, Store рдкрд░ Load рд╕рд╛рде ctx рдХреЛ рдмрджрд▓реЗрдВ, рд╕рд╣реА рдСрдкрд░реЗрдВрдб рд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдирд╛рдо рдФрд░ рдЙрд╕рдХреЗ рддрд░реНрдХ (рд╕реНрдерд┐рддрд┐, kw, рдФрд░ "рд╕реНрдЯрд╛рд░" - *, **) рдирд┐рдХрд╛рд▓реЗрдВред
  5. рдкрд╣рд▓реЗ рд╕реНрдерд┐рддреАрдп рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди ( self.db.posts.find_e ) рдХрд╛ рдирд╛рдо рдЬреЛрдбрд╝реЗрдВ ( self.db.posts.find_e , рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╣рдореЗрдВ рд╕реНрдерд┐рддрд┐ рд╕рдВрдмрдВрдзреА рддрд░реНрдХ [self.db.posts.find_e, {'name': 'post'}] , рдФрд░ рдмрд╛рдХреА рд╕рднреА рдЦрд╛рд▓реА рд╣реИрдВред
  6. рдЗрди рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ Call рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА gen.Task рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдБ
  7. рдЗрд╕реЗ рдЙрдкрдЬ рдореЗрдВ рд▓рдкреЗрдЯреЗрдВ
  8. Assign(targets, value) рдмрдирд╛рдПрдВ рдФрд░ рд▓рдХреНрд╖реНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╣рд▓реЗ рдмрд╛рдИрдВ рдУрд░ рд╕реНрдерд┐рдд рдСрдкрд░реЗрдВрдб BinOp рдФрд░ рдореВрд▓реНрдп рдХреЗ рд░реВрдк рдореЗрдВ - рдмрд╕ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ Yield
  9. рд╣рдорд╛рд░реЗ рддрд╛рдЬрд╛ Expr Assign рд╕рд╛рде Expr рд╕реНрд░реЛрдд рдХреЗ рдкреЗрдбрд╝ рдореЗрдВ рдмрджрд▓реЗрдВ


рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЬрдЯрд┐рд▓ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрдб рдореЗрдВ рдпрд╣ 50 рд╕реЗ рдЕрдзрд┐рдХ рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рд▓реЗ рдЧрдпрд╛ред рдЕрдЧрд░ рдХреБрдЫ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ - рд╡рд╣реАрдВ рджреЗрдЦреЗрдВред

рдЗрд╕реЗ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдП? рдЖрдк рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓реВрдк рдпрд╛ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдорд╛рдереЗ рдореЗрдВ рдПрдХ рд╕рдорд╛рдзрд╛рди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╣рдо рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдкреИрдЯрд░реНрди рдФрд░ рдЗрд╕рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ ast.NodeTransformer

рдпрд╣ рдПрдХ рдРрд╕рд╛ рд╡рд░реНрдЧ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЖрдк рдЗрдирд╣реЗрд░рд┐рдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ visit_[NodeType] рдЬреИрд╕реЗ рддрд░реАрдХреЗ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ visit_FunctionDef рдпрд╛ visit_Expr ред рдорд╛рди рдЬреЛ рджреЗрддрд╛ рд╣реИ рд╡рд╣ рд╡рд┐рдзрд┐ AST рддрддреНрд╡ рдХрд╛ рдирдпрд╛ рдорд╛рди рдмрди рдЬрд╛рдПрдЧрд╛ред рдФрд░ рд╡рд┐рдЬрд╝рд┐рдЯрд░ рдЦреБрдж рд╣реА рдкреЗрдбрд╝ рдХреА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ рдЬрдм рдкреЗрдбрд╝ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рддрддреНрд╡ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рдЖрд╕рд╛рдиреА рд╕реЗ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдорд┐рд▓реЗрдЧреАред
  1. рд╣рдо рд╕рдЬрд╛рдпрд╛ рд╕рдорд╛рд░реЛрд╣ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП visit_FunctionDef рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕рдореЗрдВ, рд╣рдо self.decorated рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВ, рдпрджрд┐ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВ, рддреЛ рд╣рдо рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдорд╛рд░реНрдХ рдХреЛ self.decorated
  2. рд╣рдо рдмрд╛рдЗрдирд░реА рд╢рд┐рдлреНрдЯ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ visit_Expression рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕рдореЗрдВ рд╣рдо рдЬрд╛рдБрдЪрддреЗ рд╣реИрдВ рдХрд┐ self.decorated рдзреНрд╡рдЬ рдХреЛ self.decorated рдФрд░ Expr рдмрд┐рд▓реНрдХреБрд▓ рдмрд╛рдЗрдирд░реА рд╢рд┐рдлреНрдЯ рд╣реИред рд╣рдо рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрд╛рдХреА рдЬреЛрдбрд╝рддреЛрдбрд╝ ( Expr рдХреЛ Expr рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдирд╛) рдХрд░рддреЗ рд╣реИрдВред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд╛рд╕ рд╣реИред


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЛрдб
 # -*- coding: utf-8 -*- ''' Created on 2012-10-07 @author: Sergey <me@seriyps.ru>      http://habrahabr.ru/post/153595/    AST ''' import ast import marshal import py_compile import time import os.path class RewriteGenTask(ast.NodeTransformer): def __init__(self, *args, **kwargs): self.on_decorator = [] self.on_assign = [] super(RewriteGenTask, self).__init__(*args, **kwargs) def shortgen_deco_pos(self, decorator_list): # ,         # shortgen    . for pos, deco in enumerate(decorator_list): # Name(id='shortgen', ctx=Load()) if isinstance(deco, ast.Name) and deco.id == 'shortgen': return pos return -1 def visit_FunctionDef(self, node): """ ,      shortgen.  ,     . FunctionDef( name='get_short', args=arguments(...), body=[...], decorator_list=[ Attribute(value=Name(id='web', ...), attr='asynchronous', ...), Attribute(value=Name(id='gen', ...), attr='engine', ...), Name(id='shortgen', ctx=Load())]) """ deco_pos = self.shortgen_deco_pos(node.decorator_list) if deco_pos >= 0: #     shortgen ,  , #       Visitor   #  self.on_decorator.append(True) node.decorator_list.pop(deco_pos) self.generic_visit(node) #    self.on_decorator.pop() return node def visit_Expr(self, expr): """ ==   ==  result2 << func(arg, k=v, *args, **kwargs)  result2 = gen.Task(func, arg, k=v, *args, **kwargs)  AST  "stmt << func(...)" ( ): Expr(value=BinOp(left=Name(id='result', ctx=Load()), op=LShift(), right=Call( func=Name(id='fetch', ctx=Load()), args=[Num(n=1)], keywords=[keyword(arg='k', value=Num(n=2))], starargs=Tuple(elts=[Num(n=3)], ctx=Load()), kwargs=Dict(keys=[Str(s='k2')], values=[Num(n=4)]))))) ---- vvvvvvvvvvv ----  AST  "stmt = yield func(...)" (): Assign(targets=[Name(id='result', ctx=Store())], value=Yield(value=Call( func=Attribute(value=Name(id='gen', ctx=Load()), attr='Task', ctx=Load()), args=[Name(id='fetch', ctx=Load()), Num(n=1)], keywords=[keyword(arg='k', value=Num(n=2))], starargs=Tuple(elts=[Num(n=3)], ctx=Load()), kwargs=Dict(keys=[Str(s='k2')], values=[Num(n=4)])))) """ node = expr.value # BinOp if not (self.on_decorator and isinstance(expr.value, ast.BinOp) and isinstance(node.op, ast.LShift)): #       (on_decorator ),  #   return expr #  ,  LShift,   , #     gen.Task() #       (stmt <<)  #  (stmt =).    ctx=Load  # ctx=Store ( self.visit_Load()) self.on_assign.append(True) assign_target = self.visit(node.left) self.on_assign.pop() #   ... = ... (new_node, ) = ast.Assign( targets = [assign_target], value = ast.Yield( value=self.construct_gen_task_call(node.right))), #      new_node = ast.fix_missing_locations(ast.copy_location(new_node, expr)) return new_node def construct_gen_task_call(self, func_call): """      gen.Task      func(arg, k=v, *args, **kwargs)  gen.Task(func, arg, k=v, *args, **kwargs)  AST  "func(...)": Call( func=Name(id='fetch', ctx=Load()), args=[Num(n=1)], keywords=[keyword(arg='k', value=Num(n=2))], starargs=Tuple(elts=[Num(n=3)], ctx=Load()), kwargs=Dict(keys=[Str(s='k2')], values=[Num(n=4)]))) ---- vvvvvvvvv ----  AST  "gen.Task(func, ...)": Call( func=Attribute(value=Name(id='gen', ctx=Load()), attr='Task', ctx=Load()), args=[Name(id='fetch', ctx=Load()), Num(n=1)], keywords=[keyword(arg='k', value=Num(n=2))], starargs=Tuple(elts=[Num(n=3)], ctx=Load()), kwargs=Dict(keys=[Str(s='k2')], values=[Num(n=4)])) """ #  gen.Task gen_task = ast.Attribute( value=ast.Name(id='gen', ctx=ast.Load()), attr='Task', ctx=ast.Load()) #   gen.Task(func, ...) call = ast.Call( func=gen_task, #   - 1- : args=[func_call.func] + func_call.args, keywords=func_call.keywords, starargs=func_call.starargs, kwargs=func_call.kwargs) return self.visit(call) def visit_Load(self, node): #  Load()  Store() if self.on_assign: return ast.copy_location(ast.Store(), node) return node def shortgen(f): raise RuntimeError("ERROR! file must be compiled with yield_ast!") def compile_file(filepath): path, filename = os.path.split(filepath) with open(filepath) as src: orig_ast = ast.parse(src.read()) new_ast = RewriteGenTask().visit(orig_ast) code = compile(new_ast, filename, 'exec') pyc_filename = os.path.splitext(filename)[0] + '.pyc' pyc_filepath = os.path.join(path, pyc_filename) with open(pyc_filepath, 'wb') as fc: fc.write(py_compile.MAGIC) py_compile.wr_long(fc, long(time.time())) marshal.dump(code, fc) fc.flush() if __name__ == '__main__': import sys if len(sys.argv) < 2: print "Usage: %s file_to_compile1.py [file2.py] ..." % sys.argv[0] for filename in sys.argv[1:]: compile_file(filename) 

рд╕рд╛рд░

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдПрдПрд╕рдЯреА рдХреЛ рдпрд╛ рддреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

 with open(filepath) as src: orig_ast = ast.parse(src.read()) new_ast = RewriteGenTask().visit(orig_ast) code = compile(new_ast, filename, 'exec') exec code 


рдпрд╛ .pyo рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВ
stackoverflow.com/questions/8627835/generate-pyc-from-python-ast
gist.github.com/3849217#L172
рдФрд░ рдлрд┐рд░ python my_module.pyo рдЖрдпрд╛рдд рдХрд░реЗрдВ, рдпрд╛ рдХреЙрд▓ рдХрд░реЗрдВ

рдирд┐рд╖реНрдХрд░реНрд╖


рдПрдПрд╕рдЯреА рдкрд░рд┐рд╡рд░реНрддрди рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛрдб рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдФрд░ рдкреЛрд░реНрдЯреЗрдмрд▓ рддрд░реАрдХрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рдЯреНрд░рд╛рдВрд╕рдлрд╝реЙрд░реНрдореЗрд╢рди рд▓рд┐рдЦрдирд╛ рдмрд╛рдИрдЯреЗрдХреЛрдб рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдХрдИ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд▓рд┐рд╕реНрдк рдпрд╛ рдПрд░реНрд▓реИрдВрдЧред
рджреВрд╕рд░рд╛ рдкреНрд▓рд╕ - рдХреБрдЫ рднреА рдкреИрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдкрд░рд┐рд╡рд░реНрддрди рд╣рдорд╛рд░реЗ рдФрд░ рдмрд╛рд╣рд░реА рдХреЛрдб рджреЛрдиреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╢реЗрд╖ рдкреЗрд╢реЗрд╡рд░реЛрдВ рдФрд░ рд╡рд┐рдкрдХреНрд╖ рдХрд╛ рд╡рд░реНрдгрди рдореВрд▓ рд▓реЗрдЦ рдкрд░ рдореЗрд░реА рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ред рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдореИрдВ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдореБрдЦреНрдп рджреЛрд╖ рдпрд╣ рд╣реИ рдХрд┐ рдордХреНрдЦреА рдкрд░ рдПрдПрд╕рдЯреА рдкрд░рд┐рд╡рд░реНрддрди рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд рд╣реИред рдЗрд╕реЗ рдПрдХ .pyc рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдХрд▓рди рдЪрд░рдг рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред (рдареАрдХ рд╣реИ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдпрджрд┐ рдЖрдк рдЗрд╕ рддрд░рд╣ рдХреЗ рд╣реИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕реЗ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред
рдРрд╕реА рдЫреЛрдЯреА-рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рдЬрд┐рдирдореЗрдВ рдпрд╣ рдкреИрджрд╛рд╡рд╛рд░ рдПрдХ-рджреЛ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдРрд╕реА рдЪреАрдиреА рдХрд╛ рдмрд╣реБрдд рдорддрд▓рдм рдирд╣реАрдВ рд╣реЛрддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдЬрдЯрд┐рд▓ рдмрдирд╛рддреА рд╣реИ рдлрд╝рд╛рдЗрд▓ рд╕рдВрдХрд▓рди рдХрд╛ рдПрдХ рдЕрд▓рдЧ рдЪрд░рдг рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдмрдбрд╝реЗ рдмрд╡рдВрдбрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░, рдЖрдк рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рдВрджрд░реНрдн


рд╕рднреА Gist рдХреЛрдб
рдПрдПрд╕рдЯреА рдкреНрд░рд▓реЗрдЦрди
Tornado.gen рдХреЗ рд▓рд┐рдП рдкреНрд░рд▓реЗрдЦрди
рдПрдПрд╕рдЯреА рд╕реЗ .pyc рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдирд╛
рдпрджрд┐ рдпрд╣ рд╕рдм рдбрд░рд╛рд╡рдирд╛ рдмреИрд╕рд╛рдЦреА рдХреА рддрд░рд╣ рд▓рдЧрддрд╛ рд╣реИ, рддреЛ xD рд╣реИ

рдШрд░ рдХрд╛ рдкрд╛рда


Source: https://habr.com/ru/post/In153949/


All Articles