objectbox/objectbox-python

Model code generation

vaind opened this issue · 2 comments

vaind commented

Currently, the model is declared directly by constructing python objects:

@Entity(id=1, uid=1)
class Person:
    id = Id(id=1, uid=1001)
    first_name = Property(str, id=2, uid=1002)
    last_name = Property(str, id=3, uid=1003)

model = objectbox.Model()
model.entity(Person, last_property_id=objectbox.model.IdUid(3, 1003))
model.last_entity_id = objectbox.model.IdUid(1, 1)
ob = objectbox.Builder().model(model).directory("db").build()

This is a little cumbersome to write and update and thus opens up room for hard to find errors.
It would be nicer if we could generate the model similar to other ObjectBox bindings. There are two ways we do that, e.g. with a language-specific build process integration (e.g. in java, swift, dart/flutter) or with a standalone tool that does code generation (go, c, c++).

Is there something like dart source_gen that would help with easy-to-use python code generation?
If there isn't, then adding "FBS->python" generation support to objectbox-generator would be an option as well.

To add a "third" option: keep the dynamic aspect (no code generation) but model the entity class like a data class and use additional annotations.

This would be in line with other languages supported by ObjectBox already. I could image that modelling more "as-is" could have other advantages as well; e.g. use additional tooling on it. E.g. PEP 557 mentions static type checkers. I could also imagine the "more static typing" could be of advantage in compiled approaches like Mojo, but that's just a wild guess.

A first step could simply move the model info into annotations, e.g.:

@Entity(id=1, uid=1)
class Person:
    @Property(id=1, uid=1001)
    id: int
    @Property(id=2, uid=1002)
    first_name: str
    @Property(id=3, uid=1003)
    last_name: str

Next step after that could be to move ids/uids into a model json and manage that file via some (no need for standard annotations anymore at that point). I think that, at that point, the best thing about this approach becomes visible: the definitions will look quite simple and intuitive:

@Entity
class Person:
    id: int
    first_name: str
    last_name: str

Of course, we still need the annotations for certain mappings, e.g. (conceptually):

    @Property(type=DateNano)
    creation_time: int

Or (as-is):

    creation_time: Property(int, type=DateNano)

Maybe there are other ways to add metainformation to attributes in Python too? Maybe there is some tooling like we use in Swift that e.g. relies on comments. E.g. conceptually:

    // objectbox: type=date_nano
    creation_time: int

Some research at other similar tools in the Python world could be useful. E.g. SQLAlchemy and Django rather take the initial approach.