|
1 | 1 | from inspect import isclass |
2 | | -from typing import Annotated |
3 | 2 | from typing import Any |
4 | 3 | from typing import Optional |
5 | 4 | from typing import get_args |
|
8 | 7 | from pydantic import AliasGenerator |
9 | 8 | from pydantic import BaseModel as PydanticBaseModel |
10 | 9 | from pydantic import ConfigDict |
11 | | -from pydantic import Field |
12 | 10 | from pydantic import FieldSerializationInfo |
13 | 11 | from pydantic import SerializationInfo |
14 | 12 | from pydantic import SerializerFunctionWrapHandler |
|
25 | 23 | from scim2_models.annotations import Required |
26 | 24 | from scim2_models.annotations import Returned |
27 | 25 | from scim2_models.context import Context |
28 | | -from scim2_models.reference import Reference |
29 | 26 | from scim2_models.utils import normalize_attribute_name |
30 | 27 | from scim2_models.utils import to_camel |
31 | 28 |
|
@@ -341,6 +338,8 @@ def check_mutability_issues( |
341 | 338 | cls, original: "BaseModel", replacement: "BaseModel" |
342 | 339 | ) -> None: |
343 | 340 | """Compare two instances, and check for differences of values on the fields marked as immutable.""" |
| 341 | + from .attributes import is_complex_attribute |
| 342 | + |
344 | 343 | model = replacement.__class__ |
345 | 344 | for field_name in model.model_fields: |
346 | 345 | mutability = model.get_field_annotation(field_name, Mutability) |
@@ -371,6 +370,8 @@ def mark_with_schema(self) -> None: |
371 | 370 | """ |
372 | 371 | from scim2_models.rfc7643.resource import Resource |
373 | 372 |
|
| 373 | + from .attributes import is_complex_attribute |
| 374 | + |
374 | 375 | for field_name in self.__class__.model_fields: |
375 | 376 | attr_type = self.get_field_root_type(field_name) |
376 | 377 | if not attr_type or not is_complex_attribute(attr_type): |
@@ -579,48 +580,4 @@ def get_attribute_urn(self, field_name: str) -> str: |
579 | 580 | return full_urn |
580 | 581 |
|
581 | 582 |
|
582 | | -class ComplexAttribute(BaseModel): |
583 | | - """A complex attribute as defined in :rfc:`RFC7643 §2.3.8 <7643#section-2.3.8>`.""" |
584 | | - |
585 | | - _schema: Optional[str] = None |
586 | | - |
587 | | - def get_attribute_urn(self, field_name: str) -> str: |
588 | | - """Build the full URN of the attribute. |
589 | | -
|
590 | | - See :rfc:`RFC7644 §3.10 <7644#section-3.10>`. |
591 | | - """ |
592 | | - alias = ( |
593 | | - self.__class__.model_fields[field_name].serialization_alias or field_name |
594 | | - ) |
595 | | - return f"{self._schema}.{alias}" |
596 | | - |
597 | | - |
598 | | -class MultiValuedComplexAttribute(ComplexAttribute): |
599 | | - type: Optional[str] = None |
600 | | - """A label indicating the attribute's function.""" |
601 | | - |
602 | | - primary: Optional[bool] = None |
603 | | - """A Boolean value indicating the 'primary' or preferred attribute value |
604 | | - for this attribute.""" |
605 | | - |
606 | | - display: Annotated[Optional[str], Mutability.immutable] = None |
607 | | - """A human-readable name, primarily used for display purposes.""" |
608 | | - |
609 | | - value: Optional[Any] = None |
610 | | - """The value of an entitlement.""" |
611 | | - |
612 | | - ref: Optional[Reference] = Field(None, serialization_alias="$ref") |
613 | | - """The reference URI of a target resource, if the attribute is a |
614 | | - reference.""" |
615 | | - |
616 | | - |
617 | | -def is_complex_attribute(type_: type) -> bool: |
618 | | - # issubclass raise a TypeError with 'Reference' on python < 3.11 |
619 | | - return ( |
620 | | - get_origin(type_) != Reference |
621 | | - and isclass(type_) |
622 | | - and issubclass(type_, (ComplexAttribute, MultiValuedComplexAttribute)) |
623 | | - ) |
624 | | - |
625 | | - |
626 | 583 | BaseModelType: type = type(BaseModel) |
0 commit comments