click-extended 1.0.8__tar.gz → 1.0.10__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.
Files changed (158) hide show
  1. {click_extended-1.0.8/click_extended.egg-info → click_extended-1.0.10}/PKG-INFO +1 -1
  2. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/option.py +16 -0
  3. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/_root_node.py +27 -1
  4. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/catch.py +55 -12
  5. {click_extended-1.0.8 → click_extended-1.0.10/click_extended.egg-info}/PKG-INFO +1 -1
  6. {click_extended-1.0.8 → click_extended-1.0.10}/pyproject.toml +1 -1
  7. {click_extended-1.0.8 → click_extended-1.0.10}/AUTHORS.md +0 -0
  8. {click_extended-1.0.8 → click_extended-1.0.10}/LICENSE +0 -0
  9. {click_extended-1.0.8 → click_extended-1.0.10}/README.md +0 -0
  10. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/__init__.py +0 -0
  11. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/classes.py +0 -0
  12. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/__init__.py +0 -0
  13. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/__init__.py +0 -0
  14. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/argument.py +0 -0
  15. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/command.py +0 -0
  16. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/context.py +0 -0
  17. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/env.py +0 -0
  18. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/group.py +0 -0
  19. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/prompt.py +0 -0
  20. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/selection.py +0 -0
  21. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/decorators/tag.py +0 -0
  22. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/__init__.py +0 -0
  23. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/argument_node.py +0 -0
  24. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/child_node.py +0 -0
  25. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/child_validation_node.py +0 -0
  26. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/node.py +0 -0
  27. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/option_node.py +0 -0
  28. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/parent_node.py +0 -0
  29. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/nodes/validation_node.py +0 -0
  30. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/__init__.py +0 -0
  31. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/_click_command.py +0 -0
  32. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/_click_group.py +0 -0
  33. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/_tree.py +0 -0
  34. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/context.py +0 -0
  35. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/core/other/get_context.py +0 -0
  36. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/__init__.py +0 -0
  37. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/__init__.py +0 -0
  38. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/conflicts.py +0 -0
  39. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/contains.py +0 -0
  40. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/dependencies.py +0 -0
  41. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/divisible_by.py +0 -0
  42. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/ends_with.py +0 -0
  43. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/exclusive.py +0 -0
  44. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/falsy.py +0 -0
  45. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_email.py +0 -0
  46. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_hex_color.py +0 -0
  47. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_hostname.py +0 -0
  48. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_ipv4.py +0 -0
  49. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_ipv6.py +0 -0
  50. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_json.py +0 -0
  51. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_mac_address.py +0 -0
  52. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_negative.py +0 -0
  53. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_non_zero.py +0 -0
  54. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_port.py +0 -0
  55. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_positive.py +0 -0
  56. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_url.py +0 -0
  57. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/is_uuid.py +0 -0
  58. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/length.py +0 -0
  59. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/not_empty.py +0 -0
  60. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/regex.py +0 -0
  61. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/requires.py +0 -0
  62. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/starts_with.py +0 -0
  63. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/check/truthy.py +0 -0
  64. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/__init__.py +0 -0
  65. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/at_least.py +0 -0
  66. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/at_most.py +0 -0
  67. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/between.py +0 -0
  68. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/greater_than.py +0 -0
  69. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/compare/less_than.py +0 -0
  70. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/__init__.py +0 -0
  71. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_angle.py +0 -0
  72. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_area.py +0 -0
  73. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_bits.py +0 -0
  74. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_distance.py +0 -0
  75. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_energy.py +0 -0
  76. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_power.py +0 -0
  77. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_pressure.py +0 -0
  78. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_speed.py +0 -0
  79. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_temperature.py +0 -0
  80. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_time.py +0 -0
  81. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_volume.py +0 -0
  82. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/convert/convert_weight.py +0 -0
  83. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/load/__init__.py +0 -0
  84. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/load/load_csv.py +0 -0
  85. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/load/load_json.py +0 -0
  86. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/load/load_toml.py +0 -0
  87. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/load/load_yaml.py +0 -0
  88. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/__init__.py +0 -0
  89. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/absolute.py +0 -0
  90. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/add.py +0 -0
  91. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/ceil.py +0 -0
  92. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/clamp.py +0 -0
  93. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/divide.py +0 -0
  94. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/floor.py +0 -0
  95. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/maximum.py +0 -0
  96. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/minimum.py +0 -0
  97. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/modulo.py +0 -0
  98. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/multiply.py +0 -0
  99. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/normalize.py +0 -0
  100. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/power.py +0 -0
  101. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/rounded.py +0 -0
  102. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/sqrt.py +0 -0
  103. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/subtract.py +0 -0
  104. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/math/to_percent.py +0 -0
  105. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/__init__.py +0 -0
  106. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/choice.py +0 -0
  107. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/confirm_if.py +0 -0
  108. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/default.py +0 -0
  109. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/deprecated.py +0 -0
  110. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/experimental.py +0 -0
  111. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/misc/now.py +0 -0
  112. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/__init__.py +0 -0
  113. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_bool.py +0 -0
  114. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_choice.py +0 -0
  115. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_datetime.py +0 -0
  116. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_float.py +0 -0
  117. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_integer.py +0 -0
  118. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_prime.py +0 -0
  119. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_string.py +0 -0
  120. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/random/random_uuid.py +0 -0
  121. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/__init__.py +0 -0
  122. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/add_prefix.py +0 -0
  123. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/add_suffix.py +0 -0
  124. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/apply.py +0 -0
  125. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/basename.py +0 -0
  126. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/dirname.py +0 -0
  127. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/expand_vars.py +0 -0
  128. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/remove_prefix.py +0 -0
  129. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/remove_suffix.py +0 -0
  130. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/replace.py +0 -0
  131. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/slugify.py +0 -0
  132. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/split.py +0 -0
  133. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/strip.py +0 -0
  134. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_case.py +0 -0
  135. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_date.py +0 -0
  136. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_datetime.py +0 -0
  137. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_path.py +0 -0
  138. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_time.py +0 -0
  139. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/to_timestamp.py +0 -0
  140. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/decorators/transform/truncate.py +0 -0
  141. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/errors.py +0 -0
  142. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/types.py +0 -0
  143. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/__init__.py +0 -0
  144. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/casing.py +0 -0
  145. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/checks.py +0 -0
  146. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/dispatch.py +0 -0
  147. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/format.py +0 -0
  148. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/humanize.py +0 -0
  149. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/naming.py +0 -0
  150. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/process.py +0 -0
  151. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/selection.py +0 -0
  152. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended/utils/time.py +0 -0
  153. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended.egg-info/SOURCES.txt +0 -0
  154. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended.egg-info/dependency_links.txt +0 -0
  155. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended.egg-info/requires.txt +0 -0
  156. {click_extended-1.0.8 → click_extended-1.0.10}/click_extended.egg-info/top_level.txt +0 -0
  157. {click_extended-1.0.8 → click_extended-1.0.10}/setup.cfg +0 -0
  158. {click_extended-1.0.8 → click_extended-1.0.10}/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.8
