# HG changeset patch # User Matt Harbison # Date 1727388936 14400 # Node ID b455dfddfed07c3e14a472bba3319ea77d27e0e4 # Parent 13aa1751258310a5ab7e484d0c353d7bd14a890d interfaces: convert the zope `Attribute` attrs to regular fields At this point, we should have a useful protocol class. The file syntax requires the type to be supplied for any fields that are declared, but we'll leave the complex ones partially unspecified for now, for simplicity. (Also, the things documented as `Callable` are really as future type annotating worked showed- roll with it for now, but they're marked as TODO for fixing later.) All of the fields and all of the attrs will need type annotations, or the type rules say they are considered to be `Any`. That can be done in a separate pass, possibly applying the `dirstate.pyi` file generated from the concrete class. The first cut of this turned the `interfaceutil.Attribute` fields into plain fields, and thus the types on them. PyCharm flagged a few things as having incompatible signatures when the concrete dirstate class subclassed this, when the concrete class has them declared as `@property`. So they've been changed to `@property` here in those cases. The remaining fields that are decorated in the concrete class have comments noting the differences. We'll see if they need to be changed going forward, but leave them for now. We'll be in trouble if the `@util.propertycache` is needed, because we can't import that module here at runtime, due to circular imports. diff -r 13aa17512583 -r b455dfddfed0 mercurial/interfaces/dirstate.py --- a/mercurial/interfaces/dirstate.py Thu Sep 26 18:09:33 2024 -0400 +++ b/mercurial/interfaces/dirstate.py Thu Sep 26 18:15:36 2024 -0400 @@ -1,12 +1,19 @@ from __future__ import annotations import contextlib +import typing from typing import ( + Callable, Protocol, ) -from . import util as interfaceutil +if typing.TYPE_CHECKING: + # Almost all mercurial modules are only imported in the type checking phase + # to avoid circular imports + from .. import ( + match as matchmod, + ) class idirstate(Protocol): @@ -31,16 +38,22 @@ # TODO: all these private methods and attributes should be made # public or removed from the interface. - _ignore = interfaceutil.Attribute("""Matcher for ignored files.""") - is_changing_any = interfaceutil.Attribute( + + # TODO: decorate with `@rootcache(b'.hgignore')` like dirstate class? + _ignore: matchmod.basematcher + """Matcher for ignored files.""" + + @property + def is_changing_any(self) -> bool: """True if any changes in progress.""" - ) - is_changing_parents = interfaceutil.Attribute( + + @property + def is_changing_parents(self) -> bool: """True if parents changes in progress.""" - ) - is_changing_files = interfaceutil.Attribute( + + @property + def is_changing_files(self) -> bool: """True if file tracking changes in progress.""" - ) def _ignorefiles(self): """Return a list of files containing patterns to ignore.""" @@ -48,8 +61,19 @@ def _ignorefileandline(self, f): """Given a file `f`, return the ignore file and line that ignores it.""" - _checklink = interfaceutil.Attribute("""Callable for checking symlinks.""") - _checkexec = interfaceutil.Attribute("""Callable for checking exec bits.""") + # TODO: decorate with `@util.propertycache` like dirstate class? + # (can't because circular import) + # TODO: The doc looks wrong- the core class has this as a @property, not a + # callable. + _checklink: Callable + """Callable for checking symlinks.""" + + # TODO: decorate with `@util.propertycache` like dirstate class? + # (can't because circular import) + # TODO: The doc looks wrong- the core class has this as a @property, not a + # callable. + _checkexec: Callable + """Callable for checking exec bits.""" @contextlib.contextmanager def changing_parents(self, repo):