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"]
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"]
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)