Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modified publish script to allow untracked gitinfo.json file. #297

Merged
merged 66 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
986b144
Support for gitinfo.json
dmichaels-harvard Jan 3, 2024
68d3be3
Support for gitinfo.json
dmichaels-harvard Jan 3, 2024
68fd0fa
Support for gitinfo.json
dmichaels-harvard Jan 3, 2024
0d10e16
Corrected comments in portal_utils.py.
dmichaels-harvard Jan 3, 2024
27ac343
Corrected comments in portal_utils.py.
dmichaels-harvard Jan 3, 2024
a075355
merge in master
dmichaels-harvard Jan 4, 2024
45ed176
Support for gitinfo.json
dmichaels-harvard Jan 4, 2024
b6f4a9a
Support for gitinfo.json
dmichaels-harvard Jan 4, 2024
1d143b4
Added Portal.is_specified_type to portal_utils.py
dmichaels-harvard Jan 4, 2024
5882abc
Added Portal.is_specified_type to portal_utils.py
dmichaels-harvard Jan 4, 2024
8525315
Added Portal.is_specified_type to portal_utils.py
dmichaels-harvard Jan 4, 2024
10a421d
Added Portal.is_specified_type to portal_utils.py
dmichaels-harvard Jan 4, 2024
844bf1b
Sanity check in portal_utils.Portal constructor.
dmichaels-harvard Jan 4, 2024
3db336b
Sanity check in portal_utils.Portal constructor.
dmichaels-harvard Jan 4, 2024
cc13a97
Minor fix to portal_utils.Portal.schema_name
dmichaels-harvard Jan 4, 2024
7e2950b
Minor updates to portal_utils.Portal
dmichaels-harvard Jan 4, 2024
b439795
Minor updates to portal_utils.Portal
dmichaels-harvard Jan 4, 2024
1253b5d
corrections to portal_utils to make mocking work better
dmichaels-harvard Jan 5, 2024
2d42b0b
corrections to portal_utils to make mocking work better
dmichaels-harvard Jan 5, 2024
46eaeb4
minor code cleanup and comments in portal_utils
dmichaels-harvard Jan 5, 2024
2d276f7
minor code cleanup and comments in portal_utils
dmichaels-harvard Jan 5, 2024
2dd91d6
sanity check for app added to portal_utils
dmichaels-harvard Jan 6, 2024
fb5ff19
minor fixups in portal_utils
dmichaels-harvard Jan 7, 2024
938ec12
minor fixups in portal_utils
dmichaels-harvard Jan 7, 2024
80ec4d3
minor fixups in portal_utils
dmichaels-harvard Jan 7, 2024
38ef0df
minor portal_utils updates
dmichaels-harvard Jan 7, 2024
f2c543e
minor portal_utils updates
dmichaels-harvard Jan 7, 2024
0abc046
minor tweaks to portal_utils
dmichaels-harvard Jan 7, 2024
25d2bd5
minor tweaks to portal_utils
dmichaels-harvard Jan 7, 2024
b1ebd0d
minor portal_utils refactor and new tests
dmichaels-harvard Jan 8, 2024
8a59409
minor portal_utils tweaks
dmichaels-harvard Jan 8, 2024
45ae0b8
minor portal_utils fix
dmichaels-harvard Jan 9, 2024
1078685
minor portal_utils fix
dmichaels-harvard Jan 9, 2024
0ef2f6f
fix to tmpfile_utils
dmichaels-harvard Jan 9, 2024
252818e
minor structured_data.Portal update
dmichaels-harvard Jan 10, 2024
0cb38f9
minor fix in portal_utils
dmichaels-harvard Jan 10, 2024
c011b98
comment
dmichaels-harvard Jan 11, 2024
e8c0c0d
version-update
dmichaels-harvard Jan 11, 2024
03289ca
very minor fix in portal_utils - report correct incorrect app
dmichaels-harvard Jan 11, 2024
40f21a6
stupid typo
dmichaels-harvard Jan 11, 2024
f563d09
very minor update to portal_utils.Portal.is_schema_type; type check
dmichaels-harvard Jan 11, 2024
e5f4f9b
comment update
dmichaels-harvard Jan 12, 2024
195a33c
Fix (I think) in structured_data.Portal.ref_exists.
dmichaels-harvard Jan 14, 2024
9f11513
Added raw and database support to portal_utils.Portal.get/get_metadata.
dmichaels-harvard Jan 17, 2024
435aaaa
Added portal_object_utils.
dmichaels-harvard Jan 18, 2024
799b447
updated doc with portal_object_utils
dmichaels-harvard Jan 18, 2024
3d1f559
minor updates to portal_object_utils
dmichaels-harvard Jan 18, 2024
9dfb506
minor updates to portal_object_utils
dmichaels-harvard Jan 18, 2024
51ca5e7
Added structured_data.StructuredDataSet.upload_files_located.
dmichaels-harvard Jan 18, 2024
793f3ac
New file_utils.py
dmichaels-harvard Jan 19, 2024
64c2ca9
updated doc
dmichaels-harvard Jan 19, 2024
214a009
minor fix in structured_data.upload_files
dmichaels-harvard Jan 19, 2024
8b70261
minor refactor of args to file_utils.search_for_file
dmichaels-harvard Jan 19, 2024
64c61fa
minor refactor of args to file_utils.search_for_file
dmichaels-harvard Jan 19, 2024
b3294a0
minor portal_object_utils update
dmichaels-harvard Jan 20, 2024
7e21031
added portal_object_utils.PortalObject.compare
dmichaels-harvard Jan 20, 2024
eb416c1
Added schema_utils.Schema.get_property_by_path
dmichaels-harvard Jan 21, 2024
fd2ee1e
Added schema_utils.Schema.get_property_by_path
dmichaels-harvard Jan 21, 2024
1fc57c3
New compare functionality in portal_object_utils.
dmichaels-harvard Jan 21, 2024
da9a752
Comments in code
dmichaels-harvard Jan 22, 2024
bb5198b
comment updates
dmichaels-harvard Jan 22, 2024
e5dd073
comment updates
dmichaels-harvard Jan 22, 2024
b1bfb5f
comment updates
dmichaels-harvard Jan 22, 2024
e43c16b
minor refactor
dmichaels-harvard Jan 22, 2024
a65ee4a
minor refactor
dmichaels-harvard Jan 22, 2024
f479004
minor refactor
dmichaels-harvard Jan 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ dcicutils
Change Log
----------


8.7.1
=====

* Changed scripts/publish_to_pypi.py to allow gitinfo.json to have unstaged changes;
this is so we can optionally have repos write relevant git (repo, branch, commit) info
to this file (via GitHub Actions) and make it accessible to the package for inspection.
* Added is_schema_type and is_specified_schema to portal_utils.Portal.
* Refactoring in portal_utils; added portal_object_utils; added file_utils.py.


8.7.0
=====

Expand Down
54 changes: 54 additions & 0 deletions dcicutils/file_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import glob
import os
import pathlib
from typing import List, Optional, Union


def search_for_file(file: str,
location: Union[str, Optional[List[str]]] = None,
recursive: bool = False,
single: bool = False) -> Union[List[str], Optional[str]]:
"""
Searches for the existence of the given file name, first directly in the given directory or list
of directories, if specified, and if not then just in the current (working) directory; if the
given recursive flag is True then also searches all sub-directories of these directories;
returns the full path name to the file if found. If the single flag is True then just the
first file which is found is returns (as a string), or None if none; if the single flag
is False, then all matched files are returned in a list, or and empty list if none.
"""
if file and isinstance(file, (str, pathlib.PosixPath)):
if os.path.isabs(file):
if os.path.exists(file):
return file if single else [file]
return None if single else []
files_found = []
if not location:
location = ["."]
elif isinstance(location, (str, pathlib.PosixPath)):
location = [location]
elif not isinstance(location, list):
location = []
for directory in location:
if isinstance(directory, (str, pathlib.PosixPath)) and os.path.exists(os.path.join(directory, file)):
file_found = os.path.abspath(os.path.normpath(os.path.join(directory, file)))
if single:
return file_found
if file_found not in files_found:
files_found.append(file_found)
if recursive:
for directory in location:
if not directory.endswith("/**") and not file.startswith("**/"):
path = f"{directory}/**/{file}"
else:
path = f"{directory}/{file}"
files = glob.glob(path, recursive=recursive)
if files:
for file_found in files:
file_found = os.path.abspath(file_found)
if single:
return file_found
if file_found not in files_found:
files_found.append(file_found)
if files_found:
return files_found[0] if single else files_found
return None if single else []
112 changes: 112 additions & 0 deletions dcicutils/portal_object_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from functools import lru_cache
from typing import List, Optional, Tuple, Type, Union
from dcicutils.portal_utils import Portal

