def _get_remaining_packages(self, remove_packages): """Get package paths to install. Get list of packages that remain after given list of packages have been removed. Args: remove_packages (List[str]): List of packages to remove. Raises: ValueError: Given package to remove is not installed Returns: List[str]: The remaining packages. """ remove_pkgs = set() installed_pkgs = dict(self.get_installed_packages(return_path=True)) for pkg in remove_packages: if pkg.endswith(".yml") and os.path.exists(pkg): pkg = Parser.get_identifier(pkg) if pkg in installed_pkgs: remove_pkgs.add(pkg) else: raise ValueError("Could not uninstall %s. No file nor " "installed ontology package. " "Make sure to only specify valid " "yml files or ontology package names." % pkg) return [v for k, v in installed_pkgs.items() if k not in remove_pkgs]
def run_from_terminal(): """Run ontology2dot from the terminal.""" # Parse the user arguments parser = argparse.ArgumentParser( description="Convert an ontology in OWL format to " "an ontology in YAML format." ) parser.add_argument("to_plot", metavar="to_plot", type=str, nargs="+", help="Either installed namespaces or paths " "to yaml ontology files") parser.add_argument("--output-filename", "-o", type=os.path.abspath, default=None, help="The name of the output file") parser.add_argument("--group", "-g", action="store_true", help="Whether to organize each namespace in a " "separate cluster") args = parser.parse_args() namespaces = list() parser = Parser(_namespace_registry._graph) for x in args.to_plot: if x in _namespace_registry: namespaces.append(x) continue for n in Parser.get_namespace_names(x): if n in _namespace_registry: logger.warning("Using installed version of namespace %s" % n) namespaces.append(_namespace_registry[n]) else: parser.parse(x) _namespace_registry.update_namespaces() namespaces.append(_namespace_registry[n]) # Convert the ontology to dot converter = Ontology2Dot( namespaces=namespaces, output_filename=args.output_filename, group=args.group ) converter.render()
def _install(self, files, filter_func, clear): """Install the ontology. Args: files (List[str]): The ontology files to install filter_func (Callable): Function that takes the list of files as input and returns a list of files that need to be installed. clear (bool): Whether it is necessary to clear what is already installed. """ graph = self.namespace_registry._graph installed = set(self.get_installed_packages()) if clear: graph = self.namespace_registry.clear() installed = set() files = self._sort_for_installation(filter_func(files), installed) parser = Parser(graph) for file in files: parser.parse(file) self.namespace_registry.update_namespaces() # serialize the result if clear: shutil.rmtree(self.path) os.makedirs(self.path) parser.store(self.path) self.namespace_registry.store(self.path)
def _sort_for_installation(self, files, installed): """Get the right order to install the files. Args: files (List[str]): The list of file paths to sort. Raises: RuntimeError: Unsatisfied requirements after installation. Returns: List[str]: The sorted list of file paths. """ result = list() files = {Parser.get_identifier(f): f for f in files} requirements = { n: Parser.get_requirements(f) for n, f in files.items() } # order the files while requirements: add_to_result = list() for namespace, req in requirements.items(): req -= installed | set(result) if not req: add_to_result.append(namespace) if not add_to_result: raise RuntimeError( "Installation failed. Unsatisfied requirements: \n - %s" % "\n - ".join( ["%s: %s" % (n, r) for n, r in requirements.items()])) result += add_to_result for x in add_to_result: del requirements[x] logger.info("Will install the following namespaces: %s" % result) return [files[n] for n in result]
def _get_replaced_packages(self, new_packages): """Get package paths to install. Get the package paths that by replacing the package paths of already installed packages with new packages, Args: new_packages (List[str]): Path to new package files. Returns: List[str]: Resulting list of package paths. """ installed = dict(self.get_installed_packages(return_path=True)) for pkg in new_packages: installed[Parser.get_identifier(pkg)] = pkg return installed.values()
def test_get_iri(self): """Test the get_iri method of the YAML parser.""" logging.getLogger("osp.core.ontology.yml.yml_parser").addFilter( lambda record: False) self.graph.parse(CUBA_FILE, format="ttl") self.assertEqual( self.parser._get_iri("Entity", "CUBA"), rdflib.term.URIRef('http://www.osp-core.com/cuba#Entity')) self.assertEqual( self.parser._get_iri("ENTITY", "CUBA"), rdflib.term.URIRef('http://www.osp-core.com/cuba#Entity')) self.assertEqual( self.parser._get_iri("ENTITY", "cuba"), rdflib.term.URIRef('http://www.osp-core.com/cuba#Entity')) self.assertEqual( self.parser._get_iri("entity", "CUBA"), rdflib.term.URIRef('http://www.osp-core.com/cuba#Entity')) self.assertRaises(AttributeError, self.parser._get_iri, "A", "B") self.graph.add( (rdflib.term.URIRef('http://www.osp-core.com/ns#MY_CLASS'), rdflib.RDF.type, rdflib.OWL.Class)) self.assertEqual( self.parser._get_iri("my_class", "NS"), rdflib.term.URIRef('http://www.osp-core.com/ns#MY_CLASS')) self.assertEqual( self.parser._get_iri("MY_CLASS", "NS"), rdflib.term.URIRef('http://www.osp-core.com/ns#MY_CLASS')) self.assertEqual( self.parser._get_iri("myClass", "ns"), rdflib.term.URIRef('http://www.osp-core.com/ns#MY_CLASS')) self.assertEqual( self.parser._get_iri("MyClass", "NS"), rdflib.term.URIRef('http://www.osp-core.com/ns#MY_CLASS')) # no entity name --> no checks self.assertEqual(self.parser._get_iri(None, "B"), rdflib.term.URIRef('http://www.osp-core.com/b#')) self.assertEqual(self.parser._get_iri(None, "b"), rdflib.term.URIRef('http://www.osp-core.com/b#')) Parser(self.graph).parse(EMMO_FILE) self.assertEqual( self.parser._get_iri("Molecule", "materials"), rdflib.URIRef("http://emmo.info/emmo/middle/materials#" "EMMO_3397f270_dfc1_4500_8f6f_4d0d85ac5f71"))
def _get_new_packages(self, packages): """From the given list of packages, return the ones that are new. Args: packages (List[str]): Path to ontology file. Returns: List[str]: List of package path that are new """ result = set(packages) installed = set(self.get_installed_packages()) for pkg in packages: identifier = Parser.get_identifier(pkg) if identifier in installed: logger.info("Skipping package %s with identifier %s, " "because it is already installed." % (pkg, identifier)) result.remove(pkg) return result
def setUp(self): """Set up Graph and Parser.""" self.graph = rdflib.Graph() self.parser = Parser(self.graph)
class TestParser(unittest.TestCase): """Test the default parser used for parsing OWL ontologies.""" def setUp(self): """Set up Graph and Parser.""" self.graph = rdflib.Graph() self.parser = Parser(self.graph) def test_add_cuba_triples(self): """Test adding the cuba triples, like active relationships.""" self.graph.add((rdflib.URIRef("has_part"), rdflib.RDF.type, rdflib.OWL.ObjectProperty)) self.graph.add((rdflib.URIRef("encloses"), rdflib.RDF.type, rdflib.OWL.ObjectProperty)) pre = set(self.graph) self.parser._add_cuba_triples([ rdflib.URIRef("has_part"), rdflib.URIRef("encloses") ]) self.assertEqual(set(self.graph) - pre, { (rdflib.URIRef("encloses"), rdflib.RDFS.subPropertyOf, rdflib_cuba.activeRelationship), (rdflib.URIRef("has_part"), rdflib.RDFS.subPropertyOf, rdflib_cuba.activeRelationship) }) def test_add_default_rel_triples(self): """Test adding the default rel triples.""" self.parser._add_default_rel_triples({ "ns1": "has_part", "ns2": "encloses" }) self.assertEqual(set(self.graph), { (rdflib.URIRef("ns1"), rdflib_cuba._default_rel, rdflib.URIRef("has_part")), (rdflib.URIRef("ns2"), rdflib_cuba._default_rel, rdflib.URIRef("encloses")) }) def test_parse_rdf(self): """Test parsing an rdf file.""" self.graph.parse(CUBA_FILE, format="ttl") len_cuba = len(self.graph) self.assertRaises(TypeError, self.parser._parse_rdf, ontology_file=RDF_FILE, namespaces={}) self.assertRaises(TypeError, self.parser._parse_rdf, namespaces={}, identifier="x") self.assertRaises(TypeError, self.parser._parse_rdf, ontology_file=RDF_FILE, identifier="x") self.assertRaises(TypeError, self.parser._parse_rdf, ontology_file=RDF_FILE, namespaces={}, identifier="x", invalid=True) with tempfile.NamedTemporaryFile() as f: self.parser._parse_rdf( identifier="parser_test", ontology_file=RDF_FILE, namespaces={ "parser_test": "http://www.osp-core.com/parser_test" }, format="ttl", file=f ) rdf = rdflib.Graph() rdf.parse(RDF_FILE, format="ttl") self.assertEqual(len(self.graph), len(rdf) + len_cuba) self.assertEqual(len(self.parser._graphs), 1) self.assertEqual(len(self.parser._graphs["parser_test"]), len(rdf)) self.assertTrue(isomorphic(self.parser._graphs["parser_test"], rdf)) self.assertIn(dict(self.graph.namespaces())["parser_test"], rdflib.URIRef("http://www.osp-core.com/parser_test#")) def test_parse_yml(self): """Test parsing the yaml file.""" invalid = dict(YML_DOC) invalid["identifier"] = "parser.test" self.assertRaises(ValueError, self.parser._parse_yml, invalid, "/a/b/c/parser_test.yml", None) if os.name == "posix": result = self.parser._parse_yml(dict(YML_DOC), "/a/b/c/parser_test.yml", None) self.assertEqual(result["ontology_file"], "/a/b/c/parser_test.ttl") else: result = self.parser._parse_yml(dict(YML_DOC), "C:\\a\\b\\parser_test.yml", None) self.assertEqual(result["ontology_file"], "C:\\a\\b\\parser_test.ttl") @responses.activate def test_parse_yml_download(self): """Test downloading owl ontologies.""" def request_callback(request): headers = {'request-id': '728d329e-0e86-11e4-a748-0c84dc037c13'} return (200, headers, "TEST FILE CONTENT") url = "http://my_ontology.com/ontology.owl" responses.add_callback( responses.GET, url, callback=request_callback, content_type='text/plain', ) doc = dict(YML_DOC) doc["ontology_file"] = url with tempfile.NamedTemporaryFile(mode="wb+") as f: r = self.parser._parse_yml(doc, "/a/b/c/parser_test.yml", f) self.assertEqual(r["ontology_file"], f.name) f.seek(0) self.assertEqual(f.read(), b"TEST FILE CONTENT") def test_get_file_path(self): """Test the get_file_path method.""" self.assertEqual(self.parser.get_file_path("test/my_file.yml"), "test/my_file.yml") self.assertEqual( self.parser.get_file_path("my_file").lower(), os.path.abspath(os.path.relpath(os.path.join( os.path.dirname(__file__), "..", "osp", "core", "ontology", "docs", "my_file.yml" ))).lower() ) self.assertEqual( self.parser.get_file_path("emmo").lower(), os.path.abspath(os.path.relpath(os.path.join( os.path.dirname(__file__), "..", "osp", "core", "ontology", "docs", "emmo.yml" ))).lower() ) self.assertEqual( self.parser.get_file_path("city").lower(), os.path.abspath(os.path.relpath(os.path.join( os.path.dirname(__file__), "..", "osp", "core", "ontology", "docs", "city.ontology.yml" ))).lower() ) def test_get_identifier(self): """Test the get_identifier method.""" self.assertEqual(self.parser.get_identifier(YML_DOC), "parser_test") self.assertEqual(self.parser.get_identifier(YML_FILE), "parser_test") self.assertEqual(self.parser.get_identifier("parser_test"), "parser_test") self.assertEqual(self.parser.get_identifier("emmo"), "emmo") def test_get_namespace_name(self): """Test the get_namespace_name method.""" self.assertEqual(self.parser.get_namespace_names(YML_DOC), ["parser_test"]) self.assertEqual(self.parser.get_namespace_names(YML_FILE), ["parser_test"]) self.assertEqual(self.parser.get_namespace_names("parser_test"), ["parser_test"]) self.assertEqual(self.parser.get_namespace_names("emmo"), ['mereotopology', 'physical', 'top', 'semiotics', 'perceptual', 'reductionistic', 'holistic', 'physicalistic', 'math', 'properties', 'materials', 'metrology', 'models', 'manufacturing', 'isq', 'siunits']) def test_get_requirements(self): """Test the get_requirements() method.""" self.assertEqual(self.parser.get_requirements(YML_DOC), set()) self.assertEqual(self.parser.get_requirements(YML_FILE), set()) self.assertEqual(self.parser.get_requirements("parser_test"), {"city"}) def test_store(self): """Test the store method.""" self.parser.parse(YML_FILE) with tempfile.TemporaryDirectory() as destination: self.parser.store(destination) self.assertEqual(os.listdir(destination), ["parser_test.xml", "parser_test.yml"]) with open(os.path.join(destination, "parser_test.yml")) as f: yml_doc = yaml.safe_load(f) self.assertEqual(yml_doc["ontology_file"], "parser_test.xml") yml_doc["ontology_file"] = YML_DOC["ontology_file"] self.assertEqual(yml_doc, YML_DOC) g = rdflib.Graph() g.parse(os.path.join(destination, "parser_test.xml"), format="xml") self.assertTrue( isomorphic(g, self.parser._graphs["parser_test"])) def test_parse(self): """Test the parse method.""" self.parser.parse(YML_FILE) g1 = rdflib.Graph() g1.parse(CUBA_FILE, format="ttl") g1.parse(RDF_FILE, format="ttl") self.assertTrue(self.parser.graph, g1) g2 = rdflib.Graph() g2.parse(RDF_FILE, format="ttl") self.assertTrue(self.parser._graphs["parser_test"], [g1]) self.assertEqual(len(self.parser._yaml_docs), 1) self.assertEqual( self.parser._yaml_docs[0]["ontology_file"].lower(), os.path.abspath(os.path.realpath(os.path.join( os.path.dirname(__file__), "parser_test.ttl"))).lower() ) x = dict(self.parser._yaml_docs[0]) x["ontology_file"] = YML_DOC["ontology_file"] self.assertEqual(x, YML_DOC) def test_add_reference_style_triples(self): """Test adding the reference style triples.""" self.parser._add_reference_style_triples({ "ns1": True, "ns2": False, "ns3": True }) self.assertEqual(set(self.graph), { (rdflib.URIRef("ns1"), rdflib_cuba._reference_by_label, rdflib.Literal(True)), (rdflib.URIRef("ns3"), rdflib_cuba._reference_by_label, rdflib.Literal(True)), })