Skip to content

[portage] Start of stubs#15391

Open
Tatsh wants to merge 16 commits intopython:mainfrom
Tatsh:portage
Open

[portage] Start of stubs#15391
Tatsh wants to merge 16 commits intopython:mainfrom
Tatsh:portage

Conversation

@Tatsh
Copy link
Contributor

@Tatsh Tatsh commented Feb 8, 2026

This is a port of portage-stubs. It is a very minimal set of stubs just enough for my livecheck project to use. The Portage API is fairly unstable, massive, and not entirely what you can call 'public'. However, the parts I have been using have not changed much in the last few years.

Once merged I will deprecate and archive portage-stubs here and on PyPI.

The upstream Portage project is not likely to be fully typed anytime soon. The authors are also not interested in the necessary workarounds such as having a lot of if TYPE_CHECKING: blocks to workaround the dynamic typing in the API.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.


db: Mapping[str, _DBRootDict]
root: str
settings: config
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since there are other public members that are not part of this stub file, we need to add the following:

def __getattr__(name: str): ...  # incomplete module

The partial_stub marker in METADATA.toml only tells type checkers that whole modules are missing, not that modules that do exist might be incomplete. That's what the __getattr__ does.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

With this line added as is, how do I get past the stricter Pyright check? I saw that no other stubs with this added a return type.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@github-actions

This comment has been minimized.

@Tatsh
Copy link
Contributor Author

Tatsh commented Mar 18, 2026

Confused on why Black and flake8 are failing. They run fine and have no issues here:

(.venv) tatsh@limelight ~/dev/typeshed/stubs/portage
 $ black . && flake8 .
All done! ✨ 🍰 ✨
8 files left unchanged.

@github-actions

This comment has been minimized.

@brianschubert
Copy link
Collaborator

brianschubert commented Mar 18, 2026

The pre-commit failures are unrelated. Not sure what's causing them (they started appearing a few days ago, but also occur when I check out older commits, so I'm not sure it's something on our end)

mytree: str | None = ...,
myrepo: str | None = ...,
) -> list[str]: ...
def match(self, mydep: str, use_cache: Literal[0, 1] = ...) -> list[str] | str: ...
Copy link
Collaborator

Choose a reason for hiding this comment

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

Literal defaults should use the actual value:

Suggested change
def match(self, mydep: str, use_cache: Literal[0, 1] = ...) -> list[str] | str: ...
def match(self, mydep: str, use_cache: Literal[0, 1] = 1) -> list[str] | str: ...

@@ -0,0 +1,6 @@
version = "3.0.*"
upstream_repository = "https://gitweb.gentoo.org/proj/portage.git"
Copy link
Collaborator

Choose a reason for hiding this comment

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

GitHub mirror, which seems to be up to date and used for active development. Generally github upstream repos play nicer with our automation

Suggested change
upstream_repository = "https://gitweb.gentoo.org/proj/portage.git"
upstream_repository = "https://github.com/gentoo/portage"


@type_check_only
class _DBRootDict(TypedDict):
bintree: Any
Copy link
Collaborator

Choose a reason for hiding this comment

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

These days we require a comment for each use of Any explaining why it's necessary / what the allowable runtime types are. If you are unsure what the correct types are, you can use Incomplete (from _typeshed) – which is an alias of Any – instead.

root: str
settings: config

def __getattr__(name: str): ... # incomplete module
Copy link
Collaborator

Choose a reason for hiding this comment

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

To fix the pyright errors, you'll need to either add these stubs to to pyrightconfig.stricter.json, or use -> Incomplete for the return type (import from _typeshed, only allowed for __getattr__)

@Tatsh
Copy link
Contributor Author

Tatsh commented Mar 18, 2026

Had to make changes for strict Pyright and not use Incomplete in some places as that would then fail the pre-commit check. I do not have an explanation for every use of Any yet or the type info so I will have to come back to this.

@github-actions

This comment has been minimized.

@brianschubert
Copy link
Collaborator

brianschubert commented Mar 18, 2026

You can add these stubs to the exclude list in the config file mentioned in #15391 (comment) to suppress the pyright errors. For "top-level" incomplete types it's better to leave the type unannotated than to use an explicit Any (the reason being that some type checkers treat missing annotations and explicit Any annotations differently). Incomplete can be used when the type is partially known (e.g. list[Incomplete]) or when it's not possible to omit the annotation (e.g. attributes).

See also https://typing.python.org/en/latest/guides/writing_stubs.html#incomplete-stubs for other tips on writing partial stubs

@github-actions
Copy link
Contributor

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

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