Changelog#

[0.12.1] - 2026-10-07#

Added#

  • Path.iter_paths takes attributes and excluded_attributes, and then only yields the paths a response keeps. A storage can skip loading the other ones.

Fixed#

  • A complex attribute returned on request is kept when attributes holds one of its sub-attributes, as for an attribute returned by default.

[0.12.0] - 2026-10-06#

Added#

  • ScimPolicy.comparison_key decides the form strings are compared under in filters, sorting and PATCH operations. It can apply the PRECIS rules RFC 7644 §5 requires for userName and password. A request that writes a string the key refuses is rejected with invalidValue.

Changed#

  • Strings are mapped to lowercase instead of case folded, as PRECIS does. Straße no longer matches STRASSE.

  • A PATCH add no longer duplicates a value the attribute holds under another case or normalization form, and a removal by value finds it. A case-exact sub-attribute still tells two entries apart.

[0.11.0] - 2026-10-06#

Added#

  • Filters accept a compared sub-attribute after a value selection, as Microsoft Entra ID sends it: emails[type eq "work"].value eq "x" reads as emails[type eq "work" and value eq "x"].

  • AttributeBinding.comparable returns the form a value is compared under: NFC, and case folded unless the attribute is caseExact. A storage can keep this form to filter, sort and check uniqueness as match() does.

Changed#

  • SCIM dumps omit empty complex attributes, empty arrays, and empty entries of multi-valued attributes, as unassigned values. A PATCH that removes the last sub-attribute of name, or a projection that selects none of them, no longer returns "name": {}. Message attributes and PATCH values are still dumped when empty.

  • An empty array no longer satisfies a required attribute in creation and replacement requests, as RFC 7643 §2.5 makes it an unassigned value. A bulk request with no Operations is refused.

  • schemas lists only the extensions present in the dump. A PATCH that removes an extension schema from schemas, such as schemas[value eq "urn:…:enterprise:2.0:User"], removes the extension. Before, the operation reported a change but the extension stayed.

Fixed#

  • SearchRequest.sort normalizes strings to NFC, as filters do. A composed and a decomposed José now sort together.

[0.10.6] - 2026-10-06#

Fixed#

  • Reference[User[EnterpriseUser]] publishes User as its reference type, instead of User[EnterpriseUser].

[0.10.5] - 2026-10-06#

Added#

  • Path.iter_paths takes a target_type filter. It yields the paths whose value is one of the given types, sub-attributes and extensions included. target_type=[Reference] yields members.$ref on a group.

[0.10.4] - 2026-10-06#

Added#

  • Path.resolve takes an optional model. It picks one type of a union, or resolves an unbound path.

  • SearchRequest.sort_binding returns the attribute that sort() orders by on a model, for backends that sort on their own. It returns None when the model cannot sort on it. emails binds as emails.value.

Fixed#

[0.10.3] - 2026-10-03#

Added#

Changed#

[0.10.2] - 2026-10-01#

Fixed#

  • PatchOp.build_from leaves out the read-only sub-attributes of multi-valued attributes, such as a read-only members.display. The patch it builds is no longer rejected.

[0.10.1] - 2026-09-30#

Removed#

Fixed#

  • ListResponse reads the pagination capabilities of the ScimProvider, including a provider opened around the validation. The last page of a server that only supports cursor pagination no longer needs totalResults.

  • The policy of a ScimProvider passed as scim_provider applies to the validation and the serialization. It wins over the policy of an open block. scim_policy still wins over both.

[0.10.0] - 2026-09-30#

Added#

  • Support for RFC9865

  • Resource.replace returns whether the replacement changes the resource, the order of multi-valued entries aside. A server can keep meta.version and meta.lastModified when a PUT changes nothing.

  • In the BULK_REQUEST context, an invalid operation of a BulkRequest no longer fails the whole request. It becomes its own failed result, with a status and an Error, as RFC7644 §3.7.3 requires. Under a ScimProvider, each operation is read as the resource type its path targets. An endpoint that serves none of the types of the request fails the operation with invalidPath.

  • BulkOperation.endpoint and BulkOperation.resource_id read the target of an operation from its path.

