Weird behaviour using different variable names in select and filter function #203

Closed
Limit64 opened this Issue Oct 22, 2016 · 1 comment

Projects

None yet

2 participants

@Limit64
Limit64 commented Oct 22, 2016

PonyORM raised an exception that didn't make any sense to me. After some hours of trying I found a solution for it, but I think it is a bug because imho the code should work.

from pony.orm import *

db = Database()

class Person(db.Entity):
    name = PrimaryKey(str)
    phone_numbers = Set("PhoneNumber")

class PhoneNumber(db.Entity):
    number = PrimaryKey(int)
    persons = Set(Person)

db.bind("sqlite", ":memory:")
db.generate_mapping(create_tables=True)

with db_session:
    persons = select(p for p in Person)
    persons = persons.filter(
        lambda pers: exists(pn for pn in PhoneNumber if pers in pn.persons)
    )

    print(persons[:])

This code leads to the following exception.

Traceback (most recent call last):
  File "test.py", line 19, in <module>
    lambda pers: exists(pn for pn in PhoneNumber if pers in pn.persons)
  File "<string>", line 2, in filter
  File "/usr/lib/python3.5/site-packages/pony/utils.py", line 65, in cut_traceback
    return func(*args, **kwargs)
  File "/usr/lib/python3.5/site-packages/pony/orm/core.py", line 5332, in filter
    return query._process_lambda(func, globals, locals, order_by=False)
  File "/usr/lib/python3.5/site-packages/pony/orm/core.py", line 5296, in _process_lambda
    new_translator = prev_translator.apply_lambda(filter_num, order_by, func_ast, argnames, extractors, vartypes)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 598, in apply_lambda
    translator.dispatch(func_ast)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 79, in dispatch
    return ASTTranslator.dispatch(translator, node)  # default route
  File "/usr/lib/python3.5/site-packages/pony/orm/asttranslation.py", line 23, in dispatch
    stop = translator.call(pre_method, node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 129, in call
    reraise(exc_class, exc, tb)
  File "/usr/lib/python3.5/site-packages/pony/utils.py", line 92, in reraise
    try: raise exc.with_traceback(tb)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 119, in call
    try: monad = method(node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 708, in preCallFunc
    translator.dispatch(arg)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 79, in dispatch
    return ASTTranslator.dispatch(translator, node)  # default route
  File "/usr/lib/python3.5/site-packages/pony/orm/asttranslation.py", line 23, in dispatch
    stop = translator.call(pre_method, node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 129, in call
    reraise(exc_class, exc, tb)
  File "/usr/lib/python3.5/site-packages/pony/utils.py", line 92, in reraise
    try: raise exc.with_traceback(tb)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 119, in call
    try: monad = method(node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 622, in preGenExpr
    subtranslator = translator.__class__(inner_tree, translator.extractors, translator.vartypes, translator)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 263, in __init__
    translator.dispatch(if_)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 79, in dispatch
    return ASTTranslator.dispatch(translator, node)  # default route
  File "/usr/lib/python3.5/site-packages/pony/orm/asttranslation.py", line 28, in dispatch
    translator.dispatch(child)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 79, in dispatch
    return ASTTranslator.dispatch(translator, node)  # default route
  File "/usr/lib/python3.5/site-packages/pony/orm/asttranslation.py", line 23, in dispatch
    stop = translator.call(pre_method, node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 129, in call
    reraise(exc_class, exc, tb)
  File "/usr/lib/python3.5/site-packages/pony/utils.py", line 92, in reraise
    try: raise exc.with_traceback(tb)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 119, in call
    try: monad = method(node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 632, in preCompare
    translator.dispatch(left)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 79, in dispatch
    return ASTTranslator.dispatch(translator, node)  # default route
  File "/usr/lib/python3.5/site-packages/pony/orm/asttranslation.py", line 34, in dispatch
    translator.call(post_method, node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 129, in call
    reraise(exc_class, exc, tb)
  File "/usr/lib/python3.5/site-packages/pony/utils.py", line 92, in reraise
    try: raise exc.with_traceback(tb)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 119, in call
    try: monad = method(node)
  File "/usr/lib/python3.5/site-packages/pony/orm/sqltranslation.py", line 672, in postName
    else: assert False, name  # pragma: no cover
AssertionError: pers

If I use the same variable name in the select statement and for the lambdas it works as expected.

    persons = select(p for p in Person)
    persons = persons.filter(
        lambda p: exists(pn for pn in PhoneNumber if p in pn.persons)
    )
@Limit64 Limit64 changed the title from Weired behaviour using different variable names in select and filter function to Weird behaviour using different variable names in select and filter function Oct 22, 2016
@kozlovsky kozlovsky added the bug label Oct 25, 2016
@kozlovsky kozlovsky added this to the 0.7.1 milestone Oct 25, 2016
@kozlovsky kozlovsky self-assigned this Oct 25, 2016
@kozlovsky kozlovsky closed this in 54275da Oct 25, 2016
@kozlovsky
Contributor

Thanks for reporting, should be fixed now

@kozlovsky kozlovsky added a commit that referenced this issue Jan 10, 2017
@kozlovsky kozlovsky Pony ORM Release 0.7.1 (2017-01-10)
# New features

* New warning DatabaseContainsIncorrectEmptyValue added, it is raised when the required attribute is empty during loading an entity from the database

# Bugfixes

* Fixes #216: Added Python 3.6 support
* Fixes #203: subtranslator should use argnames from parent translator
* Change a way aliases in SQL query are generated in order to fix a problem when a subquery alias masks a base query alias
* Volatile attribute bug fixed
* Fix creation of self-referenced foreign keys - before this Pony didn't create the foreign key for self-referenced attributes
* Bug fixed: when required attribute is empty the loading from the database shouldn't raise the validation error. Now Pony raises the warning DatabaseContainsIncorrectEmptyValue
* Throw an error with more clear explanation when a list comprehension is used inside a query instead of a generator expression: "Use generator expression (... for ... in ...) instead of list comprehension [... for ... in ...] inside query"
5c123dd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment