scim2-models 0.3.4__tar.gz → 0.3.5__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 (108) hide show
  1. {scim2_models-0.3.4 → scim2_models-0.3.5}/PKG-INFO +1 -1
  2. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/changelog.rst +7 -0
  3. {scim2_models-0.3.4 → scim2_models-0.3.5}/pyproject.toml +1 -1
  4. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/resource.py +9 -6
  5. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_dynamic_schemas.py +50 -0
  6. {scim2_models-0.3.4 → scim2_models-0.3.5}/uv.lock +1 -1
  7. {scim2_models-0.3.4 → scim2_models-0.3.5}/.github/FUNDING.yml +0 -0
  8. {scim2_models-0.3.4 → scim2_models-0.3.5}/.github/workflows/release.yml +0 -0
  9. {scim2_models-0.3.4 → scim2_models-0.3.5}/.github/workflows/tests.yaml +0 -0
  10. {scim2_models-0.3.4 → scim2_models-0.3.5}/.gitignore +0 -0
  11. {scim2_models-0.3.4 → scim2_models-0.3.5}/.pre-commit-config.yaml +0 -0
  12. {scim2_models-0.3.4 → scim2_models-0.3.5}/.readthedocs.yml +0 -0
  13. {scim2_models-0.3.4 → scim2_models-0.3.5}/LICENSE +0 -0
  14. {scim2_models-0.3.4 → scim2_models-0.3.5}/README.md +0 -0
  15. {scim2_models-0.3.4 → scim2_models-0.3.5}/conftest.py +0 -0
  16. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/__init__.py +0 -0
  17. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/conf.py +0 -0
  18. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/contributing.rst +0 -0
  19. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/index.rst +0 -0
  20. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/reference.rst +0 -0
  21. {scim2_models-0.3.4 → scim2_models-0.3.5}/doc/tutorial.rst +0 -0
  22. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.1-user-minimal.json +0 -0
  23. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.2-user-full.json +0 -0
  24. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.3-enterprise_user.json +0 -0
  25. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.4-group.json +0 -0
  26. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.5-service_provider_configuration.json +0 -0
  27. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.6-resource_type-group.json +0 -0
  28. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.6-resource_type-user.json +0 -0
  29. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.1-schema-enterprise_user.json +0 -0
  30. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.1-schema-group.json +0 -0
  31. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.1-schema-user.json +0 -0
  32. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.2-schema-resource_type.json +0 -0
  33. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.2-schema-schema.json +0 -0
  34. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7643-8.7.2-schema-service_provider_configuration.json +0 -0
  35. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.12-error-bad_request.json +0 -0
  36. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.12-error-not_found.json +0 -0
  37. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.14-user-post_request.json +0 -0
  38. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.14-user-post_response.json +0 -0
  39. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.3-user-post_request.json +0 -0
  40. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.3-user-post_response.json +0 -0
  41. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.4.1-user-known-resource.json +0 -0
  42. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.4.2-list_response-partial_attributes.json +0 -0
  43. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.4.3-list_response-post_query.json +0 -0
  44. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.4.3-search_request.json +0 -0
  45. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.1-user-put_request.json +0 -0
  46. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.1-user-put_response.json +0 -0
  47. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.1-patch_op-add_emails.json +0 -0
  48. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.1-patch_op-add_members.json +0 -0
  49. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.2-patch_op-remove_all_members.json +0 -0
  50. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.2-patch_op-remove_and_add_one_member.json +0 -0
  51. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.2-patch_op-remove_multi_complex_value.json +0 -0
  52. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.2-patch_op-remove_one_member.json +0 -0
  53. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.3-patch_op-replace_all_email_values.json +0 -0
  54. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.3-patch_op-replace_all_members.json +0 -0
  55. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.3-patch_op-replace_street_address.json +0 -0
  56. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.5.2.3-patch_op-replace_user_work_address.json +0 -0
  57. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.6-error-not_found.json +0 -0
  58. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.1-bulk_request-circular_conflict.json +0 -0
  59. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.1-list_response-circular_reference.json +0 -0
  60. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.2-bulk_request-enterprise_user.json +0 -0
  61. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.2-bulk_request-temporary_identifier.json +0 -0
  62. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.2-bulk_response-temporary_identifier.json +0 -0
  63. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.3-bulk_request-multiple_operations.json +0 -0
  64. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.3-bulk_response-error_invalid_syntax.json +0 -0
  65. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.3-bulk_response-multiple_errors.json +0 -0
  66. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.3-bulk_response-multiple_operations.json +0 -0
  67. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.3-error-invalid_syntax.json +0 -0
  68. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.7.4-error-payload_too_large.json +0 -0
  69. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-3.9-user-partial_response.json +0 -0
  70. {scim2_models-0.3.4 → scim2_models-0.3.5}/samples/rfc7644-4-list_response-resource_types.json +0 -0
  71. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/__init__.py +0 -0
  72. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/base.py +0 -0
  73. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/constants.py +0 -0
  74. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/py.typed +0 -0
  75. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/__init__.py +0 -0
  76. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/enterprise_user.py +0 -0
  77. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/group.py +0 -0
  78. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/resource_type.py +0 -0
  79. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/schema.py +0 -0
  80. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/service_provider_config.py +0 -0
  81. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7643/user.py +0 -0
  82. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/__init__.py +0 -0
  83. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/bulk.py +0 -0
  84. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/error.py +0 -0
  85. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/list_response.py +0 -0
  86. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/message.py +0 -0
  87. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/patch_op.py +0 -0
  88. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/rfc7644/search_request.py +0 -0
  89. {scim2_models-0.3.4 → scim2_models-0.3.5}/scim2_models/utils.py +0 -0
  90. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/__init__.py +0 -0
  91. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/conftest.py +0 -0
  92. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_dynamic_resources.py +0 -0
  93. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_enterprise_user.py +0 -0
  94. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_errors.py +0 -0
  95. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_group.py +0 -0
  96. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_list_response.py +0 -0
  97. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_model_attributes.py +0 -0
  98. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_model_serialization.py +0 -0
  99. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_model_validation.py +0 -0
  100. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_models.py +0 -0
  101. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_patch_op.py +0 -0
  102. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_resource_extension.py +0 -0
  103. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_resource_type.py +0 -0
  104. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_schema.py +0 -0
  105. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_search_request.py +0 -0
  106. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_service_provider_configuration.py +0 -0
  107. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_user.py +0 -0
  108. {scim2_models-0.3.4 → scim2_models-0.3.5}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scim2-models
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: SCIM2 models serialization and validation with pydantic
5
5
  Project-URL: documentation, https://scim2-models.readthedocs.io
6
6
  Project-URL: repository, https://github.com/python-scim/scim2-models
@@ -1,6 +1,13 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ [0.3.5] - 2025-06-05
5
+ --------------------
6
+
7
+ Added
8
+ ^^^^^
9
+ - Fix dynamic schema generation for user defined classes with inheritance.
10
+
4
11
  [0.3.4] - 2025-06-05
5
12
  --------------------
6
13
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "scim2-models"
7
- version = "0.3.4"
7
+ version = "0.3.5"
8
8
  description = "SCIM2 models serialization and validation with pydantic"
9
9
  authors = [{name="Yaal Coop", email="contact@yaal.coop"}]
10
10
  license = {file = "LICENSE"}
@@ -17,6 +17,7 @@ from ..base import BaseModelType
17
17
  from ..base import CaseExact
18
18
  from ..base import ComplexAttribute
19
19
  from ..base import ExternalReference
20
+ from ..base import MultiValuedComplexAttribute
20
21
  from ..base import Mutability
21
22
  from ..base import Required
22
23
  from ..base import Returned
@@ -253,8 +254,8 @@ class Resource(BaseModel, Generic[AnyExtension], metaclass=ResourceMetaclass):
253
254
  AnyResource = TypeVar("AnyResource", bound="Resource")
254
255
 
255
256
 
256
- def dedicated_attributes(model):
257
- """Return attributes that are not members of parent classes."""
257
+ def dedicated_attributes(model, excluded_models):
258
+ """Return attributes that are not members the parent 'excluded_models'."""
258
259
 
259
260
  def compare_field_infos(fi1, fi2):