Changed#

  • SCIMException.from_error reconstructs InvalidCursorException, ExpiredCursorException and InvalidCountException from an Error carrying the matching scimType, as RFC9865 §2.1 defines them. They used to fall back to the base SCIMException.

  • AttributeBinding.urn and the error messages that quote it spell the attribute as the schema declares it, such as userName, whatever case the path used.

  • Validation errors locate the value with an attribute path, such as emails[1].value, and no longer expose internal names of pydantic.

Fixed#

  • A ScimProvider or ScimPolicy block that exits in a context where it did not enter, such as another thread or another asyncio task, raises an error. It used to remove the provider or the policy of another block.

Security#

  • The password of a User is case-exact, so password eq "SECRET" no longer matches secret. RFC 7643 declares it case-insensitive, but compares passwords by salted hash (RFC7643 §4.1.1), and the rules of RFC7644 §5 keep the case of passwords.

  • A filter or a PATCH path that nests more than 32 expressions, such as not(not(...)), is refused with invalidFilter or invalidPath. A deep one used to raise a RecursionError. Parentheses and chains of and or or do not count.

  • Filters and paths from clients no longer grow memory without limit. Each unknown attribute name, and each spelling of a known one such as USERNAME, used to stay in memory for the life of the process. Filters and paths longer than 1024 characters are no longer cached.

  • Write-only and never-returned attributes, such as password, no longer appear in the repr of a model. A PatchOperation bound to a resource type, as in a PatchOp[User], leaves out a value that writes one of them. Validation error messages no longer include the input values, which ValidationError.errors() still returns.

  • Under RemoveValue.apply, a PATCH remove whose value has a key that is not an attribute name, such as "value pr or value", is refused with invalidValue.

  • In a BulkRequest, the data of a PATCH operation must be a PatchOp, and the data of a POST or a PUT must be a resource. A full resource sent as the data of a PATCH used to be accepted with its read-only attributes, such as id and groups. An invalid data only reports the errors of the type the method expects.

  • In the BULK_REQUEST context, the location, status and response of an operation are ignored, and they are left out of a serialized request. A client can no longer make an operation look like it failed.

[0.9.0] - 2026-09-27#

Added#

  • ScimPolicy.unmatched_path_filter can make a PATCH add or replace create the entry its path filter describes when no entry matches, as Microsoft Entra ID expects. By default, the operation still fails with noTarget.

Changed#

  • Python 3.11 is now the minimum supported version.

  • The enumerations, such as Mutability, are StrEnum: str and f-strings give their value, readOnly rather than Mutability.read_only.

  • In a model built from a schema, an attribute named after a member of the model, such as copy, is held as copy_. Its SCIM name is unchanged.

  • A PATCH add whose path filter matches no entry, such as emails[type eq "work"].value on a user without a work email, now fails with noTarget instead of silently doing nothing. Path.set raises NoTargetException in that case when strict.

  • A PATCH add or replace on a filtered path, such as emails[type eq "work"], merges its value into the matching entries instead of replacing them (RFC7644 §3.5.2.3). The entries are updated in place, so the immutable sub-attributes of a group member cannot be changed this way.

Fixed#

  • A PatchOperation with a null value keeps it when dumped. A replace that clears its target used to be sent without a value.

  • Setting a null value under an unset complex attribute or extension no longer creates an empty one, and no longer reports the resource as modified.

  • A PatchOp with no operation, or with an operation other than add, remove and replace, fails with invalidValue instead of a validation error without scimType.

  • A PATCH add or replace on a complex attribute keeps the sub-attributes its value leaves out, instead of replacing the whole attribute (RFC7644 §3.5.2.3).

  • A PATCH add without a path adds to the multi-valued attributes in its value, like an add with a path, instead of replacing their values.

  • A key of a PATCH value can be an attribute path, such as name.givenName or urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:employeeNumber, as Microsoft Entra ID and its SCIM Validator send. It used to be rejected as an undeclared attribute.

  • Undeclared attributes and sub-attributes in a PATCH value follow ScimPolicy.unknown.

  • PATCH checks immutable attributes at every level and in every operation, including operations with no path, an empty path or a schema URN, and the removal of an extension. For example, the value of a group member can be added and removed, but not changed (RFC7643 §4.2). Setting a first value with replace, or writing back the current value, is accepted.

  • PATCH checks read-only attributes at every level, such as the displayName of the enterprise manager. A path to one is rejected. A value that contains one is rejected only if it changes it, so an attribute sent back as it was read is accepted. Okta, for example, sends back the id of a group it renames.

  • PATCH rejects a change to a required attribute only when it leaves the attribute unset (RFC7644 §3.5.2.2). Removing some values of a required multi-valued attribute, removing a sub-attribute of a required complex attribute, or adding an empty list is now accepted. Required sub-attributes and extensions are checked too.

  • A PATCH replace without a value fails with invalidValue instead of clearing its target. So does an operation whose path targets the resource or an extension with a value that is not an object, which used to be ignored.

  • A PATCH replace that sets several primary entries fails with invalidValue, like add already did, instead of keeping one of them at random.

  • PatchOp.patch raises InvalidValueException when the attribute rejects a value, instead of a pydantic ValidationError without scimType.

  • PatchOp.patch no longer reports a resource as modified when an operation writes a complex or multi-valued value it already has.

  • A PATCH path to an undeclared attribute follows ScimPolicy.unknown, like a value does. With ignore or keep, the operation changes nothing instead of failing the whole patch with invalidPath. An undeclared sub-attribute in a filter still fails with invalidFilter.

Security#

[0.8.2] - 2026-09-25#

Added#

Changed#

  • A filter on a write-only attribute, such as password, only takes eq, ne and pr, RFC7643 §4.1.1 comparing it for equality alone. Any other operator answers invalidFilter.

  • SearchRequest.sort_by refuses a complex attribute, such as name or addresses, where RFC7644 §3.4.2.3 asks for a sub-attribute, a binary attribute, and a write-only attribute, such as password. A multi-valued attribute holding a value, such as emails, is still sorted on it.

Fixed#

  • Resource.id is case-exact, as RFC7643 §3.1 declares it, so filters and orders on it respect the case.

  • The Meta sub-attributes are read-only, and resourceType and version are case-exact, as RFC7643 §3.1 declares them.

  • Resource.replace keeps a write-only attribute, such as password, that the replacement leaves out, and clears it on an explicit null only. A client never gets that value back, so a PUT built from a GET used to erase it.

  • A model built with Resource.from_schema or Extension.from_schema is named as its schema, and its docstring is the description of the schema, so to_schema publishes both again. A schema named petOwner used to build a PetOwner class, and to lose its description.

[0.8.1] - 2026-09-25#

Changed#

Fixed#

  • from_error() keeps the Error object it is built from, and to_error() gives it back. The status and the scimType a server sent used to be replaced by the ones of the exception class, which dropped everything it has no class for, such as a 429 status or a vendor specific scimType.

  • Validation error messages name attributes as SCIM spells them, such as userName instead of user_name, and extensions by their schema URN.

[0.8.0] - 2026-09-20#

Added#

