Ben
Hey! Quick question: is there any plan to add Python 11 compatibility to Pony?
Alexander
Hi! Yes. Don't have a specific schedule for it yet. Compared to Python 3.10 support, it should be much easier
Ben
Thanks a lot! What about PyPy support?
Ben
I'm not clear what is the latest supported version
Alexander
I thought it was specified at setup.py but it is not.
Alexander
So me neither
Ben
😕
Ben
I'll do some test with PyPy and let you know.
Ben
Can you do queries with pony to know if a particular value is inside of an IntArray column?
Ben
Nevermind, I was doing something wrong, it seems to work perfectly :)
Alexander
Christian
Hi, I'm trying to set up testing with PonyORM and Pytest. I separated database and entity creation as described in https://github.com/ponyorm/pony/issues/32. I am getting a strange error though with one test, which comes down to, I think, different db objects. # file: tests/conftest.py @pytest.fixture(scope='module') def db(): database = src.start.get_db() run_startup_tasks(database) yield database database_path = get_project_root().joinpath('src', 'db_testing.sqlite') database_path.unlink() # file: tests/unit/test_create.py @db_session def test_create_game_relationships(db, monkeypatch): # monkeypatch.setattr('src.start.get_db', lambda: db) game = db.Game() request = {'game_types': ['ice', 'ener', 'trust', 'prob', 'name', 'brain', 'song']} create_game_relationships(game, request) # file: src/services/create.py db = src.start.get_db() ... @db_session def create_game_relationships(game, request): for item in request['game_types']: game.game_types.add(db.GameType.get(slug=item)
Christian
I'm getting TypeError: Item of collection Game.game_types must be an instance of GameType. Got: GameType[1] which should be identical. My hypothesis is, that both GameType come from different db objects (one from test, one from src). The commented out monkeypatch doesn't work, but passing db directly to create_game_relationships(db,...) seems to fix the problem.
Christian
I could do something like def some_func(db=get_db()): ... but would really like to find a better solution.
Saint
? R u ok?
J
? R u ok?
Sorry pocket
Christian
I could do something like def some_func(db=get_db()): ... but would really like to find a better solution.
If I use @cache on the original get_db() function, my problem seems to disappear. Any downsides on using the cache decorator there?
Christian
@cache def get_db(): if int(os.environ.get('FLASK_TESTING')) == 1: database = Database(provider='sqlite', filename='db_testing.sqlite', create_db=True) else: # development database = Database(provider='sqlite', filename='db_myapp.sqlite', create_db=True) define_entities_game(database) define_entities_meta(database) define_entities_user(database) database.generate_mapping(create_tables=True) set_sql_debug(False) return database
Christian
...and then in every module, I load db = get_db() after the import statements and use db object in the module functions. It's working now, but I have to reload the modules manually in testing with importlib.reload()
Alexander
I think the method should return a singleton. Something like: database = None db_lock = theading.Lock() def get_db(): global database with db_lock: if database is not None: return database database = Database(...) ... return database
Alexander
With cache you basically make it a singleton
Christian
Thanks, I'll try that. And are there any downsides to sharing the db object as a singleton?
Alexander
If all tests use the same db with the same schema, I think there are no downsides
Christian
I was thinking in production - Pony should return the same object anyways, correct?
Alexander
Yes, in each process you should have a single instance of the Database
Christian
:) ...and a process is the entire lifetime of my application or does every db_session create its own database object?
Christian
I seem to remember that when playing around with Pony some time ago, I somehow managed to create a few different database objects.
Alexander
I mean the Python process. If for example you use Gunicorn you may have multiple Python processes working in parallel. But if you have just a single Python process, you probably should use a single Database instance > I seem to remember that when playing around with Pony some time ago, I somehow managed to create a few different database objects. It may be useful if you have several databases you want to connect in parallel If you have just a single database, then you most probably should use a single Database object. But you may have several ways to create it - one for test environment, another in production environment (just as you have inside your get_db function)
Christian
That's great, thanks!
Christian
I have identical model definitions in 5 five places. Is it possible to refactor them to make it more DRY? class Name(db.Entity): games = Set(Game) slug = Required(str) full = Required(str) class Material(db.Entity): games = Set(Game) slug = Required(str) full = Required(str) (Obviously, it's more of an academic question than necessity ;) )
Christian
I tried with a BaseClass but inheritance seems a bit tricky, unless I'm completely mistaken.
Alexander
What about class BaseClass(db.Entity): games = ... slug = ... full = ... class Name(BaseClass): pass class Material(BaseClass): pass ?
Christian
That gives pony.orm.core.ERDiagramError: Reverse attribute for Game.materials not found.
Christian
If I try class BaseClass(db.Entity): slug = Required(str) full = Required(str) class Name(BaseClass): games = Set(Game) ...then Name is not created in the database (`db.Entity`missing?).
Christian
But thanks for the affirmation! That was my first intuition as well! :)
Alexander
Ugh, when you use inheritance, it only creates a table for a base class. All inherited entities will be stored in a same table.
Alexander
https://docs.ponyorm.org/entities.html?highlight=inheritance#entity-inheritance
Christian
Ah, thanks for looking it up!
Muhammed
Hi, I have a Flask application that I use PonyORM. I am using PostgreSQL as database. I will change my service provider and my new service provider supports MySQL. So I need to migrate data from my PostgreSQL database to MySQL. Is there any easy way for me to do this with PonyORM? Or do I need to save the data as a file with my own backup application and then restore from this file?
Alexander
Hi! There is no ready way for such migration, you need to write some code. In application you can connect to two database at the same time, select objects from one database and insert them in another database. But probably it is easier to lookup a tool that can migrate table content from PostgreSQL to MySQL
Muhammed
Ok, thanks for your answer
By Default auto primary key with step = 1 how can i incrase step for example 2 id = 1 id = 3 id = 5 etc...
Alexander
Hi! What database do you use?
Hi! What database do you use?
Maybe after finish test i will edit this data to connect to elephantsql postgres
Alexander
SQLite does not support step for autoincrement other than 1
SQLite does not support step for autoincrement other than 1
Ok, I got it now Thanks for this information 🌹
Please Any way to transform data from db to other db any Example or method usefull to do ? I want to transform data from sqlite3 db to postgres db
Amo
Create two pony objects and connect them to the databases. Then read your data from one into the other
Create two pony objects and connect them to the databases. Then read your data from one into the other
Yes I try Read this https://stackoverflow.com/questions/45848795/using-multiple-databases-with-pony-orm And i'm here but how to insert to second database ?
Amo
Db2.Anime(anim)
Db2.Anime(anim)
ok i see error
Db2.Anime(anim)
core.py", line 4696, in __init__ if args: raise TypeError('%s constructor accept only keyword arguments. Got: %d positional argument%s' TypeError: Anime constructor accept only keyword arguments. Got: 1 positional argument
Db2.Anime(**anim.to_dict()) Try
Great ! Working fine can you explain what happen ?
Жека
Db2.Anime(**anim.to_dict()) Try
don't try anime, you will regret
Amo
Great ! Working fine can you explain what happen ?
Anim.to_dict() makes a python dictionary out of the anime instance. Something like {"id": 1, "name": "Foo", "URL": "www.foo.com"} Db2.Anime(**dictionary) translates to Db2.Anime(id=1, name="Foo", url=..) and so on. Read the python docs on this. The Anime constructor needs all this keyword arguments
Amo
The constructor of Class Anime(DB.entity) BTW I am not a maintainer of pony orm, so I am not totally sure how everything works
class Anime(): pass # without Constructer (init) class Anime(db.Entity): pass # with Constructer (init) Correct ?
Amo
https://stackoverflow.com/a/36926 You can see some examples here for the ** notation
Amo
Class Anime(DB.entity) looks like an empty entity to me
https://stackoverflow.com/a/36926 You can see some examples here for the ** notation
Yeah This pack and unpack way I know now why use this to convert dict to parameters as you explain
Christian
Hi. Is this necessary or can I rely on Queries being sorted in ascending order of id anyways? for name in game.names.select().sort_by(db.Name.id): print(name.id)
Alexander
Usually in databases records are "sorted" in a way they were last updated. So you cannot rely on id being sorted
Alexander
Pony fetches rows in a same way they returned from db
Christian
I'll leave it like this then. Thanks!
Mario
Hey guys! Do you know if there is a way to set a callback function to be executed after committing?
Alexander
Hi! What actions do you want to perform on commit?
Mario
Send some data to an external service, but only if the data has been persisted correctly in the db
Alexander
To be sure that data has been persisted in the db, you need to do it after commit, not before it So you can do in your code: db.commit() send_data_to_external_service() or with db_session: # assume it is the top-level db session (not a nested one) ... send_data_to_external_service() But I agree that the after_commit hook for db object could be useful; maybe we'll add it later
Mario
Yes the problem with that is that is that i have to manually go to each db_session and add the function call, and not even that will work as expected cause as far as I'm know pony could commit internally inside the db_session in some cases to retrieve the updated data
Alexander
Pony performs inserts/updates for modified objects before performing the following select, but it does not perform an implicit commit internally, so commit is possible only if you leave the top-level db_session or manually call commit() inside the db_session. Yes, after_commit can be useful to be sure that some check is performed after every commit