value-object-pattern 1.25.0__tar.gz → 1.26.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 (178) hide show
  1. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/PKG-INFO +1 -1
  2. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/__init__.py +3 -2
  3. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/decorators/value_object_process.py +1 -1
  4. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/decorators/value_object_validation.py +1 -1
  5. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/__init__.py +2 -0
  6. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/base_model.py +82 -29
  7. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/collections/dict_value_object.py +31 -157
  8. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/collections/list_value_object.py +25 -82
  9. value_object_pattern-1.26.0/value_object_pattern/models/primitive_conversion.py +438 -0
  10. value_object_pattern-1.26.0/value_object_pattern/models/type_matching.py +51 -0
  11. value_object_pattern-1.26.0/value_object_pattern/models/union_value_object.py +294 -0
  12. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/.gitignore +0 -0
  13. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/LICENSE.md +0 -0
  14. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/README.md +0 -0
  15. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/pyproject.toml +0 -0
  16. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/decorators/__init__.py +0 -0
  17. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/decorators/classproperty.py +0 -0
  18. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/collections/__init__.py +0 -0
  19. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/enumeration_value_object.py +0 -0
  20. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/models/value_object.py +0 -0
  21. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/py.typed +0 -0
  22. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/__init__.py +0 -0
  23. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/__init__.py +0 -0
  24. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/date/__init__.py +0 -0
  25. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/date/date_value_object.py +0 -0
  26. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/date/string_date_value_object.py +0 -0
  27. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/datetime/__init__.py +0 -0
  28. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/datetime/datetime_value_object.py +0 -0
  29. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +0 -0
  30. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/timezone/__init__.py +0 -0
  31. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/timezone/string_timezone_value_object.py +0 -0
  32. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/dates/timezone/timezone_value_object.py +0 -0
  33. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/__init__.py +0 -0
  34. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/__init__.py +0 -0
  35. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v1_value_object.py +0 -0
  36. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v3_value_object.py +0 -0
  37. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v4_value_object.py +0 -0
  38. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v5_value_object.py +0 -0
  39. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v6_value_object.py +0 -0
  40. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v7_value_object.py +0 -0
  41. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_v8_value_object.py +0 -0
  42. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/string_uuid_value_object.py +0 -0
  43. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v1_value_object.py +0 -0
  44. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v3_value_object.py +0 -0
  45. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v4_value_object.py +0 -0
  46. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v5_value_object.py +0 -0
  47. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v6_value_object.py +0 -0
  48. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v7_value_object.py +0 -0
  49. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_v8_value_object.py +0 -0
  50. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/uuid/uuid_value_object.py +0 -0
  51. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/__init__.py +0 -0
  52. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/country_tld_value_object.py +0 -0
  53. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/__init__.py +0 -0
  54. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/__init__.py +0 -0
  55. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/dni_value_object.py +0 -0
  56. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/nie_value_object.py +0 -0
  57. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/nif_value_object.py +0 -0
  58. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/nuss_value_object.py +0 -0
  59. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/passport_value_object.py +0 -0
  60. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/phone_number_value_object.py +0 -0
  61. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/__init__.py +0 -0
  62. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/administrative_technician_vehicle_plate_value_object.py +0 -0
  63. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/air_force_vehicle_plate_value_object.py +0 -0
  64. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/army_vehicle_plate_value_object.py +0 -0
  65. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/canarias_police_vehicle_plate_value_object.py +0 -0
  66. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/catalan_police_vehicle_plate_value_object.py +0 -0
  67. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/civil_guard_vehicle_plate_value_object.py +0 -0
  68. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/consular_corps_vehicle_plate_value_object.py +0 -0
  69. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/diplomatic_corps_vehicle_plate_value_object.py +0 -0
  70. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/especial_plate_vehicle_plate_value_object.py +0 -0
  71. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/historical_vehicle_plate_value_object.py +0 -0
  72. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/international_organization_vehicle_plate_value_object.py +0 -0
  73. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_development_vehicle_plate_value_object.py +0 -0
  74. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ministry_environment_vehicle_plate_value_object.py +0 -0
  75. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/national_police_vehicle_plate_value_object.py +0 -0
  76. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/navy_vehicle_plate_value_object.py +0 -0
  77. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_truck_vehicle_plate_value_object.py +0 -0
  78. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/ordinary_vehicle_plate_value_object.py +0 -0
  79. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/provincial_system_vehicle_plate_value_object.py +0 -0
  80. {value_object_pattern-1.25.0 → value_object_pattern-1.26.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.25.0 → value_object_pattern-1.26.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.25.0 → value_object_pattern-1.26.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.25.0 → value_object_pattern-1.26.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.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/two_wheels_vehicle_plate_value_object.py +0 -0
  85. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/__init__.py +0 -0
  86. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/plates/utils/provincial_plate_codes.txt +0 -0
  87. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/__init__.py +0 -0
  88. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/utils/provincial_codes.txt +0 -0
  89. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/europe/spain/vehicle_plate_value_object.py +0 -0
  90. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha2_code_value_object.py +0 -0
  91. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/iso3166_alpha3_code_value_object.py +0 -0
  92. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/iso3166_numeric_code_value_object.py +0 -0
  93. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/phone_code_value_object.py +0 -0
  94. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/__init__.py +0 -0
  95. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_codes.txt +0 -0
  96. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_alpha3_mapping.txt +0 -0
  97. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_numeric_mapping.txt +0 -0
  98. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_phone_code_mapping.txt +0 -0
  99. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha2_to_tld_mapping.txt +0 -0
  100. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_alpha3_codes.txt +0 -0
  101. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/utils/iso3166_numeric_codes.txt +0 -0
  102. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/identifiers/world/vin_value_object.py +0 -0
  103. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/__init__.py +0 -0
  104. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/aws_cloud_region_value_object.py +0 -0
  105. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/domain_value_object.py +0 -0
  106. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/email_address_value_object.py +0 -0
  107. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/host_value_object.py +0 -0
  108. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/ip_address_value_object.py +0 -0
  109. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/ipv4_address_value_object.py +0 -0
  110. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/ipv4_network_value_object.py +0 -0
  111. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/ipv6_address_value_object.py +0 -0
  112. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/ipv6_network_value_object.py +0 -0
  113. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/key_value_object.py +0 -0
  114. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_address_value_object.py +0 -0
  115. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/__init__.py +0 -0
  116. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/cisco_mac_address_value_object.py +0 -0
  117. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/raw_mac_address_value_object.py +0 -0
  118. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/space_mac_address_value_object.py +0 -0
  119. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/universal_mac_address_value_object.py +0 -0
  120. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mac_addresses/windows_mac_address_value_object.py +0 -0
  121. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mobile/__init__.py +0 -0
  122. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/mobile/imei_value_object.py +0 -0
  123. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/port_value_object.py +0 -0
  124. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/slug_value_object.py +0 -0
  125. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/uri/__init__.py +0 -0
  126. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/uri/http_https_url_value_object.py +0 -0
  127. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/uri/http_url_value_object.py +0 -0
  128. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/uri/https_url_value_object.py +0 -0
  129. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/uri/url_value_object.py +0 -0
  130. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/utils/__init__.py +0 -0
  131. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/utils/aws_regions.txt +0 -0
  132. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/internet/utils/tld_domains.txt +0 -0
  133. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/__init__.py +0 -0
  134. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_card_value_object.py +0 -0
  135. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_cards/__init__.py +0 -0
  136. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_cards/amex_credit_card_value_object.py +0 -0
  137. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_cards/discover_credit_card_value_object.py +0 -0
  138. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_cards/mastercard_credit_card_value_object.py +0 -0
  139. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/credit_cards/visa_credit_card_value_object.py +0 -0
  140. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/iban_value_object.py +0 -0
  141. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/utils/__init__.py +0 -0
  142. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/money/utils/iban_lengths.txt +0 -0
  143. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/__init__.py +0 -0
  144. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/boolean/__init__.py +0 -0
  145. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/boolean/boolean_value_object.py +0 -0
  146. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/boolean/false_value_object.py +0 -0
  147. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/boolean/true_value_object.py +0 -0
  148. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/bytes/__init__.py +0 -0
  149. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/bytes/bytes_value_object.py +0 -0
  150. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/__init__.py +0 -0
  151. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/float_value_object.py +0 -0
  152. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/negative_float_value_object.py +0 -0
  153. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/negative_or_zero_float_value_object.py +0 -0
  154. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/positive_float_value_object.py +0 -0
  155. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/float/positive_or_zero_float_value_object.py +0 -0
  156. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/__init__.py +0 -0
  157. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/even_integer_value_object.py +0 -0
  158. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/integer_value_object.py +0 -0
  159. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +0 -0
  160. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/negative_or_zero_integer_value_object.py +0 -0
  161. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +0 -0
  162. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +0 -0
  163. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/integer/positive_or_zero_integer_value_object.py +0 -0
  164. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/none/__init__.py +0 -0
  165. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/none/none_value_object.py +0 -0
  166. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/none/not_none_value_object.py +0 -0
  167. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/__init__.py +0 -0
  168. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/alpha_value_object.py +0 -0
  169. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +0 -0
  170. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/digit_value_object.py +0 -0
  171. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +0 -0
  172. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +0 -0
  173. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/printable_string_value_object.py +0 -0
  174. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/string_value_object.py +0 -0
  175. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +0 -0
  176. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +0 -0
  177. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/utils/__init__.py +0 -0
  178. {value_object_pattern-1.25.0 → value_object_pattern-1.26.0}/value_object_pattern/usables/utils/luhn_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: value-object-pattern
3
- Version: 1.25.0
3
+ Version: 1.26.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
@@ -1,11 +1,12 @@
1
- __version__ = '1.25.0'
1
+ __version__ = '1.26.0'
2
2
 
3
3
  from .decorators import process, validation
4
- from .models import BaseModel, EnumerationValueObject, ValueObject
4
+ from .models import BaseModel, EnumerationValueObject, UnionValueObject, ValueObject
5
5
 
6
6
  __all__ = (
7
7
  'BaseModel',
8
8
  'EnumerationValueObject',
9
+ 'UnionValueObject',
9
10
  'ValueObject',
10
11
  'process',
11
12
  'validation',
@@ -64,7 +64,7 @@ def process(order: int | None = None) -> Callable[[Callable[..., T]], Callable[.
64
64
  function._is_process = True # type: ignore[attr-defined]
65
65
  function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
66
66
 
67
- @wraps(wrapped=function)
67
+ @wraps(function)
68
68
  def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> T:
69
69
  """
70
70
  Wrapper for process.
@@ -72,7 +72,7 @@ def validation(
72
72
  function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
73
73
  function._early_process = early_process # type: ignore[attr-defined]
74
74
 
75
- @wraps(wrapped=function)
75
+ @wraps(function)
76
76
  def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> None:
77
77
  """
78
78
  Wrapper for validation.
@@ -1,9 +1,11 @@
1
1
  from .base_model import BaseModel
2
2
  from .enumeration_value_object import EnumerationValueObject
3
+ from .union_value_object import UnionValueObject
3
4
  from .value_object import ValueObject
4
5
 
5
6
  __all__ = (
6
7
  'BaseModel',
7
8
  'EnumerationValueObject',
9
+ 'UnionValueObject',
8
10
  'ValueObject',
9
11
  )
@@ -13,11 +13,12 @@ else:
13
13
 
14
14
  from abc import ABC, abstractmethod
15
15
  from copy import deepcopy
16
- from enum import Enum
17
16
  from inspect import Parameter, _empty, signature
18
- from typing import Any, NoReturn, Self
17
+ from types import UnionType
18
+ from typing import Any, NoReturn, Self, Union, get_args, get_origin, get_type_hints
19
19
 
20
- from .value_object import ValueObject
20
+ from .primitive_conversion import from_primitive, to_primitive
21
+ from .type_matching import matches_expected_type
21
22
 
22
23
 
23
24
  class BaseModel(ABC):
@@ -387,7 +388,83 @@ class BaseModel(ABC):
387
388
  if missing or extra:
388
389
  cls._raise_value_constructor_parameters_mismatch(primitives=set(primitives), missing=missing, extra=extra)
389
390
 
390
- return cls(**primitives)
391
+ constructor_annotations = cls._get_constructor_annotations()
392
+ converted_primitives: dict[str, Any] = {}
393
+ for parameter_name in parameters:
394
+ if parameter_name not in primitives:
395
+ continue
396
+
397
+ expected_type = constructor_annotations.get(parameter_name, parameters[parameter_name].annotation)
398
+ converted_value = from_primitive(
399
+ value=primitives[parameter_name],
400
+ expected_type=expected_type,
401
+ )
402
+ if get_origin(tp=expected_type) in (Union, UnionType) and not matches_expected_type(
403
+ value=converted_value,
404
+ expected_type=expected_type,
405
+ ):
406
+ cls._raise_value_is_not_of_type(
407
+ parameter=parameter_name,
408
+ value=converted_value,
409
+ expected_type=expected_type,
410
+ )
411
+
412
+ converted_primitives[parameter_name] = converted_value
413
+
414
+ return cls(**converted_primitives)
415
+
416
+ @classmethod
417
+ def _get_constructor_annotations(cls) -> dict[str, Any]:
418
+ """
419
+ Returns resolved constructor annotations when available.
420
+
421
+ Returns:
422
+ dict[str, Any]: Mapping from constructor parameter names to annotations.
423
+ """
424
+ try:
425
+ return get_type_hints(cls.__init__)
426
+
427
+ except Exception:
428
+ return {}
429
+
430
+ @classmethod
431
+ def _raise_value_is_not_of_type(cls, *, parameter: str, value: Any, expected_type: Any) -> NoReturn:
432
+ """
433
+ Raises a TypeError when a primitive cannot be converted to the expected type.
434
+
435
+ Args:
436
+ parameter (str): Constructor parameter name.
437
+ value (Any): Converted value.
438
+ expected_type (Any): Expected type annotation.
439
+
440
+ Raises:
441
+ TypeError: When value is not of expected type.
442
+ """
443
+ raise TypeError(f'{cls.__name__} parameter <<<{parameter}>>> value <<<{value}>>> must be of type <<<{cls._type_label(type=expected_type)}>>> type. Got <<<{type(value).__name__}>>> type.') # noqa: E501 # fmt: skip
444
+
445
+ @staticmethod
446
+ def _type_label(*, type: Any) -> str:
447
+ """
448
+ Returns a readable label for the given type annotation.
449
+
450
+ Args:
451
+ type (Any): Type annotation.
452
+
453
+ Returns:
454
+ str: Formatted type label.
455
+ """
456
+ origin = get_origin(tp=type)
457
+ if origin in (Union, UnionType):
458
+ parts = [BaseModel._type_label(type=item) for item in get_args(type)]
459
+ return ' | '.join(parts)
460
+
461
+ if type is Any:
462
+ return 'Any'
463
+
464
+ if hasattr(type, '__name__'):
465
+ return type.__name__ # type: ignore[no-any-return]
466
+
467
+ return str(type).replace('typing.', '')
391
468
 
392
469
  @classmethod
393
470
  def _raise_value_is_not_dict_of_strings(cls, value: Any) -> NoReturn:
@@ -457,32 +534,8 @@ class BaseModel(ABC):
457
534
  # >>> {'name': 'John Doe', 'birthdate': '1900-01-01T00:00:00+00:00'}
458
535
  ```
459
536
  """
460
- primitive_types: tuple[type, ...] = (int, float, str, bool, bytes, bytearray, memoryview, type(None))
461
- collection_types: tuple[type, ...] = (list, dict, tuple, set, frozenset)
462
-
463
537
  dictionary = self._to_dict(ignore_private=True)
464
538
  for key, value in dictionary.items():
465
- if isinstance(value, BaseModel) or hasattr(value, 'to_primitives'):
466
- value = value.to_primitives()
467
-
468
- elif isinstance(value, Enum):
469
- value = value.value
470
-
471
- elif isinstance(value, ValueObject) or hasattr(value, 'value'):
472
- value = value.value
473
-
474
- if isinstance(value, Enum):
475
- value = value.value
476
-
477
- elif isinstance(value, primitive_types): # noqa: SIM114
478
- pass
479
-
480
- elif isinstance(value, collection_types):
481
- pass
482
-
483
- else:
484
- value = str(object=value)
485
-
486
- dictionary[key] = value
539
+ dictionary[key] = to_primitive(value=value)
487
540
 
488
541
  return dictionary
@@ -12,13 +12,14 @@ else:
12
12
  from typing_extensions import override # pragma: no cover
13
13
 
14
14
  from collections.abc import Iterator
15
- from enum import Enum
16
15
  from inspect import isclass
17
16
  from types import UnionType
18
17
  from typing import Any, Generic, ItemsView, KeysView, NoReturn, Self, TypeVar, Union, ValuesView, get_args, get_origin
19
18
 
20
19
  from value_object_pattern.decorators import validation
21
- from value_object_pattern.models import BaseModel, ValueObject
20
+ from value_object_pattern.models import ValueObject
21
+ from value_object_pattern.models.primitive_conversion import from_primitive, to_primitive
22
+ from value_object_pattern.models.type_matching import matches_expected_type
22
23
 
23
24
  K = TypeVar('K', bound=Any)
24
25
  V = TypeVar('V', bound=Any)
@@ -325,25 +326,8 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
325
326
  if self._key_type is Any:
326
327
  return
327
328
 
328
- origin = get_origin(tp=self._key_type)
329
- if origin in (Union, UnionType):
330
- allowed_types: list[type[Any] | UnionType] = []
331
- for allowed in get_args(self._key_type):
332
- if allowed is Any:
333
- return
334
-
335
- allowed_origin = get_origin(tp=allowed)
336
- allowed_types.append(allowed_origin or allowed)
337
-
338
- for key in value.keys(): # noqa: SIM118
339
- if not any(isinstance(key, allowed) for allowed in allowed_types):
340
- self._raise_key_is_not_of_type(value=key)
341
-
342
- return
343
-
344
- expected_type = origin or self._key_type
345
329
  for key in value.keys(): # noqa: SIM118
346
- if not isinstance(key, expected_type):
330
+ if not matches_expected_type(value=key, expected_type=self._key_type):
347
331
  self._raise_key_is_not_of_type(value=key)
348
332
 
349
333
  def _raise_key_is_not_of_type(self, value: Any) -> NoReturn:
@@ -372,25 +356,8 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
372
356
  if self._value_type is Any:
373
357
  return
374
358
 
375
- origin = get_origin(tp=self._value_type)
376
- if origin in (Union, UnionType):
377
- allowed_types: list[type[Any] | UnionType] = []
378
- for allowed in get_args(self._value_type):
379
- if allowed is Any:
380
- return
381
-
382
- allowed_origin = get_origin(tp=allowed)
383
- allowed_types.append(allowed_origin or allowed)
384
-
385
- for item in value.values():
386
- if not any(isinstance(item, allowed) for allowed in allowed_types):
387
- self._raise_value_is_not_of_type(value=item)
388
-
389
- return
390
-
391
- expected_type = origin or self._value_type
392
359
  for item in value.values():
393
- if not isinstance(item, expected_type):
360
+ if not matches_expected_type(value=item, expected_type=self._value_type):
394
361
  self._raise_value_is_not_of_type(value=item)
395
362
 
396
363
  def _raise_value_is_not_of_type(self, value: Any) -> NoReturn:
@@ -430,7 +397,7 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
430
397
  # >>> 3
431
398
  ```
432
399
  """
433
- if default is not None and not self._is_instance_of_type(value=default, expected_type=self._value_type):
400
+ if default is not None and not matches_expected_type(value=default, expected_type=self._value_type):
434
401
  self._raise_value_is_not_of_type(value=default)
435
402
 
436
403
  return self._value.get(key, default)
@@ -458,36 +425,6 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
458
425
  """
459
426
  return not self._value
460
427
 
461
- @staticmethod
462
- def _is_instance_of_type(*, value: Any, expected_type: Any) -> bool:
463
- """
464
- Checks if the value matches the expected type, supporting unions and Any.
465
-
466
- Args:
467
- value (Any): The value to check.
468
- expected_type (Any): The expected type or typing annotation.
469
-
470
- Returns:
471
- bool: True if the value matches the expected type, otherwise False.
472
- """
473
- if expected_type is Any:
474
- return True
475
-
476
- origin = get_origin(tp=expected_type)
477
- if origin in (Union, UnionType):
478
- for allowed in get_args(expected_type):
479
- if allowed is Any:
480
- return True
481
-
482
- allowed_origin = get_origin(tp=allowed) or allowed
483
- if isinstance(value, allowed_origin):
484
- return True
485
-
486
- return False
487
-
488
- expected = origin or expected_type
489
- return isinstance(value, expected)
490
-
491
428
  @staticmethod
492
429
  def _type_label(*, type: Any) -> str:
493
430
  """
@@ -535,50 +472,36 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
535
472
 
536
473
  Returns:
537
474
  Self: The created DictValueObject.
538
- """
539
- items: dict[Any, Any] = {}
540
-
541
- for key, item in value.items():
542
- primitive_key = cls._convert_from_primitives(value=key, expected_type=cls._key_type)
543
- primitive_value = cls._convert_from_primitives(value=item, expected_type=cls._value_type)
544
- items[primitive_key] = primitive_value
545
475
 
546
- return cls(value=items)
547
-
548
- @classmethod
549
- def _convert_from_primitives(cls, *, value: Any, expected_type: Any) -> Any:
550
- """
551
- Converts a primitive value to the expected type.
476
+ Example:
477
+ ```python
478
+ from value_object_pattern.models import ValueObject
479
+ from value_object_pattern.models.collections import DictValueObject
552
480
 
553
- Args:
554
- value (Any): The primitive value to convert.
555
- expected_type (Any): The expected type.
556
481
 
557
- Returns:
558
- Any: The converted value.
559
- """
560
- if expected_type is Any:
561
- return value
482
+ class Age(ValueObject[int]):
483
+ pass
562
484
 
563
- origin = get_origin(tp=expected_type)
564
- if origin in (Union, UnionType):
565
- return value
566
485
 
567
- if hasattr(expected_type, 'from_primitives'):
568
- return expected_type.from_primitives(value)
486
+ class StrAgeDict(DictValueObject[str, Age]):
487
+ pass
569
488
 
570
- if isclass(expected_type) and issubclass(expected_type, Enum):
571
- if isinstance(value, expected_type):
572
- return value
573
489
 
574
- return expected_type(value)
490
+ dictionary = StrAgeDict.from_primitives(value={'john': 30, 'jane': 25})
491
+ print({key: age.value for key, age in dictionary.items()})
492
+ # >>> {'john': 30, 'jane': 25}
493
+ ```
494
+ """
495
+ dictionary: dict[Any, Any] = {}
575
496
 
576
- if hasattr(expected_type, 'value'):
577
- return expected_type(value=value)
497
+ for key, item in value.items():
498
+ primitive_key = from_primitive(value=key, expected_type=cls._key_type)
499
+ primitive_value = from_primitive(value=item, expected_type=cls._value_type)
500
+ dictionary[primitive_key] = primitive_value
578
501
 
579
- return value
502
+ return cls(value=dictionary)
580
503
 
581
- def to_primitives(self) -> dict[Any, Any]: # noqa: C901
504
+ def to_primitives(self) -> dict[Any, Any]:
582
505
  """
583
506
  Returns the dictionary as a dictionary of primitives, recursively converting each key and value.
584
507
 
@@ -604,59 +527,10 @@ class DictValueObject(ValueObject[dict[K, V]], Generic[K, V]): # noqa: UP046
604
527
  # >>> {'john': 30, 'jane': 25}
605
528
  ```
606
529
  """
607
- primitive_types: tuple[type, ...] = (int, float, str, bool, bytes, bytearray, memoryview, type(None))
608
- collection_types: tuple[type, ...] = (list, dict, tuple, set, frozenset)
609
-
610
- primitives_dict: dict[Any, Any] = {}
530
+ dictionary: dict[Any, Any] = {}
611
531
  for key, value in self._value.items():
612
- primitive_key = key
613
- if isinstance(key, BaseModel) or hasattr(key, 'to_primitives'):
614
- primitive_key = key.to_primitives() # type: ignore[assignment]
615
-
616
- elif isinstance(key, Enum):
617
- primitive_key = key.value
618
-
619
- elif isinstance(key, ValueObject) or hasattr(key, 'value'):
620
- key_value = key.value
621
-
622
- if isinstance(key_value, Enum):
623
- key_value = key_value.value
624
-
625
- primitive_key = key_value
626
-
627
- elif isinstance(key, primitive_types): # noqa: SIM114
628
- pass
629
-
630
- elif isinstance(key, collection_types):
631
- pass
632
-
633
- else:
634
- primitive_key = str(object=key) # type: ignore[assignment]
635
-
636
- primitive_value = value
637
- if isinstance(value, BaseModel) or hasattr(value, 'to_primitives'):
638
- primitive_value = value.to_primitives() # type: ignore[assignment]
639
-
640
- elif isinstance(value, Enum):
641
- primitive_value = value.value
642
-
643
- elif isinstance(value, ValueObject) or hasattr(value, 'value'):
644
- val_value = value.value
645
-
646
- if isinstance(val_value, Enum):
647
- val_value = val_value.value
648
-
649
- primitive_value = val_value
650
-
651
- elif isinstance(value, primitive_types): # noqa: SIM114
652
- pass
653
-
654
- elif isinstance(value, collection_types):
655
- pass
656
-
657
- else:
658
- primitive_value = str(object=value) # type: ignore[assignment]
659
-
660
- primitives_dict[primitive_key] = primitive_value
532
+ primitive_key = to_primitive(value=key)
533
+ primitive_value = to_primitive(value=value)
534
+ dictionary[primitive_key] = primitive_value
661
535
 
662
- return primitives_dict
536
+ return dictionary
@@ -19,6 +19,8 @@ from typing import Any, Generic, NoReturn, Self, TypeVar, Union, get_args, get_o
19
19
 
20
20
  from value_object_pattern.decorators import validation
21
21
  from value_object_pattern.models import BaseModel, ValueObject
22
+ from value_object_pattern.models.primitive_conversion import from_primitive, to_primitive
23
+ from value_object_pattern.models.type_matching import matches_expected_type
22
24
 
23
25
  T = TypeVar('T', bound=Any)
24
26
 
@@ -313,25 +315,8 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
313
315
  if self._type is Any:
314
316
  return
315
317
 
316
- origin = get_origin(tp=self._type)
317
- if origin in (Union, UnionType):
318
- allowed_types: list[type[Any] | UnionType] = []
319
- for allowed in get_args(self._type):
320
- if allowed is Any:
321
- return
322
-
323
- allowed_origin = get_origin(tp=allowed)
324
- allowed_types.append(allowed_origin or allowed)
325
-
326
- for item in value:
327
- if not any(isinstance(item, allowed) for allowed in allowed_types):
328
- self._raise_value_is_not_of_type(value=item)
329
-
330
- return
331
-
332
- expected_type = origin or self._type
333
318
  for item in value:
334
- if not isinstance(item, expected_type):
319
+ if not matches_expected_type(value=item, expected_type=self._type):
335
320
  self._raise_value_is_not_of_type(value=item)
336
321
 
337
322
  def _raise_value_is_not_of_type(self, value: Any) -> NoReturn:
@@ -436,7 +421,7 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
436
421
  # >>> False
437
422
  ```
438
423
  """
439
- item = self._convert_from_primitives(value=item)
424
+ item = from_primitive(value=item, expected_type=self._type)
440
425
 
441
426
  return self.add(item=item)
442
427
 
@@ -507,7 +492,7 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
507
492
  # >>> False
508
493
  ```
509
494
  """
510
- items = [self._convert_from_primitives(value=item) for item in items]
495
+ items = [from_primitive(value=item, expected_type=self._type) for item in items]
511
496
 
512
497
  return self.extend(items=items)
513
498
 
@@ -598,7 +583,7 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
598
583
  # >>> False
599
584
  ```
600
585
  """
601
- item = self._convert_from_primitives(value=item)
586
+ item = from_primitive(value=item, expected_type=self._type)
602
587
 
603
588
  return self.delete(item=item)
604
589
 
@@ -675,31 +660,10 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
675
660
  # >>> False
676
661
  ```
677
662
  """
678
- items = [self._convert_from_primitives(value=item) for item in items]
663
+ items = [from_primitive(value=item, expected_type=self._type) for item in items]
679
664
 
680
665
  return self.delete_all(items=items)
681
666
 
682
- def _convert_from_primitives(self, *, value: Any) -> T:
683
- """
684
- Converts a primitive value to the appropriate type T.
685
-
686
- Args:
687
- value (Any): The primitive value to convert.
688
-
689
- Returns:
690
- T: The converted value.
691
- """
692
- if hasattr(self._type, 'from_primitives'):
693
- return self._type.from_primitives(value) # type: ignore[no-any-return]
694
-
695
- if get_origin(tp=self._type) in (Union, UnionType):
696
- return value # type: ignore[no-any-return]
697
-
698
- if hasattr(self._type, 'value'):
699
- return self._type(value=value) # type: ignore[no-any-return]
700
-
701
- return value # type: ignore[no-any-return]
702
-
703
667
  def _type_label(self) -> str:
704
668
  """
705
669
  Returns a readable label for the configured type, including unions.
@@ -743,20 +707,27 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
743
707
 
744
708
  Returns:
745
709
  Self: The created ListValueObject.
746
- """
747
- items: list[Any] = []
748
710
 
749
- for item in value:
750
- if hasattr(cls._type, 'from_primitives'):
751
- items.append(cls._type.from_primitives(item)) # BaseModel
711
+ Example:
712
+ ```python
713
+ from value_object_pattern.models import ValueObject
714
+ from value_object_pattern.models.collections import ListValueObject
752
715
 
753
- elif hasattr(cls._type, 'value'):
754
- items.append(cls._type(value=item)) # ValueObject
755
716
 
756
- else:
757
- items.append(item)
717
+ class Age(ValueObject[int]):
718
+ pass
758
719
 
759
- return cls(value=items)
720
+
721
+ class AgeListValueObject(ListValueObject[Age]):
722
+ pass
723
+
724
+
725
+ age_list = AgeListValueObject.from_primitives(value=[10, 20, 30])
726
+ print([age.value for age in age_list])
727
+ # >>> [10, 20, 30]
728
+ ```
729
+ """
730
+ return cls(value=[from_primitive(value=item, expected_type=cls._type) for item in value])
760
731
 
761
732
  def to_primitives(self) -> list[Any]:
762
733
  """
@@ -784,32 +755,4 @@ class ListValueObject(ValueObject[list[T]], Generic[T]): # noqa: UP046
784
755
  # >>> [10, 20]
785
756
  ```
786
757
  """
787
- primitive_types: tuple[type, ...] = (int, float, str, bool, bytes, bytearray, memoryview, type(None))
788
- collection_types: tuple[type, ...] = (list, dict, tuple, set, frozenset)
789
-
790
- primitives_list: list[Any] = []
791
- for item in self._value:
792
- if isinstance(item, BaseModel) or hasattr(item, 'to_primitives'):
793
- primitives_list.append(item.to_primitives())
794
-
795
- elif isinstance(item, Enum):
796
- primitives_list.append(item.value)
797
-
798
- elif isinstance(item, ValueObject) or hasattr(item, 'value'):
799
- value = item.value
800
-
801
- if isinstance(value, Enum):
802
- value = value.value
803
-
804
- primitives_list.append(value)
805
-
806
- elif isinstance(item, primitive_types): # noqa: SIM114
807
- primitives_list.append(item)
808
-
809
- elif isinstance(item, collection_types):
810
- primitives_list.append(item)
811
-
812
- else:
813
- primitives_list.append(str(object=item))
814
-
815
- return primitives_list
758
+ return [to_primitive(value=item) for item in self._value]