-
Notifications
You must be signed in to change notification settings - Fork 76
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
Make ArangoClient generic to support typing when a custom serialiser is used #304
Comments
Hi @marcuslimdw, This is not at all a bad idea. However, if that relies on something which works only on Python 3.12, it's going to heavily reduce the number of Python versions we can support. Currently, we go all the way from Python 3.8 to Python 3.11. So, if a feature requires features that are available only since Python 3.12, we unfortunately cannot adopt it. Maybe I've misunderstood the limitation to Python 3.12, in which case let me know. I've labeled this as an enhancement so we can keep it around. |
@apetenchea the "inline type parameter" syntax (that's how I think of it) is only available in 3.12, so to support >=3.8, we can use the older syntax instead. The above example might look like this in 3.8:
|
I agree that having the However, I have thought about it carefully and I am not convinced that going full generic is exactly what we need right now. The reason for having I'm not adamant against it, and I can see why would someone opt for your proposed solution, but I'm wondering if there's other benefits you see that this potential change could bring to the driver. |
Perhaps it might help if I explained my use case. At work, we use ArangoDB for storage, but our data models are defined with Pydantic. We've created a custom serialiser that allows us to pass Pydantic models directly to, for example, We also use Pyright for type checking, which necessarily fails because these methods expect builtin Python objects, but get Pydantic models. To put it another way, we're widening the types that the An example that doesn't use Pydantic:
This works at runtime, but fails type checking:
Could you please suggest an alternative? I'd be happy to hear any possible solution to my problem. |
Hello @marcuslimdw, Please excuse my late reply, I've been away from the project for a while. Just wanted to let you know that I've given it a go, but unfortunately, the change is not as simple as it looks like. Let me explain why. ProblemThe driver is already designed with having
The change necessarily spills all over the place, in many of their functions (especially in the ExampleA small example, just to give you an idea of the problems we could be facing as a result of this: # an actual function which is used quite a lot in our code
def _ensure_key_from_id(self, body: T) -> T:
if "_id" in body and "_key" not in body:
doc_id = self._validate_id(body["_id"])
body = body.copy()
body["_key"] = doc_id[len(self._id_prefix) :]
return body On See my (incomplete) pull request for an in-depth look: #343 Believe me, I really tried. But this is proving to be a way bigger refactoring than anticipated, and I don't foresee these changes coming in the near future. If one would ever be so inclined to open a PR, that would be welcome, but I'd rather use my limited time now to get python-arango-async started. That's a new driver, where we'll have the chance to improve upon things (such as the problem you raised right now). But for now, I tend to close with with "won't fix", due to lack of time. Don't get me wrong, I like the idea of introducing more generic type hints into our code, is just that I can't prioritize it. I'm really sorry if that causes inconveniences for your project, wish I could help. AlternativesIn the meantime, you may try to:
IMHO a combination of the latter two would be the most desirable. Creating a sub-class having, for example, and def foo(t: datetime) -> None:
# use the custom serialiser in the ArangoClient
ArangoClient(serializer=serialiser).db().aql.execute(
"INSERT @document INTO @@collection", bind_vars={"document": {"timestamp": t}, "@collection": "my_collection"} # type: ignore
)
foo(datetime.now(tz=timezone.utc)) # no warning
foo(3) # pyright complains
|
Hi @apetenchea, thanks so much for the detailed writeup + your effort! To be honest, I was not expecting anything like what you did - I just wanted to start a discussion on improving typing in I agree with your conclusions - what I would have liked to do, had I been at my current company when they started using ArangoDB, was to introduce an abstraction around the driver that handles such cross-cutting concerns, but I wasn't 😔 such is life. I understand that you have lots of do and that this is a relatively minor improvement, so thanks once again! Would you like me to close this issue? |
It's great to have such discussions within the community, feel free to bring them up anytime. Although my lack of availability can sometimes take a toll on the development, I'm always up for improving the driver. |
Closing as not planned. Feel free to open another issue for discussing potential improvements. |
whoops, I reopened it because I wanted to close as not completed and I think the second request didn't go through thanks again! |
Currently, the parameters of methods such as
insert
andaql.execute
are typed concretely (withJson
andOptional[MutableMapping[str, str]]
respectively).This is overly restrictive because these methods will in fact accept other types, as long as the serialiser in use supports them (and in fact, even the default
json.loads
serialiser can accept a wider range of types).My suggestion:
Make
ArangoClient
,AQL
,Database
, andCollection
generic in their serializer type (with the client's serializer type being passed down to everything created from it), something like this (using Python 3.12's new type parameter syntax):The text was updated successfully, but these errors were encountered: