python-argtools 0.0.1__tar.gz → 0.0.3__tar.gz

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.
@@ -1,27 +1,28 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: python-argtools
3
- Version: 0.0.1
3
+ Version: 0.0.3
4
4
  Summary: Python argument tools.
5
- Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-argtools
6
5
  License: MIT
6
+ License-File: LICENSE
7
7
  Keywords: argument,tools
8
8
  Author: ChenyangGao
9
9
  Author-email: wosiwujm@gmail.com
10
- Requires-Python: >=3.10,<4.0
10
+ Requires-Python: >=3.12,<4.0
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Programming Language :: Python :: 3 :: Only
21
21
  Classifier: Topic :: Software Development
22
22
  Classifier: Topic :: Software Development :: Libraries
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
- Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-argtools
24
+ Project-URL: Homepage, https://github.com/ChenyangGao/python-modules/tree/main/python-argtools
25
+ Project-URL: Repository, https://github.com/ChenyangGao/python-modules/tree/main/python-argtools
25
26
  Description-Content-Type: text/markdown
26
27
 
27
28
  # Python argument tools.
@@ -31,7 +32,7 @@ Description-Content-Type: text/markdown
31
32
  You can install from [pypi](https://pypi.org/project/python-argtools/)
32
33
 
33
34
  ```console
34
- pip install -U argtools
35
+ pip install -U python-argtools
35
36
  ```
36
37
 
37
38
  ## Usage
@@ -6,68 +6,88 @@ some arguments at one time and then use them repeatedly later.
6
6
  """
7
7
 
8
8
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
9
- __version__ = (0, 0, 1)
10
- __all__ = ["argcount", "Args", "UpdativeArgs"]
9
+ __version__ = (0, 0, 3)
10
+ __all__ = ["argcount", "Args", "UpdativeArgs", "Call"]
11
11
 
12
12
  from collections.abc import Callable
13
13
  from copy import copy
14
+ from functools import partial, update_wrapper
14
15
  from inspect import getfullargspec
15
- from typing import Any, Callable, Generic, ParamSpec, TypeVar
16
+ from types import MethodType, MethodWrapperType
17
+ from typing import Any
16
18
 
17
19
 
18
- T = TypeVar("T")
19
- P = ParamSpec("P")
20
-
21
-
22
- def argcount(func: Callable) -> int:
20
+ def argcount(func: Callable, /) -> int:
21
+ if isinstance(func, partial):
22
+ return max(0, argcount(func.func) - len(func.args))
23
+ is_method = isinstance(func, (MethodType, MethodWrapperType))
23
24
  try:
24
- return func.__code__.co_argcount
25
+ return func.__code__.co_argcount - is_method
25
26
  except AttributeError:
26
- return len(getfullargspec(func).args)
27
+ return len(getfullargspec(func).args) - is_method
27
28
 
28
29
 
29
- class Args(Generic[T, P]):
30
+ class Args:
30
31
  """Takes some positional arguments and keyword arguments,
31
32
  and put them into an instance, which can be used repeatedly
32
33
  every next time.
33
34
 
34
35
  Fields::
35
- self.pargs: the collected positional arguments
36
- self.kargs: the collected keyword arguments
36
+ self.args: the collected positional arguments
37
+ self.kwargs: the collected keyword arguments
37
38
  """
38
- __slots__ = ("pargs", "kargs")
39
+ __slots__ = ("args", "kwargs")
39
40
 
40
- def __init__(self, /, *pargs, **kargs):
41
- self.pargs: P.args = pargs
42
- self.kargs: P.kwargs = kargs
41
+ def __init__(self, /, *args, **kwargs):
42
+ self.args = args
43
+ self.kwargs = kwargs
43
44
 
44
- def __call__(self, /, func: Callable[..., T]) -> T:
45
+ def __call__[T](self, /, func: Callable[..., T]) -> T:
45
46
  """Pass in the collected positional arguments and keyword
46
47
  arguments when calling the callable `func`."""
47
- return func(*self.pargs, **self.kargs)
48
+ return func(*self.args, **self.kwargs)
48
49
 
49
50
  def __copy__(self, /):
50
- return type(self)(*self.pargs, **self.kargs)
51
+ return type(self)(*self.args, **self.kwargs)
51
52
 
52
53
  def __eq__(self, other):
53
54
  if isinstance(other, Args):
54
- return self.pargs == other.pargs and self.kargs == other.kargs
55
+ return self.args == other.args and self.kwargs == other.kwargs
55
56
  return False
56
57
 
58
+ def __getitem__(self, idx: int | slice | str | tuple[int | slice | str, ...], /):
59
+ cls = type(self)
60
+ pget = self.args.__getitem__
61
+ if isinstance(idx, (int, slice)):
62
+ return cls(pget(idx))
63
+ kget = self.kwargs.__getitem__
64
+ if isinstance(idx, str):
65
+ return cls(idx=kget(idx))
66
+ else:
67
+ pargs: list = []
68
+ kargs: dict = {}
69
+ add_parg = pargs.append
70
+ for idx_ in idx:
71
+ if isinstance(idx_, (int, slice)):
72
+ add_parg(pget(idx_))
73
+ else:
74
+ kargs[idx_] = kget(idx_)
75
+ return cls(*pargs, **kargs)
76
+
57
77
  def __iter__(self, /):
58
- return iter((self.pargs, self.kargs))
78
+ return iter((self.args, self.kwargs))
59
79
 
60
80
  def __repr__(self):
61
81
  return "%s(%s)" % (
62
82
  type(self).__qualname__,
63
83
  ", ".join((
64
- *map(repr, self.pargs),
65
- *("%s=%r" % e for e in self.kargs.items()),
84
+ *map(repr, self.args),
85
+ *("%s=%r" % e for e in self.kwargs.items()),
66
86
  )),
67
87
  )
68
88
 
69
89
  @classmethod
70
- def call(cls, /, func: Callable[..., T], args: Any = ()) -> T:
90
+ def call[T](cls, /, func: Callable[..., T], args: Any = ()) -> T:
71
91
  """Call the callable `func` and pass in the arguments `args`.
72
92
 
73
93
  The actual behavior as below:
@@ -81,12 +101,13 @@ class Args(Generic[T, P]):
81
101
  """
82
102
  if isinstance(args, Args):
83
103
  return args(func)
84
- type_ = type(args)
85
- if type_ is tuple:
104
+ args_type = type(args)
105
+ if args_type == tuple:
86
106
  return func(*args)
87
- elif type_ is dict:
107
+ elif args_type == dict:
88
108
  return func(**args)
89
- return func(args)
109
+ else:
110
+ return func(args)
90
111
 
91
112
 
92
113
  class UpdativeArgs(Args):
@@ -97,12 +118,12 @@ class UpdativeArgs(Args):
97
118
  collected arguments.
98
119
 
99
120
  Fields::
100
- self.pargs: the collected positional arguments
101
- self.kargs: the collected keyword arguments
121
+ self.args: the collected positional arguments
122
+ self.kwargs: the collected keyword arguments
102
123
  """
103
- __slots__ = ("pargs", "kargs")
124
+ __slots__ = ("args", "kwargs")
104
125
 
105
- def extend(self, /, *pargs, **kargs):
126
+ def extend(self, /, *args, **kwargs):
106
127
  """Extend the collected arguments.
107
128
 
108
129
  Examples::
@@ -113,17 +134,17 @@ class UpdativeArgs(Args):
113
134
  >>> args is args2
114
135
  True
115
136
  """
116
- if pargs:
117
- self.pargs += pargs
118
- if kargs:
119
- kargs0 = self.kargs
120
- kargs0.update(
121
- (k, kargs[k])
122
- for k in kargs.keys() - kargs0.keys()
137
+ if args:
138
+ self.args += args
139
+ if kwargs:
140
+ kwargs0 = self.kwargs
141
+ kwargs0.update(
142
+ (k, kwargs[k])
143
+ for k in kwargs.keys() - kwargs0.keys()
123
144
  )
124
145
  return self
125
146
 
126
- def copy_extend(self, /, *pargs, **kargs):
147
+ def copy_extend(self, /, *args, **kwargs):
127
148
  """Extend the collected arguments in a copied instance.
128
149
 
129
150
  Examples::
@@ -134,9 +155,9 @@ class UpdativeArgs(Args):
134
155
  >>> args is args2
135
156
  False
136
157
  """
137
- return copy(self).extend(*pargs, **kargs)
158
+ return copy(self).extend(*args, **kwargs)
138
159
 
139
- def prepend(self, /, *pargs, **kargs):
160
+ def prepend(self, /, *args, **kwargs):
140
161
  """Prepend the collected arguments.
141
162
 
142
163
  Examples::
@@ -147,13 +168,13 @@ class UpdativeArgs(Args):
147
168
  >>> args is args2
148
169
  True
149
170
  """
150
- if pargs:
151
- self.pargs = pargs + self.pargs
152
- if kargs:
153
- self.kargs.update(kargs)
171
+ if args:
172
+ self.args = args + self.args
173
+ if kwargs:
174
+ self.kwargs.update(kwargs)
154
175
  return self
155
176
 
156
- def copy_prepend(self, /, *pargs, **kargs):
177
+ def copy_prepend(self, /, *args, **kwargs):
157
178
  """Prepend the collected arguments in a copied instance.
158
179
 
159
180
  Examples::
@@ -164,9 +185,9 @@ class UpdativeArgs(Args):
164
185
  >>> args is args2
165
186
  False
166
187
  """
167
- return copy(self).prepend(*pargs, **kargs)
188
+ return copy(self).prepend(*args, **kwargs)
168
189
 
169
- def update(self, /, *pargs, **kargs):
190
+ def update(self, /, *args, **kwargs):
170
191
  """Update the collected arguments.
171
192
 
172
193
  Examples::
@@ -180,17 +201,17 @@ class UpdativeArgs(Args):
180
201
  >>> args.update(7, 8, 10, 11, x=9, r=0)
181
202
  UpdativeArgs(7, 8, 10, 11, x=9, y=5, z=6, r=0)
182
203
  """
183
- if pargs:
184
- n = len(pargs) - len(self.pargs)
204
+ if args:
205
+ n = len(args) - len(self.args)
185
206
  if n >= 0:
186
- self.pargs = pargs
207
+ self.args = args
187
208
  else:
188
- self.pargs = pargs + self.pargs[n:]
189
- if kargs:
190
- self.kargs.update(kargs)
209
+ self.args = args + self.args[n:]
210
+ if kwargs:
211
+ self.kwargs.update(kwargs)
191
212
  return self
192
213
 
193
- def copy_update(self, /, *pargs, **kargs):
214
+ def copy_update(self, /, *args, **kwargs):
194
215
  """Update the collected arguments in a copied instance.
195
216
 
196
217
  Examples::
@@ -213,9 +234,9 @@ class UpdativeArgs(Args):
213
234
  >>> args2 == args3
214
235
  True
215
236
  """
216
- return copy(self).update(*pargs, **kargs)
237
+ return copy(self).update(*args, **kwargs)
217
238
 
218
- def update_extend(self, /, *pargs, **kargs):
239
+ def update_extend(self, /, *args, **kwargs):
219
240
  """Update and entend the collected arguments.
220
241
 
221
242
  Examples::
@@ -229,19 +250,19 @@ class UpdativeArgs(Args):
229
250
  >>> args.update_extend(7, 8, x=9, r=0)
230
251
  UpdativeArgs(1, 2, 3, x=4, y=5, z=6, r=0)
231
252
  """
232
- if pargs:
233
- n = len(self.pargs) - len(pargs)
253
+ if args:
254
+ n = len(self.args) - len(args)
234
255
  if n < 0:
235
- self.pargs += pargs[n:]
236
- if kargs:
237
- kargs0 = self.kargs
238
- kargs0.update(
239
- (k, kargs[k])
240
- for k in kargs.keys() - kargs0.keys()
256
+ self.args += args[n:]
257
+ if kwargs:
258
+ kwargs0 = self.kwargs
259
+ kwargs0.update(
260
+ (k, kwargs[k])
261
+ for k in kwargs.keys() - kwargs0.keys()
241
262
  )
242
263
  return self
243
264
 
244
- def copy_update_extend(self, /, *pargs, **kargs):
265
+ def copy_update_extend(self, /, *args, **kwargs):
245
266
  """Update and extend the collected arguments in
246
267
  a copied instance.
247
268
 
@@ -267,7 +288,37 @@ class UpdativeArgs(Args):
267
288
  >>> args2 == args3
268
289
  True
269
290
  """
270
- return copy(self).update_extend(*pargs, **kargs)
291
+ return copy(self).update_extend(*args, **kwargs)
292
+
293
+
294
+ class Call[**Params, R](partial):
295
+ """
296
+ """
297
+ def __new__(
298
+ cls,
299
+ func: Callable[Params, R],
300
+ /,
301
+ *args: Params.args,
302
+ **kwds: Params.kwargs,
303
+ ):
304
+ if hasattr(func, "func"):
305
+ args = getattr(func, "args", ()) + args # type: ignore
306
+ kwargs: None | dict = None
307
+ try:
308
+ kwargs = getattr(func, "kwargs")
309
+ except AttributeError:
310
+ kwargs = getattr(func, "keywords", None)
311
+ if kwargs:
312
+ kwds = {**kwargs, **kwds} # type: ignore
313
+ func = func.func
314
+ return update_wrapper(super().__new__(cls, func, *args, **kwds), func)
315
+
316
+ @property
317
+ def kwargs(self, /) -> dict:
318
+ return self.keywords
319
+
320
+ def __call__(self, /) -> R:
321
+ return self.func(*self.args, **self.kwargs)
271
322
 
272
323
 
273
324
  if __name__ == "__main__":
@@ -1,19 +1,19 @@
1
1
  [tool.poetry]
2
2
  name = "python-argtools"
3
- version = "0.0.1"
3
+ version = "0.0.3"
4
4
  description = "Python argument tools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
7
7
  readme = "readme.md"
8
- homepage = "https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-argtools"
9
- repository = "https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-argtools"
8
+ homepage = "https://github.com/ChenyangGao/python-modules/tree/main/python-argtools"
9
+ repository = "https://github.com/ChenyangGao/python-modules/tree/main/python-argtools"
10
10
  keywords = ["argument", "tools"]
11
11
  classifiers = [
12
12
  "License :: OSI Approved :: MIT License",
13
13
  "Development Status :: 5 - Production/Stable",
14
14
  "Programming Language :: Python",
15
15
  "Programming Language :: Python :: 3",
16
- "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.12",
17
17
  "Programming Language :: Python :: 3 :: Only",
18
18
  "Operating System :: OS Independent",
19
19
  "Intended Audience :: Developers",
@@ -26,7 +26,7 @@ include = [
26
26
  ]
27
27
 
28
28
  [tool.poetry.dependencies]
29
- python = "^3.10"
29
+ python = "^3.12"
30
30
 
31
31
  [build-system]
32
32
  requires = ["poetry-core"]
@@ -5,7 +5,7 @@
5
5
  You can install from [pypi](https://pypi.org/project/python-argtools/)
6
6
 
7
7
  ```console
8
- pip install -U argtools
8
+ pip install -U python-argtools
9
9
  ```
10
10
 
11
11
  ## Usage
File without changes