PortalObject = Type["PortalObject"] # Forward type reference for type hints.


class PortalObject:

def __init__(self, portal: Portal, portal_object: dict, portal_object_type: Optional[str] = None) -> None:
self._portal = portal
self._data = portal_object
self._type = portal_object_type if isinstance(portal_object_type, str) and portal_object_type else None

@property
def data(self):
return self._data

@property
@lru_cache(maxsize=1)
def type(self):
return self._type or Portal.get_schema_type(self._data)

@property
@lru_cache(maxsize=1)
def types(self):
return self._type or Portal.get_schema_types(self._data)

@property
@lru_cache(maxsize=1)
def uuid(self) -> Optional[str]:
return self._data.get("uuid") if isinstance(self._data, dict) else None

@property
@lru_cache(maxsize=1)
def schema(self):
return self._portal.get_schema(self.type)

@property
@lru_cache(maxsize=1)
def identifying_properties(self) -> List[str]:
"""
Returns the list of all identifying property names of this Portal object which actually have values.
Implicitly include "uuid" and "identifier" properties as identifying properties if they are actually
properties in the object schema, and favor these (first); defavor "aliases"; no other ordering defined.
"""
if not (schema := self.schema) or not (schema_identifying_properties := schema.get("identifyingProperties")):
return []
identifying_properties = []
for identifying_property in schema_identifying_properties:
if identifying_property not in ["uuid", "identifier", "aliases"]:
if self._data.get(identifying_property):
identifying_properties.append(identifying_property)
if self._data.get("identifier"):
identifying_properties.insert(0, "identifier")
if self._data.get("uuid"):
identifying_properties.insert(0, "uuid")
if "aliases" in schema_identifying_properties and self._data.get("aliases"):
identifying_properties.append("aliases")
return identifying_properties

@property
@lru_cache(maxsize=1)
def identifying_paths(self) -> List[str]:
"""
Returns a list of the possible Portal URL paths identifying this Portal object.
"""
if not (identifying_properties := self.identifying_properties):
return []
identifying_paths = []
for identifying_property in identifying_properties:
if (identifying_value := self._data.get(identifying_property)):
if identifying_property == "uuid":
identifying_paths.append(f"/{self.type}/{identifying_value}")
identifying_paths.append(f"/{identifying_value}")
# For now at least we include the path both with and without the schema type component,
# as for some identifying values, it works (only) with, and some, it works (only) without.
# For example: If we have FileSet with "accession", an identifying property, with value
# SMAFSFXF1RO4 then /SMAFSFXF1RO4 works but /FileSet/SMAFSFXF1RO4 does not; and
# conversely using "submitted_id", also an identifying property, with value
# UW_FILE-SET_COLO-829BL_HI-C_1 then /UW_FILE-SET_COLO-829BL_HI-C_1 does
# not work but /FileSet/UW_FILE-SET_COLO-829BL_HI-C_1 does work.
elif isinstance(identifying_value, list):
for identifying_value_item in identifying_value:
identifying_paths.append(f"/{self.type}/{identifying_value_item}")
identifying_paths.append(f"/{identifying_value_item}")
else:
identifying_paths.append(f"/{self.type}/{identifying_value}")
identifying_paths.append(f"/{identifying_value}")
return identifying_paths

@property
@lru_cache(maxsize=1)
def identifying_path(self) -> Optional[str]:
if identifying_paths := self.identifying_paths:
return identifying_paths[0]

def lookup(self, include_identifying_path: bool = False,
raw: bool = False) -> Optional[Union[Tuple[PortalObject, str], PortalObject]]:
return self._lookup(raw=raw) if include_identifying_path else self._lookup(raw=raw)[0]

def lookup_identifying_path(self) -> Optional[str]:
return self._lookup()[1]

def _lookup(self, raw: bool = False) -> Tuple[Optional[PortalObject], Optional[str]]:
try:
for identifying_path in self.identifying_paths:
if (value := self._portal.get(identifying_path, raw=raw)) and (value.status_code == 200):
return PortalObject(self._portal, value.json(), self.type if raw else None), identifying_path
except Exception:
pass
return None, self.identifying_path
Loading
Loading