value-object-pattern 1.30.0__tar.gz → 1.31.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 (187) hide show
  1. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/.gitignore +1 -0
  2. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/PKG-INFO +4 -4
  3. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/README.md +3 -3
  4. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/__init__.py +1 -1
  5. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/collections/dict_value_object.py +186 -18
  6. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/collections/list_value_object.py +141 -10
  7. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/union_value_object.py +141 -10
  8. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/LICENSE.md +0 -0
  9. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/pyproject.toml +0 -0
  10. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/decorators/__init__.py +0 -0
  11. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/decorators/classproperty.py +0 -0
  12. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/decorators/value_object_process.py +0 -0
  13. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/decorators/value_object_validation.py +0 -0
  14. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/__init__.py +0 -0
  15. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/base_model.py +0 -0
  16. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/collections/__init__.py +0 -0
  17. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/enumeration_value_object.py +0 -0
  18. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/primitive_conversion.py +0 -0
  19. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/type_matching.py +0 -0
  20. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/models/value_object.py +0 -0
  21. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/py.typed +0 -0
  22. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/__init__.py +0 -0
  23. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/__init__.py +0 -0
  24. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/date/__init__.py +0 -0
  25. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/date/date_value_object.py +0 -0
  26. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/date/string_date_value_object.py +0 -0
  27. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/datetime/__init__.py +0 -0
  28. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/datetime/datetime_value_object.py +0 -0
  29. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +0 -0
  30. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/timezone/__init__.py +0 -0
  31. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/timezone/string_timezone_value_object.py +0 -0
  32. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/dates/timezone/timezone_value_object.py +0 -0
  33. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/__init__.py +0 -0
  34. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/__init__.py +0 -0
  35. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v1_value_object.py +0 -0
  36. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v3_value_object.py +0 -0
  37. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v4_value_object.py +0 -0
  38. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v5_value_object.py +0 -0
  39. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v6_value_object.py +0 -0
  40. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v7_value_object.py +0 -0
  41. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v8_value_object.py +0 -0
  42. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_value_object.py +0 -0
  43. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v1_value_object.py +0 -0
  44. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v3_value_object.py +0 -0
  45. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v4_value_object.py +0 -0
  46. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v5_value_object.py +0 -0
  47. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v6_value_object.py +0 -0
  48. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v7_value_object.py +0 -0
  49. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_v8_value_object.py +0 -0
  50. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/uuid/uuid_value_object.py +0 -0
  51. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/__init__.py +0 -0
  52. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/country_tld_value_object.py +0 -0
  53. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/__init__.py +0 -0
  54. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/__init__.py +0 -0
  55. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/dni_value_object.py +0 -0
  56. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/nie_value_object.py +0 -0
  57. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/nif_value_object.py +0 -0
  58. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/nuss_value_object.py +0 -0
  59. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/passport_value_object.py +0 -0
  60. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/phone_number_value_object.py +0 -0
  61. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/__init__.py +0 -0
  62. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/administrative_technician_vehicle_plate_value_object.py +0 -0
  63. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/air_force_vehicle_plate_value_object.py +0 -0
  64. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/army_vehicle_plate_value_object.py +0 -0
  65. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/canarias_police_vehicle_plate_value_object.py +0 -0
  66. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/catalan_police_vehicle_plate_value_object.py +0 -0
  67. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/civil_guard_vehicle_plate_value_object.py +0 -0
  68. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/consular_corps_vehicle_plate_value_object.py +0 -0
  69. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/diplomatic_corps_vehicle_plate_value_object.py +0 -0
  70. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/especial_plate_vehicle_plate_value_object.py +0 -0
  71. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/historical_vehicle_plate_value_object.py +0 -0
  72. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/international_organization_vehicle_plate_value_object.py +0 -0
  73. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_development_vehicle_plate_value_object.py +0 -0
  74. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_environment_vehicle_plate_value_object.py +0 -0
  75. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/national_police_vehicle_plate_value_object.py +0 -0
  76. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/navy_vehicle_plate_value_object.py +0 -0
  77. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_truck_vehicle_plate_value_object.py +0 -0
  78. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_vehicle_plate_value_object.py +0 -0
  79. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/provincial_system_vehicle_plate_value_object.py +0 -0
  80. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/state_motor_pool_vehicle_plate_value_object.py +0 -0
  81. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_not_registered_vehicle_plate_value_object.py +0 -0
  82. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_company_registered_vehicle_plate_value_object.py +0 -0
  83. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/temporal_private_individual_vehicle_plate_value_object.py +0 -0
  84. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/two_wheels_vehicle_plate_value_object.py +0 -0
  85. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/__init__.py +0 -0
  86. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/provincial_plate_codes.txt +0 -0
  87. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/__init__.py +0 -0
  88. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/provincial_codes.txt +0 -0
  89. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/europe/spain/vehicle_plate_value_object.py +0 -0
  90. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha2_code_value_object.py +0 -0
  91. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha3_code_value_object.py +0 -0
  92. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/iso3166_numeric_code_value_object.py +0 -0
  93. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/phone_code_value_object.py +0 -0
  94. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/__init__.py +0 -0
  95. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_codes.txt +0 -0
  96. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_alpha3_mapping.txt +0 -0
  97. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_numeric_mapping.txt +0 -0
  98. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_phone_code_mapping.txt +0 -0
  99. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_tld_mapping.txt +0 -0
  100. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha3_codes.txt +0 -0
  101. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_numeric_codes.txt +0 -0
  102. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/identifiers/world/vin_value_object.py +0 -0
  103. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/__init__.py +0 -0
  104. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/aws_cloud_region_value_object.py +0 -0
  105. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/domain_value_object.py +0 -0
  106. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/email_address_value_object.py +0 -0
  107. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/host_value_object.py +0 -0
  108. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/ip_address_value_object.py +0 -0
  109. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/ipv4_address_value_object.py +0 -0
  110. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/ipv4_network_value_object.py +0 -0
  111. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/ipv6_address_value_object.py +0 -0
  112. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/ipv6_network_value_object.py +0 -0
  113. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/keys/__init__.py +0 -0
  114. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/keys/kebab_case_key_value_object.py +0 -0
  115. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/keys/snake_case_key_value_object.py +0 -0
  116. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_address_value_object.py +0 -0
  117. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/__init__.py +0 -0
  118. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/cisco_mac_address_value_object.py +0 -0
  119. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/raw_mac_address_value_object.py +0 -0
  120. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/space_mac_address_value_object.py +0 -0
  121. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/universal_mac_address_value_object.py +0 -0
  122. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mac_addresses/windows_mac_address_value_object.py +0 -0
  123. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mobile/__init__.py +0 -0
  124. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/mobile/imei_value_object.py +0 -0
  125. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/port_value_object.py +0 -0
  126. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/slug_value_object.py +0 -0
  127. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/uri/__init__.py +0 -0
  128. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/uri/http_https_url_value_object.py +0 -0
  129. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/uri/http_url_value_object.py +0 -0
  130. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/uri/https_url_value_object.py +0 -0
  131. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/uri/url_value_object.py +0 -0
  132. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/user_agent_value_object.py +0 -0
  133. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/utils/__init__.py +0 -0
  134. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/utils/aws_regions.txt +0 -0
  135. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/internet/utils/tld_domains.txt +0 -0
  136. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/__init__.py +0 -0
  137. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_card_value_object.py +0 -0
  138. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_cards/__init__.py +0 -0
  139. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_cards/amex_credit_card_value_object.py +0 -0
  140. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_cards/discover_credit_card_value_object.py +0 -0
  141. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_cards/mastercard_credit_card_value_object.py +0 -0
  142. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/credit_cards/visa_credit_card_value_object.py +0 -0
  143. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/iban_value_object.py +0 -0
  144. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/utils/__init__.py +0 -0
  145. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/money/utils/iban_lengths.txt +0 -0
  146. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/__init__.py +0 -0
  147. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/boolean/__init__.py +0 -0
  148. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/boolean/boolean_value_object.py +0 -0
  149. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/boolean/false_value_object.py +0 -0
  150. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/boolean/true_value_object.py +0 -0
  151. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/bytes/__init__.py +0 -0
  152. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/bytes/bytes_value_object.py +0 -0
  153. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/__init__.py +0 -0
  154. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/float_value_object.py +0 -0
  155. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/negative_float_value_object.py +0 -0
  156. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/negative_or_zero_float_value_object.py +0 -0
  157. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/positive_float_value_object.py +0 -0
  158. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/float/positive_or_zero_float_value_object.py +0 -0
  159. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/__init__.py +0 -0
  160. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/even_integer_value_object.py +0 -0
  161. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/integer_value_object.py +0 -0
  162. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +0 -0
  163. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/negative_or_zero_integer_value_object.py +0 -0
  164. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +0 -0
  165. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +0 -0
  166. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/integer/positive_or_zero_integer_value_object.py +0 -0
  167. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/none/__init__.py +0 -0
  168. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/none/none_value_object.py +0 -0
  169. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/none/not_none_value_object.py +0 -0
  170. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/__init__.py +0 -0
  171. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/alpha_value_object.py +0 -0
  172. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +0 -0
  173. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/camel_case_string_value_object.py +0 -0
  174. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/digit_value_object.py +0 -0
  175. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/kebab_case_string_value_object.py +0 -0
  176. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +0 -0
  177. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +0 -0
  178. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/pascal_case_string_value_object.py +0 -0
  179. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/printable_string_value_object.py +0 -0
  180. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/screaming_snake_case_string_value_object.py +0 -0
  181. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/secret_string_value_object.py +0 -0
  182. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/snake_case_string_value_object.py +0 -0
  183. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/string_value_object.py +0 -0
  184. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +0 -0
  185. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +0 -0
  186. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/utils/__init__.py +0 -0
  187. {value_object_pattern-1.30.0 → value_object_pattern-1.31.0}/value_object_pattern/usables/utils/luhn_validation.py +0 -0
