Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON Value Assignment Broken in v0.7.3 #308

Closed
SPARTAN563 opened this Issue Nov 12, 2017 · 9 comments

Comments

Projects
None yet
4 participants
@SPARTAN563
Copy link

SPARTAN563 commented Nov 12, 2017

With the release of v0.7.3 we are seeing a number of failures with the following error when attempting to assign values to JSON properties on our models.

src\app\lib\db_store.py:134: in update
    setattr(maint, key, val)
<string>:2: in __set__
    ???
..\..\python36-32\lib\site-packages\pony\utils\utils.py:58: in cut_traceback
    return func(*args, **kwargs)
..\..\python36-32\lib\site-packages\pony\orm\core.py:2120: in __set__
    new_val = attr.validate(new_val, obj, from_db=False)
..\..\python36-32\lib\site-packages\pony\orm\core.py:2352: in validate
    val = Attribute.validate(attr, val, obj, entity, from_db)
..\..\python36-32\lib\site-packages\pony\orm\core.py:2027: in validate
    val = converter.validate(val, obj)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

converter = <pony.orm.dbproviders.sqlite.SQLiteJsonConverter object at 0x0453C750>
val = {}, obj = OurModel['000000000000000000']

    def validate(converter, val, obj=None):
        if obj is None or converter.attr is None:
            return val
>       if isinstance(val, TrackedValue) and val.obj is obj and val.attr is converter.attr:
E       AttributeError: 'TrackedDict' object has no attribute 'obj'

Looking at the code, it appears that this was introduced as part of the fix for #283 and is simply a matter of the wrong property being used here to reference this.

Code that generates this error

from pony import orm
from pony.orm import db_session
from uuid import uuid4

db = orm.Database()
class OurModel(db.Entity):
  id = orm.PrimaryKey(str, default=lambda: uuid4().hex)
  data = orm.Required(orm.Json)

id = uuid4().hex
with db_session:
  # This is OK
  entity = OurModel(id=id, data={})
  db.commit()

with db_session:
  entity = OurModel[id]
  entity.data = {"test": True} # This throws an exception

@kozlovsky kozlovsky self-assigned this Nov 12, 2017

@kozlovsky kozlovsky added the bug label Nov 12, 2017

@kozlovsky kozlovsky added this to the 0.7.4 milestone Nov 12, 2017

@kozlovsky kozlovsky closed this in a5c813d Nov 12, 2017

@kozlovsky

This comment has been minimized.

Copy link
Member

kozlovsky commented Nov 12, 2017

Fixed, thanks for reporting!

Actually, the only way to reproduce the bug is to assign the attribute value to the same attribute:

obj.json_attr = obj.json_attr
@SPARTAN563

This comment has been minimized.

Copy link
Author

SPARTAN563 commented Nov 12, 2017

Ah, you're absolutely correct, sorry that I missed that in the repro code.

@Vitalium

This comment has been minimized.

Copy link

Vitalium commented Nov 12, 2017

That's not all. There is another related bug. While trying to change loaded entity object several times, it is raised exception: pony.orm.dbapiprovider.InterfaceError: Error binding parameter ## - probably unsupported type.

There is a workaround - to set Json field volatile.

I'm trying now to write a code to reproduce this issue and add it later.

@Vitalium

This comment has been minimized.

Copy link

Vitalium commented Nov 13, 2017

Unfortunately, I can't reproduce this error, but I found out that it happens when entity attributes has been changed outside current transaction. When inside core.py in _save_modified_() function where conditions extends by optimistic attributes and its values, some values isn't converted to appropriate type, in this case TrackedDict isn't converted to json-serialized string.

@kozlovsky

This comment has been minimized.

Copy link
Member

kozlovsky commented Nov 14, 2017

@Vitalium what database are you using?

@Vitalium

This comment has been minimized.

Copy link

Vitalium commented Nov 14, 2017

SQLite

@kozlovsky

This comment has been minimized.

Copy link
Member

kozlovsky commented Nov 25, 2017

Thanks @Vitalium! I was able to reproduce and fix the bug that you reported!

@Vitalium

This comment has been minimized.

Copy link

Vitalium commented Nov 25, 2017

Beautiful! :) Thank you!

@steelliberty

This comment has been minimized.

Copy link

steelliberty commented Jan 18, 2018

I am getting
InterfaceError: Error binding parameter 2 - probably unsupported type.
Error binding parameter 2 - probably unsupported type.

with version 7.3 while running 7.2 mode code runs without and error.

I am doing a Json assignment -- This is happening in numerous places in the code -- but for example the simplest case is :

class NewsFeeds(newsfeeds.Entity):
id = PrimaryKey(int, auto=True)
feedinfo = Optional(Json, default = {})
hashlist = Optional(Json, default=[])
feedlist = Optional(Json, default = {})
feeds = Optional(Json, default = {})

@classmethod
@db_session
def addHashCode(cls,h):
nf = NewsFeeds.get(id=1)
if nf:
nf.hashlist.append(h)
commit()

The same code in 7.2 works everytime .. there are other places that blow up in the full code -- sometimes the assignment above works but then later another one fails.

I can see nothing that explains this ..

Any thoughts ? (note proper code indentation changes when I save this -- however the indentation is correct in the original )

kozlovsky added a commit that referenced this issue Jul 23, 2018

Pony ORM Release 0.7.4 (2018-07-23)
# Major features

* Hybrid methods and properties added: https://docs.ponyorm.com/entities.html#hybrid-methods-and-properties
* Allow to base queries on another queries: `select(x.a for x in prev_query if x.b)`
* Added support of Python 3.7
* Added support of PyPy
* `group_concat()` aggregate function added
* pony.flask subpackage added for integration with Flask

# Other features

* `distinct` option added to aggregate functions
* Support of explicit casting to `float` and `bool` in queries

# Improvements

* Apply @cut_traceback decorator only when pony.MODE is 'INTERACTIVE'

# Bugfixes

* In SQLite3 `LIKE` is case sensitive now
* #249: Fix incorrect mixin used for Timedelta
* #251: correct dealing with qualified table names
* #301: Fix aggregation over JSON Column
* #306: Support of frozenset constants added
* #308: Fixed an error when assigning JSON attribute value to the same attribute: obj.json_attr = obj.json_attr
* #313: Fix missed retry on exception raised during db_session.__exit__
* #314: Fix AttributeError: 'NoneType' object has no attribute 'seeds'
* #315: Fix attribute lifting for JSON attributes
* #321: Fix KeyError on obj.delete()
* #325: duplicating percentage sign in raw SQL queries without parameters
* #331: Overriding __len__ in entity fails
* #336: entity declaration serialization
* #357: reconnect after PostgreSQL server closed the connection unexpectedly
* Fix Python implementation of between() function and rename arguments: between(a, x, y) -> between(x, a, b)
* Fix retry handling: in PostgreSQL and Oracle an error can be raised during commit
* Fix optimistic update checks for composite foreign keys
* Don't raise OptimisticCheckError if db_session is not optimistic
* Handling incorrect datetime values in MySQL
* Improved ImportError exception messages when MySQLdb, pymysql, psycopg2 or psycopg2cffi driver was not found
* desc() function fixed to allow reverse its effect by calling desc(desc(x))
* __contains__ method should check if objects belong to the same db_session
* Fix pony.MODE detection; mod_wsgi detection according to official doc
* A lot of inner fixes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.