Alexander
Thank you for reporting! We were able to reproduce it
Anonymous
:)
Anonymous
Thanks!
Xavier
Hi , I have a doubt definig models, there is a way to define a datetime with timezone?
Alexander
Hi, at this moment Pony you can only use datetime without timezone
Xavier
Thank you i will try to bypass this
Alexander
In bytecode or in our progress on that?
Alexander
Hi Guys! We've fixed decompiler errors on Python 3.7. Now all expressions should be translated correclty. The official release will be published in few days @vitalium, can you check that your queries are working correctly now?
Anzor
Hi all! Something similar was asked before, but still... Why not handle some after_load hook for clarity?
Alexander
Hi! Can you explain in more details, when this hook should be called?
Anzor
Hi! Can you explain in more details, when this hook should be called?
Sure. I have some parameters stored in json field to be handled by state machine that belongs to this instance. After object is loaded I want to restore the machine. It is normal to override init, but just doesn't look pony-style )
Alexander
In Pony, object may be in a partially loaded state. For example, when someone do something like with db_session: s = Student[123] g = s.group print(g.id) for c in s.courses: print(c.id) In the first line Pony loads Student object s with all non-lazy columns into memory. This Student instance contains group_id attribute. At this moment, a Group instance is created in memory as well, but this Group instance contains only id attribute received from the Student's group_id attribute. So, g object exists in a partially loaded state. If later program will try to get value of some other attribute of g object, say, g.major, then all non-lazy attributes of g object will be loaded from the database. Until that, Pony makes no attempt to load g attributes, but you still can keep g object in a variable, because its id attribute value is already known. In the next line you can see for c in s.courses loop. At this moment all courses associated with this specific students are created in memory. But in order to know the list of such courses it is not necessary to load them from the course table. Many-to-many relationship is supported using intermediary course_student table which keeps pairs (student_id, course_id). So, when Pony loads s.courses collection, it loads only course_id value from intermediary course_student table and creates partially loaded Course object for each course_id. Other fields will be loaded if you try to access any field in Course beside course_id So it is not entirely clear at which moment proposed after_load hook should be triggered. If it is called on initial creation of partially loaded object, it may immediately access some other fields and provoke unnecessary load of entire object into memory. Maybe it should be called after the actual load of all non-lazy attributes. But it may be surprising for some users. I think in you case you can have some machine_state property which initializes state from json field on first access. I'm not sure it should be tied to some after_load hook
Anzor
In Pony, object may be in a partially loaded state. For example, when someone do something like with db_session: s = Student[123] g = s.group print(g.id) for c in s.courses: print(c.id) In the first line Pony loads Student object s with all non-lazy columns into memory. This Student instance contains group_id attribute. At this moment, a Group instance is created in memory as well, but this Group instance contains only id attribute received from the Student's group_id attribute. So, g object exists in a partially loaded state. If later program will try to get value of some other attribute of g object, say, g.major, then all non-lazy attributes of g object will be loaded from the database. Until that, Pony makes no attempt to load g attributes, but you still can keep g object in a variable, because its id attribute value is already known. In the next line you can see for c in s.courses loop. At this moment all courses associated with this specific students are created in memory. But in order to know the list of such courses it is not necessary to load them from the course table. Many-to-many relationship is supported using intermediary course_student table which keeps pairs (student_id, course_id). So, when Pony loads s.courses collection, it loads only course_id value from intermediary course_student table and creates partially loaded Course object for each course_id. Other fields will be loaded if you try to access any field in Course beside course_id So it is not entirely clear at which moment proposed after_load hook should be triggered. If it is called on initial creation of partially loaded object, it may immediately access some other fields and provoke unnecessary load of entire object into memory. Maybe it should be called after the actual load of all non-lazy attributes. But it may be surprising for some users. I think in you case you can have some machine_state property which initializes state from json field on first access. I'm not sure it should be tied to some after_load hook
Great explanation, thanx! Now need for some custom initializer looks obvious
Lucky
Great explanation, thanx! Now need for some custom initializer looks obvious
Hey, a state machine sounds interesting. I'm currently implementing one myself for telegram bot chats, so I'm curious what your state machine is looking like?
Lucky
In my case though I only store the current state in the database, and not the state machine itself. Mine lies in python code.
Lucky
pm
for the benefit of everyone interested I'll share some takeaways though
Lucky
I use https://github.com/pytransitions/transitions
Permalink Bot
I use https://github.com/pytransitions/transitions
Permanent link to the pytransitions/transitions project you mentioned. (?)
Permalink Bot
I use https://github.com/pytransitions/transitions
Permanent link to the pytransitions/transitions project you mentioned. (?)
Lucky
Hey, I’m getting pony.orm.dbapiprovider.OperationalError: unable to open database file with db_params = dict(provider="sqlite", filename="/data/states.db", create_db=True) db.bind(**db_params)
Matthew
have you checked the file permissions?
Lucky
Like of the folder?
Alexander
yes, maybe you can't create file in that folder
Matthew
of the file. Can you open the file in python as that user? open('/data/states.db' ,'w')
Matthew
the above code will attempt to create it, but yeah it would be folder permissions
Matthew
are you sure you want /data/ instead of data/ ?
Lucky
Yeah, /data/ is correct as it is a docker container. I’ll check on folder permissions. To clarify: it also says unable to open database file if it cannot create a file? So it doesn’t say failure in creating file specifically?
Alexander
This message is from sqlite and potentially can depend on sqlite version
Lucky
So, /data/ is 755. >>> import os >>> os.stat(„/data/“) os.stat_result(st_mode=16877, st_ino=38012780, st_dev=2306, st_nlink=2, st_uid=0, st_gid=0, st_size=4096, st_atime=1554309461, st_mtime=1554306536, st_ctime=1554309458) >>> st_mode=16877 >>> oct(st_mode) 0o40755
Alexander
"755 means full permissions for the owner and read and execute permission for others" If I'm not mistaken, this directory is read-only if you aren't the owner
Lucky
open(„/data/test.db“) PermissionError: [Errno 13] Permission denied: '/data/test.db' Yeah seems to be a access issue.
Lucky
Yeah, switched from root to a fixed uid, and had to chown the folder. Thanks. However, now I get the following error:
Lucky
pony.orm.dbapiprovider.OperationalError: no such table: AlbumPost_Post
Lucky
pony.orm.dbapiprovider.OperationalError: no such table: AlbumPost_Post
r2tg_1 | File "./r2tg/reddit.py", line 11, in <module> r2tg_1 | from . import database # so migrations can run, etc. r2tg_1 | File "./r2tg/database.py", line 101, in <module> r2tg_1 | db.generate_mapping() r2tg_1 | File "<string>", line 2, in generate_mapping r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 78, in cut_traceback r2tg_1 | reraise(exc_type, exc, full_tb) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 95, in reraise r2tg_1 | try: raise exc.with_traceback(tb) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 61, in cut_traceback r2tg_1 | try: return func(*args, **kwargs) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/orm/core.py", line 1130, in generate_mapping r2tg_1 | elif check_tables: database.check_tables() r2tg_1 | File "<string>", line 2, in check_tables r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 78, in cut_traceback r2tg_1 | reraise(exc_type, exc, full_tb) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 95, in reraise r2tg_1 | try: raise exc.with_traceback(tb) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/utils/utils.py", line 61, in cut_traceback r2tg_1 | try: return func(*args, **kwargs) r2tg_1 | File "<string>", line 2, in check_tables r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/orm/core.py", line 528, in new_func r2tg_1 | result = func(*args, **kwargs) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/orm/core.py", line 1203, in check_tables r2tg_1 | database.schema.check_tables(database.provider, connection) r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/orm/dbschema.py", line 78, in check_tables r2tg_1 | provider.execute(cursor, sql) r2tg_1 | File "<string>", line 2, in execute r2tg_1 | File "/usr/local/lib/python3.6/site-packages/pony/orm/dbapiprovider.py", line 61, in wrap_dbapi_exceptions r2tg_1 | raise OperationalError(e) r2tg_1 | pony.orm.dbapiprovider.OperationalError: no such table: AlbumPost_Post
Lucky
It seems db.generate_mapping() is failing.
Lucky
I don’t know why it is not creating the AlbumPost_Post table, but later expecting it.
Alexander
did you specify create_tables=True in generate_mapping?
Lucky
Oh. I already had create_db = True, thought it would be not needed.
Lucky
Is there any reason why it shouldn’t be set to True?
Matthew
if you want iit to fail if the database doesn't exist
Lucky
Sorry, create_tables.
Lucky
I feel like True should be the default there.
Alexander
If a user wants to connect to some pre-existed database which was not created with Pony and mistype tanle name (for example, write it using incorrect case) it may be confusing if Pony will try to create some tables. So create_tables option is turned off by default I agree that with create_db=True it make sense to create tables as well, but changing default value may be not obvious. Probably we can improve error message so it starts suggesting setting create_tables=True if create_db=True
stsouko
I feel like True should be the default there.
for not sqlite db, user for tables creation can be differ from common user, which used for data manipulation
Lucky
class State(db.Entity, self.State): user_id = orm.Required(int) chat_id = orm.Required(int) state = orm.Required(str) data = orm.Optional(orm.Json) # can be None orm.PrimaryKey(user_id, chat_id) # end class Now I’m getting: ValueError: Attribute State.data cannot be set to None Am I missing something?
Alexander
optional Json means it can be empty (that is, {}). If you want it to be None, specify nullable=True as well
Vitaliy
Hm, that should be documented. In my app I set default={} for all JSON-fields 🙂
Alexander
I agree, we should document it #todo
Vitaliy
Alexander, I have updated pony from github, but did not tested it yet with python 3.7. I've rewrote all my expressions app wide to X and Y and ... not Z pattern 🙂
Alexander
Ok, I think it works correctly now. Hope we can do release really soon
Jacob
I see the blog post on migrations. Does that mean v0.8 is about to be released?
Alexander
Not yet, migrations still require some work
Alexander
but wouldn't null be valid json?
I don't remember all the details right now. In theory it is possible to have Json whicj consists of a single null, but note that it is different from database NULL, and follows completely different rules in comparison operations. It may be confusing to user to see Json null as a top-level value of JSON document, especialy when intermixed with database NULLs
Lucky
Not yet, migrations still require some work
I just hope that migrations didn't make the implementation of blueprints even harder 😅
Lucky
Currently I can't really use PonyORM inside a library
Lucky
It's possible, just very cumbersome
Jacob
blueprints?
Lucky
blueprints?
Concept similar to Flask blueprints: You define your database extending from blueprint.Entity instead of db.Entity This allows you to later register it with your database:
Jacob
Ooh! Is that in the works? I've only seen using the factory function to build the models.
Lucky
Concept similar to Flask blueprints: You define your database extending from blueprint.Entity instead of db.Entity This allows you to later register it with your database:
# library1.py later = orm.Blueprint() class SomeTable(later.Entity): id = Required(int) # main.py from library1 Import later db = Database("postgres...") db.register_entity(later)
Lucky
Ooh! Is that in the works? I've only seen using the factory function to build the models.
No, sadly. I would love to actually contribute it, but some inner workings in MetaEntity prohibit that without major refactoring.
Jacob
It's also not possible to build a model programmatically right now because of the implementation of PrimaryKey, composite_key, and composite_index.
Lucky
In fact, migrations were the smaller problem as you could already do those yourself if you aren't afraid of writing a bit of SQL. For example the pony_up package at https://GitHub.com/luckydonald/pony_up can already help you with that. Couldn't get anything similar to blueprints working though.
Anonymous
@luckydonald Happy birthday, btw! What's the downside of using blueprint functions? def blueprint(db): class Car(db.Entity): ... return db
Jacob
Is there a way to build a custom field type? Ie, I want to use the field as a Boolean, but I'm stuck with an irritating DB that implemented the column with CHAR(1) where the value is "Y" or "N".
Lucky
I think I had a full example in the related GitHub issue
Lucky
But am in the supermarket right now, so can't look it up
Lucky
But am in the supermarket right now, so can't look it up
Can't decide which pizza to buy, but that's off topic
Jacob
My wife says "supreme! Always supreme!" Re what Pizza to get...