comparison mercurial/interfaces/dirstate.py @ 51919:b455dfddfed0

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.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 26 Sep 2024 18:15:36 -0400
parents 13aa17512583
children 3688a984134b
comparison
equal deleted inserted replaced
51918:13aa17512583 51919:b455dfddfed0
1 from __future__ import annotations 1 from __future__ import annotations
2 2
3 import contextlib 3 import contextlib
4 import typing
4 5
5 from typing import ( 6 from typing import (
7 Callable,
6 Protocol, 8 Protocol,
7 ) 9 )
8 10
9 from . import util as interfaceutil 11 if typing.TYPE_CHECKING:
12 # Almost all mercurial modules are only imported in the type checking phase
13 # to avoid circular imports
14 from .. import (
15 match as matchmod,
16 )
10 17
11 18
12 class idirstate(Protocol): 19 class idirstate(Protocol):
13 # TODO: convert these constructor args to fields? 20 # TODO: convert these constructor args to fields?
14 # def __init__( 21 # def __init__(
29 # the dirstate. 36 # the dirstate.
30 # """ 37 # """
31 38
32 # TODO: all these private methods and attributes should be made 39 # TODO: all these private methods and attributes should be made
33 # public or removed from the interface. 40 # public or removed from the interface.
34 _ignore = interfaceutil.Attribute("""Matcher for ignored files.""") 41
35 is_changing_any = interfaceutil.Attribute( 42 # TODO: decorate with `@rootcache(b'.hgignore')` like dirstate class?
43 _ignore: matchmod.basematcher
44 """Matcher for ignored files."""
45
46 @property
47 def is_changing_any(self) -> bool:
36 """True if any changes in progress.""" 48 """True if any changes in progress."""
37 ) 49
38 is_changing_parents = interfaceutil.Attribute( 50 @property
51 def is_changing_parents(self) -> bool:
39 """True if parents changes in progress.""" 52 """True if parents changes in progress."""
40 ) 53
41 is_changing_files = interfaceutil.Attribute( 54 @property
55 def is_changing_files(self) -> bool:
42 """True if file tracking changes in progress.""" 56 """True if file tracking changes in progress."""
43 )
44 57
45 def _ignorefiles(self): 58 def _ignorefiles(self):
46 """Return a list of files containing patterns to ignore.""" 59 """Return a list of files containing patterns to ignore."""
47 60
48 def _ignorefileandline(self, f): 61 def _ignorefileandline(self, f):
49 """Given a file `f`, return the ignore file and line that ignores it.""" 62 """Given a file `f`, return the ignore file and line that ignores it."""
50 63
51 _checklink = interfaceutil.Attribute("""Callable for checking symlinks.""") 64 # TODO: decorate with `@util.propertycache` like dirstate class?
52 _checkexec = interfaceutil.Attribute("""Callable for checking exec bits.""") 65 # (can't because circular import)
66 # TODO: The doc looks wrong- the core class has this as a @property, not a
67 # callable.
68 _checklink: Callable
69 """Callable for checking symlinks."""
70
71 # TODO: decorate with `@util.propertycache` like dirstate class?
72 # (can't because circular import)
73 # TODO: The doc looks wrong- the core class has this as a @property, not a
74 # callable.
75 _checkexec: Callable
76 """Callable for checking exec bits."""
53 77
54 @contextlib.contextmanager 78 @contextlib.contextmanager
55 def changing_parents(self, repo): 79 def changing_parents(self, repo):
56 """Context manager for handling dirstate parents. 80 """Context manager for handling dirstate parents.
57 81