@@ -12,3 +12,4 @@ htmlcov/
12
12
 
13
13
  # environment folders
14
14
  **.venv**
15
+ **.agents/skills**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: value-object-pattern
3
- Version: 1.30.0
3
+ Version: 1.31.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
@@ -262,10 +262,10 @@ low-level operations, and boundary examples.
262
262
  | --- | --- |
263
263
  | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
264
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. |
265
+ | `UnionValueObject[T]` | Accepts and converts values that match a union annotation; supports subclass and inline construction. |
266
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. |
267
+ | `ListValueObject[T]` | Immutable typed list wrapper; supports subclass and inline construction. |
268
+ | `DictValueObject[K, V]` | Immutable typed dictionary wrapper; supports subclass and inline construction. |
269
269
 
270
270
  See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
271
271
 
@@ -237,10 +237,10 @@ low-level operations, and boundary examples.
237
237
  | --- | --- |
238
238
  | `ValueObject[T]` | Base class for immutable validated single-value wrappers. |
239
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. |
240
+ | `UnionValueObject[T]` | Accepts and converts values that match a union annotation; supports subclass and inline construction. |
241
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. |
242
+ | `ListValueObject[T]` | Immutable typed list wrapper; supports subclass and inline construction. |
243
+ | `DictValueObject[K, V]` | Immutable typed dictionary wrapper; supports subclass and inline construction. |
244
244
 
