瀏覽代碼

Add typing.

Jelmer Vernooij 4 年之前
父節點
當前提交
06bfbd92a0
共有 1 個文件被更改,包括 53 次插入36 次删除
  1. 53 36
      dulwich/ignore.py

+ 53 - 36
dulwich/ignore.py

@@ -24,11 +24,23 @@ For details for the matching rules, see https://git-scm.com/docs/gitignore
 
 import os.path
 import re
+from typing import (
+    BinaryIO,
+    Iterable,
+    List,
+    Optional,
+    TYPE_CHECKING,
+    Dict,
+    Union,
+    )
 
-from dulwich.config import get_xdg_config_home_path
+if TYPE_CHECKING:
+    from dulwich.repo import Repo
 
+from dulwich.config import get_xdg_config_home_path, Config
 
-def _translate_segment(segment):
+
+def _translate_segment(segment: bytes) -> bytes:
     if segment == b"*":
         return b'[^/]+'
     res = b""
@@ -63,7 +75,7 @@ def _translate_segment(segment):
     return res
 
 
-def translate(pat):
+def translate(pat: bytes) -> bytes:
     """Translate a shell PATTERN to a regular expression.
 
     There is no way to quote meta-characters.
@@ -100,7 +112,7 @@ def translate(pat):
     return res + b'\\Z'
 
 
-def read_ignore_patterns(f):
+def read_ignore_patterns(f: BinaryIO) -> Iterable[bytes]:
     """Read a git ignore file.
 
     Args:
@@ -127,7 +139,8 @@ def read_ignore_patterns(f):
         yield line
 
 
-def match_pattern(path, pattern, ignorecase=False):
+def match_pattern(
+        path: bytes, pattern: bytes, ignorecase: bool = False) -> bool:
     """Match a gitignore-style pattern against a path.
 
     Args:
@@ -143,7 +156,7 @@ def match_pattern(path, pattern, ignorecase=False):
 class Pattern(object):
     """A single ignore pattern."""
 
-    def __init__(self, pattern, ignorecase=False):
+    def __init__(self, pattern: bytes, ignorecase: bool = False):
         self.pattern = pattern
         self.ignorecase = ignorecase
         if pattern[0:1] == b'!':
@@ -158,22 +171,22 @@ class Pattern(object):
             flags = re.IGNORECASE
         self._re = re.compile(translate(pattern), flags)
 
-    def __bytes__(self):
+    def __bytes__(self) -> bytes:
         return self.pattern
 
-    def __str__(self):
+    def __str__(self) -> str:
         return os.fsdecode(self.pattern)
 
-    def __eq__(self, other):
-        return (type(self) == type(other) and
+    def __eq__(self, other: object) -> bool:
+        return (isinstance(other, type(self)) and
                 self.pattern == other.pattern and
                 self.ignorecase == other.ignorecase)
 
-    def __repr__(self):
-        return "%s(%s, %r)" % (
+    def __repr__(self) -> str:
+        return "%s(%r, %r)" % (
             type(self).__name__, self.pattern, self.ignorecase)
 
-    def match(self, path):
+    def match(self, path: bytes) -> bool:
         """Try to match a path against this ignore pattern.
 
         Args:
@@ -185,23 +198,25 @@ class Pattern(object):
 
 class IgnoreFilter(object):
 
-    def __init__(self, patterns, ignorecase=False):
-        self._patterns = []
+    def __init__(self, patterns: Iterable[bytes], ignorecase: bool = False,
+                 path=None):
+        self._patterns = []  # type: List[Pattern]
         self._ignorecase = ignorecase
+        self._path = path
         for pattern in patterns:
             self.append_pattern(pattern)
 
-    def append_pattern(self, pattern):
+    def append_pattern(self, pattern: bytes) -> None:
         """Add a pattern to the set."""
         self._patterns.append(Pattern(pattern, self._ignorecase))
 