260
261
  return (
@@ -268,8 +269,8 @@ def dedicated_attributes(model):
268
269
 
269
270
  parent_field_infos = {
270
271
  field_name: field_info
271
- for parent in model.__bases__
272
- for field_name, field_info in parent.model_fields.items()
272
+ for excluded_model in excluded_models
273
+ for field_name, field_info in excluded_model.model_fields.items()
273
274
  }
274
275
  field_infos = {
275
276
  field_name: field_info
@@ -283,7 +284,7 @@ def model_to_schema(model: type[BaseModel]):
283
284
  from scim2_models.rfc7643.schema import Schema
284
285
 
285
286
  schema_urn = model.model_fields["schemas"].default[0]
286
- field_infos = dedicated_attributes(model)
287
+ field_infos = dedicated_attributes(model, [Resource])
287
288
  attributes = [
288
289
  model_attribute_to_attribute(model, attribute_name)
289
290
  for attribute_name in field_infos
@@ -323,7 +324,9 @@ def model_attribute_to_attribute(model, attribute_name):
323
324
  sub_attributes = (
324
325
  [
325
326
  model_attribute_to_attribute(root_type, sub_attribute_name)
326
- for sub_attribute_name in dedicated_attributes(root_type)
327
+ for sub_attribute_name in dedicated_attributes(
328
+ root_type, [MultiValuedComplexAttribute]
329
+ )
327
330
  if (
328
331
  attribute_name != "sub_attributes"
329
332
  or sub_attribute_name != "sub_attributes"
@@ -1,8 +1,12 @@
1
1
  import operator
2
+ from typing import Annotated
3
+ from typing import Optional
2
4
 
3
5
  from scim2_models.base import Context
6
+ from scim2_models.base import Required
4
7
  from scim2_models.rfc7643.enterprise_user import EnterpriseUser
5
8
  from scim2_models.rfc7643.group import Group
9
+ from scim2_models.rfc7643.resource import Resource
6
10
  from scim2_models.rfc7643.resource_type import ResourceType
7
11
  from scim2_models.rfc7643.schema import Schema
8
12
  from scim2_models.rfc7643.service_provider_config import ServiceProviderConfig
@@ -127,3 +131,49 @@ def test_dump_with_context():
127
131
  models = [User, EnterpriseUser, Group, ResourceType, Schema, ServiceProviderConfig]
128
132
  for model in models:
129
133
  model.to_schema().model_dump(scim_ctx=Context.RESOURCE_QUERY_RESPONSE)
134
+
135
+
136
+ def test_inheritance():
137
+ """Check that parent attributes are included in the schema."""
138
+
139
+ class Foo(Resource):
140
+ schemas: Annotated[list[str], Required.true] = [
141
+ "urn:ietf:params:scim:schemas:core:2.0:Foo"
142
+ ]
143
+
144
+ foo: Optional[str] = None
145
+
146
+ class Bar(Foo):
147
+ bar: Optional[str] = None
148
+
149
+ schema = Bar.to_schema()
150
+ assert schema.model_dump() == {
151
+ "attributes": [
152
+ {
153
+ "caseExact": False,
154
+ "multiValued": False,
155
+ "mutability": "readWrite",
156
+ "name": "foo",
157
+ "required": False,
158
+ "returned": "default",
159
+ "type": "string",
160
+ "uniqueness": "none",
161
+ },
162
+ {
163
+ "caseExact": False,
164
+ "multiValued": False,
165
+ "mutability": "readWrite",
166
+ "name": "bar",
167
+ "required": False,
168
+ "returned": "default",
169
+ "type": "string",
170
+ "uniqueness": "none",
171
+ },
172
+ ],
173
+ "description": "Bar",
174
+ "id": "urn:ietf:params:scim:schemas:core:2.0:Foo",
175
+ "name": "Bar",
176
+ "schemas": [
177
+ "urn:ietf:params:scim:schemas:core:2.0:Schema",
178
+ ],
179
+ }
@@ -939,7 +939,7 @@ wheels = [
939
939
 
940
940
  [[package]]
941
941
  name = "scim2-models"
942
- version = "0.3.4"
942
+ version = "0.3.5"
943
943
  source = { editable = "." }
944
944
  dependencies = [
945
945
  { name = "pydantic", extra = ["email"] },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes