Skip to content

Commit

Permalink
fix: formatting of SequencePath and AlternativePath (#2504)
Browse files Browse the repository at this point in the history
These path types were formatted without parentheses even if they
contained multiple elements, resulting in string representations that
did not accurately represent the path.

This change fixes the formatting so that the string representations are
enclosed in parentheses when necessary.

- Fixes <#2503>.
  • Loading branch information
lukasmu committed Jul 31, 2023
1 parent bd797ac commit 9c73581
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 11 deletions.
24 changes: 14 additions & 10 deletions rdflib/paths.py
Expand Up @@ -213,6 +213,15 @@
ZeroOrOne = "?"


def _n3(
arg: Union["URIRef", "Path"], namespace_manager: Optional["NamespaceManager"] = None
) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
if isinstance(arg, (SequencePath, AlternativePath)) and len(arg.args) > 1:
return "(%s)" % arg.n3(namespace_manager)
return arg.n3(namespace_manager) # type: ignore[union-attr]


@total_ordering
class Path:
__or__: Callable[["Path", Union["URIRef", "Path"]], "AlternativePath"]
Expand Down Expand Up @@ -260,8 +269,7 @@ def __repr__(self) -> str:
return "Path(~%s)" % (self.arg,)

def n3(self, namespace_manager: Optional["NamespaceManager"] = None) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
return "^%s" % self.arg.n3(namespace_manager) # type: ignore[union-attr]
return "^%s" % _n3(self.arg, namespace_manager)


class SequencePath(Path):
Expand Down Expand Up @@ -318,8 +326,7 @@ def __repr__(self) -> str:
return "Path(%s)" % " / ".join(str(x) for x in self.args)

def n3(self, namespace_manager: Optional["NamespaceManager"] = None) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
return "/".join(a.n3(namespace_manager) for a in self.args) # type: ignore[union-attr]
return "/".join(_n3(a, namespace_manager) for a in self.args)


class AlternativePath(Path):
Expand All @@ -345,8 +352,7 @@ def __repr__(self) -> str:
return "Path(%s)" % " | ".join(str(x) for x in self.args)

def n3(self, namespace_manager: Optional["NamespaceManager"] = None) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
return "|".join(a.n3(namespace_manager) for a in self.args) # type: ignore[union-attr]
return "|".join(_n3(a, namespace_manager) for a in self.args)


class MulPath(Path):
Expand Down Expand Up @@ -470,8 +476,7 @@ def __repr__(self) -> str:
return "Path(%s%s)" % (self.path, self.mod)

def n3(self, namespace_manager: Optional["NamespaceManager"] = None) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
return "%s%s" % (self.path.n3(namespace_manager), self.mod) # type: ignore[union-attr]
return "%s%s" % (_n3(self.path, namespace_manager), self.mod)


class NegatedPath(Path):
Expand Down Expand Up @@ -505,8 +510,7 @@ def __repr__(self) -> str:
return "Path(! %s)" % ",".join(str(x) for x in self.args)

def n3(self, namespace_manager: Optional["NamespaceManager"] = None) -> str:
# type error: Item "Path" of "Union[Path, URIRef]" has no attribute "n3" [union-attr]
return "!(%s)" % ("|".join(arg.n3(namespace_manager) for arg in self.args)) # type: ignore[union-attr]
return "!(%s)" % ("|".join(_n3(arg, namespace_manager) for arg in self.args))


class PathList(list):
Expand Down
27 changes: 26 additions & 1 deletion test/test_path.py
Expand Up @@ -54,15 +54,40 @@
"rdfs:subClassOf?",
),
(
RDF.type / RDFS.subClassOf * "*",
RDF.type / MulPath(RDFS.subClassOf, "*"),
f"<{RDF.type}>/<{RDFS.subClassOf}>*",
"rdf:type/rdfs:subClassOf*",
),
(
RDF.type / ((SequencePath(RDFS.subClassOf)) * "*"),
f"<{RDF.type}>/<{RDFS.subClassOf}>*",
"rdf:type/rdfs:subClassOf*",
),
(
RDF.type / RDFS.subClassOf * "*",
f"(<{RDF.type}>/<{RDFS.subClassOf}>)*",
"(rdf:type/rdfs:subClassOf)*",
),
(
-(RDF.type | RDFS.subClassOf),
f"!(<{RDF.type}>|<{RDFS.subClassOf}>)",
"!(rdf:type|rdfs:subClassOf)",
),
(
-(RDF.type | ((SequencePath(RDFS.subClassOf)) * "*")),
f"!(<{RDF.type}>|<{RDFS.subClassOf}>*)",
"!(rdf:type|rdfs:subClassOf*)",
),
(
SequencePath(RDFS.subClassOf),
f"<{RDFS.subClassOf}>",
"rdfs:subClassOf",
),
(
AlternativePath(RDFS.subClassOf),
f"<{RDFS.subClassOf}>",
"rdfs:subClassOf",
),
],
)
def test_paths_n3(
Expand Down

0 comments on commit 9c73581

Please sign in to comment.