def test_schema_match_their_examples(self, schema_path_with_example): schema = Schema.get_schema(schema_path_with_example) validator = Schema.get_validator(schema_path_with_example) examples = schema["examples"] for example in examples: validator.validate_all(example)
def test_get_validator(self, upsert_group_body): validator = Schema.get_validator("bulk_api/command/upsert_group.json") assert isinstance(validator, Validator) # Check something that should pass validator.validate_all(upsert_group_body)
class UpsertGroup(JSONAPIData): """The data to upsert a group.""" validator = Schema.get_validator("bulk_api/command/upsert_group.json") @classmethod def create(cls, attributes, id_reference): """ Create an upsert group body. :param attributes: Group attributes :param id_reference: A custom reference for this group :return: """ group_id = attributes.pop("groupid", None) return super().create( DataType.GROUP, attributes=attributes, meta={ "query": { "groupid": group_id }, "$anchor": id_reference }, )
def test_get_validator_configured_to_load_referenced_schema( self, upsert_group_body): validator = Schema.get_validator("bulk_api/command/upsert_group.json") # Modify one value which proves we configured the Validator to load # chained schema upsert_group_body["data"]["attributes"]["NOT A KEY"] = "WRONG" with pytest.raises(SchemaValidationError): validator.validate_all(upsert_group_body)
def test_get_validator_configured_to_load_referenced_schema( self, upsert_group_body): validator = Schema.get_validator("bulk_api/command/upsert_group.json") # Modify one value which proves we configured the Validator to load # chained schema upsert_group_body["data"]["meta"]["query"]["groupid"] = "wrong_pattern" with pytest.raises(SchemaValidationError): validator.validate_all(upsert_group_body)
class CreateGroupMembership(JSONAPIData): """The data to add a user to a group.""" validator = Schema.get_validator( "bulk_api/command/create_group_membership.json") @classmethod def create(cls, user_ref, group_ref): """ Create a create group membership body for adding users to groups. :param user_ref: Custom user reference :param group_ref: Custom group reference :return: """ return super().create( DataType.GROUP_MEMBERSHIP, relationships={ "member": { "data": { "type": DataType.USER.value, "id": { "$ref": user_ref } } }, "group": { "data": { "type": DataType.GROUP.value, "id": { "$ref": group_ref } } }, }, ) @property def member(self): """The user which is a member of this group. :return: A value object with `id` and `ref` properties. """ return _IdRef(self.relationships["member"]["data"]["id"]) @property def group(self): """The group which this user is a member of. :return: A value object with `id` and `ref` properties. """ return _IdRef(self.relationships["group"]["data"]["id"])
def schema_with_examples(): for file_name in schema_file_names(): schema = Schema.get_schema(file_name) if "examples" in schema: yield file_name defs = schema.get("$defs") if not defs: continue for key, sub_schema in defs.items(): if "examples" in sub_schema: yield f"{file_name}#/$defs/{key}"
class UpsertUser(JSONAPIData): """The data to upsert a user.""" validator = Schema.get_validator("bulk_api/command/upsert_user.json") @classmethod def create(cls, _id, attributes): """ Create an upsert user body. :param _id: User id :param attributes: User attributes :return: """ return super().create(DataType.USER, _id=_id, attributes=attributes)
class Command(Model): """A single abstract command provided to the API.""" validator = Schema.get_validator("bulk_api/wrapper.json") validation_error_title = "Cannot interpret command as the wrapper is malformed" def validate(self): super().validate() if isinstance(self.body, Model): self.body.validate() @classmethod def create(cls, type_, body): """ Create a command. :param type_: The CommandType of the command :param body: The payload for the command :return: An instance of Command """ return cls([CommandType(type_).value, cls.extract_raw(body)]) @property def type(self): """ Get the command type. :return: The CommandType of this command """ return CommandType(self.raw[0]) @property def body(self): """ Get the body of this command. :return: The raw body """ return self.raw[1] def __repr__(self): return f"<{self.__class__.__name__} {self.body}>"
def test_get_schema(self): schema = Schema.get_schema("core.json#/$defs/userId") assert isinstance(schema, dict) assert schema["type"] == "string"
def get_schema_example(schema_path): return deepcopy(Schema.get_schema(schema_path)["examples"][0])
class Configuration(Model): validator = Schema.get_validator("bulk_api/command/configuration.json") WILD_CARD = "*" @classmethod def create(cls, effective_user, total_instructions): """ Create a configuration object. :param effective_user: User to execute the command as :param total_instructions: Number of instructions (including this) """ return cls({ "view": None, "user": { "effective": effective_user }, "instructions": { "total": int(total_instructions) }, "defaults": [ ["create", "*", { "on_duplicate": "continue" }], ["upsert", "*", { "merge_query": True }], ], }) @property def view(self): """The return type of view requested by the user.""" return self.raw["view"] @property def effective_user(self): """The user to execute the request as.""" return self.raw["user"]["effective"] @property def total_instructions(self): """ The number of instructions in the request. This count includes configuration commands. """ return self.raw["instructions"]["total"] def defaults_for(self, command_type, data_type): """ Provide default configuration for the given command and data type. This will use any wild card options first, overlaying more specific defaults as they are found. :param command_type: Type of modification (e.g. Types.UPSERT) :param data_type: Data type being modified :return: A dict of config """ defaults = self._command_defaults config = {} wild = defaults.get(self.WILD_CARD, {}) specific = defaults.get(CommandType(command_type), {}) data_type = DataType(data_type) for container in (wild, specific): if self.WILD_CARD in container: config.update(container[self.WILD_CARD]) if data_type in container: config.update(container[data_type]) return config @property @lru_cache(1) def _command_defaults(self): config = defaultdict(dict) for command_type, data_type, defaults in self.raw["defaults"]: if command_type != self.WILD_CARD: command_type = CommandType(command_type) if data_type != self.WILD_CARD: data_type = DataType(data_type) config[command_type][data_type] = defaults return config
class CreateGroupMembership(JSONAPIData): """The data to add a user to a group.""" validator = Schema.get_validator( "bulk_api/command/create_group_membership.json") @classmethod def create(cls, user_id, group_ref): """ Create a create group membership body for adding users to groups. :param user_id: User id :param group_ref: Custom group reference :return: """ return super().create( DataType.GROUP_MEMBERSHIP, relationships={ "member": { "data": { "type": DataType.USER.value, "id": user_id } }, "group": { "data": { "type": DataType.GROUP.value, "id": { "$ref": group_ref } } }, }, ) @property def member_id(self): """The user which is a member of this group.""" return self.relationships["member"]["data"]["id"] @property def group_id(self): """The group the user is a member of.""" _group_id = self._group_id if "$ref" in _group_id: return None return _group_id @property def group_ref(self): """ A client provided reference for this group. If you don't know the group id yet, you can use your own reference. """ return self._group_id.get("$ref") @property def _group_id(self): return self.relationships["group"]["data"]["id"]
def test_schema_is_a_valid_schema(self, schema_path): schema = Schema.get_schema(schema_path) Draft7Validator.check_schema(schema)
class UpsertGroup(UpsertBody): """The data to upsert a group.""" validator = Schema.get_validator("bulk_api/command/upsert_group.json") data_type = DataType.GROUP query_fields = ["authority", "authority_provided_id"]
class UpsertUser(UpsertBody): """The data to upsert a user.""" validator = Schema.get_validator("bulk_api/command/upsert_user.json") data_type = DataType.USER query_fields = ["authority", "username"]