Skip to content

context

Ontokit module for generating JSON-LD context from an ontology.

context_arguments(subparsers)

Define arguments for the context sub-command.

Source code in ontopy/ontokit/context.py
def context_arguments(subparsers):
    """Define arguments for the context sub-command."""
    parser = subparsers.add_parser(
        "context", help="Generate a context file from ontology."
    )
    parser.set_defaults(subcommand=context_subcommand)
    parser.add_argument(
        "input",
        metavar="ONTOLOGY",
        help="Input ontology. Either a file path or a URL.",
    )
    parser.add_argument(
        "output",
        metavar="CONTEXT",
        nargs="?",
        help=(
            "Name of output context file. "
            "If omitted, the context is written to stdout."
        ),
    )
    parser.add_argument(
        "--include-imported",
        "-i",
        action="store_true",
        help=(
            "Whether to include properties and classes from imported "
            "ontologies."
        ),
    )
    parser.add_argument(
        "--indent", type=int, default=2, help="Indentation in JSON-LD output."
    )
    parser.add_argument(
        "--namespace",
        "-n",
        metavar="PREFIX:NAMESPACE",
        action="append",
        default=[],
        help=(
            "Additional prefix:namespace pair that will be added to the "
            "output context.  May be added multiple times."
        ),
    )
    parser.add_argument(
        "--include-namespace",
        metavar="NAMESPACE",
        action="append",
        default=[],
        help=(
            "Only include terms whose namespace starts with NAMESPACE. "
            "May be added multiple times."
        ),
    )

context_subcommand(args)

Implements the context sub-command.

Source code in ontopy/ontokit/context.py
def context_subcommand(args):
    """Implements the context sub-command."""
    # pylint: disable=invalid-name
    RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    OWL = "http://www.w3.org/2002/07/owl#"
    XSD = "http://www.w3.org/2001/XMLSchema#"

    # Data properties known by owlready2
    dataprop = {
        int: XSD + "int",
        float: XSD + "double",
        bool: XSD + "boolean",
        str: XSD + "int",
        owlready2.normstr: XSD + "normalizedString",
        owlready2.locstr: RDF + "langString",
        datetime.date: XSD + "date",
        datetime.time: XSD + "time",
        datetime.datetime: XSD + "dateTime",
    }

    onto = get_ontology(args.input).load()
    prefixes = {}
    items = {}

    # Get default prefixes from arguments
    for arg in args.namespace:
        prefix, ns = arg.split(":", 1)
        prefixes[prefix] = ns

    include_namespaces = tuple(args.include_namespace)

    def namespace_allowed(entity):
        if not include_namespaces:
            return True
        base_iri = entity.namespace.base_iri
        return any(base_iri.startswith(ns) for ns in include_namespaces)

    # Object properties
    d = {}
    for prop in onto.object_properties(args.include_imported):
        if not namespace_allowed(prop):
            continue
        label = get_label(prop)
        if label:
            d[label] = {"@id": prop.iri, "@type": "@id"}
            prefixes.setdefault(prop.namespace.name, prop.namespace.base_iri)
    items.update({k: d[k] for k in sorted(d)})

    # Annotations and data properties
    d = {}
    for prop in chain(
        onto.annotation_properties(args.include_imported),
        onto.data_properties(args.include_imported),
    ):
        if not namespace_allowed(prop):
            continue
        label = get_label(prop)
        tp = (
            RDF + "plainLiteral"
            if not prop.range or prop.range[0] not in dataprop
            else dataprop[prop.range[0]]
        )
        if label:
            d[label] = {"@id": prop.iri, "@type": tp}
            prefixes[prop.namespace.name] = prop.namespace.base_iri
    items.update({k: d[k] for k in sorted(d)})

    # Classes
    d = {}
    for cls in onto.classes(args.include_imported):
        if not namespace_allowed(cls):
            continue
        label = get_label(cls)
        if label:
            d[label] = {"@id": cls.iri, "@type": OWL + "Class"}
            prefixes[cls.namespace.name] = cls.namespace.base_iri
    items.update({k: d[k] for k in sorted(d)})

    ctx = {"@version": 1.1}
    ctx.update({k: prefixes[k] for k in sorted(prefixes)})
    ctx.update(items)
    context = {"@context": ctx}

    if args.output:
        with open(args.output, "wt", encoding="utf-8") as f:
            json.dump(context, f, indent=args.indent)
    else:
        print(json.dumps(context, indent=args.indent))