click-extended 1.0.6__tar.gz → 1.0.8__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.
- {click_extended-1.0.6/click_extended.egg-info → click_extended-1.0.8}/PKG-INFO +1 -1
- click_extended-1.0.8/click_extended/decorators/check/regex.py +65 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/__init__.py +4 -0
- click_extended-1.0.8/click_extended/decorators/misc/catch.py +300 -0
- {click_extended-1.0.6 → click_extended-1.0.8/click_extended.egg-info}/PKG-INFO +1 -1
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended.egg-info/SOURCES.txt +1 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/pyproject.toml +8 -2
- click_extended-1.0.6/click_extended/decorators/check/regex.py +0 -47
- {click_extended-1.0.6 → click_extended-1.0.8}/AUTHORS.md +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/LICENSE +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/README.md +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/classes.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/argument.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/command.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/context.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/env.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/group.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/option.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/prompt.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/selection.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/decorators/tag.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/_root_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/argument_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/child_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/child_validation_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/option_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/parent_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/validation_node.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/_click_command.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/_click_group.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/_tree.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/context.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/other/get_context.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/conflicts.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/contains.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/dependencies.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/divisible_by.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/ends_with.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/exclusive.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/falsy.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_email.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_hex_color.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_hostname.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_ipv4.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_ipv6.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_json.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_mac_address.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_negative.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_non_zero.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_port.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_positive.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_url.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_uuid.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/length.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/not_empty.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/requires.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/starts_with.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/truthy.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/at_least.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/at_most.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/between.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/greater_than.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/less_than.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_angle.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_area.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_bits.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_distance.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_energy.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_power.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_pressure.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_speed.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_temperature.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_time.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_volume.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_weight.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/load/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/load/load_csv.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/load/load_json.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/load/load_toml.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/load/load_yaml.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/absolute.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/add.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/ceil.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/clamp.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/divide.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/floor.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/maximum.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/minimum.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/modulo.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/multiply.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/normalize.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/power.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/rounded.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/sqrt.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/subtract.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/math/to_percent.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/choice.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/confirm_if.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/default.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/deprecated.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/experimental.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/now.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_bool.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_choice.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_datetime.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_float.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_integer.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_prime.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_string.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_uuid.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/add_prefix.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/add_suffix.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/apply.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/basename.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/dirname.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/expand_vars.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/remove_prefix.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/remove_suffix.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/replace.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/slugify.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/split.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/strip.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_case.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_date.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_datetime.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_path.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_time.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_timestamp.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/truncate.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/errors.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/types.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/__init__.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/casing.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/checks.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/dispatch.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/format.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/humanize.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/naming.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/process.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/selection.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended/utils/time.py +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended.egg-info/dependency_links.txt +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended.egg-info/requires.txt +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/click_extended.egg-info/top_level.txt +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/setup.cfg +0 -0
- {click_extended-1.0.6 → click_extended-1.0.8}/tests/test_lifecycle.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: click_extended
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: An extension to Click with additional features like automatic async support, aliasing and a modular decorator system.
|
|
5
5
|
Author-email: Marcus Fredriksson <marcus@marcusfredriksson.com>
|
|
6
6
|
License: MIT License
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Check if a value matches a regex pattern."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any, Union
|
|
5
|
+
|
|
6
|
+
from click_extended.core.nodes.child_node import ChildNode
|
|
7
|
+
from click_extended.core.other.context import Context
|
|
8
|
+
from click_extended.types import Decorator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Regex(ChildNode):
|
|
12
|
+
"""Check if a value matches a regex pattern."""
|
|
13
|
+
|
|
14
|
+
def handle_str(
|
|
15
|
+
self,
|
|
16
|
+
value: str,
|
|
17
|
+
context: Context,
|
|
18
|
+
*args: Any,
|
|
19
|
+
**kwargs: Any,
|
|
20
|
+
) -> Any:
|
|
21
|
+
patterns: tuple[Union[str, re.Pattern[str]], ...] = kwargs["patterns"]
|
|
22
|
+
flags: int = kwargs.get("flags", 0)
|
|
23
|
+
|
|
24
|
+
for pattern in patterns:
|
|
25
|
+
compiled_pattern: re.Pattern[str]
|
|
26
|
+
if isinstance(pattern, re.Pattern):
|
|
27
|
+
compiled_pattern = pattern
|
|
28
|
+
else:
|
|
29
|
+
compiled_pattern = re.compile(pattern, flags)
|
|
30
|
+
|
|
31
|
+
if compiled_pattern.fullmatch(value):
|
|
32
|
+
return value
|
|
33
|
+
|
|
34
|
+
pattern_strs: list[str] = [
|
|
35
|
+
p.pattern if isinstance(p, re.Pattern) else p for p in patterns
|
|
36
|
+
]
|
|
37
|
+
raise ValueError(
|
|
38
|
+
f"Value '{value}' does not match any "
|
|
39
|
+
+ f"of the patterns: {pattern_strs}"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def regex(*patterns: Union[str, re.Pattern[str]], flags: int = 0) -> Decorator:
|
|
44
|
+
"""
|
|
45
|
+
Check if a value matches a regex pattern.
|
|
46
|
+
|
|
47
|
+
Type: `ChildNode`
|
|
48
|
+
|
|
49
|
+
Supports: `str`
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
*patterns (Union[str, Pattern[str]]):
|
|
53
|
+
The regex patterns to check against. Can be strings or compiled
|
|
54
|
+
Pattern objects. If strings are provided, they will be compiled
|
|
55
|
+
with the specified flags.
|
|
56
|
+
flags (int):
|
|
57
|
+
Regex flags to use when compiling string patterns (e.g.,
|
|
58
|
+
re.IGNORECASE, re.MULTILINE). Ignored for pre-compiled patterns.
|
|
59
|
+
Default is 0 (no flags).
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Decorator:
|
|
63
|
+
The decorated function.
|
|
64
|
+
"""
|
|
65
|
+
return Regex.as_decorator(patterns=patterns, flags=flags)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Initialization file for the `click_extended.decorators.misc` module."""
|
|
2
2
|
|
|
3
|
+
# pylint: disable=wrong-import-position
|
|
4
|
+
|
|
5
|
+
from click_extended.decorators.misc.catch import catch
|
|
3
6
|
from click_extended.decorators.misc.choice import choice
|
|
4
7
|
from click_extended.decorators.misc.confirm_if import confirm_if
|
|
5
8
|
from click_extended.decorators.misc.default import default
|
|
@@ -8,6 +11,7 @@ from click_extended.decorators.misc.experimental import experimental
|
|
|
8
11
|
from click_extended.decorators.misc.now import now
|
|
9
12
|
|
|
10
13
|
__all__ = [
|
|
14
|
+
"catch",
|
|
11
15
|
"choice",
|
|
12
16
|
"confirm_if",
|
|
13
17
|
"default",
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validation node to catch and handle exceptions from command/group functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import inspect
|
|
7
|
+
from functools import wraps
|
|
8
|
+
from typing import Any, Callable
|
|
9
|
+
from weakref import WeakKeyDictionary
|
|
10
|
+
|
|
11
|
+
from click_extended.core.nodes.validation_node import ValidationNode
|
|
12
|
+
from click_extended.core.other._tree import Tree
|
|
13
|
+
from click_extended.core.other.context import Context
|
|
14
|
+
from click_extended.types import Decorator
|
|
15
|
+
|
|
16
|
+
_catch_handlers: WeakKeyDictionary[
|
|
17
|
+
Callable[..., Any],
|
|
18
|
+
list[
|
|
19
|
+
tuple[tuple[type[BaseException], ...], Callable[..., Any] | None, bool]
|
|
20
|
+
],
|
|
21
|
+
] = WeakKeyDictionary()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Catch(ValidationNode):
|
|
25
|
+
"""
|
|
26
|
+
Catch and handle exceptions from command/group functions.
|
|
27
|
+
|
|
28
|
+
Wraps the decorated function in a try-except block. When an exception
|
|
29
|
+
is caught, an optional handler is invoked. Without a handler, exceptions
|
|
30
|
+
are silently suppressed.
|
|
31
|
+
|
|
32
|
+
Handler signatures supported:
|
|
33
|
+
- `handler()` - No arguments, just execute code
|
|
34
|
+
- `handler(exception)` - Receive the exception object
|
|
35
|
+
- `handler(exception, context)` - Receive exception and Context object
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
```py
|
|
39
|
+
# Simple error logging
|
|
40
|
+
@command()
|
|
41
|
+
@catch(ValueError, handler=lambda: print("Invalid value!"))
|
|
42
|
+
def cmd():
|
|
43
|
+
raise ValueError("Bad input")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```py
|
|
47
|
+
# Handle exception with details
|
|
48
|
+
@command()
|
|
49
|
+
@catch(ValueError, handler=lambda e: print(f"Error: {e}"))
|
|
50
|
+
def cmd():
|
|
51
|
+
raise ValueError("Count must be positive")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```py
|
|
55
|
+
# Access context information
|
|
56
|
+
@command()
|
|
57
|
+
@catch(
|
|
58
|
+
ValueError,
|
|
59
|
+
handler=lambda e, ctx: print(f"{ctx.info_name}: {e}"),
|
|
60
|
+
)
|
|
61
|
+
def cmd():
|
|
62
|
+
raise ValueError("Failed!")
|
|
63
|
+
```
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
name: str,
|
|
69
|
+
process_args: tuple[Any, ...] | None = None,
|
|
70
|
+
process_kwargs: dict[str, Any] | None = None,
|
|
71
|
+
**kwargs: Any,
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Initialize Catch validation node with function to wrap."""
|
|
74
|
+
super().__init__(name, process_args, process_kwargs, **kwargs)
|
|
75
|
+
self.wrapped_func: Callable[..., Any] | None = None
|
|
76
|
+
|
|
77
|
+
def on_finalize(self, context: Context, *args: Any, **kwargs: Any) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Store exception handler configuration for later use.
|
|
80
|
+
|
|
81
|
+
The actual exception catching happens when the function is invoked,
|
|
82
|
+
which is done by wrapping the function in the decorator.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
context: The execution context
|
|
86
|
+
*args: Contains exception types tuple at index 0
|
|
87
|
+
**kwargs: Contains handler, reraise parameters
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def catch(
|
|
92
|
+
*exception_types: type[BaseException],
|
|
93
|
+
handler: Callable[..., Any] | None = None,
|
|
94
|
+
reraise: bool = False,
|
|
95
|
+
) -> Decorator:
|
|
96
|
+
"""
|
|
97
|
+
Catch and handle exceptions from command/group functions.
|
|
98
|
+
|
|
99
|
+
Wraps the function in a try-except block. When exceptions occur, an optional
|
|
100
|
+
handler is invoked. If no exception types are specified, catches Exception.
|
|
101
|
+
|
|
102
|
+
Type: `ValidationNode`
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
*exception_types: Exception types to catch (defaults to Exception)
|
|
106
|
+
handler: Optional function with signature `()`, `(exception)`, or
|
|
107
|
+
`(exception, context)` to handle caught exceptions
|
|
108
|
+
reraise: If True, re-raise after handling (default: False)
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Decorator function
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
TypeError: If exception_types contains non-exception classes
|
|
115
|
+
|
|
116
|
+
Examples:
|
|
117
|
+
```python
|
|
118
|
+
# Simple notification (no arguments)
|
|
119
|
+
@command()
|
|
120
|
+
@catch(ValueError, handler=lambda: print("Error occurred!"))
|
|
121
|
+
def cmd():
|
|
122
|
+
raise ValueError("Invalid input")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
# Log exception details (exception argument)
|
|
127
|
+
@command()
|
|
128
|
+
@catch(ValueError, handler=lambda e: print(f"Error: {e}"))
|
|
129
|
+
def cmd():
|
|
130
|
+
raise ValueError("Count must be positive")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# Access context (exception + context arguments)
|
|
135
|
+
@command()
|
|
136
|
+
@catch(
|
|
137
|
+
ValueError,
|
|
138
|
+
handler=lambda e, ctx: print(f"{ctx.info_name}: {e}"),
|
|
139
|
+
)
|
|
140
|
+
def cmd():
|
|
141
|
+
raise ValueError("Failed!")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Catch multiple exception types
|
|
146
|
+
@command()
|
|
147
|
+
@catch(ValueError, TypeError, handler=lambda e: log_error(e))
|
|
148
|
+
def cmd():
|
|
149
|
+
raise ValueError("Something went wrong")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# Silent suppression (no handler)
|
|
154
|
+
@command()
|
|
155
|
+
@catch(RuntimeError)
|
|
156
|
+
def cmd():
|
|
157
|
+
raise RuntimeError("Silently suppressed")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# Log then re-raise
|
|
162
|
+
@command()
|
|
163
|
+
@catch(
|
|
164
|
+
ValueError,
|
|
165
|
+
handler=lambda e: print(f"Logging: {e}"),
|
|
166
|
+
reraise=True,
|
|
167
|
+
)
|
|
168
|
+
def cmd():
|
|
169
|
+
raise ValueError("This will be logged and re-raised")
|
|
170
|
+
```
|
|
171
|
+
"""
|
|
172
|
+
if not exception_types:
|
|
173
|
+
exception_types = (Exception,)
|
|
174
|
+
|
|
175
|
+
for exc_type in exception_types:
|
|
176
|
+
if not isinstance(exc_type, type) or not issubclass(
|
|
177
|
+
exc_type, BaseException
|
|
178
|
+
):
|
|
179
|
+
raise TypeError(
|
|
180
|
+
f"catch() requires exception types, got {exc_type!r}"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
184
|
+
"""The actual decorator that wraps the function."""
|
|
185
|
+
|
|
186
|
+
instance = Catch(
|
|
187
|
+
name="catch",
|
|
188
|
+
process_args=(exception_types,),
|
|
189
|
+
process_kwargs={"handler": handler, "reraise": reraise},
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
Tree.queue_validation(instance)
|
|
193
|
+
|
|
194
|
+
original_func = func
|
|
195
|
+
while hasattr(original_func, "__wrapped__"):
|
|
196
|
+
original_func = original_func.__wrapped__ # type: ignore
|
|
197
|
+
|
|
198
|
+
if original_func not in _catch_handlers:
|
|
199
|
+
_catch_handlers[original_func] = []
|
|
200
|
+
_catch_handlers[original_func].insert(
|
|
201
|
+
0, (exception_types, handler, reraise)
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Only wrap if this is the first @catch (check handlers dict)
|
|
205
|
+
if len(_catch_handlers[original_func]) > 1:
|
|
206
|
+
return func
|
|
207
|
+
|
|
208
|
+
if asyncio.iscoroutinefunction(func):
|
|
209
|
+
|
|
210
|
+
@wraps(func)
|
|
211
|
+
async def async_wrapper(*call_args: Any, **call_kwargs: Any) -> Any:
|
|
212
|
+
"""Async wrapper that catches exceptions."""
|
|
213
|
+
try:
|
|
214
|
+
return await func(*call_args, **call_kwargs)
|
|
215
|
+
except BaseException as exc:
|
|
216
|
+
for exc_types, hdlr, reraise_flag in _catch_handlers.get(
|
|
217
|
+
original_func, []
|
|
218
|
+
):
|
|
219
|
+
if isinstance(exc, exc_types):
|
|
220
|
+
if hdlr is not None:
|
|
221
|
+
if asyncio.iscoroutinefunction(hdlr):
|
|
222
|
+
await _call_handler_async(hdlr, exc)
|
|
223
|
+
else:
|
|
224
|
+
_call_handler_sync(hdlr, exc)
|
|
225
|
+
|
|
226
|
+
if reraise_flag:
|
|
227
|
+
raise
|
|
228
|
+
|
|
229
|
+
return None
|
|
230
|
+
raise
|
|
231
|
+
|
|
232
|
+
return async_wrapper
|
|
233
|
+
|
|
234
|
+
@wraps(func)
|
|
235
|
+
def sync_wrapper(*call_args: Any, **call_kwargs: Any) -> Any:
|
|
236
|
+
"""Sync wrapper that catches exceptions."""
|
|
237
|
+
try:
|
|
238
|
+
return func(*call_args, **call_kwargs)
|
|
239
|
+
except BaseException as exc:
|
|
240
|
+
for exc_types, hdlr, reraise_flag in _catch_handlers.get(
|
|
241
|
+
original_func, []
|
|
242
|
+
):
|
|
243
|
+
if isinstance(exc, exc_types):
|
|
244
|
+
if hdlr is not None:
|
|
245
|
+
if asyncio.iscoroutinefunction(hdlr):
|
|
246
|
+
asyncio.run(_call_handler_async(hdlr, exc))
|
|
247
|
+
else:
|
|
248
|
+
_call_handler_sync(hdlr, exc)
|
|
249
|
+
|
|
250
|
+
if reraise_flag:
|
|
251
|
+
raise
|
|
252
|
+
|
|
253
|
+
return None
|
|
254
|
+
raise
|
|
255
|
+
|
|
256
|
+
return sync_wrapper
|
|
257
|
+
|
|
258
|
+
return decorator
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
async def _call_handler_async(
|
|
262
|
+
handler: Callable[..., Any], exc: BaseException
|
|
263
|
+
) -> Any:
|
|
264
|
+
"""Call async handler with appropriate number of arguments."""
|
|
265
|
+
sig = inspect.signature(handler)
|
|
266
|
+
params = list(sig.parameters.values())
|
|
267
|
+
|
|
268
|
+
if len(params) == 0:
|
|
269
|
+
return await handler()
|
|
270
|
+
if len(params) == 1:
|
|
271
|
+
return await handler(exc)
|
|
272
|
+
|
|
273
|
+
import click
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
ctx = click.get_current_context()
|
|
277
|
+
custom_context = ctx.meta.get("click_extended", {}).get("context")
|
|
278
|
+
return await handler(exc, custom_context)
|
|
279
|
+
except RuntimeError:
|
|
280
|
+
return await handler(exc, None)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def _call_handler_sync(handler: Callable[..., Any], exc: BaseException) -> Any:
|
|
284
|
+
"""Call sync handler with appropriate number of arguments."""
|
|
285
|
+
sig = inspect.signature(handler)
|
|
286
|
+
params = list(sig.parameters.values())
|
|
287
|
+
|
|
288
|
+
if len(params) == 0:
|
|
289
|
+
return handler()
|
|
290
|
+
if len(params) == 1:
|
|
291
|
+
return handler(exc)
|
|
292
|
+
|
|
293
|
+
import click
|
|
294
|
+
|
|
295
|
+
try:
|
|
296
|
+
ctx = click.get_current_context()
|
|
297
|
+
custom_context = ctx.meta.get("click_extended", {}).get("context")
|
|
298
|
+
return handler(exc, custom_context)
|
|
299
|
+
except RuntimeError:
|
|
300
|
+
return handler(exc, None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: click_extended
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.8
|
|
4
4
|
Summary: An extension to Click with additional features like automatic async support, aliasing and a modular decorator system.
|
|
5
5
|
Author-email: Marcus Fredriksson <marcus@marcusfredriksson.com>
|
|
6
6
|
License: MIT License
|
|
@@ -107,6 +107,7 @@ click_extended/decorators/math/sqrt.py
|
|
|
107
107
|
click_extended/decorators/math/subtract.py
|
|
108
108
|
click_extended/decorators/math/to_percent.py
|
|
109
109
|
click_extended/decorators/misc/__init__.py
|
|
110
|
+
click_extended/decorators/misc/catch.py
|
|
110
111
|
click_extended/decorators/misc/choice.py
|
|
111
112
|
click_extended/decorators/misc/confirm_if.py
|
|
112
113
|
click_extended/decorators/misc/default.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "click_extended"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.8"
|
|
4
4
|
description = "An extension to Click with additional features like automatic async support, aliasing and a modular decorator system."
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Marcus Fredriksson", email = "marcus@marcusfredriksson.com" },
|
|
@@ -85,7 +85,13 @@ ignore = [
|
|
|
85
85
|
".mypy_cache",
|
|
86
86
|
"*.egg-info",
|
|
87
87
|
]
|
|
88
|
-
ignore-paths = [
|
|
88
|
+
ignore-paths = [
|
|
89
|
+
"^tests/.*$",
|
|
90
|
+
"^docs/.*$",
|
|
91
|
+
"^\\..*$",
|
|
92
|
+
"^click_extended/core/nodes/_root_node\\.py$",
|
|
93
|
+
"^click_extended/utils/dispatch\\.py$",
|
|
94
|
+
]
|
|
89
95
|
persistent = true
|
|
90
96
|
|
|
91
97
|
[tool.pylint.messages_control]
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"""Check if a value matches a regex pattern."""
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
from typing import Any
|
|
5
|
-
|
|
6
|
-
from click_extended.core.nodes.child_node import ChildNode
|
|
7
|
-
from click_extended.core.other.context import Context
|
|
8
|
-
from click_extended.types import Decorator
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Regex(ChildNode):
|
|
12
|
-
"""Check if a value matches a regex pattern."""
|
|
13
|
-
|
|
14
|
-
def handle_str(
|
|
15
|
-
self,
|
|
16
|
-
value: str,
|
|
17
|
-
context: Context,
|
|
18
|
-
*args: Any,
|
|
19
|
-
**kwargs: Any,
|
|
20
|
-
) -> Any:
|
|
21
|
-
patterns = kwargs["patterns"]
|
|
22
|
-
for pattern in patterns:
|
|
23
|
-
if re.fullmatch(pattern, value):
|
|
24
|
-
return value
|
|
25
|
-
|
|
26
|
-
raise ValueError(
|
|
27
|
-
f"Value '{value}' does not match any of the patterns: {patterns}"
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def regex(*patterns: str) -> Decorator:
|
|
32
|
-
"""
|
|
33
|
-
Check if a value matches a regex pattern.
|
|
34
|
-
|
|
35
|
-
Type: `ChildNode`
|
|
36
|
-
|
|
37
|
-
Supports: `str`
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
*patterns (str):
|
|
41
|
-
The regex patterns to check against.
|
|
42
|
-
|
|
43
|
-
Returns:
|
|
44
|
-
Decorator:
|
|
45
|
-
The decorated function.
|
|
46
|
-
"""
|
|
47
|
-
return Regex.as_decorator(patterns=patterns)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/core/nodes/child_validation_node.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/dependencies.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/divisible_by.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_hex_color.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_hostname.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_mac_address.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_negative.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_non_zero.py
RENAMED
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/is_positive.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/check/starts_with.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/greater_than.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/compare/less_than.py
RENAMED
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_angle.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_area.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_bits.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_distance.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_energy.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_power.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_pressure.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_speed.py
RENAMED
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_time.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_volume.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/convert/convert_weight.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/misc/experimental.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_bool.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_choice.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_datetime.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_float.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_integer.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_prime.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_string.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/random/random_uuid.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/__init__.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/add_prefix.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/add_suffix.py
RENAMED
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/basename.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/dirname.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/expand_vars.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/remove_prefix.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/remove_suffix.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/replace.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/slugify.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_case.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_date.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_datetime.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_path.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_time.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/to_timestamp.py
RENAMED
|
File without changes
|
{click_extended-1.0.6 → click_extended-1.0.8}/click_extended/decorators/transform/truncate.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|