Skip to content

Commit

Permalink
refactor: merge attributes.py in base.py
Browse files Browse the repository at this point in the history
  • Loading branch information
azmeuk committed Oct 15, 2024
1 parent 2af466d commit 0a7d451
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 95 deletions.
92 changes: 0 additions & 92 deletions scim2_models/attributes.py

This file was deleted.

89 changes: 87 additions & 2 deletions scim2_models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Generic
from typing import List
from typing import Optional
from typing import Tuple
from typing import Type
from typing import TypeVar
from typing import Union
Expand All @@ -32,8 +33,6 @@
from typing_extensions import NewType
from typing_extensions import Self

from scim2_models.attributes import contains_attribute_or_subattributes
from scim2_models.attributes import validate_attribute_urn
from scim2_models.utils import normalize_attribute_name
from scim2_models.utils import to_camel

Expand All @@ -42,6 +41,92 @@
ExternalReference = NewType("ExternalReference", str)


def validate_model_attribute(model: Type, attribute_base: str) -> None:
"""Validate that an attribute name or a sub-attribute path exist for a
given model."""

from scim2_models.base import BaseModel

attribute_name, *sub_attribute_blocks = attribute_base.split(".")
sub_attribute_base = ".".join(sub_attribute_blocks)

aliases = {field.validation_alias for field in model.model_fields.values()}

if normalize_attribute_name(attribute_name) not in aliases:
raise ValueError(
f"Model '{model.__name__}' has no attribute named '{attribute_name}'"
)

if sub_attribute_base:
attribute_type = model.get_field_root_type(attribute_name)

if not issubclass(attribute_type, BaseModel):
raise ValueError(
f"Attribute '{attribute_name}' is not a complex attribute, and cannot have a '{sub_attribute_base}' sub-attribute"
)

validate_model_attribute(attribute_type, sub_attribute_base)


def extract_schema_and_attribute_base(attribute_urn: str) -> Tuple[str, str]:
# Extract the schema urn part and the attribute name part from attribute
# name, as defined in :rfc:`RFC7644 §3.10 <7644#section-3.10>`.

*urn_blocks, attribute_base = attribute_urn.split(":")
schema = ":".join(urn_blocks)
return schema, attribute_base


def validate_attribute_urn(
attribute_name: str,
default_resource: Optional[Type] = None,
resource_types: Optional[List[Type]] = None,
) -> str:
"""Validate that an attribute urn is valid or not.
:param attribute_name: The attribute urn to check.
:default_resource: The default resource if `attribute_name` is not an absolute urn.
:resource_types: The available resources in which to look for the attribute.
:return: The normalized attribute URN.
"""

from scim2_models.rfc7643.resource import Resource

if not resource_types:
resource_types = []

if default_resource and default_resource not in resource_types:
resource_types.append(default_resource)

default_schema = (
default_resource.model_fields["schemas"].default[0]
if default_resource
else None
)

schema, attribute_base = extract_schema_and_attribute_base(attribute_name)
if not schema:
schema = default_schema

if not schema:
raise ValueError("No default schema and relative URN")

resource = Resource.get_by_schema(resource_types, schema)
if not resource:
raise ValueError(f"No resource matching schema '{schema}'")

validate_model_attribute(resource, attribute_base)

return f"{schema}:{attribute_base}"


def contains_attribute_or_subattributes(attribute_urns: List[str], attribute_urn: str):
return attribute_urn in attribute_urns or any(
item.startswith(f"{attribute_urn}.") or item.startswith(f"{attribute_urn}:")
for item in attribute_urns
)


class Reference(UserString, Generic[ReferenceTypes]):
"""Reference type as defined in :rfc:`RFC7643 §2.3.7 <7643#section-2.3.7>`.
Expand Down
2 changes: 1 addition & 1 deletion tests/test_model_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

import pytest

from scim2_models.attributes import validate_attribute_urn
from scim2_models.base import BaseModel
from scim2_models.base import ComplexAttribute
from scim2_models.base import Context
from scim2_models.base import Returned
from scim2_models.base import validate_attribute_urn
from scim2_models.rfc7643.enterprise_user import EnterpriseUser
from scim2_models.rfc7643.resource import Meta
from scim2_models.rfc7643.resource import Resource
Expand Down

0 comments on commit 0a7d451

Please sign in to comment.