diff --git a/src/pyobo/struct/struct.py b/src/pyobo/struct/struct.py index 0a74695e..c053291f 100644 --- a/src/pyobo/struct/struct.py +++ b/src/pyobo/struct/struct.py @@ -158,7 +158,6 @@ def from_text( ) acronym = SynonymTypeDef(reference=Reference(prefix="omo", identifier="0003012", name="acronym")) - ReferenceHint = Union[Reference, "Term", tuple[str, str], str] @@ -406,7 +405,13 @@ def iterate_properties(self) -> Iterable[tuple[str, str]]: for value in sorted(values): yield prop, value - def iterate_obo_lines(self, *, ontology, typedefs) -> Iterable[str]: + def iterate_obo_lines( + self, + *, + ontology: str, + typedefs: list[TypeDef] | None = None, + emit_object_properties: bool = True, + ) -> Iterable[str]: """Iterate over the lines to write in an OBO file.""" yield f"\n[{self.type}]" yield f"id: {self.preferred_curie}" @@ -430,6 +435,18 @@ def iterate_obo_lines(self, *, ontology, typedefs) -> Iterable[str]: for parent in sorted(self.parents, key=attrgetter("prefix", "identifier")): yield f"{parent_tag}: {parent}" # __str__ bakes in the ! name + if emit_object_properties: + yield from self._emit_relations(ontology, typedefs) + + yield from self._emit_properties() + + for synonym in sorted(self.synonyms, key=attrgetter("name")): + yield synonym.to_obo() + + + def _emit_relations( + self, ontology: str, typedefs: list[TypeDef] | None = None + ) -> Iterable[str]: for typedef, references in sorted(self.relationships.items(), key=_sort_relations): if (not typedefs or typedef not in typedefs) and ( ontology, @@ -449,12 +466,11 @@ def iterate_obo_lines(self, *, ontology, typedefs) -> Iterable[str]: s += f" {reference.name}" yield s + def _emit_properties(self) -> Iterable[str]: for prop, value in sorted(self.iterate_properties(), key=_sort_properties): # TODO deal with typedefs for properties yield f'property_value: {prop} "{value}" xsd:string' # TODO deal with types later - for synonym in sorted(self.synonyms, key=attrgetter("name")): - yield synonym.to_obo() @staticmethod def _escape(s) -> str: @@ -666,7 +682,7 @@ def _iter_terms(self, use_tqdm: bool = False, desc: str = "terms") -> Iterable[T else: yield from self - def iterate_obo_lines(self) -> Iterable[str]: + def iterate_obo_lines(self, emit_object_properties: bool = True) -> Iterable[str]: """Iterate over the lines to write in an OBO file.""" yield f"format-version: {self.format_version}" @@ -707,13 +723,20 @@ def iterate_obo_lines(self) -> Iterable[str]: yield from typedef.iterate_obo_lines() for term in self: - yield from term.iterate_obo_lines(ontology=self.ontology, typedefs=self.typedefs) + yield from term.iterate_obo_lines( + ontology=self.ontology, + typedefs=self.typedefs, + emit_object_properties=emit_object_properties, + ) def write_obo( - self, file: Union[None, str, TextIO, Path] = None, use_tqdm: bool = False + self, + file: Union[None, str, TextIO, Path] = None, + use_tqdm: bool = False, + emit_object_properties: bool = True, ) -> None: """Write the OBO to a file.""" - it = self.iterate_obo_lines() + it = self.iterate_obo_lines(emit_object_properties=emit_object_properties) if use_tqdm: it = tqdm(it, desc=f"Writing {self.ontology}", unit_scale=True, unit="line") if isinstance(file, (str, Path, os.PathLike)):