diff --git a/comparejsonld.py b/comparejsonld.py index ac49e2c..3a92eeb 100644 --- a/comparejsonld.py +++ b/comparejsonld.py @@ -74,7 +74,8 @@ def _get_entity_json(self) -> None: Downloads the entity from wikidata and assigns the json to self._entities """ url: str = f"https://www.wikidata.org/wiki/Special:EntityData/{self._entity}.json" - response: Response = requests.get(url) + response: Response = requests.get(url=url, + headers={'User-Agent': 'Userscript Entityshape by User:Teester'}) self._entities = response.json() def _get_props(self, claims: dict) -> None: @@ -108,9 +109,13 @@ def _get_property_names(self, language: str) -> None: for i in range((len(self._props) + 48) // 48)] for element in wikidata_property_list: required_properties: str = "|".join(element) - url: str = f"https://www.wikidata.org/w/api.php?action=wbgetentities&ids=" \ - f"{required_properties}&props=labels&languages={language}&format=json" - response: Response = requests.get(url) + response: Response = requests.get(url="https://www.wikidata.org/w/api.php", + params={"action": "wbgetentities", + "ids": required_properties, + "props": "labels", + "languages": language, + "format": "json"}, + headers={'User-Agent': 'Entityshape API by User:Teester'}) json_text: dict = response.json() for item in element: try: @@ -167,6 +172,13 @@ def compare_properties(self) -> dict: :return: """ + if "entities" not in self._entities: + return {} + if self._entity not in self._entities["entities"]: + return {} + if "claims" not in self._entities["entities"][self._entity]: + return {} + claims: dict = self._entities["entities"][self._entity]["claims"] properties: dict = {} if self._start_shape is None: @@ -213,6 +225,9 @@ def check_claims_for_props(self, claims: dict, prop: str) -> str: return response def _get_allowed_list(self, claims: dict, prop: str, expression: dict) -> list: + if prop not in claims: + return [] + allowed_list: list = [] for statement in claims[prop]: is_it_allowed: str = "" @@ -278,9 +293,12 @@ def _process_triple_constraint(statement: dict, expression: dict, allowed: str) :param str allowed: Whether the statement is allowed by the expression or not currently :return: allowed """ - statement_property: str = statement["property"] - if "predicate" in expression and \ - expression["predicate"].endswith(statement_property): + if "property" not in statement: + return allowed + if "predicate" not in expression: + return allowed + + if expression["predicate"].endswith(statement["property"]): allowed = "present" try: if expression["valueExpr"]["type"] == "NodeConstraint": @@ -305,6 +323,9 @@ def compare_statements(self) -> dict: :return: statements """ + if "entities" not in self._entities: + return {} + statements: dict = {} claims: dict = self._entities["entities"][self._entity]['claims'] for claim in claims: @@ -342,6 +363,13 @@ def _process_shape(self, statement: dict, shape: dict, child: dict) -> Tuple[Any return child, allowed def process_expressions(self, expression: dict, shape: dict, statement: dict, allowed: str) -> str: + if "type" not in expression: + return allowed + if "predicate" not in expression: + return allowed + if "property" not in statement: + return allowed + if expression["type"] == "TripleConstraint" and expression["predicate"].endswith(statement["property"]): allowed = self._process_triple_constraint(statement, expression, @@ -362,9 +390,12 @@ def _process_triple_constraint(statement: dict, expression: dict, allowed: str) :param allowed: Whether the statement is allowed by the expression or not currently :return: allowed """ - statement_property: str = statement["property"] - if "predicate" in expression and \ - expression["predicate"].endswith(statement_property): + if "property" not in statement: + return allowed + if "predicate" not in expression: + return allowed + + if expression["predicate"].endswith(statement["property"]): allowed = "allowed" Utilities.process_cardinalities(expression, {"mainsnak": statement}) try: @@ -453,6 +484,13 @@ def process_node_constraint(statement: dict, expression: dict, allowed: str) -> :param str allowed: Whether the statement is allowed by the expression or not currently :return: allowed """ + if "snaktype" not in statement: + return allowed + if "datavalue" not in statement: + return allowed + if "type" not in statement["datavalue"]: + return allowed + if statement["snaktype"] == "value" and \ statement["datavalue"]["type"] == "wikibase-entityid": obj = f'http://www.wikidata.org/entity/{statement["datavalue"]["value"]["id"]}' diff --git a/compareshape.py b/compareshape.py index 739051a..c2da10d 100644 --- a/compareshape.py +++ b/compareshape.py @@ -150,7 +150,8 @@ def _get_entity_json(self): Downloads the entity from wikidata """ url: str = f"https://www.wikidata.org/wiki/Special:EntityData/{self._entity}.json" - response: Response = requests.get(url) + response: Response = requests.get(url=url, + headers={'User-Agent': 'Userscript Entityshape by User:Teester'}) self._entities = response.json() def _get_props(self, claims: dict): @@ -175,9 +176,14 @@ def _get_property_names(self, language: str): for i in range((len(self._props) + 48) // 48)] for element in wikidata_property_list: required_properties: str = "|".join(element) - url: str = f"https://www.wikidata.org/w/api.php?action=wbgetentities&ids=" \ - f"{required_properties}&props=labels&languages={language}&format=json" - response: Response = requests.get(url) + response: Response = requests.get(url="https://www.wikidata.org/w/api.php", + params={"action": "wbgetentities", + "ids": required_properties, + "props": "labels", + "languages": language, + "format": "json"}, + headers={'User-Agent': 'Entityshape API by User:Teester'} + ) json_text: dict = response.json() for item in element: try: @@ -206,9 +212,12 @@ def _process_required_in_shape_claim(shape_claim, datavalue): required_value: str = shape_claim["required"][required_property][0] query_entity: str = datavalue["value"]["id"] - url: str = f"https://www.wikidata.org/w/api.php?action=wbgetclaims" \ - f"&entity={query_entity}&property={required_property}&format=json" - response: Response = requests.get(url) + response: Response = requests.get(url="https://www.wikidata.org/w/api.php", + params={"action": "wbgetclaims", + "entity": query_entity, + "property": required_property, + "format": "json"}, + headers={'User-Agent': 'Entityshape API by User:Teester'}) json_text: dict = response.json() if required_property in json_text["claims"]: for key in json_text["claims"][required_property]: diff --git a/shape.py b/shape.py index 0cb4cee..4fadbc1 100644 --- a/shape.py +++ b/shape.py @@ -164,7 +164,8 @@ def _get_schema_json(self, schema) -> None: :param schema: the entityschema to be downloaded """ url: str = f"https://www.wikidata.org/wiki/EntitySchema:{schema}?action=raw" - response = requests.get(url) + response = requests.get(url=url, + headers={'User-Agent': 'Userscript Entityshape by User:Teester'}) self._json_text: dict = response.json() def _strip_schema_comments(self) -> None: diff --git a/test_schemas.py b/test_schemas.py index ff5312e..6b4714c 100644 --- a/test_schemas.py +++ b/test_schemas.py @@ -19,10 +19,6 @@ def setUp(self) -> None: app.config['DEBUG'] = False self.app = app.test_client() - def tearDown(self) -> None: - # Wait before performing the next test to avoid running into Wikidata's request limits when using Github Actions - time.sleep(4) - def test_specific_wikidata_item_against_schema(self): """ Tests a specific entity against a certain schema and checks that @@ -52,6 +48,7 @@ def test_lexical_category(self): self.assertIsNotNone(response.json["general"][0]["lexicalCategory"]) self.assertIsNotNone(response.json["general"][0]["language"]) + @unittest.skip("Not running check on all wikidata schemas as they take too long") def test_wikidata_entityschemas(self) -> None: """ Tests all wikidata entityschemas return 200 @@ -75,7 +72,8 @@ def test_wikidata_entityschemas(self) -> None: with self.subTest(schema=schema): if schema in skips: self.skipTest(f"Schema {schema} not supported") - # Wait before performing the next test to avoid running into Wikidata's request limits when using Github Actions + # Wait before performing the next test to avoid running into Wikidata's request limits + # when using GitHub Actions time.sleep(4) response = self.app.get(f'/api/v2?entityschema={schema}&entity=Q100532807&language=en', follow_redirects=True) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_compare_properties.py b/tests/test_compare_properties.py new file mode 100644 index 0000000..6269558 --- /dev/null +++ b/tests/test_compare_properties.py @@ -0,0 +1,173 @@ +import unittest + +from comparejsonld import CompareProperties + + +class TestCompareProperties(unittest.TestCase): + def setUp(self): + entity = {'entities': + {'Q1': + {'title': 'Q1', + 'type': 'item', + 'id': 'Q1', + 'claims': {'P31': [{'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'}, + 'type': 'statement', + 'id': '1', + 'rank': 'normal'}], + }, + 'sitelinks': {}}}} + entities = "Q1" + statement = { "type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + ] + }} + props = ["P31"] + names = {"P31": "instance of"} + self.compare_properties = CompareProperties(entities, entity, props, names, statement) + + def test_compare_properties_with_nothing(self): + entity = {} + entities = "" + statement = {} + props = [] + names = {} + test_method = CompareProperties(entities, entity, props, names, statement) + self.assertEqual({}, test_method.compare_properties()) + + def test_compare_properties_with_values(self): + result = {'P31': {'name': 'instance of', + 'necessity': 'required', + 'response': 'present'}} + self.assertEqual(result, self.compare_properties.compare_properties()) + + def test_check_claims_for_prop_with_nothing(self): + claims = {} + prop = "" + self.assertEqual('not enough correct statements', self.compare_properties.check_claims_for_props(claims, prop)) + + def test_check_claims_for_prop_with_values(self): + claims = {'Q1': + {'title': 'Q1', + 'type': 'item', + 'id': 'Q1', + 'claims': {'P31': [{'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'}, + 'type': 'statement', + 'id': '1', + 'rank': 'normal'}], + }, + 'sitelinks': {}}} + prop = "P31" + self.assertEqual('not enough correct statements', self.compare_properties.check_claims_for_props(claims, prop)) + + def test_get_allowed_list_with_nothing(self): + claims = {} + prop = "" + expression = {} + self.assertEqual([], self.compare_properties._get_allowed_list(claims, prop, expression)) + + def test_get_allowed_list_with_values(self): + claims = {'Q1': + {'title': 'Q1', + 'type': 'item', + 'id': 'Q1', + 'claims': {'P31': [{'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'}, + 'type': 'statement', + 'id': '1', + 'rank': 'normal'}], + }, + 'sitelinks': {}}} + prop = "P31" + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'valueExpr': {'type': 'NodeConstraint', 'values': ['http://www.wikidata.org/entity/Q5']}} + self.assertEqual([], self.compare_properties._get_allowed_list(claims, prop, expression)) + + def test_process_cardinalities_with_nothing(self): + expression = {} + shape = {} + prop = "" + allowed = [] + self.assertEqual("", self.compare_properties._process_cardinalities(expression, allowed, shape, prop)) + + def test_process_cardinalities_with_values(self): + expression = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + shape = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'valueExpr': {'type': 'NodeConstraint', 'values': ['http://www.wikidata.org/entity/Q5']}} + prop = "P31" + allowed = ["Q5"] + self.assertEqual("", self.compare_properties._process_cardinalities(expression, allowed, shape, prop)) + + def test_get_cardinalities_with_nothing(self): + occurrences = 1 + expression = {} + self.assertEqual("correct", self.compare_properties._get_cardinalities(occurrences, expression)) + + def test_get_cardinalities_with_values(self): + occurrences = 1 + expression = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + self.assertEqual("correct", self.compare_properties._get_cardinalities(occurrences, expression)) + + def test_process_triple_constraint_with_nothing(self): + statement = {} + expression = {} + allowed = "" + self.assertEqual("", self.compare_properties._process_triple_constraint(statement, expression, allowed)) + + def test_process_triple_constraint_with_values(self): + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'valueExpr': {'type': 'NodeConstraint', 'values': ['http://www.wikidata.org/entity/Q2']}} + allowed = "Q2" + self.assertEqual("correct", self.compare_properties._process_triple_constraint(statement, expression, allowed)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_compare_statements.py b/tests/test_compare_statements.py new file mode 100644 index 0000000..ff36741 --- /dev/null +++ b/tests/test_compare_statements.py @@ -0,0 +1,139 @@ +import unittest + +from comparejsonld import CompareStatements + + +class TestCompareStatements(unittest.TestCase): + def setUp(self): + entities = {"entities": + {'Q1': + {'title': 'Q1', + 'type': 'item', + 'id': 'Q1', + 'claims': {'P31': [{'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'}, + 'type': 'statement', + 'id': '1', + 'rank': 'normal'}], + }, + 'sitelinks': {}}}} + entity = "Q1" + statement = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + ] + }} + self.compare_statements = CompareStatements(entities, entity, statement) + + def test_compare_statements_with_nothing(self): + entities = {} + entity = "" + statement = {} + test_method = CompareStatements(entities, entity, statement) + self.assertEqual({}, test_method.compare_statements()) + + def test_compare_statements(self): + result = {'1': {'necessity': 'required', + 'property': 'P31', + 'response': 'allowed'}} + self.assertEqual(result, self.compare_statements.compare_statements()) + + def test_process_shape_with_nothing(self): + statement = {} + shape = {} + child = {} + child, allowed = self.compare_statements._process_shape(statement, shape, child) + self.assertEqual({"response": "not in schema"}, child) + self.assertEqual("not in schema", allowed) + + def test_process_shape_with_values(self): + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + shape = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + ] + }} + child = {} + child, allowed = self.compare_statements._process_shape(statement, shape, child) + self.assertEqual({"response": "allowed"}, child) + self.assertEqual("allowed", allowed) + + def test_process_expressions_with_nothing(self): + expression = {} + shape = {} + statement = {} + allowed = "" + self.assertEqual("", self.compare_statements.process_expressions(expression, shape, statement, allowed)) + + def test_process_expressions_with_values(self): + expression = {"type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + shape = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + ] + }} + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + allowed = "allowed" + self.assertEqual("allowed", self.compare_statements.process_expressions(expression, shape, statement, allowed)) + + def test_process_triple_constraint_with_nothing(self): + statement = {} + expression = {} + allowed = "" + self.assertEqual("", self.compare_statements._process_triple_constraint(statement, expression, allowed)) + + def test_process_triple_constraint_with_values(self): + expression = {"type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '1', + 'datavalue': {'value': + {'entity-type': 'item', 'numeric-id': 2, 'id': 'Q2'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item'} + allowed = "allowed" + self.assertEqual("allowed", self.compare_statements._process_triple_constraint(statement, expression, allowed)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_compare_v1_v2.py b/tests/test_compare_v1_v2.py index 1c001dc..507ce53 100644 --- a/tests/test_compare_v1_v2.py +++ b/tests/test_compare_v1_v2.py @@ -21,25 +21,6 @@ def tearDown(self) -> None: # We don't need to tear anything down after the test pass - def test_specific_wikidata_item_against_schema(self): - """ - Tests a specific entity against a certain schema and checks that - a statements and a properties response are returned - """ - test_pairs: dict = {"E236": "Q1728820", - "E236": "Q100532807" - } - - for key in test_pairs: - with self.subTest(key=key): - value = test_pairs[key] - response = self.app.get(f'/api?entityschema={key}&entity={value}&language=en', - follow_redirects=True) - response2 = self.app.get(f'/api/v2?entityschema={key}&entity={value}&language=en', - follow_redirects=True) - self.assertEqual(response.json["statements"], response2.json["statements"][0]) - self.assertEqual(response.json["properties"], response2.json["properties"][0]) - def test_lexical_category(self): """ This test checks that a lexicalCategory response is returned when a @@ -51,9 +32,10 @@ def test_lexical_category(self): value = test_pairs[key] response = self.app.get(f'/api/v2?entityschema={key}&entity={value}&language=en', follow_redirects=True) - self.assertIsNotNone(response.json["general"]["lexicalCategory"]) - self.assertIsNotNone(response.json["general"]["language"]) + self.assertIsNotNone(response.json["general"][0]["lexicalCategory"]) + self.assertIsNotNone(response.json["general"][0]["language"]) + @unittest.skip("Not running check on all wikidata schemas as they take too long") def test_wikidata_entityschemas(self) -> None: """ Tests all wikidata entityschemas return 200 @@ -90,9 +72,9 @@ def test_specific_entityschema(self) -> None: response = self.app.get(f'/api/v2?entityschema={schema}&entity=Q100532807&language=en', follow_redirects=True) self.assertEqual(200, response.status_code) - self.assertEqual("Member of the Oireachtas", response.json["name"]) + self.assertEqual("Member of the Oireachtas", response.json["name"][0]) self.assertEqual({'name': 'occupation', 'necessity': 'required', 'response': 'missing'}, - response.json["properties"]["P106"]) + response.json["properties"][0]["P106"]) def test_entityschema_e3(self): """ @@ -204,11 +186,13 @@ def test_entityschema_e236_2(self): response2 = self.app.get('/api?entityschema=E236&entity=Q185272&language=en', follow_redirects=True) self.assertEqual(200, response.status_code) - properties: list = ["P39","P106", "P18", "P4690"] + properties: list = ["P39", "P106", "P18", "P4690"] for prop in properties: with self.subTest(prop=prop): - self.assertIn(response.json["properties"][0][prop]["response"], ["correct", "present", "allowed"]) - self.assertEqual(response.json["properties"][0][prop]["response"], response2.json["properties"][prop]["response"]) + self.assertIn(response.json["properties"][0][prop]["response"], + ["correct", "present", "allowed"]) + self.assertEqual(response.json["properties"][0][prop]["response"], + response2.json["properties"][prop]["response"]) def test_entityschema_e239(self): """ @@ -257,21 +241,6 @@ def test_entityschema_e278(self): follow_redirects=True) self.assertEqual(200, response.status_code) - def test_entityschema_e292(self): - """ - Tests item with cardinality of 0 evaluates correctly - - This test tests entityschema E295 (townland) against entity Q85396849 (Drumlohan). - The schema has a P361 (part of) with a cardinality of 0, meaning the item should - not contain any P361. The test checks that the response is false for this item - """ - response = self.app.get('/api?entityschema=E292&entity=Q51792612&language=en', - follow_redirects=True) - response2 = self.app.get('/api/v2?entityschema=E292&entity=Q51792612&language=en', - follow_redirects=True) - self.assertEqual(response.status_code, response2.status_code) - self.assertEqual(response.json["properties"], response2.json["properties"][0]) - def test_entityschema_e295(self): """ Tests item with cardinality of 0 evaluates correctly @@ -355,7 +324,7 @@ def test_entityschema_e351(self): """ response = self.app.get('/api/v2?entityschema=E351&entity=Q743656&language=en', follow_redirects=True) - self.assertIn(response.json["properties"]["P31"]["response"], ["not enough correct statements"]) + self.assertIn(response.json["properties"][0]["P31"]["response"], ["not enough correct statements"]) if __name__ == '__main__': diff --git a/tests/test_utilities.py b/tests/test_utilities.py new file mode 100644 index 0000000..7696e6c --- /dev/null +++ b/tests/test_utilities.py @@ -0,0 +1,197 @@ +import unittest + +from comparejsonld import Utilities + + +class UtilitiesTests(unittest.TestCase): + + def setUp(self): + self.utilities = Utilities() + + def test_calculate_necessity_with_nothing(self): + prop = "" + shape = {} + test_method = self.utilities.calculate_necessity(prop, shape) + self.assertEqual("absent", test_method) + + def test_calculate_necessity_with_values_with_required(self): + prop = "P31" + shape = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31" + } + ] + } + } + necessity = self.utilities.calculate_necessity(prop, shape) + self.assertEqual("required", necessity) + + def test_calculate_necessity_with_values_with_optional(self): + prop = "P31" + shape = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31", + "min": 0 + } + ] + } + } + test_method = self.utilities.calculate_necessity(prop, shape) + self.assertEqual("optional", test_method) + + def test_calculate_necessity_with_values_with_absent(self): + prop = "P32" + shape = {"type": "Shape", + "id": "test", + "expression": { + "type": "EachOf", + "expressions": [ + { + "type": "TripleConstraint", + "predicate": "http://www.wikidata.org/prop/direct/P31", + "min": 0 + } + ] + } + } + test_method = self.utilities.calculate_necessity(prop, shape) + self.assertEqual("absent", test_method) + + def test_required_or_absent_with_nothing(self): + expression = {} + test_method = self.utilities.required_or_absent(expression) + self.assertEqual("required", test_method) + + def test_required_or_absent_with_optional(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'min': 0, + } + test_method = self.utilities.required_or_absent(expression) + self.assertEqual("optional", test_method) + + def test_required_or_absent_with_required(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'min': 1, + } + test_method = self.utilities.required_or_absent(expression) + self.assertEqual("required", test_method) + + def test_required_or_absent_with_absent(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'min': 0, + 'max': 0, + } + test_method = self.utilities.required_or_absent(expression) + self.assertEqual("absent", test_method) + + def test_process_cardinalities_with_nothing(self): + expression = {} + claim = {} + test_method = self.utilities.process_cardinalities(expression, claim) + self.assertEqual("not enough correct statements", test_method) + + def test_process_cardinalities_with_max(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'max': 0, + } + claim = {'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '851b1c24539bd7aa725376baba4bcf0928099a66', + 'datatype': 'wikibase-item' + } + } + + test_method = self.utilities.process_cardinalities(expression, claim) + self.assertEqual("too many statements", test_method) + + def test_process_cardinalities_with_min(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'min': 0, + } + claim = {'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '851b1c24539bd7aa725376baba4bcf0928099a66', + 'datatype': 'wikibase-item' + } + } + test_method = self.utilities.process_cardinalities(expression, claim) + self.assertEqual("correct", test_method) + + def test_process_cardinalities_with_max_and_min(self): + expression = {'type': 'TripleConstraint', + 'predicate': 'http://www.wikidata.org/prop/direct/P31', + 'min': 0, + 'max': 0 + } + claim = {'mainsnak': + {'snaktype': 'value', + 'property': 'P31', + 'hash': '851b1c24539bd7aa725376baba4bcf0928099a66', + 'datatype': 'wikibase-item' + } + } + test_method = self.utilities.process_cardinalities(expression, claim) + self.assertEqual("too many statements", test_method) + + def test_process_node_constraint_incorrect(self): + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '851b1c24539bd7aa725376baba4bcf0928099a66', + 'datavalue': { + 'value': { + 'entity-type': 'item', + 'numeric-id': 110430875, + 'id': 'Q110430875'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item' + } + expression = {'type': 'NodeConstraint', + 'values': ['http://www.wikidata.org/entity/Q5'] + } + test_method = self.utilities.process_node_constraint(statement, expression, "") + self.assertEqual("incorrect", test_method) + + def test_process_node_constraint_nothing(self): + statement = {} + expression = {} + test_method = self.utilities.process_node_constraint(statement, expression, "") + self.assertEqual("", test_method) + + def test_process_node_constraint_correct(self): + statement = {'snaktype': 'value', + 'property': 'P31', + 'hash': '851b1c24539bd7aa725376baba4bcf0928099a66', + 'datavalue': { + 'value': { + 'entity-type': 'item', + 'numeric-id': 110430875, + 'id': 'Q5'}, + 'type': 'wikibase-entityid'}, + 'datatype': 'wikibase-item' + } + expression = {'type': 'NodeConstraint', + 'values': ['http://www.wikidata.org/entity/Q5'] + } + test_method = self.utilities.process_node_constraint(statement, expression, "") + self.assertEqual("correct", test_method) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_v1.py b/tests/test_v1.py index 6e515bd..e5b595e 100644 --- a/tests/test_v1.py +++ b/tests/test_v1.py @@ -49,6 +49,7 @@ def test_lexical_category(self): self.assertIsNotNone(response.json["general"]["lexicalCategory"]) self.assertIsNotNone(response.json["general"]["language"]) + @unittest.skip("Not running check on all wikidata schemas as they take too long") def test_wikidata_entityschemas(self) -> None: """ Tests all wikidata entityschemas return 200