Skip to content

Commit

Permalink
Check rdflib version is >=6.0.0 for turtle output
Browse files Browse the repository at this point in the history
An error will be thrown if this is not satisfied.
This is also true for the `ontoconvert` CLI tool.
  • Loading branch information
CasperWA committed Sep 17, 2021
1 parent 38c456d commit a836428
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 23 deletions.
112 changes: 112 additions & 0 deletions emmo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import datetime
import tempfile
import types
from typing import TYPE_CHECKING
import urllib.request
import xml.etree.ElementTree as ET

Expand All @@ -15,6 +16,11 @@
import owlready2


if TYPE_CHECKING:
from packaging.version import Version, LegacyVersion
from typing import Union


# Format mappings: file extension -> rdflib format name
FMAP = {
'n3': 'ntriples',
Expand All @@ -28,6 +34,16 @@
OWLREADY2_FORMATS = 'rdfxml', 'owl', 'xml', 'ntriples'


class IncompatibleVersion(Exception):
"""An installed dependency version is incompatible with a functionality of
this package."""


class UnknownVersion(Exception):
"""Cannot retrieve version from a package."""



def isinteractive():
"""Returns true if we are running from an interactive interpreater,
false otherwise."""
Expand Down Expand Up @@ -324,13 +340,69 @@ def write_catalog(mappings, output='catalog-v001.xml'):
f.write('\n'.join(s) + '\n')


def _validate_installed_version(
package: str, min_version: "Union[str, Version, LegacyVersion]"
) -> bool:
"""Validate an installed package.
Examine whether a minimum version is installed in the used Python
interpreter for a specific package.
Parameters:
package: The package to be investigated as a string, e.g., `"rdflib"`.
min_version: The minimum version expected to be installed.
Raises:
UnknownVersion: If the supplied package does not have a `__version__`
attribute.
Returns:
Whether or not the installed version is equal to or greater than the
`min_version`.
"""
import importlib
from packaging.version import parse as parse_version, LegacyVersion, Version

if isinstance(min_version, str):
min_version = parse_version(min_version)
elif isinstance(min_version, (LegacyVersion, Version)):
# We have the format we want
pass
else:
raise TypeError(
"min_version should be either a str, LegacyVersion or Version. "
"The latter classes being from the packaging.version module."
)

installed_package = importlib.import_module(
name=".", package=package
)
installed_package_version = getattr(installed_package, "__version__", None)
if not installed_package_version:
raise UnknownVersion(
f"Cannot retrieve version information from package {package!r}."
)

return parse_version(installed_package_version) >= min_version


def convert_imported(input, output, input_format=None, output_format='xml',
url_from_catalog=None, catalog_file='catalog-v001.xml'):
"""Convert imported ontologies.
Store the output in a directory structure matching the source
files. This require catalog file(s) to be present.
Warning:
To convert to Turtle (`.ttl`) format, you must have installed
`rdflib>=6.0.0`. See [Known issues](../README.md#Known-issues) in the
README for more information.
Raises:
IncompatibleVersion: If `rdflib<6.0.0` and the desired output format is
Turtle.
Args:
input: input ontology file name
output: output ontology file path. The directory part of `output`
Expand Down Expand Up @@ -395,6 +467,20 @@ def recur(graph, outext):

# Write output files
fmt = input_format if input_format else guess_format(input, fmap=FMAP)

if (
not _validate_installed_version(package="rdflib", min_version="6.0.0")
and (output_format == FMAP.get("ttl", "") or outext == "ttl")
):
from rdflib import __version__ as __rdflib_version__

raise IncompatibleVersion(
"To correctly convert to Turtle format, rdflib must be version "
"6.0.0 or greater, however, the detected rdflib version used "
f"by your Python interpreter is {__rdflib_version__!r}. For "
"more information see the 'Known issues' section of the README."
)

g = Graph()
g.parse(input, format=fmt)
g.serialize(destination=output, format=output_format)
Expand All @@ -410,6 +496,16 @@ def squash_imported(input, output, input_format=None, output_format='xml',
only be used if it exists in the same directory as the input file.
The the squash rdflib graph is returned.
Warning:
To convert to Turtle (`.ttl`) format, you must have installed
`rdflib>=6.0.0`. See [Known issues](../README.md#Known-issues) in the
README for more information.
Raises:
IncompatibleVersion: If `rdflib<6.0.0` and the desired output format is
Turtle.
"""
inroot = os.path.dirname(os.path.abspath(input))

Expand Down Expand Up @@ -440,6 +536,22 @@ def recur(g):
graph.parse(input, format=input_format)
recur(graph)
if output:
if (
not _validate_installed_version(package="rdflib", min_version="6.0.0")
and (
output_format == FMAP.get("ttl", "")
or os.path.splitext(output)[1] == "ttl"
)
):
from rdflib import __version__ as __rdflib_version__

raise IncompatibleVersion(
"To correctly convert to Turtle format, rdflib must be version"
" 6.0.0 or greater, however, the detected rdflib version used "
f"by your Python interpreter is {__rdflib_version__!r}. For "
"more information see the 'Known issues' section of the README."
)

graph.serialize(destination=output, format=output_format)
return graph

Expand Down
75 changes: 52 additions & 23 deletions tools/ontoconvert
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
"""Converts file format of input ontology and write it to output file(s).
"""
import argparse
import os
import sys

from rdflib.util import Graph, guess_format

from emmo.utils import convert_imported, squash_imported
from emmo.utils import (
convert_imported,
FMAP,
IncompatibleVersion,
squash_imported,
_validate_installed_version,
)
from emmo.factpluspluswrapper.factppgraph import FaCTPPGraph


Expand Down Expand Up @@ -64,28 +72,49 @@ def main():
output_format = 'xml'

# Perform conversion
if args.recursive:
convert_imported(args.input, args.output,
input_format=input_format,
output_format=output_format,
url_from_catalog=args.url_from_catalog)
elif args.inferred:
g = squash_imported(args.input, None,
input_format=input_format)
fg = FaCTPPGraph(g)
if args.base_iri:
fg.base_iri = args.base_iri
g2 = fg.inferred_graph()
g2.serialize(destination=args.output, format=output_format)
elif args.squash:
squash_imported(args.input, args.output,
input_format=input_format,
output_format=output_format,
url_from_catalog=args.url_from_catalog)
else:
g = Graph()
g.parse(args.input, format=input_format)
g.serialize(destination=args.output, format=output_format)
try:
if args.recursive:
convert_imported(args.input, args.output,
input_format=input_format,
output_format=output_format,
url_from_catalog=args.url_from_catalog)
elif args.inferred:
g = squash_imported(args.input, None,
input_format=input_format)
fg = FaCTPPGraph(g)
if args.base_iri:
fg.base_iri = args.base_iri
g2 = fg.inferred_graph()
g2.serialize(destination=args.output, format=output_format)
elif args.squash:
squash_imported(args.input, args.output,
input_format=input_format,
output_format=output_format,
url_from_catalog=args.url_from_catalog)
else:
if (
not _validate_installed_version(
package="rdflib", min_version="6.0.0"
)
and (
output_format == FMAP.get("ttl", "")
or os.path.splitext(args.output)[1] == "ttl"
)
):
from rdflib import __version__ as __rdflib_version__

raise IncompatibleVersion(
"To correctly convert to Turtle format, rdflib must be version"
" 6.0.0 or greater, however, the detected rdflib version used "
f"by your Python interpreter is {__rdflib_version__!r}. For "
"more information see the 'Known issues' section of the README."
)

g = Graph()
g.parse(args.input, format=input_format)
g.serialize(destination=args.output, format=output_format)
except IncompatibleVersion as exc:
sys.exit(f"\033[91mERROR\033[0m: {exc}")


if __name__ == '__main__':
Expand Down

0 comments on commit a836428

Please sign in to comment.