245
245
  See [`docs/usage/README.md`](docs/usage/README.md) for examples of each model.
246
246
 
@@ -1,4 +1,4 @@
1
- __version__ = '1.30.0'
1
+ __version__ = '1.31.0'
2
2
 
3
3
  from .decorators import process, validation
4
4
  from .models import BaseModel, EnumerationValueObject, UnionValueObject, ValueObject
@@ -14,7 +14,20 @@ else:
14
14
  from collections.abc import Iterator
15
15
  from inspect import isclass
16
16
  from types import UnionType
17
- from typing import Any, Generic, ItemsView, KeysView, NoReturn, Self, TypeVar, Union, ValuesView, get_args, get_origin
17
+ from typing import (
18
+ Any,
19
+ ClassVar,
20
+ Generic,
21
+ ItemsView,
22
+ KeysView,
23
+ NoReturn,
24
+ Self,
25
+ TypeVar,
26
+ Union,
27
+ ValuesView,
28
+ get_args,
29
+ get_origin,
30
+ )
18
31
 
19
32
  from value_object_pattern.decorators import validation
20
33
  from value_object_pattern.models import ValueObject
@@ -25,6 +38,154 @@ K = TypeVar('K', bound=Any)
25
38
  V = TypeVar('V', bound=Any)
26
39
 
27
40
 