3
+ Version: 1.0.10
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
@@ -4,6 +4,7 @@
4
4
  # pylint: disable=too-many-positional-arguments
5
5
  # pylint: disable=too-many-locals
6
6
  # pylint: disable=too-many-branches
7
+ # pylint: disable=too-many-statements
7
8
  # pylint: disable=redefined-builtin
8
9
 
9
10
  import asyncio
@@ -82,6 +83,21 @@ class Option(OptionNode):
82
83
  **kwargs (Any):
83
84
  Additional Click option parameters.
84
85
  """
86
+ if is_short_flag(name):
87
+ long_flag = next(
88
+ (flag for flag in flags if is_long_flag(flag)), None
89
+ )
90
+ if long_flag is None:
91
+ raise ValueError(
92
+ f"Short flag '{name}' provided without a long flag. "
93
+ "Provide a long flag to derive the option name, e.g. "
94
+ f"@option('{name}', '--flag'), or pass an explicit "
95
+ f"snake_case name like @option('flag', '{name}')."
96
+ )
97
+ if name not in flags:
98
+ flags = (name,) + flags
99
+ name = long_flag
100
+
85
101
  if name.startswith("--"):
86
102
  if is_long_flag(name):
87
103
  derived_name = name[2:]
@@ -664,7 +664,33 @@ class RootNode(Node):
664
664
  context,
665
665
  )
666
666
 
667
- for validation_node in root.tree.validations:
667
+ catch_nodes = [
668
+ v
669
+ for v in root.tree.validations
670
+ if v.__class__.__name__ == "Catch"
671
+ ]
672
+ other_nodes = [
673
+ v
674
+ for v in root.tree.validations
675
+ if v.__class__.__name__ != "Catch"
676
+ ]
677
+ root.tree.validations = catch_nodes + other_nodes
678
+
679
+ for i, validation_node in enumerate(root.tree.validations):
680
+ if validation_node.__class__.__name__ == "Catch":
681
+ if hasattr(
682
+ validation_node, "remaining_validations"
683
+ ):
684
+ validation_node.remaining_validations = (
685
+ root.tree.validations[i + 1 :]
686
+ )
687
+ validation_node.on_finalize(
688
+ custom_context,
689
+ *validation_node.process_args,
690
+ **validation_node.process_kwargs,
691
+ )
692
+ break
693
+
668
694
  validation_node.on_finalize(
669
695
  custom_context,
670
696
  *validation_node.process_args,
@@ -2,6 +2,10 @@
2
2
  Validation node to catch and handle exceptions from command/group functions.
3
3
  """
4
4
 
5
+ # pylint: disable=wrong-import-position
6
+ # pylint: disable=wrong-import-order
7
+ # pylint: disable=ungrouped-imports
8
+
5
9
  import asyncio
6
10
  import inspect
7
11
  from functools import wraps
@@ -23,11 +27,16 @@ _catch_handlers: WeakKeyDictionary[
23
27
 
24
28
  class Catch(ValidationNode):
25
29
  """
26
- Catch and handle exceptions from command/group functions.
30
+ Catch and handle exceptions from command/group functions and
31
+ validators.
32
+
33
+ Wraps both the validation phase and function execution in a
34
+ try-except block. When an exception is caught, an optional handler
35
+ is invoked. Without a handler, exceptions are silently suppressed.
27
36
 
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.
37
+ Catches exceptions from:
38
+ - Validation decorators (e.g., @exclusive, @requires)
39
+ - The command/group function itself
31
40
 
32
41
  Handler signatures supported:
33
42
  - `handler()` - No arguments, just execute code
@@ -36,15 +45,16 @@ class Catch(ValidationNode):
36
45
 
37
46
  Examples:
38
47
  ```py
39
- # Simple error logging
48
+ # Catch validation errors from @exclusive
40
49
  @command()
41
- @catch(ValueError, handler=lambda: print("Invalid value!"))
42
- def cmd():
43
- raise ValueError("Bad input")
50
+ @exclusive("--stock", "--query")
51
+ @catch(ValueError, handler=lambda e: print(f"Error: {e}"))
52
+ def search(stock, query):
53
+ pass
44
54
  ```
45
55
 
46
56
  ```py
47
- # Handle exception with details
57
+ # Catch errors from command function
48
58
  @command()
49
59
  @catch(ValueError, handler=lambda e: print(f"Error: {e}"))
50
60
  def cmd():
@@ -73,19 +83,52 @@ class Catch(ValidationNode):
73
83
  """Initialize Catch validation node with function to wrap."""
74
84
  super().__init__(name, process_args, process_kwargs, **kwargs)
75
85
  self.wrapped_func: Callable[..., Any] | None = None
86
+ self.remaining_validations: list[ValidationNode] = []
76
87
 
77
88
  def on_finalize(self, context: Context, *args: Any, **kwargs: Any) -> None:
78
89
  """
79
- Store exception handler configuration for later use.
90
+ Execute remaining validations wrapped in exception handling.
80
91
 
81
- The actual exception catching happens when the function is invoked,
82
- which is done by wrapping the function in the decorator.
92
+ This catches exceptions from all validators that run after @catch,
93
+ allowing it to catch validation errors like those from @exclusive.
83
94
 
84
95
  Args:
85
96
  context: The execution context
86
97
  *args: Contains exception types tuple at index 0
87
98
  **kwargs: Contains handler, reraise parameters
88
99
  """
100
+ exception_types: tuple[type[BaseException], ...] = args[0]
101
+ handler: Callable[..., Any] | None = kwargs.get("handler")
102
+ reraise: bool = kwargs.get("reraise", False)
103
+
104
+ for validation_node in self.remaining_validations:
105
+ try:
106
+ if asyncio.iscoroutinefunction(validation_node.on_finalize):
107
+ asyncio.run(
108
+ validation_node.on_finalize(
109
+ context,
110
+ *validation_node.process_args,
111
+ **validation_node.process_kwargs,
112
+ )
113
+ )
114
+ else:
115
+ validation_node.on_finalize(
116
+ context,
117
+ *validation_node.process_args,
118
+ **validation_node.process_kwargs,
119
+ )
120
+ except BaseException as exc:
121
+ if isinstance(exc, exception_types):
122
+ if handler is not None:
123
+ if asyncio.iscoroutinefunction(handler):
124
+ asyncio.run(_call_handler_async(handler, exc))
125
+ else:
126
+ _call_handler_sync(handler, exc)
127
+
128
+ if not reraise:
129
+ return
130
+
131
+ raise
89
132
 
90
133
 
91
134
  def catch(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: click_extended
3
- Version: 1.0.8
3
+ Version: 1.0.10
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "click_extended"
3
- version = "1.0.8"
3
+ version = "1.0.10"
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" },
File without changes