title: How Pony (ORM) does its tricks?
body: <p><a href="https://docs.ponyorm.org/" rel="noreferrer">Pony ORM</a> does the nice trick of converting a generator expression into SQL. Example:</p>
  <pre><code>&gt;&gt;&gt; select(p for p in Person if p.name.startswith('Paul'))
          .order_by(Person.name)[:2]
  
  SELECT &quot;p&quot;.&quot;id&quot;, &quot;p&quot;.&quot;name&quot;, &quot;p&quot;.&quot;age&quot;
  FROM &quot;Person&quot; &quot;p&quot;
  WHERE &quot;p&quot;.&quot;name&quot; LIKE &quot;Paul%&quot;
  ORDER BY &quot;p&quot;.&quot;name&quot;
  LIMIT 2
  
  [Person[3], Person[1]]
  &gt;&gt;&gt;
  </code></pre>
  <p>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.</p>
  <p>[update]</p>
  <p>Blender wrote:</p>
  <blockquote>
  <p><a href="https://github.com/ponyorm/pony/blob/orm/pony/orm/decompiling.py#L52" rel="noreferrer">Here is the file</a> 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</p>
  </blockquote>
  <p>I was thinking they were exploring some feature from the generator expression protocol, but looking this file, and seeing the <code>ast</code> module involved... No, they are not inspecting the program source on the fly, are they? Mind-blowing...</p>
  <p>@BrenBarn: If I try to call the generator outside the <code>select</code> function call, the result is:</p>
  <pre><code>&gt;&gt;&gt; x = (p for p in Person if p.age &gt; 20)
  &gt;&gt;&gt; x.next()
  Traceback (most recent call last):
    File &quot;&lt;interactive input&gt;&quot;, line 1, in &lt;module&gt;
    File &quot;&lt;interactive input&gt;&quot;, line 1, in &lt;genexpr&gt;
    File &quot;C:\Python27\lib\site-packages\pony\orm\core.py&quot;, line 1822, in next
      % self.entity.__name__)
    File &quot;C:\Python27\lib\site-packages\pony\utils.py&quot;, line 92, in throw
      raise exc
  TypeError: Use select(...) function or Person.select(...) method for iteration
  &gt;&gt;&gt;
  </code></pre>
  <p>Seems like they are doing more arcane incantations like inspecting the <code>select</code> function call and processing the Python abstract syntax grammar tree on the fly.</p>
  <p>I still would like to see someone explaining it, the source is way beyond my wizardry level.</p>