value-object-pattern 1.33.1__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 (215) hide show
  1. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/PKG-INFO +31 -3
  2. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/README.md +29 -1
  3. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/pyproject.toml +8 -11
  4. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/__init__.py +3 -2
  5. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/decorators/value_object_process.py +6 -21
  6. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/decorators/value_object_validation.py +7 -19
  7. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/__init__.py +2 -0
  8. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/base_model.py +6 -6
  9. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/dict_value_object.py +8 -8
  10. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/list_value_object.py +22 -22
  11. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/enumeration_value_object.py +2 -2
  12. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/primitive_conversion.py +78 -2
  13. value_object_pattern-1.38.0/value_object_pattern/models/secret_value_object.py +44 -0
  14. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/union_value_object.py +7 -5
  15. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/value_object.py +84 -30
  16. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/__init__.py +18 -8
  17. value_object_pattern-1.38.0/value_object_pattern/usables/dates/__init__.py +25 -0
  18. value_object_pattern-1.38.0/value_object_pattern/usables/dates/duration_value_object.py +245 -0
  19. value_object_pattern-1.38.0/value_object_pattern/usables/dates/negative_duration_value_object.py +53 -0
  20. value_object_pattern-1.38.0/value_object_pattern/usables/dates/negative_or_zero_duration_value_object.py +53 -0
  21. value_object_pattern-1.38.0/value_object_pattern/usables/dates/positive_duration_value_object.py +53 -0
  22. value_object_pattern-1.38.0/value_object_pattern/usables/dates/positive_or_zero_duration_value_object.py +53 -0
  23. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/__init__.py +7 -0
  24. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/string_time_value_object.py +71 -0
  25. value_object_pattern-1.38.0/value_object_pattern/usables/dates/time/time_value_object.py +52 -0
  26. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/__init__.py +2 -0
  27. value_object_pattern-1.38.0/value_object_pattern/usables/identifiers/ulid_value_object.py +72 -0
  28. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/dni_value_object.py +1 -1
  29. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nie_value_object.py +1 -1
  30. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nif_value_object.py +1 -1
  31. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/nuss_value_object.py +2 -2
  32. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/provincial_system_vehicle_plate_value_object.py +1 -1
  33. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/vehicle_plate_value_object.py +1 -1
  34. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/__init__.py +8 -0
  35. value_object_pattern-1.38.0/value_object_pattern/usables/internet/http_method_value_object.py +251 -0
  36. value_object_pattern-1.38.0/value_object_pattern/usables/internet/http_status_code_value_object.py +1370 -0
  37. value_object_pattern-1.38.0/value_object_pattern/usables/internet/ip_network_value_object.py +135 -0
  38. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_address_value_object.py +2 -2
  39. value_object_pattern-1.38.0/value_object_pattern/usables/internet/media_type_value_object.py +515 -0
  40. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/tld_domains.txt +2 -1
  41. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/__init__.py +2 -0
  42. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_card_value_object.py +1 -1
  43. value_object_pattern-1.38.0/value_object_pattern/usables/money/currency_code_value_object.py +71 -0
  44. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/iban_value_object.py +64 -4
  45. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/utils/__init__.py +22 -0
  46. value_object_pattern-1.38.0/value_object_pattern/usables/money/utils/iso4217_alpha3_codes.txt +180 -0
  47. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/__init__.py +16 -2
  48. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/__init__.py +9 -0
  49. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/number_value_object.py +99 -0
  50. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/positive_number_value_object.py +53 -0
  51. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/number/positive_or_zero_number_value_object.py +53 -0
  52. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/__init__.py +11 -2
  53. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/string/base32_value_object.py +60 -0
  54. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/string/base36_value_object.py +53 -0
  55. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/string/base56_value_object.py +53 -0
  56. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/string/base58_value_object.py +53 -0
  57. value_object_pattern-1.38.0/value_object_pattern/usables/primitives/string/hexadecimal_value_object.py +60 -0
  58. value_object_pattern-1.33.1/value_object_pattern/usables/dates/__init__.py +0 -12
  59. value_object_pattern-1.33.1/value_object_pattern/usables/primitives/string/secret_string_value_object.py +0 -43
  60. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/.gitignore +0 -0
  61. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/LICENSE.md +0 -0
  62. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/decorators/__init__.py +0 -0
  63. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/decorators/classproperty.py +0 -0
  64. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/collections/__init__.py +0 -0
  65. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/models/type_matching.py +0 -0
  66. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/py.typed +0 -0
  67. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/__init__.py +0 -0
  68. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/date_value_object.py +0 -0
  69. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/date/string_date_value_object.py +0 -0
  70. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/__init__.py +0 -0
  71. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/datetime_value_object.py +0 -0
  72. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +0 -0
  73. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/__init__.py +0 -0
  74. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/string_timezone_value_object.py +0 -0
  75. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/dates/timezone/timezone_value_object.py +0 -0
  76. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/__init__.py +0 -0
  77. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v1_value_object.py +0 -0
  78. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v3_value_object.py +0 -0
  79. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v4_value_object.py +0 -0
  80. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v5_value_object.py +0 -0
  81. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v6_value_object.py +0 -0
  82. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v7_value_object.py +0 -0
  83. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v8_value_object.py +0 -0
  84. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_value_object.py +0 -0
  85. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v1_value_object.py +0 -0
  86. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v3_value_object.py +0 -0
  87. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v4_value_object.py +0 -0
  88. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v5_value_object.py +0 -0
  89. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v6_value_object.py +0 -0
  90. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v7_value_object.py +0 -0
  91. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_v8_value_object.py +0 -0
  92. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/uuid/uuid_value_object.py +0 -0
  93. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/__init__.py +0 -0
  94. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/country_tld_value_object.py +0 -0
  95. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/__init__.py +0 -0
  96. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/__init__.py +0 -0
  97. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/passport_value_object.py +0 -0
  98. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/phone_number_value_object.py +0 -0
  99. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/__init__.py +0 -0
  100. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/administrative_technician_vehicle_plate_value_object.py +0 -0
  101. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/air_force_vehicle_plate_value_object.py +0 -0
  102. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/army_vehicle_plate_value_object.py +0 -0
  103. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/canarias_police_vehicle_plate_value_object.py +0 -0
  104. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/catalan_police_vehicle_plate_value_object.py +0 -0
  105. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/civil_guard_vehicle_plate_value_object.py +0 -0
  106. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/consular_corps_vehicle_plate_value_object.py +0 -0
  107. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/diplomatic_corps_vehicle_plate_value_object.py +0 -0
  108. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/especial_plate_vehicle_plate_value_object.py +0 -0
  109. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/historical_vehicle_plate_value_object.py +0 -0
  110. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/international_organization_vehicle_plate_value_object.py +0 -0
  111. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_development_vehicle_plate_value_object.py +0 -0
  112. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_environment_vehicle_plate_value_object.py +0 -0
  113. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/national_police_vehicle_plate_value_object.py +0 -0
  114. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/navy_vehicle_plate_value_object.py +0 -0
  115. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_truck_vehicle_plate_value_object.py +0 -0
  116. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_vehicle_plate_value_object.py +0 -0
  117. {value_object_pattern-1.33.1 → 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
  118. {value_object_pattern-1.33.1 → 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
  119. {value_object_pattern-1.33.1 → 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
  120. {value_object_pattern-1.33.1 → 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
  121. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/two_wheels_vehicle_plate_value_object.py +0 -0
  122. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/__init__.py +0 -0
  123. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/provincial_plate_codes.txt +0 -0
  124. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/__init__.py +0 -0
  125. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/provincial_codes.txt +0 -0
  126. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha2_code_value_object.py +0 -0
  127. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha3_code_value_object.py +0 -0
  128. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/iso3166_numeric_code_value_object.py +0 -0
  129. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/phone_code_value_object.py +0 -0
  130. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/__init__.py +0 -0
  131. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_codes.txt +0 -0
  132. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_alpha3_mapping.txt +0 -0
  133. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_numeric_mapping.txt +0 -0
  134. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_phone_code_mapping.txt +0 -0
  135. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_tld_mapping.txt +0 -0
  136. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha3_codes.txt +0 -0
  137. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_numeric_codes.txt +0 -0
  138. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/identifiers/world/vin_value_object.py +0 -0
  139. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/aws_cloud_region_value_object.py +0 -0
  140. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/domain_or_localhost_value_object.py +0 -0
  141. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/domain_value_object.py +0 -0
  142. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/email_address_value_object.py +0 -0
  143. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/host_value_object.py +0 -0
  144. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ip_address_value_object.py +0 -0
  145. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv4_address_value_object.py +0 -0
  146. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv4_network_value_object.py +0 -0
  147. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv6_address_value_object.py +0 -0
  148. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/ipv6_network_value_object.py +0 -0
  149. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/__init__.py +0 -0
  150. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/kebab_case_key_value_object.py +0 -0
  151. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/keys/snake_case_key_value_object.py +0 -0
  152. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/__init__.py +0 -0
  153. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/cisco_mac_address_value_object.py +0 -0
  154. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/raw_mac_address_value_object.py +0 -0
  155. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/space_mac_address_value_object.py +0 -0
  156. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/universal_mac_address_value_object.py +0 -0
  157. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mac_addresses/windows_mac_address_value_object.py +0 -0
  158. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mobile/__init__.py +0 -0
  159. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/mobile/imei_value_object.py +0 -0
  160. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/port_value_object.py +0 -0
  161. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/slug_value_object.py +0 -0
  162. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/__init__.py +0 -0
  163. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/http_https_url_value_object.py +0 -0
  164. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/http_url_value_object.py +0 -0
  165. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/https_url_value_object.py +0 -0
  166. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/uri/url_value_object.py +0 -0
  167. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/user_agent_value_object.py +0 -0
  168. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/__init__.py +0 -0
  169. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/internet/utils/aws_regions.txt +0 -0
  170. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/__init__.py +0 -0
  171. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/amex_credit_card_value_object.py +0 -0
  172. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/discover_credit_card_value_object.py +0 -0
  173. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/mastercard_credit_card_value_object.py +0 -0
  174. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/credit_cards/visa_credit_card_value_object.py +0 -0
  175. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/money/utils/iban_lengths.txt +0 -0
  176. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/__init__.py +0 -0
  177. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/boolean_value_object.py +0 -0
  178. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/false_value_object.py +0 -0
  179. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/boolean/true_value_object.py +0 -0
  180. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/bytes/__init__.py +0 -0
  181. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/bytes/bytes_value_object.py +0 -0
  182. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/__init__.py +0 -0
  183. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/float_value_object.py +0 -0
  184. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/negative_float_value_object.py +0 -0
  185. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/negative_or_zero_float_value_object.py +0 -0
  186. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/positive_float_value_object.py +0 -0
  187. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/float/positive_or_zero_float_value_object.py +0 -0
  188. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/__init__.py +0 -0
  189. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/even_integer_value_object.py +0 -0
  190. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/integer_value_object.py +0 -0
  191. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +0 -0
  192. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/negative_or_zero_integer_value_object.py +0 -0
  193. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +0 -0
  194. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +0 -0
  195. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/integer/positive_or_zero_integer_value_object.py +0 -0
  196. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/__init__.py +0 -0
  197. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/none_value_object.py +0 -0
  198. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/none/not_none_value_object.py +0 -0
  199. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/alpha_value_object.py +0 -0
  200. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +0 -0
  201. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/base64_value_object.py +0 -0
  202. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/camel_case_string_value_object.py +0 -0
  203. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/digit_value_object.py +0 -0
  204. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/kebab_case_string_value_object.py +0 -0
  205. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +0 -0
  206. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +0 -0
  207. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/pascal_case_string_value_object.py +0 -0
  208. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/printable_string_value_object.py +0 -0
  209. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/screaming_snake_case_string_value_object.py +0 -0
  210. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/snake_case_string_value_object.py +0 -0
  211. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/string_value_object.py +0 -0
  212. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +0 -0
  213. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +0 -0
  214. {value_object_pattern-1.33.1 → value_object_pattern-1.38.0}/value_object_pattern/usables/utils/__init__.py +0 -0
  215. {value_object_pattern-1.33.1 → 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.33.1
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
@@ -261,6 +261,7 @@ low-level operations, and boundary examples.
261
261
  | Model | Purpose |
262
262
  | --- | --- |
263
263
  | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
264
+ | `SecretValueObject` | Composition marker that redacts any value object's display in either inheritance order. |
264
265
  | `EnumerationValueObject[E]` | Stores enum members while accepting enum members or raw enum values. |
265
266
  | `UnionValueObject[T]` | Accepts and converts values that match a union annotation; supports subclass and inline construction. |
266
267
  | `BaseModel` | Adds representation, equality, copying, and primitive conversion for aggregate-like models. |
@@ -269,6 +270,32 @@ low-level operations, and boundary examples.
269
270
 
270
271
  See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
271
272
 
273
+ Compose `SecretValueObject` with the typed value object that owns validation. The marker does not need a type argument and may appear before or after the value-object base:
274
+
275
+ ```python
276
+ from value_object_pattern import SecretValueObject
277
+ from value_object_pattern.usables import IntegerValueObject, StringValueObject
278
+
279
+
280
+ class SecretToken(SecretValueObject, StringValueObject):
281
+ pass
282
+
283
+
284
+ class SecretPin(IntegerValueObject, SecretValueObject):
285
+ pass
286
+
287
+
288
+ token = SecretToken(value='hidden-token')
289
+ pin = SecretPin(value=1234)
290
+
291
+ assert str(token) == '********'
292
+ assert str(pin) == '********'
293
+ assert token.value == 'hidden-token'
294
+ assert pin.value == 1234
295
+ ```
296
+
297
+ Display redaction is not encryption: `.value` and primitive conversion still expose the raw stored value.
298
+
272
299
  <p align="right">
273
300
  <a href="#readme-top">🔼 Back to top</a>
274
301
  </p><br><br>
@@ -282,7 +309,8 @@ The package includes reusable validators for common shapes:
282
309
  | Category | Examples |
283
310
  | --- | --- |
284
311
  | Primitives | strings, bytes, booleans, integers, floats, `None` / not-`None` |
285
- | String formats | non-empty, trimmed, alpha, alphanumeric, lower/upper case, snake case, kebab case, secret strings |
312
+ | String formats | non-empty, trimmed, alpha, alphanumeric, lower/upper case, snake case, kebab case |
313
+ | Encoded strings | hexadecimal/Base16, Base32, Base36, ambiguity-free Base56, Bitcoin Base58, standard Base64 |
286
314
  | Dates | `date`, `datetime`, date strings, datetime strings, timezone objects, timezone names |
287
315
  | Identifiers | UUIDs and UUID strings, world codes, Spanish identifiers and vehicle plates |
288
316
  | Internet | URLs, hosts, domains, ports, emails, IP addresses, networks, MAC addresses, slugs, keys |
@@ -236,6 +236,7 @@ low-level operations, and boundary examples.
236
236
  | Model | Purpose |
237
237
  | --- | --- |
238
238
  | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
239
+ | `SecretValueObject` | Composition marker that redacts any value object's display in either inheritance order. |
239
240
  | `EnumerationValueObject[E]` | Stores enum members while accepting enum members or raw enum values. |
240
241
  | `UnionValueObject[T]` | Accepts and converts values that match a union annotation; supports subclass and inline construction. |
241
242
  | `BaseModel` | Adds representation, equality, copying, and primitive conversion for aggregate-like models. |
@@ -244,6 +245,32 @@ low-level operations, and boundary examples.
244
245
 
245
246
  See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
246
247
 
248
+ Compose `SecretValueObject` with the typed value object that owns validation. The marker does not need a type argument and may appear before or after the value-object base:
249
+
250
+ ```python
251
+ from value_object_pattern import SecretValueObject
252
+ from value_object_pattern.usables import IntegerValueObject, StringValueObject
253
+
254
+
255
+ class SecretToken(SecretValueObject, StringValueObject):
256
+ pass
257
+
258
+
259
+ class SecretPin(IntegerValueObject, SecretValueObject):
260
+ pass
261
+
262
+
263
+ token = SecretToken(value='hidden-token')
264
+ pin = SecretPin(value=1234)
265
+
266
+ assert str(token) == '********'
267
+ assert str(pin) == '********'
268
+ assert token.value == 'hidden-token'
269
+ assert pin.value == 1234
270
+ ```
271
+
272
+ Display redaction is not encryption: `.value` and primitive conversion still expose the raw stored value.
273
+
247
274
  <p align="right">
248
275
  <a href="#readme-top">🔼 Back to top</a>
249
276
  </p><br><br>
@@ -257,7 +284,8 @@ The package includes reusable validators for common shapes:
257
284
  | Category | Examples |
258
285
  | --- | --- |
259
286
  | Primitives | strings, bytes, booleans, integers, floats, `None` / not-`None` |
260
- | String formats | non-empty, trimmed, alpha, alphanumeric, lower/upper case, snake case, kebab case, secret strings |
287
+ | String formats | non-empty, trimmed, alpha, alphanumeric, lower/upper case, snake case, kebab case |
288
+ | Encoded strings | hexadecimal/Base16, Base32, Base36, ambiguity-free Base56, Bitcoin Base58, standard Base64 |
261
289
  | Dates | `date`, `datetime`, date strings, datetime strings, timezone objects, timezone names |
262
290
  | Identifiers | UUIDs and UUID strings, world codes, Spanish identifiers and vehicle plates |
263
291
  | Internet | URLs, hosts, domains, ports, emails, IP addresses, networks, MAC addresses, slugs, keys |
@@ -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
  ]
@@ -63,7 +63,7 @@ release = ['build>=1.2.2', 'python-semantic-release>=10.0.2']
63
63
  test = [
64
64
  'pytest>=8.0.0',
65
65
  'pytest-randomly>=3.0.0',
66
- 'object-mother-pattern>=3.2.0',
66
+ 'object-mother-pattern>=3.16.0',
67
67
  { include-group = 'coverage' },
68
68
  ]
69
69
  types = ['types-python-dateutil>=2.9.0.20241206']
@@ -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,11 +1,12 @@
1
- __version__ = '1.33.1'
1
+ __version__ = '1.38.0'
2
2
 
3
3
  from .decorators import process, validation
4
- from .models import BaseModel, EnumerationValueObject, UnionValueObject, ValueObject
4
+ from .models import BaseModel, EnumerationValueObject, SecretValueObject, UnionValueObject, ValueObject
5
5
 
6
6
  __all__ = (
7
7
  'BaseModel',
8
8
  'EnumerationValueObject',
9
+ 'SecretValueObject',
9
10
  'UnionValueObject',
10
11
  'ValueObject',
11
12
  'process',
@@ -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
@@ -1,11 +1,13 @@
1
1
  from .base_model import BaseModel
2
2
  from .enumeration_value_object import EnumerationValueObject
3
+ from .secret_value_object import SecretValueObject
3
4
  from .union_value_object import UnionValueObject
4
5
  from .value_object import ValueObject
5
6
 
6
7
  __all__ = (
7
8
  'BaseModel',
8
9
  'EnumerationValueObject',
10
+ 'SecretValueObject',
9
11
  'UnionValueObject',
10
12
  'ValueObject',
11
13
  )
@@ -17,7 +17,7 @@ from inspect import Parameter, _empty, signature
17
17
  from types import UnionType
18
18
  from typing import Any, NoReturn, Self, Union, get_args, get_origin, get_type_hints
19
19
 
20
- from .primitive_conversion import from_primitive, to_primitive
20
+ from .primitive_conversion import from_primitive, to_display_primitive, to_primitive
21
21
  from .type_matching import matches_expected_type
22
22
 
23
23
 
@@ -158,8 +158,8 @@ class BaseModel(ABC):
158
158
  ```
159
159
  """
160
160
  attributes = []
161
- for key, value in sorted(self.to_primitives().items()):
162
- attributes.append(f'{key}={value}')
161
+ for key, value in sorted(self._to_dict(ignore_private=True).items()):
162
+ attributes.append(f'{key}={to_display_primitive(value=value)}')
163
163
 
164
164
  return f'{self.__class__.__name__}({", ".join(attributes)})'
165
165
 
@@ -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
 
@@ -18,7 +18,7 @@ from types import UnionType
18
18
  from typing import Any, ClassVar, Generic, NoReturn, Self, TypeVar, Union, cast, get_args, get_origin
19
19
 
20
20
  from value_object_pattern.decorators import validation
21
- from value_object_pattern.models import BaseModel, ValueObject
21
+ from value_object_pattern.models import ValueObject
22
22
  from value_object_pattern.models.primitive_conversion import from_primitive, to_primitive
23
23
  from value_object_pattern.models.type_matching import matches_expected_type
24
24
 
@@ -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
 
@@ -328,19 +328,19 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
328
328
  # >>> [1, 2, 3]
329
329
  ```
330
330
  """
331
+ if self._has_secret_display():
332
+ return ValueObject.__repr__(self)
333
+
331
334
  primitive_types: tuple[type, ...] = (int, float, str, bool, bytes, bytearray, memoryview, type(None))
332
335
  collection_types: tuple[type, ...] = (list, dict, tuple, set, frozenset)
333
336
 
334
337
  list_to_return: list[Any] = []
335
338
  for item in self._value:
336
- if isinstance(item, BaseModel):
337
- list_to_return.append(repr(item))
338
-
339
- elif isinstance(item, Enum):
339
+ if isinstance(item, Enum):
340
340
  list_to_return.append(item.value)
341
341
 
342
342
  elif isinstance(item, ValueObject):
343
- value = item._value_for_display()
343
+ value = item._resolved_value_for_display()
344
344
 
345
345
  if isinstance(value, Enum):
346
346
  value = value.value
@@ -388,19 +388,19 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
388
388
  # >>> [1, 2, 3]
389
389
  ```
390
390
  """
391
+ if self._has_secret_display():
392
+ return ValueObject.__str__(self)
393
+
391
394
  primitive_types: tuple[type, ...] = (int, float, str, bool, bytes, bytearray, memoryview, type(None))
392
395
  collection_types: tuple[type, ...] = (list, dict, tuple, set, frozenset)
393
396
 
394
397
  list_to_return: list[Any] = []
395
398
  for item in self._value:
396
- if isinstance(item, BaseModel):
397
- list_to_return.append(str(object=item))
398
-
399
- elif isinstance(item, Enum):
399
+ if isinstance(item, Enum):
400
400
  list_to_return.append(item.value)
401
401
 
402
402
  elif isinstance(item, ValueObject):
403
- value = item._value_for_display()
403
+ value = item._resolved_value_for_display()
404
404
 
405
405
  if isinstance(value, Enum):
406
406
  value = value.value
@@ -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]
@@ -20,7 +20,7 @@ def to_primitive(value: Any) -> Any:
20
20
  """
21
21
  Recursively convert value objects, models, enums, and collections to primitive representations.
22
22
 
23
- `ValueObject` instances are converted through their display value, `BaseModel`-like objects through
23
+ `ValueObject` instances are converted through their stored value, `BaseModel`-like objects through
24
24
  `to_primitives()`, enums through their `.value`, and collections item by item.
25
25
 
26
26
  Args:
@@ -49,6 +49,82 @@ def to_primitive(value: Any) -> Any:
49
49
  return str(object=value)
50
50
 
51
51
 
52
+ def to_display_primitive(value: Any) -> Any:
53
+ """
54
+ Recursively convert a value for display while honoring value-object redaction.
55
+
56
+ Args:
57
+ value (Any): Value to convert.
58
+
59
+ Returns:
60
+ Any: Display-safe primitive representation.
61
+ """
62
+ if isinstance(value, PRIMITIVE_TYPES):
63
+ return value
64
+
65
+ if isinstance(value, Enum):
66
+ return to_display_primitive(value=value.value)
67
+
68
+ if isinstance(value, ValueObject):
69
+ return _convert_value_for_display(value=value)
70
+
71
+ if isinstance(value, (list, tuple, set, frozenset, dict)):
72
+ return _convert_collection_for_display(value=value)
73
+
74
+ if callable(getattr(value, 'to_primitives', None)):
75
+ return str(object=value)
76
+
77
+ if hasattr(value, 'value'):
78
+ return _convert_value_for_display(value=value)
79
+
80
+ return str(object=value)
81
+
82
+
83
+ def _convert_value_for_display(*, value: Any) -> Any:
84
+ """
85
+ Convert a value-like wrapper through its display value.
86
+
87
+ Args:
88
+ value (Any): Value-like wrapper.
89
+
90
+ Returns:
91
+ Any: Display-safe primitive representation.
92
+ """
93
+ nested_value = (
94
+ value._resolved_value_for_display() if isinstance(value, ValueObject) else getattr(value, 'value', value)
95
+ )
96
+
97
+ if nested_value is value:
98
+ return str(object=value)
99
+
100
+ return to_display_primitive(value=nested_value)
101
+
102
+
103
+ def _convert_collection_for_display(*, value: Any) -> Any:
104
+ """
105
+ Recursively convert collection values for display.
106
+
107
+ Args:
108
+ value (Any): Collection value.
109
+
110
+ Returns:
111
+ Any: Display-safe collection.
112
+ """
113
+ if isinstance(value, list):
114
+ return [to_display_primitive(value=item) for item in value]
115
+
116
+ if isinstance(value, tuple):
117
+ return tuple(to_display_primitive(value=item) for item in value)
118
+
119
+ if isinstance(value, set):
120
+ return {to_display_primitive(value=item) for item in value}
121
+
122
+ if isinstance(value, frozenset):
123
+ return frozenset(to_display_primitive(value=item) for item in value)
124
+
125
+ return {to_display_primitive(value=key): to_display_primitive(value=item) for key, item in value.items()}
126
+
127
+
52
128
  def from_primitive(*, value: Any, expected_type: Any) -> Any:
53
129
  """
54
130
  Recursively convert a primitive value into `expected_type` when possible.
@@ -108,7 +184,7 @@ def _convert_with_value_attribute(*, value: Any) -> Any:
108
184
  Any: Converted value or sentinel when the branch does not apply.
109
185
  """
110
186
  if isinstance(value, ValueObject):
111
- nested_value = value._value_for_display()
187
+ nested_value = value.value
112
188
  if nested_value is value:
113
189
  return str(object=value)
114
190