-
-
Notifications
You must be signed in to change notification settings - Fork 400
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
fix _get_dialects
- properties
#1859
Conversation
CodSpeed Performance ReportMerging #1859 will not alter performanceComparing Summary
|
Pull Request Test Coverage Report for Build 12924178121Details
💛 - Coveralls |
the following def get_for_dialect(self, dialect: str, key: str) -> Any:
"""
Returns a field by dialect override.
:param dialect: The requested SQL Dialect.
:param key: The attribute/method name.
"""
cls = getattr(self, f"_db_{dialect}", None)
value = getattr(cls, key, None)
if value is None:
v = getattr(self, key, None)
if isinstance(v, property):
return getattr(self, key)
return v
elif isinstance(value, property):
return getattr(cls(self), key)
return value with the optimized version of def get_db_field_types(self) -> Optional[dict[str, str]]:
"""
Returns the DB types for this field.
:return: A dictionary that is keyed by dialect.
A blank dialect `""` means it is the default DB field type.
"""
if not self.has_db_field: # pragma: nocoverage
return None
default = getattr(self, "SQL_TYPE")
return {
"": getattr(self, "SQL_TYPE"),
**{
dialect: sql_type
for dialect, sql_type in (
(key[4:], self.get_for_dialect(key[4:], "SQL_TYPE"))
for key in dir(self)
if key.startswith("_db_")
)
if sql_type is not None and sql_type != default
},
} should I include it in this PR? It is not much, but maybe for large models the startup time could be increased by like one second **Full example**
import time
from tortoise.fields import Field
class MyField(Field):
@property
def MY_PROPERTY(self):
return f"hi from {self.__class__.__name__}!"
OTHER_PROPERTY = "something else"
class _db_sqlite:
def __init__(self, field: "Field"):
self.field = field
@property
def MY_PROPERTY(self):
return f"hi from {self.__class__.__name__} of {self.field.__class__.__name__}!"
class _db_oracle:
MY_PROPERTY = "who uses oracle?"
if __name__ == "__main__":
print(MyField().get_for_dialect("sqlite", "MY_PROPERTY"))
print(MyField().get_for_dialect_alternative("sqlite", "MY_PROPERTY"))
print(MyField().get_for_dialect("postgres", "MY_PROPERTY"))
print(MyField().get_for_dialect_alternative("postgres", "MY_PROPERTY"))
print(MyField().get_for_dialect("oracle", "MY_PROPERTY"))
print(MyField().get_for_dialect_alternative("oracle", "MY_PROPERTY"))
print(MyField().get_for_dialect("sqlite", "OTHER_PROPERTY"))
print(MyField().get_for_dialect_alternative("sqlite", "OTHER_PROPERTY"))
start_time = time.time()
for i in range(1000):
MyField().get_for_dialect("sqlite", "MY_PROPERTY")
MyField().get_for_dialect("postgres", "MY_PROPERTY")
MyField().get_for_dialect("oracle", "MY_PROPERTY")
MyField().get_for_dialect("sqlite", "OTHER_PROPERTY")
end_time = time.time()
duration = end_time - start_time
print(f"Time before: {duration}")
start_time = time.time()
for i in range(1000):
MyField().get_for_dialect_alternative("sqlite", "MY_PROPERTY")
MyField().get_for_dialect_alternative("postgres", "MY_PROPERTY")
MyField().get_for_dialect_alternative("oracle", "MY_PROPERTY")
MyField().get_for_dialect_alternative("sqlite", "OTHER_PROPERTY")
end_time = time.time()
duration = end_time - start_time
print(f"Time after: {duration}")
start_time = time.time()
for i in range(1000):
MyField().get_db_field_types()
end_time = time.time()
duration = end_time - start_time
print(f"Time before: {duration}")
start_time = time.time()
for i in range(1000):
MyField().get_db_field_types_alternative()
end_time = time.time()
duration = end_time - start_time
print(f"Time after: {duration}") output:
|
Would be better to start a new PR. |
@@ -15,6 +15,7 @@ Fixed | |||
^^^^^ | |||
- Rename pypika to pypika_tortoise for fixing package name conflict (#1829) | |||
- Concurrent connection pool initialization (#1825) | |||
- `_get_dialects`: support properties (#1859) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's more explicit to use the issue title: _get_dialects
not working for properties
@markus-96 I updated the |
A PR would be appreciated. We use Codspeed for benchmarking and it would be great if your changes are measurable with benchmarks. You can find the benchmarks here. But your changes won't necessary be reflected in the existing benchmarks, so you might need a separate PR to add a benchmark first. You can run the benchmarks locally too but the results might be a bit inconsistent: |
Thanks for reviewing @henadzit and @waketzheng !
there might be the usecase where you want to declare something as instance attribute in the init of a dialect class, this is not covered in this case. like this: class MyField(Field):
OTHER_PROPERTY = "something"
class _db_sqlite:
def __init__(self, field: "Field"):
self.field = field
self.OTHER_PROPERTY = "something else" |
@markus-96 It is recommended to use like this: class MyField(Field):
OTHER_PROPERTY = "something"
class _db_sqlite:
OTHER_PROPERTY = "something else"
def __init__(self, field: "Field"):
self.field = field |
I know, I just wanted to point this out in case someone stumbles across this in a few years or so ;) |
Description
properties in
_db_{dialect}
classes were not taken into account.Motivation and Context
see #1858
How Has This Been Tested?
make build test_sqlite test_asyncpg
also, I am not able to test against an actual oracle database, and as far as I can tell is that it is currently not tested at all in CICD. So please, someone check it for me? :)
Checklist: