def generate_code_from_examples():
    for filename in glob.glob(os.path.join(examples_dir, "*.py")):
        last_mod_time = os.path.getmtime(filename)

        # Collect the names of all files created from this one. If all exist
        # and are older, nothing needs to be done. Otherwise just regenerate
        # all.
        types = ["py", "dot", "xml", "json", "provn"]
        filenames = [get_filename(filename, "examples", _i) for _i in types]
        exists = [os.path.exists(_i) for _i in filenames]
        if all(exists):
            mtime = [os.path.getmtime(_i) > last_mod_time for _i in filenames]
            if all(mtime):
                continue
        with io.open(filename, "rt") as fh:
            code_str = BASIC_HEADER + "\n\n\n" + fh.read()

        # Write Python file.
        with open(get_filename(filename, "examples", "py"), "wt") as fh:
            fh.write(code_str)

        if "datetime(" in code_str:
            code_str = "from datetime import datetime\n" + code_str

        # Write dot file.
        exec(
            code_str +
            "\n\nfrom prov import dot\n"
            "dot.prov_to_dot(pr, use_labels=True).write_dot('%s')\n" %
            get_filename(filename, "examples", "dot"))

        # Write XML.
        fname = get_filename(filename, "examples", "xml")
        exec(code_str + "\n\n"
             "pr.serialize('%s', format='xml')" % fname)
        c14n_xml(fname)

        # Write JSON.
        jsonfile = get_filename(filename, "examples", "json")
        exec(code_str + "\n\npr.serialize('%s', format='json')" % jsonfile)
        # Read again and write in a pretty fashion.
        with io.open(jsonfile, "rt") as fh:
            data = json.load(fh)
        with io.open(jsonfile, "wt") as fh:
            json.dump(data, fh, indent=4, separators=(',', ': '),
                      sort_keys=True)

        # Finally once more with the PROV-N serialization.
        exec(code_str + "\n\n"
             "with open('%s', 'wt') as fh:\n"
             "    fh.write(pr.get_provn())" %
             get_filename(filename, "examples", "provn"))
Пример #2
0
def create_rst_representation(json_file):
    with io.open(json_file, "rt") as fh:
        data = json.load(fh)
    node_type = os.path.basename(os.path.dirname(json_file))
    # Do the attributes first.
    required_attributes = [("Name", "Type", "Description")]
    optional_attributes = [("Name", "Type", "Description")]

    for attrib in data["attributes"]:
        obj = required_attributes if attrib["required"] \
            else optional_attributes
        obj.append((
            attrib["name"],
            ", ".join("``%s``" % _i for _i in attrib["types"]),
            attrib["description"]))

    if data["name"] == "person":
        title = "Person"
    elif data["name"] == "software_agent":
        title = "Software Agent"
    elif data["name"] == "organization":
        title = "Organization"
    else:
        title = "%s" % (data["label"])

    text = TEMPLATE.format(
        title=title,
        title_line="^" * len(title),
        description=data["description"],
        two_letter_code=data["two_letter_code"],
        label=data["label"],
        required_attributes=make_table(required_attributes, prefix="    "),
        optional_attributes=make_table(optional_attributes, prefix="    "),
        json_def_file=os.path.relpath(json_file),
        name=data["name"],
        node_type=node_type)

    if len(optional_attributes) > 1:
        example = EXAMPLE_TEMPLATE.format(
            example_title="Minimal Example",
            description="A concrete ``%s`` node example is illustrated "
            "here as a graph, in code, and in various representations. This "
            "is a minimal but valid ``%s`` node. See below for a full "
            "example." % (data["name"], data["name"]),
            name=data["name"],
            dotfile=os.path.relpath(get_filename(
                json_file, node_type, "dot", "min")),
            pythonfile=os.path.relpath(get_filename(
                json_file, node_type, "py", "min")),
            xmlfile=os.path.relpath(get_filename(
                json_file, node_type, "xml", "min")),
            jsonfile=os.path.relpath(get_filename(
                json_file, node_type, "json", "min")),
            provnfile=os.path.relpath(get_filename(
                json_file, node_type, "provn", "min")),
            node_type=node_type,
            ex="ex_min")

        example += "\n\n\n" + EXAMPLE_TEMPLATE.format(
            example_title="Full Example",
            description="A concrete ``%s`` node example is illustrated "
            "here as a graph, in code, and in various representations. This "
            "is a full ``%s`` node containing the maximum amount of "
            "information." % (data["name"], data["name"]),
            name=data["name"],
            dotfile=os.path.relpath(get_filename(
                json_file, node_type, "dot", "max")),
            pythonfile=os.path.relpath(get_filename(
                json_file, node_type, "py", "max")),
            xmlfile=os.path.relpath(get_filename(
                json_file, node_type, "xml", "max")),
            jsonfile=os.path.relpath(get_filename(
                json_file, node_type, "json", "max")),
            provnfile=os.path.relpath(get_filename(
                json_file, node_type, "provn", "max")),
            node_type=node_type,
            ex="ex_max")

    else:
        example = EXAMPLE_TEMPLATE.format(
            example_title="Example",
            description="A concrete ``%s`` node example is illustrated "
            "here as a graph, in code, and in various representations." %
            data["name"],
            name=data["name"],
            dotfile=os.path.relpath(get_filename(
                json_file, node_type, "dot", "max")),
            pythonfile=os.path.relpath(get_filename(
                json_file, node_type, "py", "max")),
            xmlfile=os.path.relpath(get_filename(
                json_file, node_type, "xml", "max")),
            jsonfile=os.path.relpath(get_filename(
                json_file, node_type, "json", "max")),
            provnfile=os.path.relpath(get_filename(
                json_file, node_type, "provn", "max")),
            node_type=node_type,
            ex="ex")

    return text + "\n\n\n" + example
def generate_code():
    for filename in json_files(definitions_dir):
        last_mod_time = os.path.getmtime(filename)
        node_type = os.path.basename(os.path.dirname(filename))

        # Collect the names of all files created from this one. If all exist
        # and are older, nothing needs to be done. Otherwise just regenerate
        # all.
        types = ["py", "dot", "xml", "json", "provn"]
        filenames = [
            get_filename(filename, node_type, t, i)
            for t, i in itertools.product(types, ("min", "max"))]
        exists = [os.path.exists(_i) for _i in filenames]
        if all(exists):
            mtime = [os.path.getmtime(_i) > last_mod_time for _i in filenames]
            if all(mtime):
                continue

        with io.open(filename, "rt") as fh:
            definition = json.load(fh)

        # We will always generate two sets: a minimal one containing only the
        # bare minimum amount of information and a maximal one containing as
        # much as possible.
        # Create the minimum one.
        contents = []
        for attrib in definition["attributes"]:
            if not attrib["required"]:
                continue
            # For the example, only use the first type.
            d_type = attrib["types"][0]
            # Strings are simple.
            if d_type == "xsd:string":
                contents.append('("%s:%s", "%s")' % (
                    NS_PREFIX, attrib["name"], attrib["example_value"]))
            # Others harders as they have to be represented as literals.
            else:
                contents.append(
                    '("{prefix}:{name}", prov.model.Literal(\n'
                    '        {repr},\n        prov.constants.{type}))'.format(
                        prefix=NS_PREFIX,
                        name=attrib["name"],
                        repr=repr(attrib["example_value"]),
                        type=d_type.replace(":", "_").upper()))
        contents = ",\n    ".join(contents)
        if contents:
            contents = "    " + contents

        if definition["type"] in ["activity", "entity"]:
            name = '"%s:%s"' % (NS_PREFIX, definition["name"])
            label = definition["label"]
        elif definition["type"] == "agent":
            if definition["name"] == "software_agent":
                name = ('prov.identifier.QualifiedName(prov.constants.PROV, '
                        '"SoftwareAgent")')
                label = [_i for _i in definition["attributes"]
                         if _i["name"] == "software_name"][0]["example_value"]
            elif definition["name"] == "person":
                name = ('prov.identifier.QualifiedName(prov.constants.PROV, '
                        '"Person")')
                label = [_i for _i in definition["attributes"]
                         if _i["name"] == "name"][0]["example_value"]
            elif definition["name"] == "organization":
                name = ('prov.identifier.QualifiedName(prov.constants.PROV, '
                        '"Organization")')
                label = [_i for _i in definition["attributes"]
                         if _i["name"] == "name"][0]["example_value"]
            else:
                raise ValueError
        else:
            raise ValueError

        min_file_contents = TEMPLATE.format(
            prefix=NS_PREFIX,
            type=definition["type"],
            two_letter_code=definition["two_letter_code"],
            # Generate hash that is constant per type so the examples don't
            # change each time they are regenerated.
            short_hash=str(uuid.uuid5(uuid.NAMESPACE_OID, definition["type"] +
                                      definition["two_letter_code"] +
                                      "min_file")).replace("-", "")[:7],
            label=label,
            name=name,
            contents=contents)
        with open(get_filename(filename, node_type, "py", "min"), "wt") as fh:
            fh.write(min_file_contents)

        # Create the maximum one.
        contents = []
        for attrib in definition["attributes"]:
            if "skip_example_in_doc" in attrib and \
                    attrib["skip_example_in_doc"]:
                continue
            # For the example, only use the first type.
            d_type = attrib["types"][0]
            # Strings are simple.
            if d_type == "xsd:string":
                contents.append('("%s:%s", "%s")' % (
                    NS_PREFIX, attrib["name"], attrib["example_value"]))
            # Others harder as they have to be represented as literals.
            else:
                contents.append(
                    '("{prefix}:{name}", prov.model.Literal(\n'
                    '        {repr},\n        prov.constants.{type}))'.format(
                        prefix=NS_PREFIX,
                        name=attrib["name"],
                        repr=repr(attrib["example_value"]),
                        type=d_type.replace(":", "_").upper()))
        contents = ",\n    ".join(contents)
        if contents:
            contents = "    " + contents
        max_file_contents = TEMPLATE.format(
            prefix=NS_PREFIX,
            type=definition["type"],
            two_letter_code=definition["two_letter_code"],
            # Generate hash that is constant per type so the examples don't
            # change each time they are regenerated.
            short_hash=str(uuid.uuid5(uuid.NAMESPACE_OID, definition["type"] +
                                      definition["two_letter_code"] +
                                      "max_file")).replace("-", "")[:7],
            label=label,
            name=name,
            url=NS_URL,
            contents=contents)
        with open(get_filename(filename, node_type, "py", "max"), "wt") as fh:
            fh.write(max_file_contents)

        # Create dot files with some more code generation.
        exec(
            min_file_contents +
            "\n\nfrom prov import dot\n"
            "dot.prov_to_dot(pr, use_labels=True).write_dot('%s')\n" %
            get_filename(filename, node_type, "dot", "min"))
        exec(
            max_file_contents +
            "\n\nfrom prov import dot\n"
            "dot.prov_to_dot(pr, use_labels=True).write_dot('%s')\n" %
            get_filename(filename, node_type, "dot", "max"))

        # Same with the XML files.

        fname = get_filename(filename, node_type, "xml", "min")
        exec(min_file_contents + "\n\n"
             "pr.serialize('%s', format='xml')" % fname)
        c14n_xml(fname)

        fname = get_filename(filename, node_type, "xml", "max")
        exec(max_file_contents + "\n\n"
             "pr.serialize('%s', format='xml')" % fname)
        c14n_xml(fname)

        # And once again with JSON.
        jsonfile = get_filename(filename, node_type, "json", "min")
        exec(min_file_contents + "\n\n"
             "pr.serialize('%s', format='json')" % jsonfile)
        # Read again and write in a pretty fashion.
        with io.open(jsonfile, "rt") as fh:
            data = json.load(fh)
        with io.open(jsonfile, "wt") as fh:
            json.dump(data, fh, indent=4, separators=(',', ': '),
                      sort_keys=True)

        jsonfile = get_filename(filename, node_type, "json", "max")
        exec(max_file_contents + "\n\n"
             "pr.serialize('%s', format='json')" % jsonfile)
        # Read again and write in a pretty fashion.
        with io.open(jsonfile, "rt") as fh:
            data = json.load(fh)
        with io.open(jsonfile, "wt") as fh:
            json.dump(data, fh, indent=4, separators=(',', ': '),
                      sort_keys=True)

        # Finally once more with the PROV-N serialization.
        exec(min_file_contents + "\n\n"
             "with open('%s', 'wt') as fh:\n"
             "    fh.write(pr.get_provn())" %
             get_filename(filename, node_type, "provn", "min"))
        exec(min_file_contents + "\n\n"
             "with open('%s', 'wt') as fh:\n"
             "    fh.write(pr.get_provn())" %
             get_filename(filename, node_type, "provn", "max"))