|
70 | 70 | RELATED_TO = "related to" |
71 | 71 | AGE_IN_YEARS = "age in years" |
72 | 72 |
|
| 73 | +EMPTY = "" |
| 74 | +ID = "identifier" |
| 75 | +KEY = "key" |
| 76 | + |
73 | 77 | ALL_ELEMENTS = [PREFIXES, *SCHEMA_ELEMENTS] |
74 | 78 | EXPECTED = { |
75 | 79 | PREFIXES: {"sc1p1", "sc2p1"}, |
@@ -1631,6 +1635,125 @@ def test_type_and_slot_with_same_name() -> None: |
1631 | 1635 | assert view.get_uri("test", imports=True) == "ex:test" |
1632 | 1636 |
|
1633 | 1637 |
|
| 1638 | +@pytest.fixture(scope="module") |
| 1639 | +def identifier_key_schema() -> str: |
| 1640 | + """Return a schema that defines a set of slots with identifiers and keys, and a test class to populate.""" |
| 1641 | + return """ |
| 1642 | +# yaml-language-server: $schema=https://linkml.io/linkml-model/linkml_model/jsonschema/meta.schema.json |
| 1643 | +id: https://w3id.org/linkml/examples/identifiers |
| 1644 | +title: Identifiers and Keys |
| 1645 | +name: identifiers |
| 1646 | +description: Schema for testing identifiers and keys |
| 1647 | +slots: |
| 1648 | + slot_a: |
| 1649 | + slot_b: |
| 1650 | + id_slot_a: |
| 1651 | + identifier: true |
| 1652 | + id_slot_b: |
| 1653 | + identifier: true |
| 1654 | + id_slot_false: |
| 1655 | + identifier: false |
| 1656 | + key_slot_a: |
| 1657 | + key: true |
| 1658 | + key_slot_b: |
| 1659 | + key: true |
| 1660 | + key_slot_false: |
| 1661 | + key: false |
| 1662 | +
|
| 1663 | +classes: |
| 1664 | + TestClass: |
| 1665 | + slots: |
| 1666 | + - slot_a |
| 1667 | + - slot_b |
| 1668 | +""" |
| 1669 | + |
| 1670 | + |
| 1671 | +@pytest.mark.parametrize("id_slot_a", [EMPTY, "id_slot_a"]) |
| 1672 | +@pytest.mark.parametrize("id_slot_b", [EMPTY, "id_slot_b"]) |
| 1673 | +@pytest.mark.parametrize("id_slot_false", [EMPTY, "id_slot_false"]) |
| 1674 | +@pytest.mark.parametrize("key_slot_a", [EMPTY, "key_slot_a"]) |
| 1675 | +@pytest.mark.parametrize("key_slot_b", [EMPTY, "key_slot_b"]) |
| 1676 | +@pytest.mark.parametrize("key_slot_false", [EMPTY, "key_slot_false"]) |
| 1677 | +def test_get_identifier_get_key_slot( |
| 1678 | + identifier_key_schema: str, |
| 1679 | + id_slot_a: str, |
| 1680 | + id_slot_b: str, |
| 1681 | + id_slot_false: str, |
| 1682 | + key_slot_a: str, |
| 1683 | + key_slot_b: str, |
| 1684 | + key_slot_false: str, |
| 1685 | +) -> None: |
| 1686 | + """Test the retrieval of "identifier" and "key" slots in classes in the schema. |
| 1687 | +
|
| 1688 | + The parameters represent the slots to be added to the test class; if the value of the parameter is EMPTY, |
| 1689 | + the slot is not added. If the parameter is a string, that slot is added to the test class. |
| 1690 | +
|
| 1691 | + For example, given the following set of parameters: |
| 1692 | +
|
| 1693 | + id_slot_a: "id_slot_a" |
| 1694 | + id_slot_b: EMPTY |
| 1695 | + id_slot_false: "id_slot_false" |
| 1696 | + key_slot_a: EMPTY |
| 1697 | + key_slot_b: EMPTY |
| 1698 | + key_slot_false: "key_slot_false" |
| 1699 | +
|
| 1700 | + The following lines would be added to the bottom of the identifier_key_schema: |
| 1701 | +
|
| 1702 | + - id_slot_a |
| 1703 | + - id_slot_false |
| 1704 | + - key_slot_false |
| 1705 | +
|
| 1706 | + resulting in the following structure for `TestClass`: |
| 1707 | +
|
| 1708 | + classes: |
| 1709 | + TestClass: |
| 1710 | + slots: |
| 1711 | + - slot_a |
| 1712 | + - slot_b |
| 1713 | + - id_slot_a |
| 1714 | + - id_slot_false |
| 1715 | + - key_slot_false |
| 1716 | +
|
| 1717 | + This allows the testing of a large number of combinations without having to generate all 2^^6 (64) manually. |
| 1718 | + """ |
| 1719 | + all_id_slots = [id_slot_a, id_slot_b, id_slot_false] |
| 1720 | + all_key_slots = [key_slot_a, key_slot_b, key_slot_false] |
| 1721 | + |
| 1722 | + for k in [*all_id_slots, *all_key_slots]: |
| 1723 | + if k: |
| 1724 | + identifier_key_schema += f" - {k}\n" |
| 1725 | + |
| 1726 | + sv = SchemaView(identifier_key_schema) |
| 1727 | + test_class_slots = sv.class_slots("TestClass") |
| 1728 | + # ensure that the correct slots are in the schema |
| 1729 | + assert set(test_class_slots) == {"slot_a", "slot_b", *[s for s in [*all_id_slots, *all_key_slots] if s]} |
| 1730 | + |
| 1731 | + # Generate the expected slots to be returned by `get_***_slot` for identifiers and keys. |
| 1732 | + # Note that id_slot_false and key_slot_false have `identifier` and `key` set to `false`, |
| 1733 | + # so we would not expect `get_identifier_slot` or `get_key_slot` to return these slots. |
| 1734 | + # If the value from the parameters is EMPTY, the attribute is not present. |
| 1735 | + expected = { |
| 1736 | + # expected result of get_identifier_slot |
| 1737 | + ID: id_slot_a or id_slot_b, |
| 1738 | + # expected result of get_identifier_slot, falling back on get_key_slot |
| 1739 | + f"{ID}_or_{KEY}": id_slot_a or id_slot_b or key_slot_a or key_slot_b, |
| 1740 | + # expected result of get_key_slot |
| 1741 | + KEY: key_slot_a or key_slot_b, |
| 1742 | + } |
| 1743 | + |
| 1744 | + got = { |
| 1745 | + ID: sv.get_identifier_slot("TestClass", use_key=False), |
| 1746 | + f"{ID}_or_{KEY}": sv.get_identifier_slot("TestClass", use_key=True), |
| 1747 | + KEY: sv.get_key_slot("TestClass"), |
| 1748 | + } |
| 1749 | + |
| 1750 | + for id_key, exp in expected.items(): |
| 1751 | + if exp: |
| 1752 | + assert got[id_key].name == exp |
| 1753 | + else: |
| 1754 | + assert got[id_key] is None |
| 1755 | + |
| 1756 | + |
1634 | 1757 | """ |
1635 | 1758 | merge_schema tests: https://github.com/linkml/linkml/issues/1143 |
1636 | 1759 | """ |
|
0 commit comments