value-object-pattern 1.29.2__tar.gz → 1.30.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 (189) hide show
  1. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/.gitignore +2 -0
  2. value_object_pattern-1.30.0/PKG-INFO +351 -0
  3. value_object_pattern-1.30.0/README.md +326 -0
  4. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/__init__.py +1 -1
  5. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/decorators/value_object_process.py +9 -7
  6. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/decorators/value_object_validation.py +11 -8
  7. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/base_model.py +17 -7
  8. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/collections/dict_value_object.py +10 -7
  9. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/collections/list_value_object.py +10 -6
  10. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/enumeration_value_object.py +9 -6
  11. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/primitive_conversion.py +8 -2
  12. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/union_value_object.py +8 -8
  13. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/value_object.py +34 -22
  14. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/__init__.py +5 -5
  15. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/__init__.py +5 -5
  16. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/__init__.py +63 -63
  17. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/uri/url_value_object.py +5 -1
  18. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/utils/__init__.py +14 -6
  19. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/utils/__init__.py +7 -3
  20. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/integer_value_object.py +5 -2
  21. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/secret_string_value_object.py +5 -2
  22. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/string_value_object.py +5 -2
  23. value_object_pattern-1.29.2/PKG-INFO +0 -113
  24. value_object_pattern-1.29.2/README.md +0 -88
  25. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/LICENSE.md +0 -0
  26. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/pyproject.toml +0 -0
  27. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/decorators/__init__.py +0 -0
  28. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/decorators/classproperty.py +0 -0
  29. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/__init__.py +0 -0
  30. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/collections/__init__.py +0 -0
  31. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/models/type_matching.py +0 -0
  32. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/py.typed +0 -0
  33. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/__init__.py +0 -0
  34. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/__init__.py +0 -0
  35. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/date/__init__.py +0 -0
  36. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/date/date_value_object.py +0 -0
  37. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/date/string_date_value_object.py +0 -0
  38. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/datetime/__init__.py +0 -0
  39. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/datetime/datetime_value_object.py +0 -0
  40. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +0 -0
  41. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/timezone/__init__.py +0 -0
  42. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/timezone/string_timezone_value_object.py +0 -0
  43. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/dates/timezone/timezone_value_object.py +0 -0
  44. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/__init__.py +0 -0
  45. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/__init__.py +0 -0
  46. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v1_value_object.py +0 -0
  47. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v3_value_object.py +0 -0
  48. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v4_value_object.py +0 -0
  49. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v5_value_object.py +0 -0
  50. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v6_value_object.py +0 -0
  51. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v7_value_object.py +0 -0
  52. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v8_value_object.py +0 -0
  53. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_value_object.py +0 -0
  54. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v1_value_object.py +0 -0
  55. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v3_value_object.py +0 -0
  56. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v4_value_object.py +0 -0
  57. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v5_value_object.py +0 -0
  58. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v6_value_object.py +0 -0
  59. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v7_value_object.py +0 -0
  60. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_v8_value_object.py +0 -0
  61. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/uuid/uuid_value_object.py +0 -0
  62. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/__init__.py +0 -0
  63. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/country_tld_value_object.py +0 -0
  64. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/__init__.py +0 -0
  65. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/__init__.py +0 -0
  66. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/dni_value_object.py +0 -0
  67. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/nie_value_object.py +0 -0
  68. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/nif_value_object.py +0 -0
  69. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/nuss_value_object.py +0 -0
  70. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/passport_value_object.py +0 -0
  71. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/phone_number_value_object.py +0 -0
  72. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/__init__.py +0 -0
  73. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/administrative_technician_vehicle_plate_value_object.py +0 -0
  74. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/air_force_vehicle_plate_value_object.py +0 -0
  75. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/army_vehicle_plate_value_object.py +0 -0
  76. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/canarias_police_vehicle_plate_value_object.py +0 -0
  77. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/catalan_police_vehicle_plate_value_object.py +0 -0
  78. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/civil_guard_vehicle_plate_value_object.py +0 -0
  79. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/consular_corps_vehicle_plate_value_object.py +0 -0
  80. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/diplomatic_corps_vehicle_plate_value_object.py +0 -0
  81. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/especial_plate_vehicle_plate_value_object.py +0 -0
  82. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/historical_vehicle_plate_value_object.py +0 -0
  83. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/international_organization_vehicle_plate_value_object.py +0 -0
  84. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_development_vehicle_plate_value_object.py +0 -0
  85. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_environment_vehicle_plate_value_object.py +0 -0
  86. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/national_police_vehicle_plate_value_object.py +0 -0
  87. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/navy_vehicle_plate_value_object.py +0 -0
  88. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_truck_vehicle_plate_value_object.py +0 -0
  89. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_vehicle_plate_value_object.py +0 -0
  90. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/provincial_system_vehicle_plate_value_object.py +0 -0
  91. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/state_motor_pool_vehicle_plate_value_object.py +0 -0
  92. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_not_registered_vehicle_plate_value_object.py +0 -0
  93. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_registered_vehicle_plate_value_object.py +0 -0
  94. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_private_individual_vehicle_plate_value_object.py +0 -0
  95. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/two_wheels_vehicle_plate_value_object.py +0 -0
  96. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/provincial_plate_codes.txt +0 -0
  97. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/provincial_codes.txt +0 -0
  98. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/europe/spain/vehicle_plate_value_object.py +0 -0
  99. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha2_code_value_object.py +0 -0
  100. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha3_code_value_object.py +0 -0
  101. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/iso3166_numeric_code_value_object.py +0 -0
  102. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/phone_code_value_object.py +0 -0
  103. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_codes.txt +0 -0
  104. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_alpha3_mapping.txt +0 -0
  105. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_numeric_mapping.txt +0 -0
  106. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_phone_code_mapping.txt +0 -0
  107. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_tld_mapping.txt +0 -0
  108. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha3_codes.txt +0 -0
  109. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_numeric_codes.txt +0 -0
  110. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/identifiers/world/vin_value_object.py +0 -0
  111. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/__init__.py +0 -0
  112. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/aws_cloud_region_value_object.py +0 -0
  113. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/domain_value_object.py +0 -0
  114. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/email_address_value_object.py +0 -0
  115. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/host_value_object.py +0 -0
  116. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/ip_address_value_object.py +0 -0
  117. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/ipv4_address_value_object.py +0 -0
  118. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/ipv4_network_value_object.py +0 -0
  119. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/ipv6_address_value_object.py +0 -0
  120. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/ipv6_network_value_object.py +0 -0
  121. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/keys/__init__.py +0 -0
  122. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/keys/kebab_case_key_value_object.py +0 -0
  123. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/keys/snake_case_key_value_object.py +0 -0
  124. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_address_value_object.py +0 -0
  125. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/__init__.py +0 -0
  126. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/cisco_mac_address_value_object.py +0 -0
  127. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/raw_mac_address_value_object.py +0 -0
  128. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/space_mac_address_value_object.py +0 -0
  129. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/universal_mac_address_value_object.py +0 -0
  130. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mac_addresses/windows_mac_address_value_object.py +0 -0
  131. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mobile/__init__.py +0 -0
  132. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/mobile/imei_value_object.py +0 -0
  133. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/port_value_object.py +0 -0
  134. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/slug_value_object.py +0 -0
  135. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/uri/__init__.py +0 -0
  136. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/uri/http_https_url_value_object.py +0 -0
  137. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/uri/http_url_value_object.py +0 -0
  138. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/uri/https_url_value_object.py +0 -0
  139. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/user_agent_value_object.py +0 -0
  140. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/utils/aws_regions.txt +0 -0
  141. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/internet/utils/tld_domains.txt +0 -0
  142. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/__init__.py +0 -0
  143. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_card_value_object.py +0 -0
  144. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_cards/__init__.py +0 -0
  145. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_cards/amex_credit_card_value_object.py +0 -0
  146. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_cards/discover_credit_card_value_object.py +0 -0
  147. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_cards/mastercard_credit_card_value_object.py +0 -0
  148. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/credit_cards/visa_credit_card_value_object.py +0 -0
  149. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/iban_value_object.py +0 -0
  150. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/money/utils/iban_lengths.txt +0 -0
  151. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/__init__.py +0 -0
  152. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/boolean/__init__.py +0 -0
  153. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/boolean/boolean_value_object.py +0 -0
  154. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/boolean/false_value_object.py +0 -0
  155. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/boolean/true_value_object.py +0 -0
  156. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/bytes/__init__.py +0 -0
  157. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/bytes/bytes_value_object.py +0 -0
  158. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/__init__.py +0 -0
  159. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/float_value_object.py +0 -0
  160. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/negative_float_value_object.py +0 -0
  161. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/negative_or_zero_float_value_object.py +0 -0
  162. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/positive_float_value_object.py +0 -0
  163. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/float/positive_or_zero_float_value_object.py +0 -0
  164. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/__init__.py +0 -0
  165. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/even_integer_value_object.py +0 -0
  166. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +0 -0
  167. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/negative_or_zero_integer_value_object.py +0 -0
  168. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +0 -0
  169. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +0 -0
  170. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/integer/positive_or_zero_integer_value_object.py +0 -0
  171. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/none/__init__.py +0 -0
  172. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/none/none_value_object.py +0 -0
  173. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/none/not_none_value_object.py +0 -0
  174. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/__init__.py +0 -0
  175. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/alpha_value_object.py +0 -0
  176. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +0 -0
  177. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/camel_case_string_value_object.py +0 -0
  178. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/digit_value_object.py +0 -0
  179. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/kebab_case_string_value_object.py +0 -0
  180. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +0 -0
  181. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +0 -0
  182. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/pascal_case_string_value_object.py +0 -0
  183. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/printable_string_value_object.py +0 -0
  184. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/screaming_snake_case_string_value_object.py +0 -0
  185. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/snake_case_string_value_object.py +0 -0
  186. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +0 -0
  187. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +0 -0
  188. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/utils/__init__.py +0 -0
  189. {value_object_pattern-1.29.2 → value_object_pattern-1.30.0}/value_object_pattern/usables/utils/luhn_validation.py +0 -0