Changed#

  • Resource.from_schema and Extension.from_schema refuse a schema declaring two attributes whose names only differ by case, and report both. RFC7643 §2.1 #166

  • Attribute names are matched case-insensitively, and nothing else: {"user-name": "x"}, which 0.7 read as userName, is now an unknown attribute that unknown governs. Paths, filters and sortBy resolve the same way, and a model whose fields answer to one attribute name raises a TypeError where it is defined. RFC7643 §2.1 #166

  • The bulk models take the resource type their operations carry, as in BulkRequest[User] or BulkRequest[User | Group], and raise a TypeError when used bare. A payload the type parameter does not cover is now refused, and a bulk response no longer dumps path.

  • ListResponse raises a TypeError when used without the resource type its entries carry, as PatchOp and the bulk models do. A bare ListResponse used to answer a pydantic error naming Resource.

  • A message type parameter must name resource types. ListResponse[str] used to build a class that read anything as its entries.

  • ListResponse[Resource], PatchOp[Resource] and their bulk counterparts stay writable where a type is expected, and raise a TypeError when they read or build a payload. PatchOp[Resource] used to be refused as a type, and ListResponse[Resource] used to read payloads.

  • SearchRequest.filter is a ScimFilter instead of a str, so a malformed filter is rejected at validation time.

  • Paths are parsed with the RFC7644 §3.5.2 grammar, so malformed ones such as emails[ or userName ==, which used to be accepted, are now rejected.

  • Path.model answers the model a path designates when it names no attribute, and None otherwise. resolve() answers what it used to.

  • SearchRequest.sort_by naming an attribute no resource type declares answers invalidPath, where it used to be carried to the endpoint.

  • A PATCH remove carrying a value is refused with invalidValue, at validation and when applied. It used to remove the entries equal to that value. Set remove_value_as_filter to keep reading it.

  • A PATCH reaching an extension attribute takes the extended resource type, as in PatchOp[User[EnterpriseUser]]. PatchOp[User] used to carry such an operation to the endpoint, and now refuses a path its type parameter leaves out.

Removed#

  • Resource.get_by_schema and Resource.get_by_payload, deprecated in 0.6.13. Use get_model_by_schema() and get_model_by_payload(), whose resource_types parameter is named models.

  • The original parameter of model_validate(), deprecated in 0.6.7. Validate the payload, then call replace() on the result to compare it against the stored resource: an immutable attribute that changed raises MutabilityException from replace instead of a ValidationError from model_validate.

  • Path.field_name, Path.field_type, Path.is_multivalued, Path.get_annotation and Path.urn. Use resolve(), whose AttributeBinding carries them.

  • Path.is_prefix_of and Path.has_prefix. They compared the text of two paths, which anything between brackets defeated.

Deprecated#

Fixed#

  • A PATCH operation carrying no path that unassigns an extension declared Required.true is refused. #166

  • A filter or a path accepts a $ anywhere in an attribute name, as nameChar allows. #166

  • A schema declaring several attributes that yield one Python name builds a field for each of them: the attribute already spelled as that name keeps it, and the others are held under their SCIM name. An attribute is read under the name SCIM gives it, as in resource["employeeId"]. #166

  • A pydantic error spells the attribute as SCIM does, userName and $ref, and so does the JSON schema a model publishes. #166

  • A field declaring its own alias is read under it, and an unknown attribute is refused under the spelling the peer used. #166

  • An extension is read under its class name as well as under its URN, so User[EnterpriseUser](EnterpriseUser=extension) is accepted and a resource carrying an extension survives a dump without aliases read back. #166

  • A bulk model indexed with something other than a resource type names itself in the error, where BulkRequest[str] used to tell the caller to write PatchOp[User].

  • A subclass of a parameterized message, such as class Users(ListResponse[User]), reads its payloads with the type parameter it inherits. It used to raise an IndexError.

  • A PATCH operation targeting an attribute of an extension answers for the constraints that extension declares, where it used to look them up on the resource and find none. A refused operation no longer leaves the extension instantiated on the resource.

  • A PATCH operation carrying no path accepts a resource as its value, and checks the attributes it names against the model. They used to go through unexamined.

  • A PATCH operation whose path names an attribute the resource schema does not declare is refused with invalidPath. #164

  • A refused PATCH add on a multi-valued attribute leaves the attribute as it was. The entry used to be appended before being validated, and outlived the failure.

  • A PATCH operation carrying no path marks the attributes it assigns as set, so exclude_unset dumps them.

  • A PATCH replace of a Required.true attribute with a null value or an empty array is refused, and an operation leaving such an attribute unassigned answers invalidValue instead of mutability.

  • Attributes annotated read_only are left out of a payload dumped in the RESOURCE_PATCH_REQUEST context, as they already are in a creation or a replacement request.

  • Paths resolve against the attributes a model declares instead of the values a resource carries, so name.unknown is refused on a resource carrying no name, and userName.foo answers invalidPath instead of raising an AttributeError.

  • A path crossing a multi-valued attribute, such as emails.value, reads, writes and removes the sub-attribute of every entry, where it used to raise an AttributeError or do nothing.

  • A path names a $ref sub-attribute under that spelling, as in members.$ref, both when it is parsed and in iter_paths().

  • A schema URN carries its attribute behind a colon, so urn:ietf:params:scim:schemas:core:2.0:UserId no longer reads as the id of a User, and a URN that is neither the schema of the model nor that of one of its extensions designates nothing.

  • Resource.replace checks the immutable and read-only sub-attributes of the entries a multi-valued attribute keeps.

  • Resource.to_schema publishes the members of a string enumeration as canonicalValues, and describes the resource alone on User[EnterpriseUser], where it used to publish the extension URN as an attribute of the User schema.

  • GroupMember.display is readWrite, as RFC7643 §8.7.1 declares it.

  • Subscribing a Path to a model, and parameterizing a resource with an extension, no longer keep those classes alive for as long as the process runs. A server building a model per schema it discovers used to accumulate every one of them.

[0.7.0] - 2026-09-05#

Added#

  • get_model_by_schema() and get_model_by_payload() look a model up among any sequence of ScimObject subclasses, and reflect the input types in the returned type.

  • ScimObject and AnyScimObject are exposed in the public API, so a downstream project can annotate a value that is either a resource or a message.

  • ExtensibleStringEnum is exposed in the public API, so a custom model can suggest canonical values without restricting them.

  • model_validate_json() takes a scim_ctx parameter, like the other validation and serialization methods, so a JSON payload can be validated without being decoded first. #150

Changed#

  • Path subclasses str instead of UserString, so a path goes wherever a string does. Its string operators answer a plain str: Path("emails.value")[6:] answers ".value" where it used to answer invalidPath.

  • A malformed Path answers invalidPath instead of invalidSyntax, and building one directly raises InvalidPathException instead of a plain ValueError. A model holding one still raises a ValidationError, now naming the field and carrying the scimType.

  • SearchRequest.sort_by, attributes and excluded_attributes refuse a path selecting values, such as emails[type eq "work"]. The attribute notation of RFC7644 §3.10 names an attribute, not the values it holds.

  • model_dump and model_dump_json move from ScimObject to BaseModel, so every model is dumped in a SCIM context by default: Name(family_name="Doe").model_dump() returns {"familyName": "Doe"} instead of {"family_name": "Doe"}.

  • model_dump() with scim_ctx=None returns the native pydantic dump, None values included, as its documentation states. Pass exclude_none=True to get the former output.

  • replace() leaves the fields it copies from the original resource unset, so model_fields_set only holds the attributes the client asserted.

  • Attributes suggesting canonical values accept values outside that set, and match it case-insensitively: Email(type="WORK").type is Email.Type.work. str() on them answers the SCIM value instead of the enum representation, and their JSON schema advertises the set as examples rather than a restrictive enum. This covers the type of Email, PhoneNumber, Im, Photo, Address and AuthenticationScheme. #34

  • The schemas attribute is built from the model definition on serialization. It holds what a peer asserted otherwise, and is empty when the payload omitted it, so the omission stays visible in model_fields_set. It is not subject to attribute filtering anymore.

  • A resource omitting its schemas attribute is read instead of being rejected, which covers the partial responses of RFC 7644 §3.4.3. Its type comes from the ListResponse parameter, so a response holding several resource types still cannot tell what an unlabelled resource is. #20

  • A schemas attribute that does not contain the model base schema is rejected whatever the validation context. It used to be accepted without a SCIM context.

Fixed#

  • The readOnly, immutable and required constraints of a PATCH operation are checked against the attribute its path resolves to, instead of a literal field name match. They used to be skipped whenever the two differed, so userName could be removed and a path spelled GROUPS could write to a readOnly attribute.

  • replace() checks the constraints an extension declares, recursively.

  • reference and binary attributes are case-exact, unless a schema states otherwise. RFC 7643 §2.3.6 and §2.3.7, erratum 6001

  • ResourceType endpoint and the value of GroupMember and GroupMembership are case-exact, the latter holding resource id values. RFC 7643 errata 8475 and 8472

  • from_schema() reads a reference attribute missing the optional referenceTypes as a URI reference, instead of crashing.

  • Looking a model up by schema no longer crashes when the model list mixes resources with messages such as ListResponse.

Removed#

  • Error.make_*_error() class methods, deprecated in 0.6.0. Use the matching SCIMException subclass and its to_error() method instead.

  • The ExternalReference and URIReference aliases, deprecated in 0.6.0. Use External and URI instead.

  • The Reference[Literal["X"]] syntax, deprecated in 0.6.0. Use Reference["X"] instead.

  • Defining a model schema with a schemas default value, deprecated in 0.6.0. Use __schema__ = URN("...") instead. Note that __schema__ only accepts valid URNs, while the removed syntax silently ignored invalid ones.

Deprecated#

  • Resource.get_by_schema and Resource.get_by_payload are deprecated in favor of get_model_by_schema() and get_model_by_payload(). Their resource_types parameter is named models in the new functions. They will be removed in 0.8.0.

Performance#

  • Validation and serialization each run through a single model validator and serializer, where every SCIM context used to add its own.

  • Commonly used field metadata is cached on __scim_info__, and so is attribute name normalization.

[0.6.12] - 2026-04-13#

Added#

  • Compatibility with Pydantic 2.13.

[0.6.11] - 2026-04-10#

Added#

  • add uniqueness, returned and case_exact filters to iter_paths

[0.6.10] - 2026-04-07#

Fixed#

  • replace copies readOnly and preserves immutable fields

[0.6.9] - 2026-04-07#

Added#

  • *RequestContext and *ResponseContext generic type aliases that wrap SCIMValidator and SCIMSerializer for each SCIM context (e.g. CreationRequestContext[User], CreationResponseContext[User]).

[0.6.8] - 2026-04-03#

Added#

Deprecated#

  • The original parameter of model_validate() is deprecated. Use replace() on the validated instance instead. Will be removed in 0.8.0.

Fixed#

  • PATCH operations on immutable fields are now validated at runtime per RFC 7644 §3.5.2: add is only allowed when the field has no previous value, replace is only allowed with the same value, and remove is only allowed on unset fields.

[0.6.7] - 2026-04-02#

Added#

[0.6.6] - 2026-03-12#

Fixed#

  • Fix ListResponse.totalResults validation when resources is none. #133

[0.6.5] - 2026-03-10#

Fixed#

  • Fix extension serialization crash when an extension is declared but not populated on a resource serialized outside of SCIM context (e.g. FastAPI response_model). #131

[0.6.4] - 2026-02-05#

Added#

  • SCIMException now accepts an optional scim_ctx parameter to indicate the SCIM context in which the exception occurred.

[0.6.3] - 2026-01-29#

Fixed#

[0.6.2] - 2026-01-25#

Added#

[0.6.1] - 2026-01-25#

Added#

  • Allow Path objects in Pydantic validation methods.

[0.6.0] - 2026-01-25#

Added#

  • Resources define their schema URN with a __schema__ classvar instead of a schemas default value. #110

  • External and URI marker classes for reference types.

Changed#

  • Introduce a Path object to handle paths. #111

  • Reference type parameters simplified:

    • Reference[ExternalReference] → Reference[External]

    • Reference[URIReference] → Reference[URI]

    • Reference[Literal["User"]] → Reference["User"]

    • Reference[Literal["User"] | Literal["Group"]] → Reference[Union["User", "Group"]]

  • Reference now validates URI format for External and URI types.

  • Reference inherits from str directly instead of UserString.

Fixed#

  • Only allow one primary complex attribute value to be true. #10

Deprecated#

  • Defining schemas with a default value is deprecated. Use __schema__ = URN("...") instead.

  • Error.make_*_error() methods are deprecated. Use <Exception>.to_error() instead.

  • Reference[Literal["X"]] syntax is deprecated. Use Reference["X"] instead. Will be removed in 0.7.0.

  • ExternalReference alias is deprecated. Use External instead. Will be removed in 0.7.0.

  • URIReference alias is deprecated. Use URI instead. Will be removed in 0.7.0.

  • Validation that the base schema is present in schemas during SCIM context validation.

  • Validation that extension schemas are known during SCIM context validation.

  • Introduce SCIM exceptions hierarchy (SCIMException and subclasses) corresponding to RFC 7644 error types. #103

  • Error.from_validation_error to convert Pydantic ValidationError to SCIM Error.

  • PatchOp.patch auto-excludes other primary values when setting one to True. #116

[0.5.2] - 2026-01-22#

Fixed#

  • Sub-attributes of requested complex attributes are now included in responses. #114

[0.5.1] - 2025-11-07#

Added#

  • Support for Python 3.14.

  • Compile regexes.

Removed#

  • Support for Python 3.9.

[0.5.0] - 2025-08-18#

Added#

  • Validation that forbid PatchOp with zero operations.

Fixed#

  • Allow PATCH operations on resources and extensions root path.

  • Multiple ComplexAttribute do not inherit from MultiValuedComplexAttribute by default. #72 #73

[0.4.2] - 2025-08-05#

Fixed#

  • The library is 100% typed with mypy strict.

[0.4.1] - 2025-07-23#

Fixed#

  • Allow TypeVar as type parameters for PatchOp.

[0.4.0] - 2025-07-23#

Added#

Fixed#

  • When using model_dump, ignore invalid attributes and excluded_attributes as suggested by RFC7644.

  • Don’t normalize attributes typed with Any. #20

[0.3.7] - 2025-07-17#

Fixed#

  • All non strict mypy type annotations are fixed.

[0.3.6] - 2025-07-02#

Added#

[0.3.5] - 2025-06-05#

Added#

  • Fix dynamic schema generation for user defined classes with inheritance.

[0.3.4] - 2025-06-05#

Added#

  • Implement User and Group attributes types shortcuts to match dynamically created model types.

[0.3.3] - 2025-05-21#

Fixed#

  • User class typing. #92

[0.3.2] - 2025-03-28#

Fixed#

  • Pydantic warning.

[0.3.1] - 2025-03-07#

Fixed#

[0.3.0] - 2024-12-11#

Added#

Changed#

[0.2.12] - 2024-12-09#

Added#

[0.2.11] - 2024-12-08#

Added#

[0.2.10] - 2024-12-02#

Changed#

  • The schema attribute is annotated with true.

Fixed#

  • Base64Bytes compatibility between pydantic 2.10+ and <2.10

[0.2.9] - 2024-12-02#

Added#

[0.2.8] - 2024-12-02#

Added#

  • Support for Pydantic 2.10.

[0.2.7] - 2024-11-30#

Added#

[0.2.6] - 2024-11-29#

Fixed#

  • Implement model_dump_json().

  • Temporarily set Pydantic 2.9 as the maximum supported version.

[0.2.5] - 2024-11-13#

Fixed#

[0.2.4] - 2024-11-03#

Fixed#

  • Python 3.9 and 3.10 compatibility.

[0.2.3] - 2024-11-01#

Added#

Changed#

[0.2.2] - 2024-09-20#

Fixed#

  • ListResponse pydantic discriminator issue introduced with pydantic 2.9.0. #75

  • Extension payloads are not required on response contexts. #77

[0.2.1] - 2024-09-06#

Fixed#

[0.2.0] - 2024-08-18#

Fixed#

Note

schema.make_model() becomes Resource.from_schema(schema) or Extension.from_schema(schema).

Changed#

[0.1.15] - 2024-08-18#

Added#

  • Add a PEP561 py.typed file to mark the package as typed.

Fixed#

Changed#

  • Remove ListResponse of method in favor of regular type parameters.

Note

ListResponse.of(User) becomes ListResponse[User] and ListResponse.of(User, Group)`` becomes ListResponse[Union[User, Group]].

Note

pet: Reference["Pet"] becomes pet: Reference[Literal["Pet"]]

[0.1.14] - 2024-07-23#

Fixed#

  • get_by_payload return None on invalid payloads

  • instance model_dump() with multiple extensions #57

[0.1.13] - 2024-07-15#

Fixed#

[0.1.12] - 2024-07-11#

Fixed#

  • Additional bugfixes about attribute case sensitivity #45

  • Dump was broken after sub-model assignments #48

  • Extension attributes dump were ignored #49

  • ListResponse tolerate any schema order #50

[0.1.11] - 2024-07-02#

Fixed#

  • Attributes are case insensitive #39

[0.1.10] - 2024-06-30#

Added#

[0.1.9] - 2024-06-29#

Added#

  • Reference type parameters represent SCIM ReferenceType

Fixed#

[0.1.8] - 2024-06-26#

Added#

  • Dynamic pydantic model creation from SCIM schemas. #6

Changed#

Fix#

  • Allow relative URLs in Reference.

  • Models with multiples extensions could not be initialized. #37

[0.1.7] - 2024-06-16#

Added#

Fix#

  • Add missing default values. #33

[0.1.6] - 2024-06-06#

Added#

  • Implement CaseExact attributes annotations.

  • Implement Required attributes annotations validation.

Changed#

  • Refactor get_field_mutability and get_field_returnability in get_field_annotation.

[0.1.5] - 2024-06-04#

Fix#

[0.1.4] - 2024-06-03#

Fix#

  • ServiceProviderConfiguration id is optional.

[0.1.3] - 2024-06-03#

Changed#

  • Rename ServiceProviderConfiguration to ServiceProviderConfig to match the RFCs naming convention.

[0.1.2] - 2024-06-02#

Added#

  • Implement Resource.guess_by_payload

[0.1.1] - 2024-06-01#

Changed#

  • Pre-defined errors are not constants anymore

[0.1.0] - 2024-06-01#

Added#

  • Initial release