예제 #1
0
def test_find_related():
    #
    #  r0
    #   | uses
    #   v
    #   r1
    #   | version
    #   v
    #   r2
    #   /\
    #  /  \ derived
    # v   v
    # r3  r4
    #
    tmp_dir = scratch_path / "find_related"
    dmf = DMF(path=tmp_dir, create=True)
    r = [resource.Resource({"name": "r{}".format(i)}) for i in range(5)]
    # r3 <-- derived <-- r2 <-- version <-- r1
    cr = resource.create_relation  # shortcut
    cr(r[2], Predicates.derived, r[3])
    cr(r[1], Predicates.version, r[2])
    # r4 <-- derived <-- r2
    cr(r[2], Predicates.derived, r[4])
    # r0 -- Uses --> r1
    cr(r[0], Predicates.uses, r[1])
    # add to dmf
    for i in range(5):
        dmf.add(r[i])
    # outgoing from r0 should include 1,2,3,4
    names = []
    for d, rr, m in dmf.find_related(r[0], meta=["aliases"]):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r1", "r2", "r3", "r4"]
    # incoming to r4 should include r0, r1, r2
    names = []
    for d, rr, m in dmf.find_related(r[4], meta=["aliases"], outgoing=False):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r0", "r1", "r2"]
예제 #2
0
def test_circular():
    #
    # r0 -> derived -> r1 -> derived >- r2 -+
    #  ^                                    |
    #  +------------------------------------+
    #     uses
    tmp_dir = scratch_path / "circular"
    dmf = DMF(path=tmp_dir, create=True)
    r = [resource.Resource({"name": "r{}".format(i)}) for i in range(3)]
    resource.create_relation(r[0], Predicates.derived, r[1])
    resource.create_relation(r[1], Predicates.derived, r[2])
    resource.create_relation(r[2], Predicates.uses, r[0])
    for rr in r:
        dmf.add(rr)
    # outgoing from r0
    names = []
    for d, rr, m in dmf.find_related(r[0], meta=["aliases"]):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r0", "r1", "r2"]
    # incoming to r1
    names = []
    for d, rr, m in dmf.find_related(r[0], meta=["aliases"], outgoing=False):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r0", "r1", "r2"]
    # reducing depth shortens output
    names = []
    for d, rr, m in dmf.find_related(r[0], meta=["aliases"], maxdepth=2):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r1", "r2"]
    names = []
    for d, rr, m in dmf.find_related(r[0], meta=["aliases"], maxdepth=1):
        names.append(m["aliases"][0])
    names.sort()
    assert names == ["r1"]
예제 #3
0
def register(
    resource_type,
    url,
    info,
    copy,
    strict,
    unique,
    contained,
    derived,
    used,
    prev,
    is_subject,
    version,
):
    _log.debug(f"Register object type='{resource_type}' url/path='{url.path}'")
    # process url
    if url.scheme in ("file", ""):
        path = url.path
    else:
        click.echo("Currently, URL must be a file")
        sys.exit(Code.NOT_SUPPORTED.value)
    # create the resource
    _log.debug("create resource")
    try:
        rsrc = resource.Resource.from_file(path,
                                           as_type=resource_type,
                                           strict=strict,
                                           do_copy=copy)
    except resource.Resource.InferResourceTypeError as err:
        click.echo(f"Failed to infer resource: {err}")
        sys.exit(Code.IMPORT_RESOURCE.value)
    except resource.Resource.LoadResourceError as err:
        click.echo(f"Failed to load resource: {err}")
        sys.exit(Code.IMPORT_RESOURCE.value)
    # connect to DMF
    try:
        dmf = DMF()
    except errors.WorkspaceError as err:
        click.echo(f"Failed to connect to DMF: {err}")
        sys.exit(Code.WORKSPACE_NOT_FOUND.value)
    except errors.DMFError as err:
        click.echo(f"Failed to connect to DMF: {err}")
        sys.exit(Code.DMF.value)
    # check uniqueness
    if unique:
        df = rsrc.v["datafiles"][0]  # file info for this upload
        query = {"datafiles": [{"sha1": df["sha1"]}]}
        query_result, dup_ids = dmf.find(query), []
        for dup in query_result:
            dup_df = dup.v["datafiles"][0]
            if dup_df["path"] in df["path"]:
                dup_ids.append(dup.id)
        n_dup = len(dup_ids)
        if n_dup > 0:
            click.echo(f"This file is already in {n_dup} resource(s): "
                       f"{' '.join(dup_ids)}")
            sys.exit(Code.DMF_OPER.value)
    # process relations
    _log.debug("add relations")
    rel_to_add = {  # translate into standard relation names
        resource.PR_CONTAINS: contained,
        resource.PR_DERIVED: derived,
        resource.PR_USES: used,
        resource.PR_VERSION: prev,
    }
    target_resources = {}  # keep target resources in dict, update at end
    for rel_name, rel_ids in rel_to_add.items():
        for rel_id in rel_ids:
            if rel_id in target_resources:
                rel_subj = target_resources[rel_id]
            else:
                rel_subj = dmf.fetch_one(rel_id)
                target_resources[rel_id] = rel_subj
            if rel_subj is None:
                click.echo(f"Relation {rel_name} target not found: {rel_id}")
                sys.exit(Code.DMF_OPER.value)
            if is_subject == "yes":
                resource.create_relation_args(rsrc, rel_name, rel_subj)
            else:
                resource.create_relation_args(rel_subj, rel_name, rsrc)
            _log.debug(f"added relation {rsrc.id} <-- {rel_name} -- {rel_id}")
    _log.debug("update resource relations")
    for rel_rsrc in target_resources.values():
        dmf.update(rel_rsrc)
    # add metadata
    if version:
        try:
            vlist = resource.version_list(version)
        except ValueError:
            click.echo(f"Invalid version `{version}`")
            sys.exit(Code.INPUT_VALUE.value)
        else:
            rsrc.v["version_info"]["version"] = vlist
    # add the resource
    _log.debug("add resource begin")
    try:
        new_id = dmf.add(rsrc)
    except errors.DuplicateResourceError as err:
        click.echo(f"Failed to add resource: {err}")
        sys.exit(Code.DMF_OPER.value)
    _log.debug(f"added resource: {new_id}")
    if info == "yes":
        pfxlen = len(new_id)
        si = _ShowInfo("term", pfxlen)
        for rsrc in dmf.find_by_id(new_id):
            si.show(rsrc)
    else:
        click.echo(new_id)