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.
J
Saint
J
Alexander
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?
Alexander
SQLite does not support step for autoincrement other than 1
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
Amo
Db2.Anime(anim)
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
Amo
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
Amo
Class Anime(DB.entity) looks like an empty entity to me
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