@@ -1,5 +1,7 @@
1
1
  # linting files
2
2
  .coverage
3
+ coverage/
4
+ htmlcov/
3
5
 
4
6
  # cache files/folders
5
7
  **cache**
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: value-object-pattern
3
+ Version: 1.30.0
4
+ Summary: The Value Object Pattern is a Python package that streamlines the creation and management of value objects in your projects.
5
+ Project-URL: Homepage, https://github.com/adriamontoto/value-object-pattern
6
+ Project-URL: Repository, https://github.com/adriamontoto/value-object-pattern
7
+ Project-URL: Issues, https://github.com/adriamontoto/value-object-pattern/issues
8
+ Author: Adria Montoto
9
+ License-Expression: MIT
10
+ License-File: LICENSE.md
11
+ Keywords: development,domain-driven-design,encapsulation,pattern,python,tools,utilities,validation,value-object
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: python-dateutil>=2.9.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ <a name="readme-top"></a>
27
+
28
+ # 📦 Value Object Pattern
29
+
30
+ <p align="center">
31
+ <a href="https://github.com/adriamontoto/value-object-pattern/actions/workflows/ci.yaml?event=push&branch=master" target="_blank">
32
+ <img src="https://github.com/adriamontoto/value-object-pattern/actions/workflows/ci.yaml/badge.svg?event=push&branch=master" alt="CI Pipeline">
33
+ </a>
34
+ <a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/adriamontoto/value-object-pattern" target="_blank">
35
+ <img src="https://coverage-badge.samuelcolvin.workers.dev/adriamontoto/value-object-pattern.svg" alt="Coverage Pipeline">
36
+ </a>
37
+ <a href="https://pypi.org/project/value-object-pattern" target="_blank">
38
+ <img src="https://img.shields.io/pypi/v/value-object-pattern?color=%2334D058&label=pypi%20package" alt="Package Version">
39
+ </a>
40
+ <a href="https://pypi.org/project/value-object-pattern/" target="_blank">
41
+ <img src="https://img.shields.io/pypi/pyversions/value-object-pattern.svg?color=%2334D058" alt="Supported Python Versions">
42
+ </a>
43
+ <a href="https://pepy.tech/projects/value-object-pattern" target="_blank">
44
+ <img src="https://static.pepy.tech/badge/value-object-pattern/month" alt="Package Downloads">
45
+ </a>
46
+ <a href="https://deepwiki.com/adriamontoto/value-object-pattern" target="_blank">
47
+ <img src="https://img.shields.io/badge/DeepWiki-adriamontoto%2Fvalue--object--pattern-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==" alt="Project Documentation">
48
+ </a>
49
+ </p>
50
+
51
+ The **Value Object Pattern** is a Python 🐍 package for building immutable, self-validating value objects 📦. It helps
52
+ move validation, normalization, primitive conversion, and domain-specific constraints out of scattered application code
53
+ and into small typed objects that can be reused across models, services, APIs, and tests.
54
+ <br><br>
55
+
56
+ ## Table of Contents
57
+
58
+ - [📥 Installation](#installation)
59
+ - [📚 Documentation](#documentation)
60
+ - [⚡ Quick Start](#quick-start)
61
+ - [🧩 Core Ideas](#core-ideas)
62
+ - [🤔 Why Value Objects?](#why-value-objects)
63
+ - [📦 Core Models](#core-models)
64
+ - [✅ Reusable Value Objects](#reusable-value-objects)
65
+ - [🔁 Primitive Conversion](#primitive-conversion)
66
+ - [🤝 Contributing](#contributing)
67
+ - [🔑 License](#license)
68
+
69
+ <p align="right">
70
+ <a href="#readme-top">🔼 Back to top</a>
71
+ </p><br><br>
72
+
73
+ <a name="installation"></a>
74
+
75
+ ## 📥 Installation
76
+
77
+ You can install **Value Object Pattern** using `pip`:
78
+
79
+ ```bash
80
+ pip install value-object-pattern
81
+ ```
82
+
83
+ You can install the companion AI-agent skill from [skills.sh](https://www.skills.sh/) with Vercel's `skills` CLI:
84
+
85
+ ```bash
86
+ npx skills add adriamontoto/value-object-pattern
87
+ ```
88
+
89
+ Review the skill source in [`skills/value-object-pattern`](skills/value-object-pattern) before installing it in
90
+ sensitive environments.
91
+
92
+ <p align="right">
93
+ <a href="#readme-top">🔼 Back to top</a>
94
+ </p><br><br>
95
+
96
+ <a name="documentation"></a>
97
+
98
+ ## 📚 Documentation
99
+
100
+ The root README is the entry point. Deeper guides live in this repository and are linked here:
101
+
102
+ - [`docs/README.md`](docs/README.md): Documentation hub.
103
+ - [`docs/usage/README.md`](docs/usage/README.md): Custom value objects, validators, processors, and model composition.
104
+ - [`docs/catalog/README.md`](docs/catalog/README.md): Feature map by reusable value-object category.
105
+ - Catalog details: [`primitives`](docs/catalog/primitives/README.md), [`dates`](docs/catalog/dates/README.md),
106
+ [`identifiers`](docs/catalog/identifiers/README.md), [`internet`](docs/catalog/internet/README.md), and
107
+ [`money`](docs/catalog/money/README.md).
108
+ - [`docs/conversion/README.md`](docs/conversion/README.md): Primitive conversion and nested model behavior.
109
+ - [`AI Skill`](skills/README.md): Installable skill package that teaches AI agents how to use Value Object Pattern.
110
+
111
+ This [project's DeepWiki documentation](https://deepwiki.com/adriamontoto/value-object-pattern) is also available for
112
+ generated repository navigation.
113
+
114
+ <p align="right">
115
+ <a href="#readme-top">🔼 Back to top</a>
116
+ </p><br><br>
117
+
118
+ <a name="quick-start"></a>
119
+
120
+ ## ⚡ Quick Start
121
+
122
+ Create a value object by subclassing `ValueObject[T]` and adding validation hooks:
123
+
124
+ ```python
125
+ from value_object_pattern import ValueObject, validation
126
+
127
+
128
+ class Age(ValueObject[int]):
129
+ @validation(order=0)
130
+ def _ensure_value_is_integer(self, value: int) -> None:
131
+ if type(value) is not int:
132
+ raise TypeError('Age value must be an integer.')
133
+
134
+ @validation(order=1)
135
+ def _ensure_value_is_positive(self, value: int) -> None:
136
+ if value <= 0:
137
+ raise ValueError('Age value must be positive.')
138
+
139
+
140
+ age = Age(value=42)
141
+
142
+ print(age.value)
143
+ # >>> 42
144
+ print(repr(age))
145
+ # >>> Age(value=42)
146
+ ```
147
+
148
+ Use reusable value objects when the package already provides the constraint:
149
+
150
+ ```python
151
+ from value_object_pattern.usables import NotEmptyStringValueObject, PositiveIntegerValueObject
152
+
153
+ name = NotEmptyStringValueObject(value='Ada')
154
+ quantity = PositiveIntegerValueObject(value=3)
155
+ ```
156
+
157
+ <p align="right">
158
+ <a href="#readme-top">🔼 Back to top</a>
159
+ </p><br><br>
160
+
161
+ <a name="core-ideas"></a>
162
+
163
+ ## 🧩 Core Ideas
164
+
165
+ Value objects in this package are designed around a few consistent rules:
166
+
167
+ - They wrap exactly one value and expose it through `.value`.
168
+ - They validate input during construction.
169
+ - They can normalize input with `@process` hooks.
170
+ - They reject attribute mutation after construction.
171
+ - They compare by concrete class and wrapped value.
172
+ - They can customize validation error context with `title` and `parameter`.
173
+
174
+ ```python
175
+ from value_object_pattern import process
176
+ from value_object_pattern.usables import StringValueObject
177
+
178
+
179
+ class LowerTrimmedName(StringValueObject):
180
+ @process(order=0)
181
+ def _trim(self, value: str) -> str:
182
+ return value.strip()
183
+
184
+ @process(order=1)
185
+ def _lower(self, value: str) -> str:
186
+ return value.lower()
187
+
188
+
189
+ name = LowerTrimmedName(value=' ADA ')
190
+
191
+ assert name.value == 'ada'
192
+ ```
193
+
194
+ <p align="right">
195
+ <a href="#readme-top">🔼 Back to top</a>
196
+ </p><br><br>
197
+
198
+ <a name="why-value-objects"></a>
199
+
200
+ ## 🤔 Why Value Objects?
201
+
202
+ Value objects make domain rules explicit. A plain `str`, `int`, or `dict` can carry almost anything, so every function
203
+ that receives it has to remember what "valid" means. A value object gives that rule a name and enforces it at the point
204
+ where the value enters the model.
205
+
206
+ Without a value object, the same rule tends to be repeated across services, controllers, tests, and serializers:
207
+
208
+ ```python
209
+ def register_user(email: str, age: int) -> None:
210
+ if '@' not in email:
211
+ raise ValueError('Invalid email.')
212
+
213
+ if age <= 0:
214
+ raise ValueError('Invalid age.')
215
+ ```
216
+
217
+ With value objects, the signature communicates the expected shape and invalid values are rejected before the rest of the
218
+ code depends on them:
219
+
220
+ ```python
221
+ from value_object_pattern.usables import PositiveIntegerValueObject
222
+ from value_object_pattern.usables.internet import EmailAddressValueObject
223
+
224
+
225
+ def register_user(email: EmailAddressValueObject, age: PositiveIntegerValueObject) -> None:
226
+ assert '@' in email.value
227
+ assert age.value > 0
228
+ ```
229
+
230
+ This is useful when a value has a reusable meaning: email address, positive quantity, trimmed name, country code, URL,
231
+ UUID, money identifier, or any project-specific concept such as `TenantSlug`, `OrderLimit`, or `CustomerName`.
232
+
233
+ Raw literals and primitives are still the right choice when the value is simple or intentionally exact:
234
+
235
+ - Use raw primitives inside low-level calculations where no domain rule is being expressed.
236
+ - Use hardcoded values for exact examples, snapshots, JSON, SQL, URLs, error messages, and public documentation output.
237
+ - Use explicit boundary values for deliberate limits such as zero, one, minimum length, maximum length, empty strings,
238
+ first date, last date, or a known invalid format.
239
+ - Use `.value` when crossing into libraries, APIs, or storage layers that expect primitives.
240
+
241
+ ```python
242
+ from value_object_pattern.usables import PositiveIntegerValueObject
243
+
244
+ quantity = PositiveIntegerValueObject(value=10)
245
+
246
+ assert quantity.value == 10
247
+ assert quantity.value + 5 == 15
248
+ ```
249
+
250
+ The practical rule is simple: use value objects for named domain constraints, and use primitives for exact literals,
251
+ low-level operations, and boundary examples.
252
+
253
+ <p align="right">
254
+ <a href="#readme-top">🔼 Back to top</a>
255
+ </p><br><br>
256
+
257
+ <a name="core-models"></a>
258
+
259
+ ## 📦 Core Models
260
+
261
+ | Model | Purpose |
262
+ | --- | --- |
263
+ | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
264
+ | `EnumerationValueObject[E]` | Stores enum members while accepting enum members or raw enum values. |
265
+ | `UnionValueObject[T]` | Accepts and converts values that match a union annotation. |
266
+ | `BaseModel` | Adds representation, equality, copying, and primitive conversion for aggregate-like models. |
267
+ | `ListValueObject[T]` | Immutable typed list wrapper with helper methods that return new instances. |
268
+ | `DictValueObject[K, V]` | Immutable typed dictionary wrapper with helper methods that return new instances. |
269
+
270
+ See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
271
+
272
+ <p align="right">
273
+ <a href="#readme-top">🔼 Back to top</a>
274
+ </p><br><br>
275
+
276
+ <a name="reusable-value-objects"></a>
277
+
278
+ ## ✅ Reusable Value Objects
279
+
280
+ The package includes reusable validators for common shapes:
281
+
282
+ | Category | Examples |
283
+ | --- | --- |
284
+ | 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 |
286
+ | Dates | `date`, `datetime`, date strings, datetime strings, timezone objects, timezone names |
287
+ | Identifiers | UUIDs and UUID strings, world codes, Spanish identifiers and vehicle plates |
288
+ | Internet | URLs, hosts, domains, ports, emails, IP addresses, networks, MAC addresses, slugs, keys |
289
+ | Money | IBANs and credit card values |
290
+
291
+ See [`docs/catalog/README.md`](docs/catalog/README.md) for import paths and category guidance.
292
+
293
+ <p align="right">
294
+ <a href="#readme-top">🔼 Back to top</a>
295
+ </p><br><br>
296
+
297
+ <a name="primitive-conversion"></a>
298
+
299
+ ## 🔁 Primitive Conversion
300
+
301
+ `BaseModel`, `ListValueObject`, `DictValueObject`, and `UnionValueObject` can convert between primitive data and richer
302
+ types.
303
+
304
+ ```python
305
+ from value_object_pattern import BaseModel
306
+ from value_object_pattern.usables import NotEmptyStringValueObject, PositiveIntegerValueObject
307
+
308
+
309
+ class User(BaseModel):
310
+ def __init__(self, name: NotEmptyStringValueObject, age: PositiveIntegerValueObject) -> None:
311
+ self.name = name
312
+ self.age = age
313
+
314
+
315
+ user = User.from_primitives(primitives={'name': 'Ada', 'age': 42})
316
+
317
+ assert isinstance(user.name, NotEmptyStringValueObject)
318
+ assert user.to_primitives() == {'age': 42, 'name': 'Ada'}
319
+ ```
320
+
321
+ More details are available in [`docs/conversion/README.md`](docs/conversion/README.md).
322
+
323
+ <p align="right">
324
+ <a href="#readme-top">🔼 Back to top</a>
325
+ </p><br><br>
326
+
327
+ <a name="contributing"></a>
328
+
329
+ ## 🤝 Contributing
330
+
331
+ We love community help! Before you open an issue or pull request, please read:
332
+
333
+ - [`🤝 How to Contribute`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/CONTRIBUTING.md)
334
+ - [`🧭 Code of Conduct`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/CODE_OF_CONDUCT.md)
335
+ - [`🔐 Security Policy`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/SECURITY.md)
336
+
337
+ _Thank you for helping make **📦 Value Object Pattern** package awesome! 🌟_
338
+
339
+ <p align="right">
340
+ <a href="#readme-top">🔼 Back to top</a>
341
+ </p><br><br>
342
+
343
+ <a name="license"></a>
344
+
345
+ ## 🔑 License
346
+
347
+ This project is licensed under the terms of the [`MIT license`](https://github.com/adriamontoto/value-object-pattern/blob/master/LICENSE.md).
348
+
349
+ <p align="right">
350
+ <a href="#readme-top">🔼 Back to top</a>
351
+ </p>
@@ -0,0 +1,326 @@
1
+ <a name="readme-top"></a>
2
+
3
+ # 📦 Value Object Pattern
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/adriamontoto/value-object-pattern/actions/workflows/ci.yaml?event=push&branch=master" target="_blank">
7
+ <img src="https://github.com/adriamontoto/value-object-pattern/actions/workflows/ci.yaml/badge.svg?event=push&branch=master" alt="CI Pipeline">
8
+ </a>
9
+ <a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/adriamontoto/value-object-pattern" target="_blank">
10
+ <img src="https://coverage-badge.samuelcolvin.workers.dev/adriamontoto/value-object-pattern.svg" alt="Coverage Pipeline">
11
+ </a>
12
+ <a href="https://pypi.org/project/value-object-pattern" target="_blank">
13
+ <img src="https://img.shields.io/pypi/v/value-object-pattern?color=%2334D058&label=pypi%20package" alt="Package Version">
14
+ </a>
15
+ <a href="https://pypi.org/project/value-object-pattern/" target="_blank">
16
+ <img src="https://img.shields.io/pypi/pyversions/value-object-pattern.svg?color=%2334D058" alt="Supported Python Versions">
17
+ </a>
18
+ <a href="https://pepy.tech/projects/value-object-pattern" target="_blank">
19
+ <img src="https://static.pepy.tech/badge/value-object-pattern/month" alt="Package Downloads">
20
+ </a>
21
+ <a href="https://deepwiki.com/adriamontoto/value-object-pattern" target="_blank">
22
+ <img src="https://img.shields.io/badge/DeepWiki-adriamontoto%2Fvalue--object--pattern-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==" alt="Project Documentation">
23
+ </a>
24
+ </p>
25
+
26
+ The **Value Object Pattern** is a Python 🐍 package for building immutable, self-validating value objects 📦. It helps
27
+ move validation, normalization, primitive conversion, and domain-specific constraints out of scattered application code
28
+ and into small typed objects that can be reused across models, services, APIs, and tests.
29
+ <br><br>
30
+
31
+ ## Table of Contents
32
+
33
+ - [📥 Installation](#installation)
34
+ - [📚 Documentation](#documentation)
35
+ - [⚡ Quick Start](#quick-start)
36
+ - [🧩 Core Ideas](#core-ideas)
37
+ - [🤔 Why Value Objects?](#why-value-objects)
38
+ - [📦 Core Models](#core-models)
39
+ - [✅ Reusable Value Objects](#reusable-value-objects)
40
+ - [🔁 Primitive Conversion](#primitive-conversion)
41
+ - [🤝 Contributing](#contributing)
42
+ - [🔑 License](#license)
43
+
44
+ <p align="right">
45
+ <a href="#readme-top">🔼 Back to top</a>
46
+ </p><br><br>
47
+
48
+ <a name="installation"></a>
49
+
50
+ ## 📥 Installation
51
+
52
+ You can install **Value Object Pattern** using `pip`:
53
+
54
+ ```bash
55
+ pip install value-object-pattern
56
+ ```
57
+
58
+ You can install the companion AI-agent skill from [skills.sh](https://www.skills.sh/) with Vercel's `skills` CLI:
59
+
60
+ ```bash
61
+ npx skills add adriamontoto/value-object-pattern
62
+ ```
63
+
64
+ Review the skill source in [`skills/value-object-pattern`](skills/value-object-pattern) before installing it in
65
+ sensitive environments.
66
+
67
+ <p align="right">
68
+ <a href="#readme-top">🔼 Back to top</a>
69
+ </p><br><br>
70
+
71
+ <a name="documentation"></a>
72
+
73
+ ## 📚 Documentation
74
+
75
+ The root README is the entry point. Deeper guides live in this repository and are linked here:
76
+
77
+ - [`docs/README.md`](docs/README.md): Documentation hub.
78
+ - [`docs/usage/README.md`](docs/usage/README.md): Custom value objects, validators, processors, and model composition.
79
+ - [`docs/catalog/README.md`](docs/catalog/README.md): Feature map by reusable value-object category.
80
+ - Catalog details: [`primitives`](docs/catalog/primitives/README.md), [`dates`](docs/catalog/dates/README.md),
81
+ [`identifiers`](docs/catalog/identifiers/README.md), [`internet`](docs/catalog/internet/README.md), and
82
+ [`money`](docs/catalog/money/README.md).
83
+ - [`docs/conversion/README.md`](docs/conversion/README.md): Primitive conversion and nested model behavior.
84
+ - [`AI Skill`](skills/README.md): Installable skill package that teaches AI agents how to use Value Object Pattern.
85
+
86
+ This [project's DeepWiki documentation](https://deepwiki.com/adriamontoto/value-object-pattern) is also available for
87
+ generated repository navigation.
88
+
89
+ <p align="right">
90
+ <a href="#readme-top">🔼 Back to top</a>
91
+ </p><br><br>
92
+
93
+ <a name="quick-start"></a>
94
+
95
+ ## ⚡ Quick Start
96
+
97
+ Create a value object by subclassing `ValueObject[T]` and adding validation hooks:
98
+
99
+ ```python
100
+ from value_object_pattern import ValueObject, validation
101
+
102
+
103
+ class Age(ValueObject[int]):
104
+ @validation(order=0)
105
+ def _ensure_value_is_integer(self, value: int) -> None:
106
+ if type(value) is not int:
107
+ raise TypeError('Age value must be an integer.')
108
+
109
+ @validation(order=1)
110
+ def _ensure_value_is_positive(self, value: int) -> None:
111
+ if value <= 0:
112
+ raise ValueError('Age value must be positive.')
113
+
114
+
115
+ age = Age(value=42)
116
+
117
+ print(age.value)
118
+ # >>> 42
119
+ print(repr(age))
120
+ # >>> Age(value=42)
121
+ ```
122
+
123
+ Use reusable value objects when the package already provides the constraint:
124
+
125
+ ```python
126
+ from value_object_pattern.usables import NotEmptyStringValueObject, PositiveIntegerValueObject
127
+
128
+ name = NotEmptyStringValueObject(value='Ada')
129
+ quantity = PositiveIntegerValueObject(value=3)
130
+ ```
131
+
132
+ <p align="right">
133
+ <a href="#readme-top">🔼 Back to top</a>
134
+ </p><br><br>
135
+
136
+ <a name="core-ideas"></a>
137
+
138
+ ## 🧩 Core Ideas
139
+
140
+ Value objects in this package are designed around a few consistent rules:
141
+
142
+ - They wrap exactly one value and expose it through `.value`.
143
+ - They validate input during construction.
144
+ - They can normalize input with `@process` hooks.
145
+ - They reject attribute mutation after construction.
146
+ - They compare by concrete class and wrapped value.
147
+ - They can customize validation error context with `title` and `parameter`.
148
+
149
+ ```python
150
+ from value_object_pattern import process
151
+ from value_object_pattern.usables import StringValueObject
152
+
153
+
154
+ class LowerTrimmedName(StringValueObject):
155
+ @process(order=0)
156
+ def _trim(self, value: str) -> str:
157
+ return value.strip()
158
+
159
+ @process(order=1)
160
+ def _lower(self, value: str) -> str:
161
+ return value.lower()
162
+
163
+
164
+ name = LowerTrimmedName(value=' ADA ')
165
+
166
+ assert name.value == 'ada'
167
+ ```
168
+
169
+ <p align="right">
170
+ <a href="#readme-top">🔼 Back to top</a>
171
+ </p><br><br>
172
+
173
+ <a name="why-value-objects"></a>
174
+
175
+ ## 🤔 Why Value Objects?
176
+
177
+ Value objects make domain rules explicit. A plain `str`, `int`, or `dict` can carry almost anything, so every function
178
+ that receives it has to remember what "valid" means. A value object gives that rule a name and enforces it at the point
179
+ where the value enters the model.
180
+
181
+ Without a value object, the same rule tends to be repeated across services, controllers, tests, and serializers:
182
+
183
+ ```python
184
+ def register_user(email: str, age: int) -> None:
185
+ if '@' not in email:
186
+ raise ValueError('Invalid email.')
187
+
188
+ if age <= 0:
189
+ raise ValueError('Invalid age.')
190
+ ```
191
+
192
+ With value objects, the signature communicates the expected shape and invalid values are rejected before the rest of the
193
+ code depends on them:
194
+
195
+ ```python
196
+ from value_object_pattern.usables import PositiveIntegerValueObject
197
+ from value_object_pattern.usables.internet import EmailAddressValueObject
198
+
199
+
200
+ def register_user(email: EmailAddressValueObject, age: PositiveIntegerValueObject) -> None:
201
+ assert '@' in email.value
202
+ assert age.value > 0
203
+ ```
204
+
205
+ This is useful when a value has a reusable meaning: email address, positive quantity, trimmed name, country code, URL,
206
+ UUID, money identifier, or any project-specific concept such as `TenantSlug`, `OrderLimit`, or `CustomerName`.
207
+
208
+ Raw literals and primitives are still the right choice when the value is simple or intentionally exact:
209
+
210
+ - Use raw primitives inside low-level calculations where no domain rule is being expressed.
211
+ - Use hardcoded values for exact examples, snapshots, JSON, SQL, URLs, error messages, and public documentation output.
212
+ - Use explicit boundary values for deliberate limits such as zero, one, minimum length, maximum length, empty strings,
213
+ first date, last date, or a known invalid format.
214
+ - Use `.value` when crossing into libraries, APIs, or storage layers that expect primitives.
215
+
216
+ ```python
217
+ from value_object_pattern.usables import PositiveIntegerValueObject
218
+
219
+ quantity = PositiveIntegerValueObject(value=10)
220
+
221
+ assert quantity.value == 10
222
+ assert quantity.value + 5 == 15
223
+ ```
224
+
225
+ The practical rule is simple: use value objects for named domain constraints, and use primitives for exact literals,
226
+ low-level operations, and boundary examples.
227
+
228
+ <p align="right">
229
+ <a href="#readme-top">🔼 Back to top</a>
230
+ </p><br><br>
231
+
232
+ <a name="core-models"></a>
233
+
234
+ ## 📦 Core Models
235
+
236
+ | Model | Purpose |
237
+ | --- | --- |
238
+ | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
239
+ | `EnumerationValueObject[E]` | Stores enum members while accepting enum members or raw enum values. |
240
+ | `UnionValueObject[T]` | Accepts and converts values that match a union annotation. |
241
+ | `BaseModel` | Adds representation, equality, copying, and primitive conversion for aggregate-like models. |
242
+ | `ListValueObject[T]` | Immutable typed list wrapper with helper methods that return new instances. |
243
+ | `DictValueObject[K, V]` | Immutable typed dictionary wrapper with helper methods that return new instances. |
244
+
245
+ See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
246
+
247
+ <p align="right">
248
+ <a href="#readme-top">🔼 Back to top</a>
249
+ </p><br><br>
250
+
251
+ <a name="reusable-value-objects"></a>
252
+
253
+ ## ✅ Reusable Value Objects
254
+
255
+ The package includes reusable validators for common shapes:
256
+
257
+ | Category | Examples |
258
+ | --- | --- |
259
+ | 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 |
261
+ | Dates | `date`, `datetime`, date strings, datetime strings, timezone objects, timezone names |
262
+ | Identifiers | UUIDs and UUID strings, world codes, Spanish identifiers and vehicle plates |
263
+ | Internet | URLs, hosts, domains, ports, emails, IP addresses, networks, MAC addresses, slugs, keys |
264
+ | Money | IBANs and credit card values |
265
+
266
+ See [`docs/catalog/README.md`](docs/catalog/README.md) for import paths and category guidance.
267
+
268
+ <p align="right">
269
+ <a href="#readme-top">🔼 Back to top</a>
270
+ </p><br><br>
271
+
272
+ <a name="primitive-conversion"></a>
273
+
274
+ ## 🔁 Primitive Conversion
275
+
276
+ `BaseModel`, `ListValueObject`, `DictValueObject`, and `UnionValueObject` can convert between primitive data and richer
277
+ types.
278
+
279
+ ```python
280
+ from value_object_pattern import BaseModel
281
+ from value_object_pattern.usables import NotEmptyStringValueObject, PositiveIntegerValueObject
282
+
283
+
284
+ class User(BaseModel):
285
+ def __init__(self, name: NotEmptyStringValueObject, age: PositiveIntegerValueObject) -> None:
286
+ self.name = name
287
+ self.age = age
288
+
289
+
290
+ user = User.from_primitives(primitives={'name': 'Ada', 'age': 42})
291
+
292
+ assert isinstance(user.name, NotEmptyStringValueObject)
293
+ assert user.to_primitives() == {'age': 42, 'name': 'Ada'}
294
+ ```
295
+
296
+ More details are available in [`docs/conversion/README.md`](docs/conversion/README.md).
297
+
298
+ <p align="right">
299
+ <a href="#readme-top">🔼 Back to top</a>
300
+ </p><br><br>
301
+
302
+ <a name="contributing"></a>
303
+
304
+ ## 🤝 Contributing
305
+
306
+ We love community help! Before you open an issue or pull request, please read:
307
+
308
+ - [`🤝 How to Contribute`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/CONTRIBUTING.md)
309
+ - [`🧭 Code of Conduct`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/CODE_OF_CONDUCT.md)
310
+ - [`🔐 Security Policy`](https://github.com/adriamontoto/value-object-pattern/blob/master/.github/SECURITY.md)
311
+
312
+ _Thank you for helping make **📦 Value Object Pattern** package awesome! 🌟_
313
+
314
+ <p align="right">
315
+ <a href="#readme-top">🔼 Back to top</a>
316
+ </p><br><br>
317
+
318
+ <a name="license"></a>
319
+
320
+ ## 🔑 License
321
+
322
+ This project is licensed under the terms of the [`MIT license`](https://github.com/adriamontoto/value-object-pattern/blob/master/LICENSE.md).
323
+
324
+ <p align="right">
325
+ <a href="#readme-top">🔼 Back to top</a>
326
+ </p>