टट्टू ओआरएम लेखक यहां है।
टट्टू SQL क्वेरी में अजगर जनरेटर तब्दील तीन चरणों में:
- जनरेटर बाईटकोड और पुनर्निर्माण जनरेटर एएसटी (सार वाक्य रचना पेड़) "सार एसक्यूएल" में अजगर AST के
- अनुवाद के Decompiling - सार्वभौमिक सूची के आधार पर एक SQL क्वेरी
- विशिष्ट डेटाबेस पर निर्भर एसक्यूएल बोली में परिवर्तित सार एसक्यूएल प्रतिनिधित्व के प्रतिनिधित्व
सबसे जटिल हिस्सा दूसरा चरण है, जहां टट्टू को पाइथन अभिव्यक्तियों के "अर्थ" को समझना चाहिए। ऐसा लगता है कि आप सबसे पहले पहले चरण में रूचि रखते हैं, तो मुझे बताएं कि कैसे कामकाजी काम करता है।
>>> from pony.orm.examples.estore import *
>>> select(c for c in Customer if c.country == 'USA').show()
निम्नलिखित में से कौन एसक्यूएल में अनुवाद किया जाएगा:
id|email |password|name |country|address
--+-------------------+--------+--------------+-------+---------
1 |[email protected] |*** |John Smith |USA |address 1
2 |[email protected]|*** |Matthew Reed |USA |address 2
4 |[email protected]|*** |Rebecca Lawson|USA |address 4
:
SELECT "c"."id", "c"."email", "c"."password", "c"."name", "c"."country", "c"."address"
FROM "Customer" "c"
WHERE "c"."country" = 'USA'
और नीचे इस क्वेरी के परिणाम जो मुद्रित हो जाएगा
के इस क्वेरी पर विचार करें
select()
फ़ंक्शन एक पायथन जनरेटर को तर्क के रूप में स्वीकार करता है, और टी मुर्गी इसके बाइटकोड का विश्लेषण करता है। हम मानक अजगर dis
मॉड्यूल का उपयोग कर इस जनरेटर के बाईटकोड निर्देश प्राप्त कर सकते हैं:
>>> gen = (c for c in Customer if c.country == 'USA')
>>> import dis
>>> dis.dis(gen.gi_frame.f_code)
1 0 LOAD_FAST 0 (.0)
>> 3 FOR_ITER 26 (to 32)
6 STORE_FAST 1 (c)
9 LOAD_FAST 1 (c)
12 LOAD_ATTR 0 (country)
15 LOAD_CONST 0 ('USA')
18 COMPARE_OP 2 (==)
21 POP_JUMP_IF_FALSE 3
24 LOAD_FAST 1 (c)
27 YIELD_VALUE
28 POP_TOP
29 JUMP_ABSOLUTE 3
>> 32 LOAD_CONST 1 (None)
35 RETURN_VALUE
टट्टू ORM मॉड्यूल pony.orm.decompiling
भीतर समारोह decompile()
जो बाईटकोड से एक एएसटी बहाल कर सकते हैं है: यहाँ
>>> from pony.orm.decompiling import decompile
>>> ast, external_names = decompile(gen)
, हम एएसटी नोड्स के पाठपरक प्रतिनिधित्व को देख सकते हैं:
>>> ast
GenExpr(GenExprInner(Name('c'), [GenExprFor(AssName('c', 'OP_ASSIGN'), Name('.0'),
[GenExprIf(Compare(Getattr(Name('c'), 'country'), [('==', Const('USA'))]))])]))
चलो अब देखें कि decompile()
फ़ंक्शन कैसे काम करता है।
decompile()
फ़ंक्शन Decompiler
ऑब्जेक्ट बनाता है, जो विज़िटर पैटर्न लागू करता है। डिकंपेलर इंस्टेंस बाइटकोड निर्देश एक-एक-एक प्राप्त करता है। प्रत्येक निर्देश के लिए decompiler ऑब्जेक्ट अपनी विधि कहता है। इस विधि का नाम वर्तमान बाइटकोड निर्देश के नाम के बराबर है।
जब पायथन एक अभिव्यक्ति की गणना करता है, तो यह स्टैक का उपयोग करता है, जो गणना के परिणामस्वरूप इंटरमीडिएट स्टोर करता है। डीकंपलर ऑब्जेक्ट का अपना स्टैक भी है, लेकिन यह स्टैक अभिव्यक्ति गणना के परिणाम, लेकिन अभिव्यक्ति के लिए एएसटी नोड का परिणाम नहीं है।
जब अगले बाईटकोड शिक्षा के लिए decompiler विधि कहा जाता है, यह ढेर से एएसटी नोड्स लेता है, एक नया एएसटी नोड में उन्हें को जोड़ती है, और फिर ढेर के शीर्ष पर इस नोड डालता है।
उदाहरण के लिए, देखते हैं कि subexpression c.country == 'USA'
की गणना कैसे की जाती है। इसी बाईटकोड टुकड़ा है:
- कॉल
decompiler.LOAD_FAST('c')
: 9 LOAD_FAST 1 (c)
12 LOAD_ATTR 0 (country)
15 LOAD_CONST 0 ('USA')
18 COMPARE_OP 2 (==)
तो, decompiler वस्तु निम्नलिखित है। यह विधि decompiler स्टैक के शीर्ष पर Name('c')
नोड रखती है।
decompiler.LOAD_ATTR('country')
पर कॉल करता है। यह विधि स्टैक से Name('c')
नोड लेती है, Geattr(Name('c'), 'country')
नोड बनाता है और इसे स्टैक के शीर्ष पर रखता है।
decompiler.LOAD_CONST('USA')
पर कॉल करता है। यह विधि स्टैक के शीर्ष पर Const('USA')
नोड रखती है।
- कॉल
decompiler.COMPARE_OP('==')
। यह विधि स्टैक, से दो नोड्स (गेटैटर और कॉन्स) लेती है और फिर स्टैक के शीर्ष पर Compare(Getattr(Name('c'), 'country'), [('==', Const('USA'))])
डालती है।
आखिर बाईटकोड निर्देश कार्रवाई की जाती है, decompiler ढेर एक भी एएसटी नोड जो पूरे जनरेटर अभिव्यक्ति से मेल खाती है शामिल हैं।
के बाद से टट्टू ORM केवल जनरेटर और lambdas डिकंपाइल करने की जरूरत है, इस, कि जटिल नहीं है क्योंकि एक जनरेटर के लिए अनुदेश प्रवाह अपेक्षाकृत सीधा है - यह सिर्फ नेस्टेड छोरों का एक समूह है।
वर्तमान में टट्टू ORM पूरे जनरेटर निर्देश दो बातें छोड़कर सेट शामिल हैं:
- इनलाइन यदि भाव:
a if b else c
- यौगिक तुलना:
a < b < c
टट्टू ऐसी अभिव्यक्ति का सामना करना पड़ता अगर यह NotImplementedError
को जन्म देती है अपवाद। लेकिन में भी इस मामले में आप जनरेटर अभिव्यक्ति को स्ट्रिंग के रूप में पास करके इसे काम कर सकते हैं। जब आप एक स्ट्रिंग के रूप में जनरेटर पास करते हैं तो टनी डिकंपेलर मॉड्यूल का उपयोग नहीं करता है। इसके बजाय इसे मानक पायथन compiler.parse
फ़ंक्शन का उपयोग करके एएसटी प्राप्त करता है।
आशा है कि यह आपके प्रश्न का उत्तर देगा।
संभावित रूप से 'पी' ऑब्जेक्ट टट्टू द्वारा लागू एक प्रकार का एक ऑब्जेक्ट है जो देखता है कि किस तरीके/गुणों पर इसका उपयोग किया जा रहा है (उदा।, 'नाम', 'startwith') और उन्हें SQL में परिवर्तित कर देता है। – BrenBarn
[यहां] (https://github.com/ponyorm/pony/blob/orm/pony/orm/decompiling.py#L52) वह फ़ाइल है जिसके बाद आप हैं। ऐसा लगता है कि कुछ आत्मनिरीक्षण जादूगर का उपयोग करके जनरेटर का पुनर्निर्माण करना प्रतीत होता है। मुझे यकीन नहीं है कि यह 100% पायथन के वाक्यविन्यास का समर्थन करता है, लेकिन यह बहुत अच्छा है। – Blender
@ ब्लेंडर: मैंने LISP में इस तरह की चाल देखी है - पाइथन में इस स्टंट को खींचना सिर्फ सादा बीमार है! –