浏览代码

Emit deprecation warnings on use rather than import (#1651)

Closes #1650
Alyssa Coghlan 1 月之前
父节点
当前提交
3403246136
共有 2 个文件被更改,包括 24 次插入8 次删除
  1. 3 0
      NEWS
  2. 21 8
      dulwich/__init__.py

+ 3 - 0
NEWS

@@ -1,5 +1,8 @@
 0.23.2	UNRELEASED
 0.23.2	UNRELEASED
 
 
+ * Print deprecations on usage, not import.
+   (Alyssa Coghlan, #1650)
+
  * Only write Git index extensions when they contain meaningful data.
  * Only write Git index extensions when they contain meaningful data.
    Previously, dulwich would write empty extensions to the index file,
    Previously, dulwich would write empty extensions to the index file,
    causing unnecessary bloat.
    causing unnecessary bloat.

+ 21 - 8
dulwich/__init__.py

@@ -23,12 +23,20 @@
 
 
 """Python implementation of the Git file formats and protocols."""
 """Python implementation of the Git file formats and protocols."""
 
 
+import sys
 from typing import Any, Callable, Optional, TypeVar
 from typing import Any, Callable, Optional, TypeVar
 
 
+if sys.version_info >= (3, 10):
+    from typing import ParamSpec
+else:
+    from typing_extensions import ParamSpec
+
 __version__ = (0, 23, 1)
 __version__ = (0, 23, 1)
 
 
 __all__ = ["replace_me"]
 __all__ = ["replace_me"]
 
 
+P = ParamSpec("P")
+R = TypeVar("R")
 F = TypeVar("F", bound=Callable[..., Any])
 F = TypeVar("F", bound=Callable[..., Any])
 
 
 try:
 try:
@@ -38,8 +46,9 @@ except ImportError:
     # of its replace_me decorator
     # of its replace_me decorator
     def replace_me(
     def replace_me(
         since: Optional[str] = None, remove_in: Optional[str] = None
         since: Optional[str] = None, remove_in: Optional[str] = None
-    ) -> Callable[[F], F]:
-        def decorator(func: F) -> F:
+    ) -> Callable[[Callable[P, R]], Callable[P, R]]:
+        def decorator(func: Callable[P, R]) -> Callable[P, R]:
+            import functools
             import warnings
             import warnings
 
 
             m = f"{func.__name__} is deprecated"
             m = f"{func.__name__} is deprecated"
@@ -52,11 +61,15 @@ except ImportError:
             else:
             else:
                 m += " and will be removed in a future version"
                 m += " and will be removed in a future version"
 
 
-            warnings.warn(
-                m,
-                DeprecationWarning,
-                stacklevel=2,
-            )
-            return func
+            @functools.wraps(func)
+            def _wrapped_func(*args: P.args, **kwargs: P.kwargs) -> R:
+                warnings.warn(
+                    m,
+                    DeprecationWarning,
+                    stacklevel=2,
+                )
+                return func(*args, **kwargs)
+
+            return _wrapped_func
 
 
         return decorator
         return decorator