fin-infra 0.1.85__py3-none-any.whl → 0.1.87__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,8 +10,22 @@ and should be imported from there:
10
10
 
11
11
  For async retry with exponential backoff:
12
12
  from fin_infra.utils.retry import retry_async, RetryError
13
+
14
+ For deprecation utilities:
15
+ from fin_infra.utils.deprecation import deprecated, deprecated_parameter
13
16
  """
14
17
 
18
+ from fin_infra.utils.deprecation import (
19
+ DeprecatedWarning,
20
+ deprecated,
21
+ deprecated_parameter,
22
+ )
15
23
  from fin_infra.utils.retry import RetryError, retry_async
16
24
 
17
- __all__ = ["RetryError", "retry_async"]
25
+ __all__ = [
26
+ "RetryError",
27
+ "retry_async",
28
+ "deprecated",
29
+ "deprecated_parameter",
30
+ "DeprecatedWarning",
31
+ ]
@@ -0,0 +1,161 @@
1
+ """Deprecation utilities for fin-infra.
2
+
3
+ This module provides decorators and functions for marking features as deprecated,
4
+ following the deprecation policy defined in DEPRECATION.md.
5
+
6
+ Example:
7
+ >>> from fin_infra.utils.deprecation import deprecated
8
+ >>>
9
+ >>> @deprecated(
10
+ ... version="1.2.0",
11
+ ... reason="Use new_function() instead",
12
+ ... removal_version="1.4.0"
13
+ ... )
14
+ ... def old_function():
15
+ ... pass
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import functools
21
+ import warnings
22
+ from collections.abc import Callable
23
+ from typing import Any, TypeVar
24
+
25
+ __all__ = [
26
+ "deprecated",
27
+ "deprecated_parameter",
28
+ "DeprecatedWarning",
29
+ ]
30
+
31
+ F = TypeVar("F", bound=Callable[..., Any])
32
+
33
+
34
+ class DeprecatedWarning(DeprecationWarning):
35
+ """Custom deprecation warning for fin-infra.
36
+
37
+ This warning is used to distinguish fin-infra deprecations from
38
+ Python's built-in DeprecationWarning.
39
+ """
40
+
41
+ pass
42
+
43
+
44
+ def deprecated(
45
+ version: str,
46
+ reason: str,
47
+ removal_version: str | None = None,
48
+ *,
49
+ stacklevel: int = 2,
50
+ ) -> Callable[[F], F]:
51
+ """Decorator to mark a function or class as deprecated.
52
+
53
+ The decorated function/class will emit a DeprecationWarning when called/instantiated.
54
+
55
+ Args:
56
+ version: The version in which the feature was deprecated (e.g., "1.2.0").
57
+ reason: The reason for deprecation and recommended alternative.
58
+ removal_version: The version in which the feature will be removed (e.g., "1.4.0").
59
+ stacklevel: Stack level for the warning (default 2 for immediate caller).
60
+
61
+ Returns:
62
+ A decorator that wraps the function/class with deprecation warning.
63
+
64
+ Example:
65
+ >>> @deprecated(
66
+ ... version="1.2.0",
67
+ ... reason="Use new_function() instead",
68
+ ... removal_version="1.4.0"
69
+ ... )
70
+ ... def old_function():
71
+ ... return "result"
72
+ >>>
73
+ >>> old_function() # Emits DeprecationWarning
74
+ 'result'
75
+ """
76
+
77
+ def decorator(func: F) -> F:
78
+ # Build the warning message
79
+ name = getattr(func, "__qualname__", getattr(func, "__name__", str(func)))
80
+ message = f"{name} is deprecated since version {version}."
81
+
82
+ if removal_version:
83
+ message += f" It will be removed in version {removal_version}."
84
+
85
+ message += f" {reason}"
86
+
87
+ if isinstance(func, type):
88
+ # Handle class deprecation
89
+ original_init = func.__init__ # type: ignore[misc]
90
+
91
+ @functools.wraps(original_init)
92
+ def new_init(self: Any, *args: Any, **kwargs: Any) -> None:
93
+ warnings.warn(message, DeprecatedWarning, stacklevel=stacklevel)
94
+ original_init(self, *args, **kwargs)
95
+
96
+ func.__init__ = new_init # type: ignore[misc]
97
+
98
+ # Add deprecation info to docstring
99
+ if func.__doc__:
100
+ func.__doc__ = f".. deprecated:: {version}\n {reason}\n\n{func.__doc__}"
101
+ else:
102
+ func.__doc__ = f".. deprecated:: {version}\n {reason}"
103
+
104
+ return func # type: ignore[return-value]
105
+ else:
106
+ # Handle function deprecation
107
+ @functools.wraps(func)
108
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
109
+ warnings.warn(message, DeprecatedWarning, stacklevel=stacklevel)
110
+ return func(*args, **kwargs)
111
+
112
+ # Add deprecation info to docstring
113
+ if wrapper.__doc__:
114
+ wrapper.__doc__ = f".. deprecated:: {version}\n {reason}\n\n{wrapper.__doc__}"
115
+ else:
116
+ wrapper.__doc__ = f".. deprecated:: {version}\n {reason}"
117
+
118
+ return wrapper # type: ignore[return-value]
119
+
120
+ return decorator
121
+
122
+
123
+ def deprecated_parameter(
124
+ name: str,
125
+ version: str,
126
+ reason: str,
127
+ removal_version: str | None = None,
128
+ *,
129
+ stacklevel: int = 2,
130
+ ) -> None:
131
+ """Emit a deprecation warning for a deprecated parameter.
132
+
133
+ Call this function when a deprecated parameter is used. This should be
134
+ called at the beginning of a function that has deprecated parameters.
135
+
136
+ Args:
137
+ name: The name of the deprecated parameter.
138
+ version: The version in which the parameter was deprecated.
139
+ reason: The reason for deprecation and recommended alternative.
140
+ removal_version: The version in which the parameter will be removed.
141
+ stacklevel: Stack level for the warning (default 2 for immediate caller).
142
+
143
+ Example:
144
+ >>> def my_function(new_param: str, old_param: str | None = None):
145
+ ... if old_param is not None:
146
+ ... deprecated_parameter(
147
+ ... name="old_param",
148
+ ... version="1.2.0",
149
+ ... reason="Use new_param instead"
150
+ ... )
151
+ ... new_param = old_param
152
+ ... return new_param
153
+ """
154
+ message = f"Parameter '{name}' is deprecated since version {version}."
155
+
156
+ if removal_version:
157
+ message += f" It will be removed in version {removal_version}."
158
+
159
+ message += f" {reason}"
160
+
161
+ warnings.warn(message, DeprecatedWarning, stacklevel=stacklevel + 1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fin-infra
3
- Version: 0.1.85
3
+ Version: 0.1.87
4
4
  Summary: Financial infrastructure toolkit: banking connections, market data, credit, cashflows, and brokerage integrations
5
5
  License: MIT
6
6
  Keywords: finance,banking,plaid,brokerage,markets,credit,tax,cashflow,fintech,infra
@@ -49,9 +49,14 @@ Description-Content-Type: text/markdown
49
49
 
50
50
  # fin-infra
51
51
 
52
- ### Financial data infrastructure for fintech apps
52
+ [![CI](https://github.com/nfraxlab/fin-infra/actions/workflows/ci.yml/badge.svg)](https://github.com/nfraxlab/fin-infra/actions/workflows/ci.yml)
53
+ [![PyPI](https://img.shields.io/pypi/v/fin-infra.svg)](https://pypi.org/project/fin-infra/)
54
+ [![Python](https://img.shields.io/pypi/pyversions/fin-infra.svg)](https://pypi.org/project/fin-infra/)
55
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
56
+ [![Downloads](https://img.shields.io/pypi/dm/fin-infra.svg)](https://pypi.org/project/fin-infra/)
57
+ [![codecov](https://codecov.io/gh/nfraxlab/fin-infra/branch/main/graph/badge.svg)](https://codecov.io/gh/nfraxlab/fin-infra)
53
58
 
54
- [![PyPI](https://img.shields.io/pypi/v/fin-infra.svg)](https://pypi.org/project/fin-infra/) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) [![Downloads](https://static.pepy.tech/badge/fin-infra/month)](https://pepy.tech/project/fin-infra)
59
+ ### Financial data infrastructure for fintech apps
55
60
 
56
61
  **Banking, investments, market data, credit scores, and financial calculations in one toolkit.**
57
62
 
@@ -169,12 +169,13 @@ fin_infra/settings.py,sha256=11JgIhjGwWnwixV-hveEWpoWd_JC0ixLnOQoLWCiwNo,1387
169
169
  fin_infra/tax/__init__.py,sha256=U0EUKQwbDqnAYwU8WRx6AD07TaB-ELdKGISOQ-904lw,6103
170
170
  fin_infra/tax/add.py,sha256=dYigcgQFEP38NLoNuhh7vpSoy07sWX6Z_DTp1tWFJXw,14553
171
171
  fin_infra/tax/tlh.py,sha256=3khtiEkGKIIHi2mbMM0ss-GKQ8vM3FS6hly8R00qseY,21482
172
- fin_infra/utils/__init__.py,sha256=gKacLSWMAis--pasd8AuVN7ap0e9Z1TjRGur0J23EDo,648
172
+ fin_infra/utils/__init__.py,sha256=x_FUlv7FONdTPHwXTbPWY-EEOBwWnm-y8TPJ1W1PrXM,944
173
+ fin_infra/utils/deprecation.py,sha256=DTcqv7ECnrWOOwoA07JOnRci4Hqqo9YtKSSmoS-DVPY,5187
173
174
  fin_infra/utils/http.py,sha256=rDEgYsEBrEe75ml5RA-iSs3xeU5W-3j-czJlT7WbrM4,632
174
175
  fin_infra/utils/retry.py,sha256=YiyTgy26eJ1ah7fE2_-ZPa4hv4bIT4OzjYolkNWb5j0,1057
175
176
  fin_infra/version.py,sha256=4t_crzhrLum--oyowUMxtjBTzUtWp7oRTF22ewEvJG4,49
176
- fin_infra-0.1.85.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
177
- fin_infra-0.1.85.dist-info/METADATA,sha256=y13UC--sOtnmoLfYI4s1Z_THKBcpLzH3JaYaXOH41y8,10479
178
- fin_infra-0.1.85.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
179
- fin_infra-0.1.85.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
180
- fin_infra-0.1.85.dist-info/RECORD,,
177
+ fin_infra-0.1.87.dist-info/LICENSE,sha256=wK-Ya7Ylxa38dSIZRhvNj1ZVLIrHC-BAI8v38PNADiA,1061
178
+ fin_infra-0.1.87.dist-info/METADATA,sha256=7yOY1JncaJbV-A9TpZ2zRwb2vxUJke1AoTCyV0VVDoE,10712
179
+ fin_infra-0.1.87.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
180
+ fin_infra-0.1.87.dist-info/entry_points.txt,sha256=Sr1uikvALZMeKm-DIkeKG4L9c4SNqysXGO_IRF8_9eU,53
181
+ fin_infra-0.1.87.dist-info/RECORD,,