41
+ def _validate_dict_type_argument(*, type_argument: Any) -> None:
42
+ """
43
+ Validate a type argument used by DictValueObject.
44
+
45
+ Args:
46
+ type_argument: The type argument to validate.
47
+
48
+ Raises:
49
+ TypeError: If the type argument is not a type-like annotation.
50
+ """
51
+ if isinstance(type_argument, TypeVar):
52
+ return
53
+
54
+ if type(type_argument) is not type and not isclass(object=type_argument) and get_origin(tp=type_argument) is None:
55
+ raise TypeError(f'DictValueObject[...] <<<{type_argument}>>> must be a type. Got <<<{type(type_argument).__name__}>>> type.') # noqa: E501 # fmt: skip
56
+
57
+
58
+ def _parse_dict_type_arguments(*, type_arguments: Any) -> tuple[Any, Any]:
59
+ """
60
+ Return key and value type arguments from `DictValueObject[K, V]` input.
61
+
62
+ Args:
63
+ type_arguments: The raw type arguments passed to `DictValueObject[...]`.
64
+
65
+ Raises:
66
+ TypeError: If exactly two type arguments are not provided.
67
+
68
+ Returns:
69
+ tuple[Any, Any]: The key and value type arguments.
70
+ """
71
+ if not isinstance(type_arguments, tuple):
72
+ raise TypeError('DictValueObject must be parameterised, e.g. `class StrIntDict(DictValueObject[str, int])`.')
73
+
74
+ if len(type_arguments) != 2:
75
+ raise TypeError('DictValueObject must be parameterised, e.g. `class StrIntDict(DictValueObject[str, int])`.')
76
+
77
+ key_type, value_type = type_arguments
78
+
79
+ return key_type, value_type
80
+
81
+
82
+ class _DictValueObjectAlias:
83
+ """
84
+ Runtime alias returned by `DictValueObject[K, V]`.
85
+
86
+ Key and value types must be available before `ValueObject.__init__` validates the dictionary. This alias keeps
87
+ subclass declarations working through `__mro_entries__` and supports direct inline construction by creating a
88
+ parameterized runtime subclass before validation starts.
89
+ """
90
+
91
+ _runtime_classes: ClassVar[dict[Any, type[DictValueObject[Any, Any]]]] = {}
92
+
93
+ def __init__(self, *, origin: type[DictValueObject[Any, Any]], key_type: Any, value_type: Any) -> None:
94
+ """
95
+ Create a runtime alias for a parameterized DictValueObject.
96
+
97
+ Args:
98
+ origin: The original DictValueObject class.
99
+ key_type: The key type argument used in `DictValueObject[K, V]`.
100
+ value_type: The value type argument used in `DictValueObject[K, V]`.
101
+ """
102
+ self.__origin__ = origin
103
+ self.__args__ = (key_type, value_type)
104
+
105
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
106
+ """
107
+ Construct an inline parameterized DictValueObject instance.
108
+
109
+ Args:
110
+ *args: Positional arguments passed to the generated value object subclass.
111
+ **kwargs: Keyword arguments passed to the generated value object subclass.
112
+
113
+ Returns:
114
+ Any: The constructed value object.
115
+ """
116
+ return self._runtime_class()(*args, **kwargs)
117
+
118
+ def __getattr__(self, name: str) -> Any:
119
+ """
120
+ Delegate class attribute access to the generated runtime subclass.
121
+
122
+ Args:
123
+ name: The attribute name to retrieve.
124
+
125
+ Returns:
126
+ Any: The resolved attribute.
127
+ """
128
+ return getattr(self._runtime_class(), name)
129
+
130
+ def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type[DictValueObject[Any, Any]], ...]:
131
+ """
132
+ Return the origin class when the alias is used as a base class.
133
+
134
+ Args:
135
+ bases: The original class bases supplied by Python.
136
+
137
+ Returns:
138
+ tuple[type[DictValueObject[Any, Any]], ...]: The base classes to use for MRO construction.
139
+ """
140
+ _ = bases
141
+
142
+ return (self.__origin__,)
143
+
144
+ def _runtime_class(self) -> type[DictValueObject[Any, Any]]:
145
+ """
146
+ Return the generated runtime subclass for this alias.
147
+
148
+ Returns:
149
+ type[DictValueObject[Any, Any]]: The runtime subclass.
150
+ """
151
+ key_type, value_type = self.__args__
152
+ _validate_dict_type_argument(type_argument=key_type)
153
+ _validate_dict_type_argument(type_argument=value_type)
154
+ key = (self.__origin__, key_type, value_type)
155
+ if key not in self._runtime_classes:
156
+ self._runtime_classes[key] = type(
157
+ f'{self.__origin__.__name__}[{self._format_type_argument(type=key_type)}, {self._format_type_argument(type=value_type)}]', # noqa: E501
158
+ (self.__origin__,),
159
+ {
160
+ '_is_inline_parameterized_dict_value_object': True,
161
+ '_key_type': key_type,
162
+ '_value_type': value_type,
163
+ },
164
+ )
165
+
166
+ return self._runtime_classes[key]
167
+
168
+ @staticmethod
169
+ def _format_type_argument(*, type: Any) -> str:
170
+ """
171
+ Return a compact type-argument label for generated runtime class names.
172
+
173
+ Args:
174
+ type: The type argument to format.
175
+
176
+ Returns:
177
+ str: A readable type label.
178
+ """
179
+ origin = get_origin(tp=type)
180
+ if origin in (Union, UnionType):
181
+ return ' | '.join(_DictValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
182
+
183
+ if hasattr(type, '__name__'):
184
+ return type.__name__ # type: ignore[no-any-return]
185
+
186
+ return str(type).replace('typing.', '')
187
+
188
+
28
189
  class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
29
190
  """
30
191
  Validate dictionary values, keys, and items against declared key and value types.
@@ -54,6 +215,21 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
54
215
  _key_type: K
55
216
  _value_type: V
56
217
 
218
+ @classmethod
219
+ def __class_getitem__(cls, item: Any) -> Any:
220
+ """
221
+ Return a runtime alias that supports subclassing and inline construction.
222
+
223
+ Args:
224
+ item: The type arguments used in `DictValueObject[item]`.
225
+
226
+ Returns:
227
+ Any: A runtime alias for the parameterized DictValueObject.
228
+ """
229
+ key_type, value_type = _parse_dict_type_arguments(type_arguments=item)
230
+
231
+ return _DictValueObjectAlias(origin=cls, key_type=key_type, value_type=value_type)
232
+
57
233
  @override
58
234
  def __init_subclass__(cls, **kwargs: Any) -> None:
59
235
  """
@@ -69,25 +245,17 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
69
245
  """
70
246
  super().__init_subclass__(**kwargs)
71
247
 
72
- for base in getattr(cls, '__orig_bases__', ()):
73
- if get_origin(base) is DictValueObject:
74
- key_type, val_type, *_ = get_args(base)
75
-
76
- if isinstance(key_type, TypeVar):
77
- cls._key_type = key_type # type: ignore[assignment]
78
- else:
79
- if type(key_type) is not type and not isclass(key_type) and get_origin(key_type) is None:
80
- raise TypeError(f'DictValueObject[...] <<<{key_type}>>> must be a type. Got <<<{type(key_type).__name__}>>> type.') # noqa: E501 # fmt: skip
81
-
82
- cls._key_type = key_type
248
+ if getattr(cls, '_is_inline_parameterized_dict_value_object', False):
249
+ return
83
250
 
84
- if isinstance(val_type, TypeVar):
85
- cls._value_type = val_type # type: ignore[assignment]
86
- else:
87
- if type(val_type) is not type and not isclass(val_type) and get_origin(val_type) is None:
88
- raise TypeError(f'DictValueObject[...] <<<{val_type}>>> must be a type. Got <<<{type(val_type).__name__}>>> type.') # noqa: E501 # fmt: skip
251
+ for base in getattr(cls, '__orig_bases__', ()):
252
+ if get_origin(base) is DictValueObject or getattr(base, '__origin__', None) is DictValueObject:
253
+ key_type, val_type = get_args(base) or base.__args__
89
254
 
90
- cls._value_type = val_type
255
+ _validate_dict_type_argument(type_argument=key_type)
256
+ cls._key_type = key_type
257
+ _validate_dict_type_argument(type_argument=val_type)
258
+ cls._value_type = val_type
91
259
 
92
260
  return
93
261
 
@@ -15,7 +15,7 @@ from collections.abc import Iterator
15
15
  from enum import Enum
16
16
  from inspect import isclass
17
17
  from types import UnionType
18
- from typing import Any, Generic, NoReturn, Self, TypeVar, Union, get_args, get_origin
18
+ from typing import Any, ClassVar, Generic, NoReturn, Self, TypeVar, Union, get_args, get_origin
19
19
 
20
20
  from value_object_pattern.decorators import validation
21
21
  from value_object_pattern.models import BaseModel, ValueObject
@@ -25,6 +25,127 @@ from value_object_pattern.models.type_matching import matches_expected_type
25
25
  T = TypeVar('T', bound=Any)
26
26
 
27
27
 
28
+ def _validate_list_type_argument(*, type_argument: Any) -> None:
29
+ """
30
+ Validate a type argument used by ListValueObject.
31
+
32
+ Args:
33
+ type_argument: The type argument to validate.
34
+
35
+ Raises:
36
+ TypeError: If the type argument is not a type-like annotation.
37
+ """
38
+ if isinstance(type_argument, TypeVar):
39
+ return
40
+
41
+ if type(type_argument) is not type and not isclass(object=type_argument) and get_origin(tp=type_argument) is None:
42
+ raise TypeError(f'ListValueObject[...] <<<{type_argument}>>> must be a type. Got <<<{type(type_argument).__name__}>>> type.') # noqa: E501 # fmt: skip
43
+
44
+
45
+ class _ListValueObjectAlias:
46
+ """
47
+ Runtime alias returned by `ListValueObject[T]`.
48
+
49
+ The item type must be available before `ValueObject.__init__` validates the list. This alias keeps subclass
50
+ declarations working through `__mro_entries__` and supports direct inline construction by creating a parameterized
51
+ runtime subclass before validation starts.
52
+ """
53
+
54
+ _runtime_classes: ClassVar[dict[Any, type[ListValueObject[Any]]]] = {}
55
+
56
+ def __init__(self, *, origin: type[ListValueObject[Any]], type_argument: Any) -> None:
57
+ """
58
+ Create a runtime alias for a parameterized ListValueObject.
59
+
60
+ Args:
61
+ origin: The original ListValueObject class.
62
+ type_argument: The type argument used in `ListValueObject[T]`.
63
+ """
64
+ self.__origin__ = origin
65
+ self.__args__ = (type_argument,)
66
+
67
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
68
+ """
69
+ Construct an inline parameterized ListValueObject instance.
70
+
71
+ Args:
72
+ *args: Positional arguments passed to the generated value object subclass.
73
+ **kwargs: Keyword arguments passed to the generated value object subclass.
74
+
75
+ Returns:
76
+ Any: The constructed value object.
77
+ """
78
+ return self._runtime_class()(*args, **kwargs)
79
+
80
+ def __getattr__(self, name: str) -> Any:
81
+ """
82
+ Delegate class attribute access to the generated runtime subclass.
83
+
84
+ Args:
85
+ name: The attribute name to retrieve.
86
+
87
+ Returns:
88
+ Any: The resolved attribute.
89
+ """
90
+ return getattr(self._runtime_class(), name)
91
+
92
+ def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type[ListValueObject[Any]], ...]:
93
+ """
94
+ Return the origin class when the alias is used as a base class.
95
+
96
+ Args:
97
+ bases: The original class bases supplied by Python.
98
+
99
+ Returns:
100
+ tuple[type[ListValueObject[Any]], ...]: The base classes to use for MRO construction.
101
+ """
102
+ _ = bases
103
+
104
+ return (self.__origin__,)
105
+
106
+ def _runtime_class(self) -> type[ListValueObject[Any]]:
107
+ """
108
+ Return the generated runtime subclass for this alias.
109
+
110
+ Returns:
111
+ type[ListValueObject[Any]]: The runtime subclass.
112
+ """
113
+ type_argument, *_ = self.__args__
114
+ _validate_list_type_argument(type_argument=type_argument)
115
+ key = (self.__origin__, type_argument)
116
+ if key not in self._runtime_classes:
117
+ self._runtime_classes[key] = type(
118
+ f'{self.__origin__.__name__}[{self._format_type_argument(type=type_argument)}]',
119
+ (self.__origin__,),
120
+ {
121
+ '_is_inline_parameterized_list_value_object': True,
122
+ '_type': type_argument,
123
+ },
124
+ )
125
+
126
+ return self._runtime_classes[key]
127
+
128
+ @staticmethod
129
+ def _format_type_argument(*, type: Any) -> str:
130
+ """
131
+ Return a compact type-argument label for generated runtime class names.
132
+
133
+ Args:
134
+ type: The type argument to format.
135
+
136
+ Returns:
137
+ str: A readable type label.
138
+ """
139
+ origin = get_origin(tp=type)
140
+ if origin in (Union, UnionType):
141
+ return ' | '.join(_ListValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
142
+
143
+ if hasattr(type, '__name__'):
144
+ return type.__name__ # type: ignore[no-any-return]
145
+
146
+ return str(type).replace('typing.', '')
147
+
148
+
28
149
  class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
29
150
  """
30
151
  Validate list values and every item against the declared item type.
@@ -50,6 +171,19 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
50
171
 
51
172
  _type: T
52
173
 
174
+ @classmethod
175
+ def __class_getitem__(cls, item: Any) -> Any:
176
+ """
177
+ Return a runtime alias that supports subclassing and inline construction.
178
+
179
+ Args:
180
+ item: The type argument used in `ListValueObject[item]`.
181
+
182
+ Returns:
183
+ Any: A runtime alias for the parameterized ListValueObject.
184
+ """
185
+ return _ListValueObjectAlias(origin=cls, type_argument=item)
186
+
53
187
  @override
54
188
  def __init_subclass__(cls, **kwargs: Any) -> None:
55
189
  """
@@ -64,17 +198,14 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
64
198
  """
65
199
  super().__init_subclass__(**kwargs)
66
200
 
67
- for base in getattr(cls, '__orig_bases__', ()):
68
- if get_origin(tp=base) is ListValueObject:
69
- _type, *_ = get_args(tp=base)
70
-
71
- if isinstance(_type, TypeVar):
72
- cls._type = _type # type: ignore[assignment]
73
- return
201
+ if getattr(cls, '_is_inline_parameterized_list_value_object', False):
202
+ return
74
203
 
75
- if type(_type) is not type and not isclass(object=_type) and get_origin(tp=_type) is None:
76
- raise TypeError(f'ListValueObject[...] <<<{_type}>>> must be a type. Got <<<{type(_type).__name__}>>> type.') # noqa: E501 # fmt: skip
204
+ for base in getattr(cls, '__orig_bases__', ()):
205
+ if get_origin(tp=base) is ListValueObject or getattr(base, '__origin__', None) is ListValueObject:
206
+ _type, *_ = get_args(tp=base) or base.__args__
77
207
 
208
+ _validate_list_type_argument(type_argument=_type)
78
209
  cls._type = _type
79
210
  return
80
211
 
@@ -14,7 +14,7 @@ else:
14
14
  from enum import Enum
15
15
  from inspect import isclass
16
16
  from types import UnionType
17
- from typing import Any, Generic, NoReturn, Self, TypeVar, Union, get_args, get_origin
17
+ from typing import Any, ClassVar, Generic, NoReturn, Self, TypeVar, Union, get_args, get_origin
18
18
 
19
19
  from value_object_pattern.decorators import process, validation
20
20
 
@@ -26,6 +26,127 @@ from .value_object import ValueObject
26
26
  T = TypeVar('T', bound=Any)
27
27
 
28
28
 
29
+ def _validate_union_type_argument(*, type_argument: Any) -> None:
30
+ """
31
+ Validate a type argument used by UnionValueObject.
32
+
33
+ Args:
34
+ type_argument: The type argument to validate.
35
+
36
+ Raises:
37
+ TypeError: If the type argument is not a type-like annotation.
38
+ """
39
+ if isinstance(type_argument, TypeVar):
40
+ return
41
+
42
+ if type(type_argument) is not type and not isclass(object=type_argument) and get_origin(tp=type_argument) is None:
43
+ raise TypeError(f'UnionValueObject[...] <<<{type_argument}>>> must be a type. Got <<<{type(type_argument).__name__}>>> type.') # noqa: E501 # fmt: skip
44
+
45
+
46
+ class _UnionValueObjectAlias:
47
+ """
48
+ Runtime alias returned by `UnionValueObject[T]`.
49
+
50
+ Python assigns `__orig_class__` only after `__init__` completes, but union conversion needs the type parameter
51
+ during `ValueObject.__init__`. This alias keeps subclass declarations working through `__mro_entries__` and supports
52
+ direct inline construction by creating a parameterized runtime subclass before validation starts.
53
+ """
54
+
55
+ _runtime_classes: ClassVar[dict[Any, type[UnionValueObject[Any]]]] = {}
56
+
57
+ def __init__(self, *, origin: type[UnionValueObject[Any]], type_argument: Any) -> None:
58
+ """
59
+ Create a runtime alias for a parameterized UnionValueObject.
60
+
61
+ Args:
62
+ origin: The original UnionValueObject class.
63
+ type_argument: The type argument used in `UnionValueObject[T]`.
64
+ """
65
+ self.__origin__ = origin
66
+ self.__args__ = (type_argument,)
67
+
68
+ def __call__(self, *args: Any, **kwargs: Any) -> Any:
69
+ """
70
+ Construct an inline parameterized UnionValueObject instance.
71
+
72
+ Args:
73
+ *args: Positional arguments passed to the generated value object subclass.
74
+ **kwargs: Keyword arguments passed to the generated value object subclass.
75
+
76
+ Returns:
77
+ Any: The constructed value object.
78
+ """
79
+ return self._runtime_class()(*args, **kwargs)
80
+
81
+ def __getattr__(self, name: str) -> Any:
82
+ """
83
+ Delegate class attribute access to the generated runtime subclass.
84
+
85
+ Args:
86
+ name: The attribute name to retrieve.
87
+
88
+ Returns:
89
+ Any: The resolved attribute.
90
+ """
91
+ return getattr(self._runtime_class(), name)
92
+
93
+ def __mro_entries__(self, bases: tuple[type, ...]) -> tuple[type[UnionValueObject[Any]], ...]:
94
+ """
95
+ Return the origin class when the alias is used as a base class.
96
+
97
+ Args:
98
+ bases: The original class bases supplied by Python.
99
+
100
+ Returns:
101
+ tuple[type[UnionValueObject[Any]], ...]: The base classes to use for MRO construction.
102
+ """
103
+ _ = bases
104
+
105
+ return (self.__origin__,)
106
+
107
+ def _runtime_class(self) -> type[UnionValueObject[Any]]:
108
+ """
109
+ Return the generated runtime subclass for this alias.
110
+
111
+ Returns:
112
+ type[UnionValueObject[Any]]: The runtime subclass.
113
+ """
114
+ type_argument, *_ = self.__args__
115
+ _validate_union_type_argument(type_argument=type_argument)
116
+ key = (self.__origin__, type_argument)
117
+ if key not in self._runtime_classes:
118
+ self._runtime_classes[key] = type(
119
+ f'{self.__origin__.__name__}[{self._format_type_argument(type=type_argument)}]',
120
+ (self.__origin__,),
121
+ {
122
+ '_is_inline_parameterized_union_value_object': True,
123
+ '_type': type_argument,
124
+ },
125
+ )
126
+
127
+ return self._runtime_classes[key]
128
+
129
+ @staticmethod
130
+ def _format_type_argument(*, type: Any) -> str:
131
+ """
132
+ Return a compact type-argument label for generated runtime class names.
133
+
134
+ Args:
135
+ type: The type argument to format.
136
+
137
+ Returns:
138
+ str: A readable type label.
139
+ """
140
+ origin = get_origin(tp=type)
141
+ if origin in (Union, UnionType):
142
+ return ' | '.join(_UnionValueObjectAlias._format_type_argument(type=allowed) for allowed in get_args(type))
143
+
144
+ if hasattr(type, '__name__'):
145
+ return type.__name__ # type: ignore[no-any-return]
146
+
147
+ return str(type).replace('typing.', '')
148
+
149
+
29
150
  class UnionValueObject(ValueObject[T], Generic[T]): # noqa: UP046
30
151
  """
31
152
  Validate and store a value as one of the allowed union candidates.
@@ -66,6 +187,19 @@ class UnionValueObject(ValueObject[T], Generic[T]): # noqa: UP046
66
187
 
67
188
  _type: T
68
189
 
190
+ @classmethod
191
+ def __class_getitem__(cls, item: Any) -> Any:
192
+ """
193
+ Return a runtime alias that supports subclassing and inline construction.
194
+
195
+ Args:
196
+ item: The type argument used in `UnionValueObject[item]`.
197
+
198
+ Returns:
199
+ Any: A runtime alias for the parameterized UnionValueObject.
200
+ """
201
+ return _UnionValueObjectAlias(origin=cls, type_argument=item)
202
+
69
203
  @override
70
204
  def __init_subclass__(cls, **kwargs: Any) -> None:
71
205
  """
@@ -80,17 +214,14 @@ class UnionValueObject(ValueObject[T], Generic[T]): # noqa: UP046
80
214
  """
81
215
  super().__init_subclass__(**kwargs)
82
216
 
83
- for base in getattr(cls, '__orig_bases__', ()):
84
- if get_origin(tp=base) is UnionValueObject:
85
- _type, *_ = get_args(tp=base)
86
-
87
- if isinstance(_type, TypeVar):
88
- cls._type = _type # type: ignore[assignment]
89
- return
217
+ if getattr(cls, '_is_inline_parameterized_union_value_object', False):
218
+ return
90
219
 
91
- if type(_type) is not type and not isclass(object=_type) and get_origin(tp=_type) is None:
92
- raise TypeError(f'UnionValueObject[...] <<<{_type}>>> must be a type. Got <<<{type(_type).__name__}>>> type.') # noqa: E501 # fmt: skip
220
+ for base in getattr(cls, '__orig_bases__', ()):
221
+ if get_origin(tp=base) is UnionValueObject or getattr(base, '__origin__', None) is UnionValueObject:
222
+ _type, *_ = get_args(tp=base) or base.__args__
93
223
 
224
+ _validate_union_type_argument(type_argument=_type)
94
225
  cls._type = _type
95
226
  return
96
227