Pony ORM does the nice trick of converting a generator expression into SQL. Example:
>>> select(p for p in Person if p.name.startswith('Paul'))
.order_by(Person.name)[:2]
SELECT "p"."id", "p"."name", "p"."age"
FROM "Person" "p"
WHERE "p"."name" LIKE "Paul%"
ORDER BY "p"."name"
LIMIT 2
[Person[3], Person[1]]
>>>
I know Python has wonderful introspection and metaprogramming builtin, but how this library is able to translate the generator expression without preprocessing? It looks like magic.
[update]
Blender wrote:
Here is the file that you're after. It seems to reconstruct the generator using some introspection wizardry. I'm not sure if it supports 100% of Python's syntax, but this is pretty cool. – Blender
I was thinking they were exploring some feature from the generator expression protocol, but looking this file, and seeing the ast
module involved... No, they are not inspecting the program source on the fly, are they? Mind-blowing...
@BrenBarn: If I try to call the generator outside the select
function call, the result is:
>>> x = (p for p in Person if p.age > 20)
>>> x.next()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 1, in <genexpr>
File "C:\Python27\lib\site-packages\pony\orm\core.py", line 1822, in next
% self.entity.__name__)
File "C:\Python27\lib\site-packages\pony\utils.py", line 92, in throw
raise exc
TypeError: Use select(...) function or Person.select(...) method for iteration
>>>
Seems like they are doing more arcane incantations like inspecting the select
function call and processing the Python abstract syntax grammar tree on the fly.
I still would like to see someone explaining it, the source is way beyond my wizardry level.