-    def find_matching(self, path):
+    def find_matching(self, path: Union[bytes, str]) -> Iterable[Pattern]:
         """Yield all matching patterns for path.
 
         Args:
           path: Path to match
         Returns:
-          Iterator over  iterators
+          Iterator over iterators
         """
         if not isinstance(path, bytes):
             path = os.fsencode(path)
@@ -209,7 +224,7 @@ class IgnoreFilter(object):
             if pattern.match(path):
                 yield pattern
 
-    def is_ignored(self, path):
+    def is_ignored(self, path: bytes) -> Optional[bool]:
         """Check whether a path is ignored.
 
         For directories, include a trailing slash.
@@ -223,17 +238,17 @@ class IgnoreFilter(object):
         return status
 
     @classmethod
-    def from_path(cls, path, ignorecase=False):
+    def from_path(cls, path, ignorecase: bool = False) -> 'IgnoreFilter':
         with open(path, 'rb') as f:
-            ret = cls(read_ignore_patterns(f), ignorecase)
-            ret._path = path
-            return ret
+            return cls(read_ignore_patterns(f), ignorecase, path=path)
 
-    def __repr__(self):
-        if getattr(self, '_path', None) is None:
-            return "<%s>" % (type(self).__name__)
+    def __repr__(self) -> str:
+        path = getattr(self, '_path', None)
+        if path is not None:
+            return "%s.from_path(%r)" % (
+                type(self).__name__, path)
         else:
-            return "%s.from_path(%r)" % (type(self).__name__, self._path)
+            return "<%s>" % (type(self).__name__)
 
 
 class IgnoreFilterStack(object):
@@ -242,7 +257,7 @@ class IgnoreFilterStack(object):
     def __init__(self, filters):
         self._filters = filters
 
-    def is_ignored(self, path):
+    def is_ignored(self, path: str) -> Optional[bool]:
         """Check whether a path is explicitly included or excluded in ignores.
 
         Args:
@@ -259,7 +274,7 @@ class IgnoreFilterStack(object):
         return status
 
 
-def default_user_ignore_filter_path(config):
+def default_user_ignore_filter_path(config: Config) -> str:
     """Return default user ignore filter path.
 
     Args:
@@ -278,19 +293,21 @@ def default_user_ignore_filter_path(config):
 class IgnoreFilterManager(object):
     """Ignore file manager."""
 
-    def __init__(self, top_path, global_filters, ignorecase):
-        self._path_filters = {}
+    def __init__(
+            self, top_path: str, global_filters: List[IgnoreFilter],
+            ignorecase: bool):
+        self._path_filters = {}  # type: Dict[str, Optional[IgnoreFilter]]
         self._top_path = top_path
         self._global_filters = global_filters
         self._ignorecase = ignorecase
 
-    def __repr__(self):
+    def __repr__(self) -> str:
         return "%s(%s, %r, %r)" % (
             type(self).__name__, self._top_path,
             self._global_filters,
             self._ignorecase)
 
-    def _load_path(self, path):
+    def _load_path(self, path: str) -> Optional[IgnoreFilter]:
         try:
             return self._path_filters[path]
         except KeyError:
@@ -304,7 +321,7 @@ class IgnoreFilterManager(object):
             self._path_filters[path] = None
         return self._path_filters[path]
 
-    def find_matching(self, path):
+    def find_matching(self, path: str) -> Iterable[Pattern]:
         """Find matching patterns for path.
 
         Stops after the first ignore file with matches.
@@ -336,7 +353,7 @@ class IgnoreFilterManager(object):
                 filters.insert(0, (i, ignore_filter))
         return iter([])
 
-    def is_ignored(self, path):
+    def is_ignored(self, path: str) -> Optional[bool]:
         """Check whether a path is explicitly included or excluded in ignores.
 
         Args:
@@ -351,7 +368,7 @@ class IgnoreFilterManager(object):
         return None
 
     @classmethod
-    def from_repo(cls, repo):
+    def from_repo(cls, repo: 'Repo') -> 'IgnoreFilterManager':
         """Create a IgnoreFilterManager from a repository.
 
         Args: