value-object-pattern 1.34.0__tar.gz → 1.38.0__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 (214) hide show
  1. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/PKG-INFO +2 -2
  2. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/pyproject.toml +7 -10
  3. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/__init__.py +1 -1
  4. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/decorators/value_object_process.py +6 -21
  5. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/decorators/value_object_validation.py +7 -19
  6. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/base_model.py +3 -3
  7. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/dict_value_object.py +8 -8
  8. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/list_value_object.py +11 -11
  9. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/enumeration_value_object.py +2 -2
  10. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/union_value_object.py +7 -5
  11. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/value_object.py +58 -26
  12. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/__init__.py +6 -6
  13. value_object_pattern-1.38.0/value_object_pattern/usables/dates/__init__.py +25 -0
  14. value_object_pattern-1.38.0/value_object_pattern/usables/dates/duration_value_object.py +245 -0
  15. value_object_pattern-1.38.0/value_object_pattern/usables/dates/negative_duration_value_object.py +53 -0
  16. value_object_pattern-1.38.0/value_object_pattern/usables/dates/negative_or_zero_duration_value_object.py +53 -0
  17. value_object_pattern-1.38.0/value_object_pattern/usables/dates/positive_duration_value_object.py +53 -0
  18. value_object_pattern-1.38.0/value_object_pattern/usables/dates/positive_or_zero_duration_value_object.py +53 -0
  19. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/__init__.py +7 -0
  20. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/string_time_value_object.py +71 -0
  21. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/time_value_object.py +52 -0
  22. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/__init__.py +2 -0
  23. value_object_pattern-1.38.0/value_object_pattern/usables/identifiers/ulid_value_object.py +72 -0
  24. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/dni_value_object.py +1 -1
  25. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nie_value_object.py +1 -1
  26. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nif_value_object.py +1 -1
  27. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nuss_value_object.py +2 -2
  28. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/provincial_system_vehicle_plate_value_object.py +1 -1
  29. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/vehicle_plate_value_object.py +1 -1
  30. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/__init__.py +8 -0
  31. value_object_pattern-1.38.0/value_object_pattern/usables/internet/http_method_value_object.py +251 -0
  32. value_object_pattern-1.38.0/value_object_pattern/usables/internet/http_status_code_value_object.py +1370 -0
  33. value_object_pattern-1.38.0/value_object_pattern/usables/internet/ip_network_value_object.py +135 -0
  34. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_address_value_object.py +2 -2
  35. value_object_pattern-1.38.0/value_object_pattern/usables/internet/media_type_value_object.py +515 -0
  36. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/tld_domains.txt +2 -1
  37. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/__init__.py +2 -0
  38. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_card_value_object.py +1 -1
  39. value_object_pattern-1.38.0/value_object_pattern/usables/money/currency_code_value_object.py +71 -0
  40. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/iban_value_object.py +64 -4
  41. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/utils/__init__.py +22 -0
  42. value_object_pattern-1.38.0/value_object_pattern/usables/money/utils/iso4217_alpha3_codes.txt +180 -0
  43. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/__init__.py +4 -0
  44. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/__init__.py +9 -0
  45. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/number_value_object.py +99 -0
  46. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/positive_number_value_object.py +53 -0
  47. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/positive_or_zero_number_value_object.py +53 -0
  48. value_object_pattern-1.34.0/value_object_pattern/usables/dates/__init__.py +0 -12
  49. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/.gitignore +0 -0
  50. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/LICENSE.md +0 -0
  51. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/README.md +0 -0
  52. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/decorators/__init__.py +0 -0
  53. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/decorators/classproperty.py +0 -0
  54. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/__init__.py +0 -0
  55. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/__init__.py +0 -0
  56. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/primitive_conversion.py +0 -0
  57. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/secret_value_object.py +0 -0
  58. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/models/type_matching.py +0 -0
  59. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/py.typed +0 -0
  60. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/__init__.py +0 -0
  61. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/date_value_object.py +0 -0
  62. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/string_date_value_object.py +0 -0
  63. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/__init__.py +0 -0
  64. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/datetime_value_object.py +0 -0
  65. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +0 -0
  66. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/__init__.py +0 -0
  67. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/string_timezone_value_object.py +0 -0
  68. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/timezone_value_object.py +0 -0
  69. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/__init__.py +0 -0
  70. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v1_value_object.py +0 -0
  71. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v3_value_object.py +0 -0
  72. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v4_value_object.py +0 -0
  73. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v5_value_object.py +0 -0
  74. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v6_value_object.py +0 -0
  75. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v7_value_object.py +0 -0
  76. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v8_value_object.py +0 -0
  77. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_value_object.py +0 -0
  78. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v1_value_object.py +0 -0
  79. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v3_value_object.py +0 -0
  80. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v4_value_object.py +0 -0
  81. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v5_value_object.py +0 -0
  82. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v6_value_object.py +0 -0
  83. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v7_value_object.py +0 -0
  84. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v8_value_object.py +0 -0
  85. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_value_object.py +0 -0
  86. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/__init__.py +0 -0
  87. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/country_tld_value_object.py +0 -0
  88. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/__init__.py +0 -0
  89. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/__init__.py +0 -0
  90. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/passport_value_object.py +0 -0
  91. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/phone_number_value_object.py +0 -0
  92. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/__init__.py +0 -0
  93. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/administrative_technician_vehicle_plate_value_object.py +0 -0
  94. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/air_force_vehicle_plate_value_object.py +0 -0
  95. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/army_vehicle_plate_value_object.py +0 -0
  96. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/canarias_police_vehicle_plate_value_object.py +0 -0
  97. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/catalan_police_vehicle_plate_value_object.py +0 -0
  98. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/civil_guard_vehicle_plate_value_object.py +0 -0
  99. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/consular_corps_vehicle_plate_value_object.py +0 -0
  100. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/diplomatic_corps_vehicle_plate_value_object.py +0 -0
  101. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/especial_plate_vehicle_plate_value_object.py +0 -0
  102. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/historical_vehicle_plate_value_object.py +0 -0
  103. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/international_organization_vehicle_plate_value_object.py +0 -0
  104. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_development_vehicle_plate_value_object.py +0 -0
  105. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_environment_vehicle_plate_value_object.py +0 -0
  106. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/national_police_vehicle_plate_value_object.py +0 -0
  107. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/navy_vehicle_plate_value_object.py +0 -0
  108. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_truck_vehicle_plate_value_object.py +0 -0
  109. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_vehicle_plate_value_object.py +0 -0
  110. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/state_motor_pool_vehicle_plate_value_object.py +0 -0
  111. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_not_registered_vehicle_plate_value_object.py +0 -0
  112. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_registered_vehicle_plate_value_object.py +0 -0
  113. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_private_individual_vehicle_plate_value_object.py +0 -0
  114. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/two_wheels_vehicle_plate_value_object.py +0 -0
  115. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/__init__.py +0 -0
  116. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/provincial_plate_codes.txt +0 -0
  117. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/__init__.py +0 -0
  118. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/provincial_codes.txt +0 -0
  119. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha2_code_value_object.py +0 -0
  120. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha3_code_value_object.py +0 -0
  121. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_numeric_code_value_object.py +0 -0
  122. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/phone_code_value_object.py +0 -0
  123. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/__init__.py +0 -0
  124. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_codes.txt +0 -0
  125. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_alpha3_mapping.txt +0 -0
  126. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_numeric_mapping.txt +0 -0
  127. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_phone_code_mapping.txt +0 -0
  128. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_tld_mapping.txt +0 -0
  129. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha3_codes.txt +0 -0
  130. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_numeric_codes.txt +0 -0
  131. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/vin_value_object.py +0 -0
  132. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/aws_cloud_region_value_object.py +0 -0
  133. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/domain_or_localhost_value_object.py +0 -0
  134. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/domain_value_object.py +0 -0
  135. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/email_address_value_object.py +0 -0
  136. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/host_value_object.py +0 -0
  137. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ip_address_value_object.py +0 -0
  138. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv4_address_value_object.py +0 -0
  139. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv4_network_value_object.py +0 -0
  140. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv6_address_value_object.py +0 -0
  141. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv6_network_value_object.py +0 -0
  142. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/__init__.py +0 -0
  143. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/kebab_case_key_value_object.py +0 -0
  144. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/snake_case_key_value_object.py +0 -0
  145. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/__init__.py +0 -0
  146. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/cisco_mac_address_value_object.py +0 -0
  147. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/raw_mac_address_value_object.py +0 -0
  148. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/space_mac_address_value_object.py +0 -0
  149. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/universal_mac_address_value_object.py +0 -0
  150. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/windows_mac_address_value_object.py +0 -0
  151. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mobile/__init__.py +0 -0
  152. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mobile/imei_value_object.py +0 -0
  153. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/port_value_object.py +0 -0
  154. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/slug_value_object.py +0 -0
  155. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/__init__.py +0 -0
  156. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/http_https_url_value_object.py +0 -0
  157. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/http_url_value_object.py +0 -0
  158. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/https_url_value_object.py +0 -0
  159. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/url_value_object.py +0 -0
  160. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/user_agent_value_object.py +0 -0
  161. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/__init__.py +0 -0
  162. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/aws_regions.txt +0 -0
  163. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/__init__.py +0 -0
  164. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/amex_credit_card_value_object.py +0 -0
  165. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/discover_credit_card_value_object.py +0 -0
  166. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/mastercard_credit_card_value_object.py +0 -0
  167. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/visa_credit_card_value_object.py +0 -0
  168. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/utils/iban_lengths.txt +0 -0
  169. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/__init__.py +0 -0
  170. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/boolean_value_object.py +0 -0
  171. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/false_value_object.py +0 -0
  172. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/true_value_object.py +0 -0
  173. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/bytes/__init__.py +0 -0
  174. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/bytes/bytes_value_object.py +0 -0
  175. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/__init__.py +0 -0
  176. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/float_value_object.py +0 -0
  177. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/negative_float_value_object.py +0 -0
  178. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/negative_or_zero_float_value_object.py +0 -0
  179. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/positive_float_value_object.py +0 -0
  180. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/positive_or_zero_float_value_object.py +0 -0
  181. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/__init__.py +0 -0
  182. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/even_integer_value_object.py +0 -0
  183. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/integer_value_object.py +0 -0
  184. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +0 -0
  185. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/negative_or_zero_integer_value_object.py +0 -0
  186. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +0 -0
  187. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +0 -0
  188. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/positive_or_zero_integer_value_object.py +0 -0
  189. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/__init__.py +0 -0
  190. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/none_value_object.py +0 -0
  191. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/not_none_value_object.py +0 -0
  192. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/__init__.py +0 -0
  193. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/alpha_value_object.py +0 -0
  194. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +0 -0
  195. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base32_value_object.py +0 -0
  196. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base36_value_object.py +0 -0
  197. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base56_value_object.py +0 -0
  198. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base58_value_object.py +0 -0
  199. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base64_value_object.py +0 -0
  200. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/camel_case_string_value_object.py +0 -0
  201. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/digit_value_object.py +0 -0
  202. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/hexadecimal_value_object.py +0 -0
  203. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/kebab_case_string_value_object.py +0 -0
  204. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +0 -0
  205. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +0 -0
  206. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/pascal_case_string_value_object.py +0 -0
  207. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/printable_string_value_object.py +0 -0
  208. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/screaming_snake_case_string_value_object.py +0 -0
  209. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/snake_case_string_value_object.py +0 -0
  210. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/string_value_object.py +0 -0
  211. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +0 -0
  212. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +0 -0
  213. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/utils/__init__.py +0 -0
  214. {value_object_pattern-1.34.0 → value_object_pattern-1.38.0}/value_object_pattern/usables/utils/luhn_validation.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: value-object-pattern
