Skip to content
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

Annotations for psycopg2.ConnectionInfo #7834

Merged
merged 5 commits into from
May 21, 2022

Conversation

DMRobertson
Copy link
Contributor

@DMRobertson DMRobertson commented May 12, 2022

These annotations come from the documentation here. If there was doubt, I referred to the libpq documentation cited by psycopg2's docs.

I wasn't completely sure about dsn_parameters. Psycopg2's docs list it as an dict, and the example suggests it's a dict[str, str] at that. From psycopg2's source I found this, with its implementation here. I'm no expert in CPython's API, but this looks to me like it's building a dict[str, str]. Additionally, the libpq docs here and here show that the underlying data just consists of C strings.

Additionally, I'm pretty sure from this chunk of source that ConnectionInfo.__init__ takes one positional-only argument, which must be a psycopg2.connection. But I don't think users are intended to
be constructing this type, so I've not added that annotation.

These annotations come from the documentation here:

https://www.psycopg.org/docs/extensions.html#psycopg2.extensions.ConnectionInfo
If there was doubt, I referred to the libpq documentation cited by
psycopg2's docs.

I wasn't completely sure about `dsn_parameters`. Psycopg2's docs list it
as an `dict`, and the example suggests it's a `dict[str, str]` at that.
From psycopg2's source I found

    https://github.com/psycopg/psycopg2/blob/1d3a89a0bba621dc1cc9b32db6d241bd2da85ad1/psycopg/conninfo_type.c#L183-L206

which is implemented here:

    https://github.com/psycopg/psycopg2/blob/1d3a89a0bba621dc1cc9b32db6d241bd2da85ad1/psycopg/utils.c#L251-L279

I'm no expert in CPython's API, but this looks to me like it's building
a `dict[str, str]`.

Additionally, the libpq docs

https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNINFO
https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNDEFAULTS

show that the underlying data just consists of strings.

Additionally, I'm pretty sure from this chunk of source

    https://github.com/psycopg/psycopg2/blob/1d3a89a0bba621dc1cc9b32db6d241bd2da85ad1/psycopg/conninfo_type.c#L581-L598

That `ConnectionInfo.__init__` takes one positional-only argument, which
must be a `psycopg2.connection`. But I don't think users are intended to
be constructing this type, so I've not added that annotation.
@DMRobertson DMRobertson force-pushed the dmr/psycopg2/connection-info branch from 119e390 to 47658db Compare May 12, 2022 21:53
@github-actions

This comment has been minimized.

@DMRobertson DMRobertson marked this pull request as ready for review May 12, 2022 22:00
@DMRobertson
Copy link
Contributor Author

(Some extra context: I was trying to use these annotations in matrix-org/synapse and found out that connection.server_info was typed as Any. This is a first step towards improving that situation.

@github-actions

This comment has been minimized.

@DMRobertson
Copy link
Contributor Author

Actually, I think I probably ought to annotate the corresponding attributes on connection too.

@DMRobertson DMRobertson marked this pull request as draft May 12, 2022 22:07
@github-actions

This comment has been minimized.

Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I looked at the C code for psycopg2 and found some possible improvements.

stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
status: int
transaction_status: int
used_password: bool
user: str
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also can be None

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this and the other parameters possibly being None: it looks like None is returned only when the corresponding libpq functions return NULL. I haven't done a thorough audit, but from a quick scan of https://github.com/postgres/postgres/blob/master/src/interfaces/libpq/fe-connect.c#L6754 it looks like libpq only returns NULL if you give it a NULL ptr in the first place; in some places they explicitly choose to return an empty string rather than NULL.

Given that, plus the fact that psycopg2's docs never mention None for these types, I think I'd be inclined to leave these types as they are. Does that sound reasonable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, but could you add a comment to the code pointing out that while technically they can be None, that's highly unlikely in practice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly, see ed4d8df

stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
stubs/psycopg2/psycopg2/_psycopg.pyi Outdated Show resolved Hide resolved
readonly: Any
server_version: Any
server_version: int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that include notices, notifies and cursor_factory? They aren't marked with READONLY in that array of structs.

The psycopg2 docs say that notices and notifies are user-writable since psycopg 2.7. No clues on cursor_factory though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I do think those are writable.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@JelleZijlstra JelleZijlstra merged commit e5594aa into python:master May 21, 2022
@DMRobertson
Copy link
Contributor Author

Thanks for your thoroughness @JelleZijlstra!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants