diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f90995d13..84c913a9d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: name: Blacken - repo: https://github.com/PyCQA/bandit - rev: '1.7.4' + rev: '1.7.5' hooks: - id: bandit args: [-r] diff --git a/docs/tools-instructions.md b/docs/tools-instructions.md index 0066cb2fb..133593c62 100644 --- a/docs/tools-instructions.md +++ b/docs/tools-instructions.md @@ -167,9 +167,9 @@ optional arguments: Note: FaCT++ is preferred with EMMO. --root ROOT, -r ROOT Name of root node in the graph. Defaults to all classes. - --leafs LEAFS Leafs nodes for plotting sub-graphs. May be provided + --leaves LEAVES Leaf nodes for plotting sub-graphs. May be provided as a comma-separated string and/or with multiple - --leafs options. + --leaves options. --exclude EXCLUDE, -E EXCLUDE Nodes, including their subclasses, to exclude from sub-graphs. May be provided as a comma-separated diff --git a/examples/emmodoc/emmo.md b/examples/emmodoc/emmo.md index 5e3626823..4f1e2aa6d 100644 --- a/examples/emmodoc/emmo.md +++ b/examples/emmodoc/emmo.md @@ -21,4 +21,4 @@ %BRANCHFIG EMMORelation caption='The complete taxonomy of EMMO relations.' terminated=0 relations=all edgelabels=0 %HEADER "The taxonomy of EMMO classes" level=2 -%BRANCHFIG EMMO caption='The almost complete taxonomy of EMMO classes. Only physical quantities and constants are left out.' terminated=0 relations=isA edgelabels=0 leafs=PhysicalDimension,BaseQuantity,DerivedQuantity,ExactConstant,MeasuredConstant,SIBaseUnit,SISpecialUnit,MetricPrefix,UTF8 +%BRANCHFIG EMMO caption='The almost complete taxonomy of EMMO classes. Only physical quantities and constants are left out.' terminated=0 relations=isA edgelabels=0 leaves=PhysicalDimension,BaseQuantity,DerivedQuantity,ExactConstant,MeasuredConstant,SIBaseUnit,SISpecialUnit,MetricPrefix,UTF8 diff --git a/examples/emmodoc/introduction.md b/examples/emmodoc/introduction.md index 8e314ceee..c06eb040a 100644 --- a/examples/emmodoc/introduction.md +++ b/examples/emmodoc/introduction.md @@ -75,7 +75,7 @@ For instance, in the graph of the top-level entity branch below, The root `EMMO` Non-defined classes are defined as an abstract group of objects, whose members are defined as belonging to the class. They are yellow in the graphical representations. -%BRANCHFIG EMMO leafs=Perspective,Elementary caption='Example of the top-level branch of EMMO showing some classes and relationships between them.' width=460 +%BRANCHFIG EMMO leaves=Perspective,Elementary caption='Example of the top-level branch of EMMO showing some classes and relationships between them.' width=460 ### Axioms diff --git a/examples/jupyter-visualization/emmographs.ipynb b/examples/jupyter-visualization/emmographs.ipynb index 1bd33ad4c..a94cd51d5 100644 --- a/examples/jupyter-visualization/emmographs.ipynb +++ b/examples/jupyter-visualization/emmographs.ipynb @@ -45,10 +45,10 @@ } ], "source": [ - "leafs = set()\n", + "leaves = set()\n", "for s in onto.Perspective.subclasses():\n", - " leafs.update(s.subclasses())\n", - "graph = OntoGraph(onto, onto.Perspective, leafs=leafs, parents=1, edgelabels=True)\n", + " leaves.update(s.subclasses())\n", + "graph = OntoGraph(onto, onto.Perspective, leaves=leaves, parents=1, edgelabels=True)\n", "\n", "graph.dot\n", "#graph = OntoGraph(onto, onto.isA, leafs=('Physical',))\n", diff --git a/ontopy/graph.py b/ontopy/graph.py index fdba5f156..569dd5225 100644 --- a/ontopy/graph.py +++ b/ontopy/graph.py @@ -166,7 +166,7 @@ class OntoGraph: # pylint: disable=too-many-instance-attributes Name or owlready2 entity of root node to plot subgraph below. If `root` is `graph.ALL`, all classes will be included in the subgraph. - leafs : None | sequence + leaves : None | sequence A sequence of leaf node names for generating sub-graphs. entities : None | sequence A sequence of entities to add to the graph. @@ -236,7 +236,7 @@ def __init__( # pylint: disable=too-many-arguments,too-many-locals self, ontology, root=None, - leafs=None, + leaves=None, entities=None, relations="isA", style=None, @@ -293,7 +293,7 @@ def __init__( # pylint: disable=too-many-arguments,too-many-locals elif root: self.add_branch( root, - leafs, + leaves, relations=relations, edgelabels=edgelabels, addnodes=addnodes, @@ -350,9 +350,9 @@ def add_entities( # pylint: disable=too-many-arguments def add_branch( # pylint: disable=too-many-arguments,too-many-locals self, root, - leafs=None, - include_leafs=True, - strict_leafs=False, + leaves=None, + include_leaves=True, + strict_leaves=False, exclude=None, relations="isA", edgelabels=None, @@ -363,17 +363,17 @@ def add_branch( # pylint: disable=too-many-arguments,too-many-locals include_parents="closest", **attrs, ): - """Adds branch under `root` ending at any entiry included in the - sequence `leafs`. If `include_leafs` is true, leafs classes are + """Adds branch under `root` ending at any entity included in the + sequence `leaves`. If `include_leaves` is true, leaf classes are also included.""" - if leafs is None: - leafs = () + if leaves is None: + leaves = () classes = self.ontology.get_branch( root=root, - leafs=leafs, - include_leafs=include_leafs, - strict_leafs=strict_leafs, + leaves=leaves, + include_leaves=include_leaves, + strict_leaves=strict_leaves, exclude=exclude, ) @@ -385,7 +385,7 @@ def add_branch( # pylint: disable=too-many-arguments,too-many-locals nodeattrs = {} nodeattrs[get_label(root)] = self.style.get("root", {}) - for leaf in leafs: + for leaf in leaves: nodeattrs[get_label(leaf)] = self.style.get("leaf", {}) self.add_entities( diff --git a/ontopy/ontodoc.py b/ontopy/ontodoc.py index efdad809f..bfd5ad412 100644 --- a/ontopy/ontodoc.py +++ b/ontopy/ontodoc.py @@ -518,9 +518,10 @@ class DocPP: # pylint: disable=too-many-instance-attributes - header_level: Header level. - terminated: Whether to branch should be terminated at all branch names in the final document. - - include_leafs: Whether to include leaf. + - include_leaves: Whether to include leaves as end points + to the branch. - %BRANCH name [header_level=3 terminated=1 include_leafs=0 + %BRANCH name [header_level=3 terminated=1 include_leaves=0 namespaces='' ontologies=''] * Insert generated figure of ontology branch `name`. The figure @@ -528,17 +529,17 @@ class DocPP: # pylint: disable=too-many-instance-attributes where `figdir` is given at class initiation. It is recommended to exclude the file extension from `path`. In this case, the default figformat will be used (and easily adjusted to the - correct format required by the backend). `leafs` may be a comma- + correct format required by the backend). `leaves` may be a comma- separated list of leaf node names. - %BRANCHFIG name [path='' caption='' terminated=1 include_leafs=1 - strict_leafs=1, width=0px leafs='' relations=all + %BRANCHFIG name [path='' caption='' terminated=1 include_leaves=1 + strict_leaves=1, width=0px leaves='' relations=all edgelabels=0 namespaces='' ontologies=''] * This is a combination of the %HEADER and %BRANCHFIG directives. %BRANCHHEAD name [level=2 path='' caption='' terminated=1 - include_leafs=1 width=0px leafs=''] + include_leaves=1 width=0px leaves=''] * This is a combination of the %HEADER, %BRANCHFIG and %BRANCH directives. It inserts documentation of branch `name`, with a @@ -546,7 +547,7 @@ class DocPP: # pylint: disable=too-many-instance-attributes element. %BRANCHDOC name [level=2 path='' title='' caption='' terminated=1 - strict_leafs=1 width=0px leafs='' relations='all' + strict_leaves=1 width=0px leaves='' relations='all' rankdir='BT' legend=1 namespaces='' ontologies=''] * Insert generated documentation for all entities of the given type. @@ -723,11 +724,11 @@ def process_branches(self): tokens[2:], header_level=3, terminated=1, - include_leafs=0, + include_leaves=0, namespaces="", ontologies="", ) - leafs = ( + leaves = ( names if opts.terminated else () ) # pylint: disable=no-member @@ -744,7 +745,7 @@ def process_branches(self): branch = filter_classes( onto.get_branch( - name, leafs, opts.include_leafs + name, leaves, opts.include_leaves ), # pylint: disable=no-member included_namespaces=included_namespaces, included_ontologies=included_ontologies, @@ -760,10 +761,10 @@ def _make_branchfig( # pylint: disable=too-many-arguments,too-many-locals name: str, path: "Union[Path, str]", terminated: bool, - include_leafs: bool, - strict_leafs: bool, + include_leaves: bool, + strict_leaves: bool, width: float, - leafs: "Union[str, list[str]]", + leaves: "Union[str, list[str]]", relations: str, edgelabels: str, rankdir: str, @@ -776,11 +777,12 @@ def _make_branchfig( # pylint: disable=too-many-arguments,too-many-locals Args: name: name of branch root path: optional figure path name - include_leafs: whether to include leafs - strict_leafs: whether strictly exclude leafs descendants + include_leaves: whether to include leaves as end points + to the branch. + strict_leaves: whether to strictly exclude leave descendants terminated: whether the graph should be terminated at leaf nodes width: optional figure width - leafs: optional leafs node names for graph termination + leaves: optional leaf node names for graph termination relations: comma-separated list of relations to include edgelabels: whether to include edgelabels rankdir: graph direction (BT, TB, RL, LR) @@ -790,19 +792,19 @@ def _make_branchfig( # pylint: disable=too-many-arguments,too-many-locals Returns: filepath: path to generated figure - leafs: used list of leaf node names + leaves: used list of leaf node names width: actual figure width """ onto = self.ontodoc.onto - if leafs: - if isinstance(leafs, str): - leafs = leafs.split(",") + if leaves: + if isinstance(leaves, str): + leaves = leaves.split(",") elif terminated: - leafs = set(self.get_branches()) - leafs.discard(name) + leaves = set(self.get_branches()) + leaves.discard(name) else: - leafs = None + leaves = None if path: figdir = os.path.dirname(path) formatext = os.path.splitext(path)[1] @@ -821,9 +823,9 @@ def _make_branchfig( # pylint: disable=too-many-arguments,too-many-locals graph = OntoGraph(onto, graph_attr={"rankdir": rankdir}) graph.add_branch( root=name, - leafs=leafs, - include_leafs=include_leafs, - strict_leafs=strict_leafs, + leaves=leaves, + include_leaves=include_leaves, + strict_leaves=strict_leaves, relations=relations, edgelabels=edgelabels, included_namespaces=included_namespaces, @@ -843,7 +845,7 @@ def _make_branchfig( # pylint: disable=too-many-arguments,too-many-locals if not os.path.exists(destdir): os.makedirs(destdir) graph.save(filepath, fmt=fmt) - return filepath, leafs, width + return filepath, leaves, width def process_branchfigs(self): """Process all %BRANCHFIG directives.""" @@ -856,10 +858,10 @@ def process_branchfigs(self): path="", caption="", terminated=1, - include_leafs=1, - strict_leafs=1, + include_leaves=1, + strict_leaves=1, width=0, - leafs="", + leaves="", relations="all", edgelabels=0, rankdir="BT", @@ -883,10 +885,10 @@ def process_branchfigs(self): name, opts.path, # pylint: disable=no-member opts.terminated, # pylint: disable=no-member - opts.include_leafs, # pylint: disable=no-member - opts.strict_leafs, # pylint: disable=no-member + opts.include_leaves, # pylint: disable=no-member + opts.strict_leaves, # pylint: disable=no-member opts.width, # pylint: disable=no-member - opts.leafs, # pylint: disable=no-member + opts.leaves, # pylint: disable=no-member opts.relations, # pylint: disable=no-member opts.edgelabels, # pylint: disable=no-member opts.rankdir, # pylint: disable=no-member @@ -921,9 +923,9 @@ def process_branchdocs(self): # pylint: disable=too-many-locals title=title, caption=title + ".", terminated=1, - strict_leafs=1, + strict_leaves=1, width=0, - leafs="", + leaves="", relations="all", edgelabels=0, rankdir="BT", @@ -943,15 +945,15 @@ def process_branchdocs(self): # pylint: disable=too-many-locals else () # pylint: disable=no-member ) - include_leafs = 1 - filepath, leafs, width = self._make_branchfig( + include_leaves = 1 + filepath, leaves, width = self._make_branchfig( name, opts.path, # pylint: disable=no-member opts.terminated, # pylint: disable=no-member - include_leafs, - opts.strict_leafs, # pylint: disable=no-member + include_leaves, + opts.strict_leaves, # pylint: disable=no-member opts.width, # pylint: disable=no-member - opts.leafs, # pylint: disable=no-member + opts.leaves, # pylint: disable=no-member opts.relations, # pylint: disable=no-member opts.edgelabels, # pylint: disable=no-member opts.rankdir, # pylint: disable=no-member @@ -972,9 +974,9 @@ def process_branchdocs(self): # pylint: disable=too-many-locals ) ) if with_branch: - include_leafs = 0 + include_leaves = 0 branch = filter_classes( - onto.get_branch(name, leafs, include_leafs), + onto.get_branch(name, leaves, include_leaves), included_namespaces=included_namespaces, included_ontologies=included_ontologies, ) @@ -1027,10 +1029,10 @@ def process_allfig(self): # pylint: disable=too-many-locals path="", level=3, terminated=0, - include_leafs=1, - strict_leafs=1, + include_leaves=1, + strict_leaves=1, width=0, - leafs="", + leaves="", relations="isA", edgelabels=0, rankdir="BT", @@ -1071,10 +1073,10 @@ def process_allfig(self): # pylint: disable=too-many-locals name, opts.path, # pylint: disable=no-member opts.terminated, # pylint: disable=no-member - opts.include_leafs, # pylint: disable=no-member - opts.strict_leafs, # pylint: disable=no-member + opts.include_leaves, # pylint: disable=no-member + opts.strict_leaves, # pylint: disable=no-member opts.width, # pylint: disable=no-member - opts.leafs, # pylint: disable=no-member + opts.leaves, # pylint: disable=no-member opts.relations, # pylint: disable=no-member opts.edgelabels, # pylint: disable=no-member opts.rankdir, # pylint: disable=no-member diff --git a/ontopy/ontology.py b/ontopy/ontology.py index 54e379c04..a7f35262d 100644 --- a/ontopy/ontology.py +++ b/ontopy/ontology.py @@ -1221,25 +1221,25 @@ def get_annotations(self, entity): def get_branch( # pylint: disable=too-many-arguments self, root, - leafs=(), - include_leafs=True, - strict_leafs=False, + leaves=(), + include_leaves=True, + strict_leaves=False, exclude=None, sort=False, ): """Returns a set with all direct and indirect subclasses of `root`. - Any subclass found in the sequence `leafs` will be included in + Any subclass found in the sequence `leaves` will be included in the returned list, but its subclasses will not. The elements - of `leafs` may be ThingClass objects or labels. + of `leaves` may be ThingClass objects or labels. - Subclasses of any subclass found in the sequence `leafs` will - be excluded from the returned list, where the elements of `leafs` + Subclasses of any subclass found in the sequence `leaves` will + be excluded from the returned list, where the elements of `leaves` may be ThingClass objects or labels. - If `include_leafs` is true, the leafs are included in the returned + If `include_leaves` is true, the leaves are included in the returned list, otherwise they are not. - If `strict_leafs` is true, any descendant of a leaf will be excluded + If `strict_leaves` is true, any descendant of a leaf will be excluded in the returned set. If given, `exclude` may be a sequence of classes, including @@ -1249,8 +1249,8 @@ def get_branch( # pylint: disable=too-many-arguments will be returned instead of a set. """ - def _branch(root, leafs): - if root not in leafs: + def _branch(root, leaves): + if root not in leaves: branch = { root, } @@ -1269,13 +1269,13 @@ def _branch(root, leafs): # include it. Requireing that the R should be a strict # parent of A solves this. if root in cls.get_parents(strict=True): - branch.update(_branch(cls, leafs)) + branch.update(_branch(cls, leaves)) else: branch = ( { root, } - if include_leafs + if include_leaves else set() ) return branch @@ -1283,25 +1283,25 @@ def _branch(root, leafs): if isinstance(root, str): root = self.get_by_label(root) - leafs = set( + leaves = set( self.get_by_label(leaf) if isinstance(leaf, str) else leaf - for leaf in leafs + for leaf in leaves ) - leafs.discard(root) + leaves.discard(root) if exclude: exclude = set( self.get_by_label(e) if isinstance(e, str) else e for e in exclude ) - leafs.update(exclude) + leaves.update(exclude) - branch = _branch(root, leafs) + branch = _branch(root, leaves) # Exclude all descendants of any leaf - if strict_leafs: + if strict_leaves: descendants = root.descendants() - for leaf in leafs: + for leaf in leaves: if leaf in descendants: branch.difference_update( leaf.descendants(include_self=False) diff --git a/tests/ontopy_tests/test_graph.py b/tests/ontopy_tests/test_graph.py index 3441eab22..74d972af1 100644 --- a/tests/ontopy_tests/test_graph.py +++ b/tests/ontopy_tests/test_graph.py @@ -92,7 +92,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: graph = OntoGraph( emmo, emmo.hasPart, - leafs=("mereological", "semiotical", "causal"), + leaves=("mereological", "semiotical", "causal"), ) graph.save(tmpdir / "hasPart.svg") @@ -128,7 +128,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: graph = OntoGraph( emmo, emmo.Quantity, - leafs=[emmo.DerivedQuantity, emmo.BaseQuantity, emmo.PhysicalConstant], + leaves=[emmo.DerivedQuantity, emmo.BaseQuantity, emmo.PhysicalConstant], relations="all", edgelabels=None, addnodes=True, @@ -145,17 +145,17 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: graph.save(tmpdir / "legend.png") graph = OntoGraph( - emmo, emmo.EMMO, leafs=[emmo.Perspective, emmo.Elementary] + emmo, emmo.EMMO, leaves=[emmo.Perspective, emmo.Elementary] ) graph.save(tmpdir / "top.png") - leafs = set() + leaves = set() for s in emmo.Perspective.subclasses(): - leafs.update(s.subclasses()) - graph = OntoGraph(emmo, emmo.Perspective, leafs=leafs, parents=1) + leaves.update(s.subclasses()) + graph = OntoGraph(emmo, emmo.Perspective, leaves=leaves, parents=1) graph.save(tmpdir / "Perspectives.png") - leafs = { + leaves = { emmo.Interpreter, emmo.Conventional, emmo.Icon, @@ -169,7 +169,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: emmo.Engineered, emmo.PhysicalPhenomenon, } - semiotic = emmo.get_branch(emmo.Holistic, leafs=leafs.union(hidden)) + semiotic = emmo.get_branch(emmo.Holistic, leaves=leaves.union(hidden)) semiotic.difference_update(hidden) graph = OntoGraph(emmo) graph.add_entities(semiotic, relations="all", edgelabels=False) @@ -182,7 +182,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: legend.save(tmpdir / "Semiotic-legend.png") # Measurement - leafs = {emmo.Object} + leaves = {emmo.Object} hidden = { emmo.SIUnitSymbol, @@ -202,7 +202,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: emmo.Theory, emmo.Variable, } - semiotic = emmo.get_branch(emmo.Holistic, leafs=leafs.union(hidden)) + semiotic = emmo.get_branch(emmo.Holistic, leaves=leaves.union(hidden)) semiotic.difference_update(hidden) graph = OntoGraph(emmo) graph.add_entities(semiotic, relations="all", edgelabels=False) @@ -215,7 +215,7 @@ def test_emmo_graphs(emmo: "Ontology", tmpdir: "Path") -> None: emmo.Reductionistic, relations="all", addnodes=False, - leafs=[ + leaves=[ emmo.Quantity, emmo.String, emmo.PrefixedUnit, diff --git a/tools/ontograph b/tools/ontograph index acc185222..874cb6f84 100755 --- a/tools/ontograph +++ b/tools/ontograph @@ -20,6 +20,7 @@ from ontopy.graph import ( # pylint: disable=import-error _default_style, ) from ontopy.utils import get_label # pylint: disable=import-error +import warnings import owlready2 @@ -113,14 +114,20 @@ def main( help="Name of root node in the graph. Defaults to all classes.", ) parser.add_argument( - "--leafs", + "--leaves", action="append", default=[], help=( - "Leafs nodes for plotting sub-graphs. May be provided as a " - "comma-separated string and/or with multiple --leafs options." + "Leaf nodes for plotting sub-graphs. May be provided as a " + "comma-separated string and/or with multiple --leaves options." ), ) + parser.add_argument( + "--leafs", + action="append", + default=[], + help=("This argument is deprecated, please use `--leaves` instead"), + ) parser.add_argument( "--exclude", "-E", @@ -209,6 +216,14 @@ def main( ) args = parser.parse_args(args=argv) + if args.leafs: + warnings.warn( + "The `--leafs` option is deprecated and will soon be removed. " + "Please use `--leaves` instead.", + DeprecationWarning, + ) + args.leaves = args.leafs + # Append to onto_path for paths in args.path: for path in paths.split(","): @@ -229,13 +244,13 @@ def main( with open(args.generate_style_file, "wt") as handle: json.dump(style, handle, indent=4) - # Join all --leafs options - leafs = set() - for leaf in args.leafs: + # Join all --leaves options + leaves = set() + for leaf in args.leaves: if "," in leaf: - leafs.update(leaf.split(",")) + leaves.update(leaf.split(",")) else: - leafs.add(leaf) + leaves.add(leaf) # Join all --exclude options exclude = set() @@ -298,7 +313,7 @@ def main( graph = OntoGraph(onto, style=style) graph.add_branch( root=root, - leafs=leafs, + leaves=leaves, exclude=exclude, relations=relations, edgelabels=args.edgelabels,