3
- Version: 1.34.0
3
+ Version: 1.38.0
4
4
  Summary: The Value Object Pattern is a Python package that streamlines the creation and management of value objects in your projects.
5
5
  Project-URL: Homepage, https://github.com/adriamontoto/value-object-pattern
6
6
  Project-URL: Repository, https://github.com/adriamontoto/value-object-pattern
@@ -55,7 +55,7 @@ develop = ['pre-commit>=3.0.0']
55
55
  format = ['ruff>=0.11.10']
56
56
  lint = [
57
57
  'ruff>=0.11.10',
58
- 'mypy[reports]>=1.0.0',
58
+ 'ty>=0.0.72',
59
59
  { include-group = 'test' },
60
60
  { include-group = 'types' },
61
61
  ]
@@ -80,6 +80,7 @@ all = [
80
80
 
81
81
  [tool.pytest.ini_options]
82
82
  pythonpath = '.'
83
+ testpaths = ['tests']
83
84
  addopts = [
84
85
  '--strict-config', # fail if an unregistered option is used
85
86
  '--strict-markers', # fail if an unregistered marker is used
@@ -183,15 +184,11 @@ known-first-party = ['value_object_pattern']
183
184
  combine-as-imports = true
184
185
 
185
186
 
186
- [tool.mypy]
187
- strict = true
188
- warn_unreachable = true
189
- enable_error_code = [
190
- 'redundant-expr',
191
- 'possibly-undefined',
192
- 'truthy-bool',
193
- 'explicit-override',
194
- ]
187
+ [tool.ty.rules]
188
+ missing-override-decorator = 'error'
189
+ missing-type-argument = 'error'
190
+ possibly-unresolved-reference = 'warn'
191
+ unsound-return-statement = 'error'
195
192
 
196
193
 
197
194
  [tool.semantic_release]
@@ -1,4 +1,4 @@
1
- __version__ = '1.34.0'
1
+ __version__ = '1.38.0'
2
2
 
3
3
  from .decorators import process, validation
4
4
  from .models import BaseModel, EnumerationValueObject, SecretValueObject, UnionValueObject, ValueObject
@@ -2,8 +2,7 @@
2
2
  Decorator used to register value-object processing hooks.
3
3
  """
4
4
 
5
- from functools import wraps
6
- from typing import Any, Callable, TypeVar
5
+ from typing import Callable, TypeVar
7
6
 
8
7
  T = TypeVar('T')
9
8
 
@@ -23,7 +22,7 @@ def process(order: int | None = None) -> Callable[[Callable[..., T]], Callable[.
23
22
  ValueError: If the order is not equal or greater than 0.
24
23
 
25
24
  Returns:
26
- Callable[[Callable[..., T]], Callable[..., T]]: Wrapper function for the process.
25
+ Callable[[Callable[..., T]], Callable[..., T]]: Decorator that marks the process function.
27
26
 
28
27
  Example:
29
28
  ```python
@@ -54,7 +53,7 @@ def process(order: int | None = None) -> Callable[[Callable[..., T]], Callable[.
54
53
  ValueError: If the order is not equal or greater than 0.
55
54
 
56
55
  Returns:
57
- Callable[..., T]: Wrapper function for the process.
56
+ Callable[..., T]: The marked process function.
58
57
  """
59
58
  if order is not None:
60
59
  if type(order) is not int:
@@ -63,23 +62,9 @@ def process(order: int | None = None) -> Callable[[Callable[..., T]], Callable[.
63
62
  if order < 0:
64
63
  raise ValueError(f'Process order <<<{order}>>> must be equal or greater than 0.')
65
64
 
66
- function._is_process = True # type: ignore[attr-defined]
67
- function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
65
+ function._is_process = True # type: ignore[ty:unresolved-attribute]
66
+ function._order = function.__name__ if order is None else str(order) # type: ignore[ty:unresolved-attribute]
68
67
 
69
- @wraps(function)
70
- def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> T:
71
- """
72
- Execute the wrapped processing method.
73
-
74
- Args:
75
- *args (tuple[Any, ...]): The arguments for the function.
76
- **kwargs (dict[str, Any]): The keyword arguments for the function.
77
-
78
- Returns:
79
- T: The return value of the function.
80
- """
81
- return function(*args, **kwargs)
82
-
83
- return wrapper
68
+ return function
84
69
 
85
70
  return decorator
@@ -2,8 +2,7 @@
2
2
  Decorator used to register value-object validation hooks.
3
3
  """
4
4
 
5
- from functools import wraps
6
- from typing import Any, Callable
5
+ from typing import Callable
7
6
 
8
7
 
9
8
  def validation(
@@ -27,7 +26,7 @@ def validation(
27
26
  TypeError: If early_process is not a boolean.
28
27
 
29
28
  Returns:
30
- Callable[[Callable[..., None]], Callable[..., None]]: Wrapper function for the validation.
29
+ Callable[[Callable[..., None]], Callable[..., None]]: Decorator that marks the validation function.
31
30
 
32
31
  Example:
33
32
  ```python
@@ -59,7 +58,7 @@ def validation(
59
58
  TypeError: If early_process is not a boolean.
60
59
 
61
60
  Returns:
62
- Callable[..., None]: Wrapper function for the validation.
61
+ Callable[..., None]: The marked validation function.
63
62
  """
64
63
  if order is not None:
65
64
  if type(order) is not int:
@@ -71,21 +70,10 @@ def validation(
71
70
  if type(early_process) is not bool:
72
71
  raise TypeError(f'Validation early_process <<<{early_process}>>> must be a boolean. Got <<<{type(early_process).__name__}>>> type.') # noqa: E501 # fmt: skip
73
72
 
74
- function._is_validation = True # type: ignore[attr-defined]
75
- function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
76
- function._early_process = early_process # type: ignore[attr-defined]
73
+ function._is_validation = True # type: ignore[ty:unresolved-attribute]
74
+ function._order = function.__name__ if order is None else str(order) # type: ignore[ty:unresolved-attribute]
75
+ function._early_process = early_process # type: ignore[ty:unresolved-attribute]
77
76
 
78
- @wraps(function)
79
- def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> None:
80
- """
81
- Execute the wrapped validation method.
82
-
83
- Args:
84
- *args (tuple[Any, ...]): The arguments for the function.
85
- **kwargs (dict[str, Any]): The keyword arguments for the function.
86
- """
87
- function(*args, **kwargs)
88
-
89
- return wrapper
77
+ return function
90
78
 
91
79
  return decorator
@@ -306,7 +306,7 @@ class BaseModel(ABC):
306
306
  ```
307
307
  """
308
308
  if id(self) in memo:
309
- return memo[id(self)] # type: ignore[no-any-return]
309
+ return memo[id(self)] # type: ignore[ty:unsound-return-statement]
310
310
 
311
311
  cls = self.__class__
312
312
  clone = cls.__new__(cls)
@@ -385,7 +385,7 @@ class BaseModel(ABC):
385
385
  # >>> {'name': 'John Doe', 'birthdate': '1900-01-01T00:00:00+00:00'}
386
386
  ```
387
387
  """ # noqa: E501
388
- if not isinstance(primitives, dict) or not all(isinstance(key, str) for key in primitives): # type: ignore[redundant-expr]
388
+ if not isinstance(primitives, dict) or not all(isinstance(key, str) for key in primitives):
389
389
  cls._raise_value_is_not_dict_of_strings(value=primitives)
390
390
 
391
391
  constructor_signature = signature(obj=cls.__init__)
@@ -470,7 +470,7 @@ class BaseModel(ABC):
470
470
  return 'Any'
471
471
 
472
472
  if hasattr(type, '__name__'):
473
- return type.__name__ # type: ignore[no-any-return]
473
+ return type.__name__ # type: ignore[ty:unsound-return-statement]
474
474
 
475
475
  return str(type).replace('typing.', '')
476
476
 
@@ -182,7 +182,7 @@ class _DictValueObjectAlias:
182
182
  return ' | '.join(_DictValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
183
183
 
184
184
  if hasattr(type, '__name__'):
185
- return type.__name__ # type: ignore[no-any-return]
185
+ return type.__name__ # type: ignore[ty:unsound-return-statement]
186
186
 
187
187
  return str(type).replace('typing.', '')
188
188
 
@@ -357,12 +357,12 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
357
357
  """
358
358
  return len(self._value)
359
359
 
360
- def __getitem__(self, key: K) -> V:
360
+ def __getitem__(self, key: Any) -> V:
361
361
  """
362
- Returns the value for the specified key.
362
+ Returns the value for the specified key, converting primitive keys when needed.
363
363
 
364
364
  Args:
365
- key (K): The key to get the value for.
365
+ key (Any): The key or primitive key to get the value for.
366
366
 
367
367
  Raises:
368
368
  KeyError: If the key is not found.
@@ -544,12 +544,12 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
544
544
  """
545
545
  raise TypeError(f'DictValueObject value <<<{value}>>> must be of type <<<{self._type_label(type=self._value_type)}>>> type. Got <<<{type(value).__name__}>>> type.') # noqa: E501 # fmt: skip
546
546
 
547
- def get(self, *, key: K, default: V | None = None) -> V | None:
547
+ def get(self, *, key: Any, default: V | None = None) -> V | None:
548
548
  """
549
- Returns the value for the specified key if key is in dictionary, else default.
549
+ Returns the value for the specified key or primitive key if it is in the dictionary, else default.
550
550
 
551
551
  Args:
552
- key (K): The key to get the value for.
552
+ key (Any): The key or primitive key to get the value for.
553
553
  default (V | None, optional): The default value to return if the key is not found. Defaults to None.
554
554
 
555
555
  Returns:
@@ -630,7 +630,7 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
630
630
  return 'Any'
631
631
 
632
632
  if hasattr(type, '__name__'):
633
- return type.__name__ # type: ignore[no-any-return]
633
+ return type.__name__ # type: ignore[ty:unsound-return-statement]
634
634
 
635
635
  return str(type).replace('typing.', '')
636
636
 
@@ -141,7 +141,7 @@ class _ListValueObjectAlias:
141
141
  return ' | '.join(_ListValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
142
142
 
143
143
  if hasattr(type, '__name__'):
144
- return type.__name__ # type: ignore[no-any-return]
144
+ return type.__name__ # type: ignore[ty:unsound-return-statement]
145
145
 
146
146
  return str(type).replace('typing.', '')
147
147
 
@@ -505,12 +505,12 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
505
505
  """
506
506
  return not self._value
507
507
 
508
- def add(self, *, item: T) -> Self:
508
+ def add(self, *, item: Any) -> Self:
509
509
  """
510
- Returns a new ListValueObject with the item added to the end.
510
+ Returns a new ListValueObject with a typed or primitive item added to the end.
511
511
 
512
512
  Args:
513
- item (T): The item to add.
513
+ item (Any): The typed or primitive item to convert and add.
514
514
 
515
515
  Raises:
516
516
  TypeError: If the item is not of type T.
@@ -576,12 +576,12 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
576
576
 
577
577
  return self.add(item=item)
578
578
 
579
- def extend(self, *, items: list[T]) -> Self:
579
+ def extend(self, *, items: list[Any]) -> Self:
580
580
  """
581
- Returns a new ListValueObject with multiple items added to the end.
581
+ Returns a new ListValueObject with typed or primitive items added to the end.
582
582
 
583
583
  Args:
584
- items (list[T]): The items to add.
584
+ items (list[Any]): The typed or primitive items to convert and add.
585
585
 
586
586
  Raises:
587
587
  TypeError: If the items are not of the correct type.
@@ -647,12 +647,12 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
647
647
 
648
648
  return self.extend(items=items)
649
649
 
650
- def delete(self, *, item: T) -> Self:
650
+ def delete(self, *, item: Any) -> Self:
651
651
  """
652
- Returns a new ListValueObject with the first occurrence of the item deleted.
652
+ Returns a new ListValueObject with the first occurrence of a typed or primitive item deleted.
653
653
 
654
654
  Args:
655
- item (T): The item to delete.
655
+ item (Any): The typed or primitive item to convert and delete.
656
656
 
657
657
  Raises:
658
658
  ValueError: If the item is not in the list.
@@ -844,7 +844,7 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
844
844
  return 'Any'
845
845
 
846
846
  if hasattr(type, '__name__'):
847
- return type.__name__ # type: ignore[no-any-return]
847
+ return type.__name__ # type: ignore[ty:unsound-return-statement]
848
848
 
849
849
  return str(type).replace('typing.', '')
850
850
 
@@ -77,7 +77,7 @@ class EnumerationValueObject(ValueObject[Any | E], Generic[E]): # noqa: UP046
77
77
  if not (isclass(object=enumeration) and issubclass(enumeration, Enum)):
78
78
  raise TypeError(f'EnumerationValueObject[...] <<<{enumeration}>>> must be an Enum subclass. Got <<<{type(enumeration).__name__}>>> type.') # noqa: E501 # fmt: skip
79
79
 
80
- cls._enumeration = enumeration # type: ignore[assignment]
80
+ cls._enumeration = enumeration
81
81
  return
82
82
 
83
83
  raise TypeError('EnumerationValueObject must be parameterized, e.g. "class ColorValueObject(EnumerationValueObject[ColorEnumeration])".') # noqa: E501 # fmt: skip
@@ -168,4 +168,4 @@ class EnumerationValueObject(ValueObject[Any | E], Generic[E]): # noqa: UP046
168
168
  # >>> ColorEnumeration.RED
169
169
  ```
170
170
  """
171
- return self._value
171
+ return self._value # type: ignore[ty:unsound-return-statement]
@@ -141,8 +141,9 @@ class _UnionValueObjectAlias:
141
141
  if origin in (Union, UnionType):
142
142
  return ' | '.join(_UnionValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
143
143
 
144
- if hasattr(type, '__name__'):
145
- return type.__name__ # type: ignore[no-any-return]
144
+ type_name = getattr(type, '__name__', None)
145
+ if isinstance(type_name, str):
146
+ return type_name
146
147
 
147
148
  return str(type).replace('typing.', '')
148
149
 
@@ -259,7 +260,7 @@ class UnionValueObject(ValueObject[T], Generic[T]): # noqa: UP046
259
260
 
260
261
  for allowed_type in allowed_types:
261
262
  try:
262
- return self._coerce_value_to_type(value=value, expected_type=allowed_type) # type: ignore[no-any-return]
263
+ return self._coerce_value_to_type(value=value, expected_type=allowed_type)
263
264
 
264
265
  except Exception as error:
265
266
  last_error = error
@@ -407,8 +408,9 @@ class UnionValueObject(ValueObject[T], Generic[T]): # noqa: UP046
407
408
  if type is Any:
408
409
  return 'Any'
409
410
 
410
- if hasattr(type, '__name__'):
411
- return type.__name__ # type: ignore[no-any-return]
411
+ type_name = getattr(type, '__name__', None)
412
+ if isinstance(type_name, str):
413
+ return type_name
412
414
 
413
415
  return str(type).replace('typing.', '')
414
416
 
@@ -12,9 +12,9 @@ else:
12
12
  from typing_extensions import override # pragma: no cover
13
13
 
14
14
  from abc import ABC
15
- from collections import deque
15
+ from builtins import type as builtins_type
16
16
  from copy import deepcopy
17
- from typing import Any, Callable, Generic, TypeVar, get_args
17
+ from typing import Any, Callable, ClassVar, Generic, TypeVar, cast, get_args
18
18
 
19
19
  T = TypeVar('T')
20
20
 
@@ -26,7 +26,8 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
26
26
  Subclasses declare their wrapped type with `ValueObject[T]`. Validation methods decorated with `@validation` run
27
27
  before the value is stored, and processing methods decorated with `@process` can normalize the value after
28
28
  validation. Instances compare by concrete class and wrapped value, expose the raw value through `.value`, and reject
29
- attribute mutation after construction.
29
+ attribute mutation after construction. Decorated hooks are cached per concrete class; subclasses that modify hooks
30
+ at runtime can set `_cache_decorated_methods = False` to rediscover them for each construction.
30
31
 
31
32
  ***This class is abstract and should not be instantiated directly***.
32
33
 
@@ -52,6 +53,9 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
52
53
  _title: str
53
54
  _parameter: str
54
55
  _early_processed: T | None
56
+ _cache_decorated_methods: ClassVar[bool] = True
57
+ _cached_process_methods: ClassVar[tuple[Callable[..., Any], ...] | None] = None
58
+ _cached_validation_methods: ClassVar[tuple[Callable[..., Any], ...] | None] = None
55
59
 
56
60
  def __init__(self, *, value: T, title: str | None = None, parameter: str | None = None) -> None:
57
61
  """
@@ -318,7 +322,7 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
318
322
  ```
319
323
  """
320
324
  if id(self) in memo:
321
- return memo[id(self)] # type: ignore[no-any-return]
325
+ return memo[id(self)] # type: ignore[ty:unsound-return-statement]
322
326
 
323
327
  clone = self.__class__(
324
328
  value=deepcopy(self._value, memo),
@@ -342,9 +346,9 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
342
346
  Returns:
343
347
  T: Processed value.
344
348
  """
345
- methods = self._gather_decorated_methods(instance=self, attribute_name='_is_process')
346
- while methods:
347
- method: Callable[..., T] = methods.popleft().__get__(self, self.__class__)
349
+ methods = self._get_cached_decorated_methods(attribute_name='_is_process')
350
+ for decorated_method in methods:
351
+ method: Callable[..., T] = decorated_method.__get__(self, self.__class__) # type: ignore[ty:unresolved-attribute]
348
352
  value = method(value=value)
349
353
 
350
354
  return value
@@ -360,9 +364,9 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
360
364
  value (T): Value to validate.
361
365
  """
362
366
  try:
363
- methods = self._gather_decorated_methods(instance=self, attribute_name='_is_validation')
364
- while methods:
365
- method: Callable[..., T] = methods.popleft().__get__(self, self.__class__)
367
+ methods = self._get_cached_decorated_methods(attribute_name='_is_validation')
368
+ for decorated_method in methods:
369
+ method: Callable[..., T] = decorated_method.__get__(self, self.__class__) # type: ignore[ty:unresolved-attribute]
366
370
  if getattr(method, '_early_process', False):
367
371
  method(value=value, processed_value=self.early_process(value=value))
368
372
  continue
@@ -409,18 +413,23 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
409
413
  """
410
414
  return callable(getattr(self, '_secret_value_for_display', None))
411
415
 
412
- def _post_order_dfs_mro(self, cls: type, visited: set[type] | None = None, cut_off: type = object) -> list[type]:
416
+ def _post_order_dfs_mro(
417
+ self,
418
+ cls: builtins_type,
419
+ visited: set[builtins_type] | None = None,
420
+ cut_off: builtins_type = object,
421
+ ) -> list[builtins_type]:
413
422
  """
414
423
  Computes the Post-Order Depth-First Search (DFS) Method Resolution Order (MRO) of a class.
415
424
 
416
425
  Args:
417
- cls (type): The class to process.
418
- visited (set[type] | None, optional): A set of already visited classes (to prevent duplicates). Defaults
419
- to None.
420
- cut_off (type, optional): The class to stop the search. Defaults to object.
426
+ cls (builtins_type): The class to process.
427
+ visited (set[builtins_type] | None, optional): A set of already visited classes (to prevent duplicates).
428
+ Defaults to None.
429
+ cut_off (builtins_type, optional): The class to stop the search. Defaults to object.
421
430
 
422
431
  Returns:
423
- list[type]: A list of classes type sorted by post-order DFS MRO.
432
+ list[builtins_type]: A list of classes type sorted by post-order DFS MRO.
424
433
 
425
434
  References:
426
435
  DFS: https://en.wikipedia.org/wiki/Depth-first_search
@@ -443,17 +452,40 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
443
452
 
444
453
  return result
445
454
 
446
- def _gather_decorated_methods(self, instance: object, attribute_name: str) -> deque[Callable[..., Any]]:
455
+ def _get_cached_decorated_methods(self, attribute_name: str) -> tuple[Callable[..., Any], ...]:
456
+ """
457
+ Return decorated methods for the concrete value-object class, caching them when enabled.
458
+
459
+ Args:
460
+ attribute_name: Marker attribute used to identify decorated methods.
461
+
462
+ Returns:
463
+ tuple[Callable[..., Any], ...]: Ordered decorated methods.
464
+ """
465
+ if not self.__class__._cache_decorated_methods:
466
+ return self._gather_decorated_methods(instance=self, attribute_name=attribute_name)
467
+
468
+ cache_attribute_name = f'_cached_{attribute_name.removeprefix("_is_")}_methods'
469
+ cached_methods = cast(tuple[Callable[..., Any], ...] | None, self.__class__.__dict__.get(cache_attribute_name))
470
+ if cached_methods is not None:
471
+ return cached_methods
472
+
473
+ methods = self._gather_decorated_methods(instance=self, attribute_name=attribute_name)
474
+ setattr(self.__class__, cache_attribute_name, methods)
475
+
476
+ return methods
477
+
478
+ def _gather_decorated_methods(self, instance: object, attribute_name: str) -> tuple[Callable[..., Any], ...]:
447
479
  """
448
480
  Gathers decorated methods from instance.__class__ and its parent classes following the post-order DFS MRO,
449
- returning them in a deque with the methods sorted by class hierarchy, method order, and method name.
481
+ returning them in a tuple sorted by class hierarchy, method order, and method name.
450
482
 
451
483
  Args:
452
484
  instance (object): The object instance whose class hierarchy is inspected.
453
485
  attribute_name (str): The attribute name used to identify the methods.
454
486
 
455
487
  Returns
456
- deque[Callable[..., Any]]: A deque of methods sorted by class hierarchy, method order, and method name.
488
+ tuple[Callable[..., Any], ...]: Methods sorted by class hierarchy, method order, and method name.
457
489
 
458
490
  References:
459
491
  DFS: https://en.wikipedia.org/wiki/Depth-first_search
@@ -475,12 +507,12 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
475
507
  class_index = classes_names.get(class_name, 999)
476
508
  order = getattr(method, '_order', method_name)
477
509
 
478
- return int(class_index), order, method_name
510
+ return int(class_index), order, method_name # type: ignore[ty:unsound-return-statement]
479
511
 
480
512
  classes = self._post_order_dfs_mro(cls=instance.__class__, cut_off=ValueObject)
481
513
  classes_names = {cls.__name__: index for index, cls in enumerate(iterable=classes)}
482
514
 
483
- classes_methods: deque[tuple[str, str, Callable[..., Any]]] = deque()
515
+ classes_methods: list[tuple[str, str, Callable[..., Any]]] = []
484
516
  for cls in classes:
485
517
  for method_name, method in cls.__dict__.items():
486
518
  if not callable(method):
@@ -492,7 +524,7 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
492
524
  classes_methods.append((method.__qualname__.split('.')[0], method_name, method))
493
525
 
494
526
  # sort by class hierarchy, method order attribute, and method name
495
- return deque([method for _, _, method in sorted(classes_methods, key=sort_key)])
527
+ return tuple(method for _, _, method in sorted(classes_methods, key=sort_key))
496
528
 
497
529
  def early_process(self, value: T) -> T:
498
530
  """
@@ -588,20 +620,20 @@ class ValueObject(ABC, Generic[T]): # noqa: UP046
588
620
  return self._parameter
589
621
 
590
622
  @classmethod
591
- def type(cls) -> type[T]:
623
+ def type(cls) -> builtins_type[T]:
592
624
  """
593
625
  Return the wrapped type declared by the `ValueObject[T]` subclass.
594
626
 
595
627
  Returns:
596
628
  type[T]: Declared wrapped type, or `Any` when it cannot be resolved.
597
629
  """
598
- for base in cls.__orig_bases__: # type: ignore[attr-defined]
630
+ for base in cls.__orig_bases__: # type: ignore[ty:unresolved-attribute]
599
631
  if hasattr(base, '__origin__') and base.__origin__ is Generic:
600
632
  continue
601
633
 
602
634
  if hasattr(base, '__origin__') and issubclass(base.__origin__, ValueObject):
603
635
  args = get_args(base)
604
636
  if args:
605
- return args[0] # type: ignore[no-any-return]
637
+ return args[0] # type: ignore[ty:unsound-return-statement]
606
638
 
607
- return Any # type: ignore[return-value]
639
+ return Any # type: ignore[ty:invalid-return-type]
@@ -25,12 +25,15 @@ from .primitives import (
25
25
  NoneValueObject,
26
26
  NotEmptyStringValueObject,
27
27
  NotNoneValueObject,
28
+ NumberValueObject,
28
29
  OddIntegerValueObject,
29
30
  PascalCaseStringValueObject,
30
31
  PositiveFloatValueObject,
31
32
  PositiveIntegerValueObject,
33
+ PositiveNumberValueObject,
32
34
  PositiveOrZeroFloatValueObject,
33
35
  PositiveOrZeroIntegerValueObject,
36
+ PositiveOrZeroNumberValueObject,
34
37
  PrintableStringValueObject,
35
38
  ScreamingSnakeCaseStringValueObject,
36
39
  SnakeCaseStringValueObject,
@@ -60,30 +63,27 @@ __all__ = (
60
63
  'IntegerValueObject',
61
64
  'KebabCaseStringValueObject',
62
65
  'LowercaseStringValueObject',
63
- 'LowercaseStringValueObject',
64
66
  'NegativeFloatValueObject',
65
67
  'NegativeIntegerValueObject',
66
68
  'NegativeOrZeroFloatValueObject',
67
69
  'NegativeOrZeroIntegerValueObject',
68
70
  'NoneValueObject',
69
71
  'NotEmptyStringValueObject',
70
- 'NotEmptyStringValueObject',
71
72
  'NotNoneValueObject',
73
+ 'NumberValueObject',
72
74
  'OddIntegerValueObject',
73
75
  'PascalCaseStringValueObject',
74
76
  'PositiveFloatValueObject',
75
77
  'PositiveIntegerValueObject',
78
+ 'PositiveNumberValueObject',
76
79
  'PositiveOrZeroFloatValueObject',
77
80
  'PositiveOrZeroIntegerValueObject',
78
- 'PrintableStringValueObject',
81
+ 'PositiveOrZeroNumberValueObject',
79
82
  'PrintableStringValueObject',
80
83
  'ScreamingSnakeCaseStringValueObject',
81
84
  'SnakeCaseStringValueObject',
82
85
  'StringValueObject',
83
- 'StringValueObject',
84
- 'TrimmedStringValueObject',
85
86
  'TrimmedStringValueObject',
86
87
  'TrueValueObject',
87
88
  'UppercaseStringValueObject',
88
- 'UppercaseStringValueObject',
89
89
  )
@@ -0,0 +1,25 @@
1
+ from .date import DateValueObject, StringDateValueObject
2
+ from .datetime import DatetimeValueObject, StringDatetimeValueObject
3
+ from .duration_value_object import DurationValueObject
4
+ from .negative_duration_value_object import NegativeDurationValueObject
5
+ from .negative_or_zero_duration_value_object import NegativeOrZeroDurationValueObject
6
+ from .positive_duration_value_object import PositiveDurationValueObject
7
+ from .positive_or_zero_duration_value_object import PositiveOrZeroDurationValueObject
8
+ from .time import StringTimeValueObject, TimeValueObject
9
+ from .timezone import StringTimezoneValueObject, TimezoneValueObject
10
+
11
+ __all__ = (
12
+ 'DateValueObject',
13
+ 'DatetimeValueObject',
14
+ 'DurationValueObject',
15
+ 'NegativeDurationValueObject',
16
+ 'NegativeOrZeroDurationValueObject',
17
+ 'PositiveDurationValueObject',
18
+ 'PositiveOrZeroDurationValueObject',
19
+ 'StringDateValueObject',
20
+ 'StringDatetimeValueObject',
21
+ 'StringTimeValueObject',
22
+ 'StringTimezoneValueObject',
23
+ 'TimeValueObject',
24
+ 'TimezoneValueObject',
25
+ )