From c33c32d08697883258f3b832a5f2a1f0c219ef85 Mon Sep 17 00:00:00 2001 From: ialarmedalien Date: Fri, 22 Nov 2024 09:20:32 -0800 Subject: [PATCH] Ensure that relative imports can be imported without requiring `./` in front of the import file name --- linkml_runtime/utils/schemaview.py | 6 +++--- .../L0_0/L1_0_0/L2_0_0_2/four.yaml | 13 +++++++++++++ .../L0_0/L1_0_0/L2_0_0_2/one.yaml | 14 ++++++++++++++ .../L0_0/L1_0_0/L2_0_0_2/stepchild.yaml | 16 ++++++++++++++++ .../L0_0/L1_0_0/L2_0_0_2/three.yaml | 14 ++++++++++++++ .../L0_0/L1_0_0/L2_0_0_2/two.yaml | 13 +++++++++++++ .../input/imports_relative/L0_0/L1_0_0/main.yaml | 3 ++- tests/test_utils/test_schemaview.py | 7 ++++++- 8 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/four.yaml create mode 100644 tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/one.yaml create mode 100644 tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/stepchild.yaml create mode 100644 tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/three.yaml create mode 100644 tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/two.yaml diff --git a/linkml_runtime/utils/schemaview.py b/linkml_runtime/utils/schemaview.py index b937964d..a15abed1 100644 --- a/linkml_runtime/utils/schemaview.py +++ b/linkml_runtime/utils/schemaview.py @@ -303,7 +303,7 @@ def imports_closure(self, imports: bool = True, traverse: Optional[bool] = None, # - subdir/types.yaml # we should treat the two `types.yaml` as separate schemas from the POV of the # origin schema. - if sn.startswith('.') and ':' not in i: + if ('/') in sn and ':' not in i: i = os.path.normpath(str(Path(sn).parent / i)) todo.append(i) @@ -1859,8 +1859,8 @@ def set_modified(self) -> None: self.modifications += 1 def materialize_patterns(self) -> None: - """Materialize schema by expanding structured patterns - into regular expressions based on composite patterns + """Materialize schema by expanding structured patterns + into regular expressions based on composite patterns provided in the settings dictionary. """ resolver = PatternResolver(self) diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/four.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/four.yaml new file mode 100644 index 00000000..153c1094 --- /dev/null +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/four.yaml @@ -0,0 +1,13 @@ +id: four +name: import_four +title: Import Four +description: | + Import loaded by the StepChild class. +imports: + - linkml:types +classes: + Four: + attributes: + value: + range: string + ifabsent: "Four" diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/one.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/one.yaml new file mode 100644 index 00000000..f234a431 --- /dev/null +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/one.yaml @@ -0,0 +1,14 @@ +id: one +name: import_one +title: Import One +description: | + Import loaded by the StepChild class. +imports: + - linkml:types + - two +classes: + One: + attributes: + value: + range: string + ifabsent: "One" diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/stepchild.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/stepchild.yaml new file mode 100644 index 00000000..08bc583c --- /dev/null +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/stepchild.yaml @@ -0,0 +1,16 @@ +id: stepchild +name: stepchild +title: stepchild +description: | + Child class that imports files in the same directory as itself without consistently using `./` in the link notation. +imports: + - linkml:types + - one + - two + - ./three +classes: + StepChild: + attributes: + value: + range: string + ifabsent: "StepChild" diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/three.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/three.yaml new file mode 100644 index 00000000..18e31dcf --- /dev/null +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/three.yaml @@ -0,0 +1,14 @@ +id: three +name: import_three +title: Import Three +description: | + Import loaded by the StepChild class. +imports: + - linkml:types + - ./four +classes: + Three: + attributes: + value: + range: string + ifabsent: "Three" diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/two.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/two.yaml new file mode 100644 index 00000000..859a3087 --- /dev/null +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/L2_0_0_2/two.yaml @@ -0,0 +1,13 @@ +id: two +name: import_two +title: Import Two +description: | + Import loaded by the StepChild class. +imports: + - linkml:types +classes: + Two: + attributes: + value: + range: string + ifabsent: "Two" diff --git a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/main.yaml b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/main.yaml index ad5c48a2..01add3d0 100644 --- a/tests/test_utils/input/imports_relative/L0_0/L1_0_0/main.yaml +++ b/tests/test_utils/input/imports_relative/L0_0/L1_0_0/main.yaml @@ -8,10 +8,11 @@ imports: - ../../L0_1/cousin - ./L2_0_0_0/child - ./L2_0_0_1/child + - L2_0_0_2/stepchild classes: Main: description: "Our intrepid main class!" attributes: value: range: string - ifabsent: "Main" \ No newline at end of file + ifabsent: "Main" diff --git a/tests/test_utils/test_schemaview.py b/tests/test_utils/test_schemaview.py index c9f28ff8..e194b160 100644 --- a/tests/test_utils/test_schemaview.py +++ b/tests/test_utils/test_schemaview.py @@ -539,6 +539,11 @@ def test_imports_relative(): '../L1_0_1/dupe', './L2_0_0_0/child', './L2_0_0_1/child', + 'L2_0_0_2/two', + 'L2_0_0_2/one', + 'L2_0_0_2/four', + 'L2_0_0_2/three', + 'L2_0_0_2/stepchild', 'main' ] @@ -896,4 +901,4 @@ def test_materialize_nonscalar_slot_usage(): assert cls.attributes["tempo"].annotations.expected_value.value == "a number between 0 and 200" assert cls.attributes["tempo"].annotations.preferred_unit.value == "BPM" assert cls.attributes["tempo"].domain_of == ["DJController"] - assert cls.slot_usage["tempo"].domain_of == [] \ No newline at end of file + assert cls.slot_usage["tempo"].domain_of == []