From a59ab3b3d10df25730f806e58aedb835bb651ebd Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Wed, 8 Nov 2023 11:32:23 -0500 Subject: [PATCH] Run `pyupgrade --py38-plus` on source --- dandi/cli/cmd_ls.py | 2 +- dandi/cli/command.py | 2 +- dandi/cli/formatter.py | 2 +- dandi/dandiapi.py | 22 ++++++++++------------ dandi/download.py | 2 +- dandi/due.py | 2 +- dandi/organize.py | 6 +++--- dandi/pynwb_utils.py | 4 ++-- dandi/support/pyout.py | 6 ++---- dandi/tests/fixtures.py | 2 +- dandi/tests/skip.py | 6 +++--- dandi/tests/test_keyring.py | 2 +- dandi/tests/test_upload.py | 6 +++--- dandi/utils.py | 11 +++++------ 14 files changed, 35 insertions(+), 40 deletions(-) diff --git a/dandi/cli/cmd_ls.py b/dandi/cli/cmd_ls.py index 9a1339718..7241dd48b 100644 --- a/dandi/cli/cmd_ls.py +++ b/dandi/cli/cmd_ls.py @@ -298,7 +298,7 @@ def flatten_meta_to_pyout_v1(meta): continue if isinstance(v, dict): for vf, vv in flatten_meta_to_pyout_v1(v).items(): - out["%s_%s" % (f, vf)] = flatten_v(vv) + out[f"{f}_{vf}"] = flatten_v(vv) else: out[f] = flatten_v(v) return out diff --git a/dandi/cli/command.py b/dandi/cli/command.py index 0723219a1..7adf66a40 100644 --- a/dandi/cli/command.py +++ b/dandi/cli/command.py @@ -99,7 +99,7 @@ def main(ctx, log_level, pdb=False): logdir = platformdirs.user_log_dir("dandi-cli", "dandi") logfile = os.path.join( - logdir, "{:%Y%m%d%H%M%SZ}-{}.log".format(datetime.utcnow(), os.getpid()) + logdir, f"{datetime.utcnow():%Y%m%d%H%M%SZ}-{os.getpid()}.log" ) os.makedirs(logdir, exist_ok=True) handler = logging.FileHandler(logfile, encoding="utf-8") diff --git a/dandi/cli/formatter.py b/dandi/cli/formatter.py index 1e831050b..05d6992b8 100644 --- a/dandi/cli/formatter.py +++ b/dandi/cli/formatter.py @@ -7,7 +7,7 @@ lgr = get_logger() -class Formatter(object): +class Formatter: def __enter__(self): pass diff --git a/dandi/dandiapi.py b/dandi/dandiapi.py index 4c2ad220c..609e5dbc5 100644 --- a/dandi/dandiapi.py +++ b/dandi/dandiapi.py @@ -438,7 +438,7 @@ def for_dandi_instance( instance: str | DandiInstance, token: str | None = None, authenticate: bool = False, - ) -> "DandiAPIClient": + ) -> DandiAPIClient: """ Construct a client instance for the server identified by ``instance`` (either the name of a registered Dandi Archive instance or a @@ -530,7 +530,7 @@ def _instance_id(self) -> str: def get_dandiset( self, dandiset_id: str, version_id: str | None = None, lazy: bool = True - ) -> "RemoteDandiset": + ) -> RemoteDandiset: """ Fetches the Dandiset with the given ``dandiset_id``. If ``version_id`` is not specified, the `RemoteDandiset`'s version is set to the most @@ -556,7 +556,7 @@ def get_dandiset( return d.for_version(version_id) return d - def get_dandisets(self) -> Iterator["RemoteDandiset"]: + def get_dandisets(self) -> Iterator[RemoteDandiset]: """ Returns a generator of all Dandisets on the server. For each Dandiset, the `RemoteDandiset`'s version is set to the most recent published @@ -565,7 +565,7 @@ def get_dandisets(self) -> Iterator["RemoteDandiset"]: for data in self.paginate("/dandisets/"): yield RemoteDandiset.from_data(self, data) - def create_dandiset(self, name: str, metadata: dict[str, Any]) -> "RemoteDandiset": + def create_dandiset(self, name: str, metadata: dict[str, Any]) -> RemoteDandiset: """Creates a Dandiset with the given name & metadata""" return RemoteDandiset.from_data( self, self.post("/dandisets/", json={"name": name, "metadata": metadata}) @@ -596,7 +596,7 @@ def check_schema_version(self, schema_version: str | None = None) -> None: " upgrade dandi and/or dandischema." ) - def get_asset(self, asset_id: str) -> "BaseRemoteAsset": + def get_asset(self, asset_id: str) -> BaseRemoteAsset: """ Fetch the asset with the given asset ID. If the given asset does not exist, a `NotFoundError` is raised. @@ -1026,7 +1026,7 @@ def wait_until_valid(self, max_time: float = 120) -> None: f"Dandiset {self.identifier} is {v.status.value}: {json.dumps(about, indent=4)}" ) - def publish(self, max_time: float = 120) -> "RemoteDandiset": + def publish(self, max_time: float = 120) -> RemoteDandiset: """ Publish the draft version of the Dandiset and wait at most ``max_time`` seconds for the publication operation to complete. If the operation @@ -1073,7 +1073,7 @@ def get_assets(self, order: str | None = None) -> Iterator[RemoteAsset]: f"No such version: {self.version_id!r} of Dandiset {self.identifier}" ) - def get_asset(self, asset_id: str) -> "RemoteAsset": + def get_asset(self, asset_id: str) -> RemoteAsset: """ Fetch the asset in this version of the Dandiset with the given asset ID. If the given asset does not exist, a `NotFoundError` is raised. @@ -1133,7 +1133,7 @@ def get_assets_by_glob( f"No such version: {self.version_id!r} of Dandiset {self.identifier}" ) - def get_asset_by_path(self, path: str) -> "RemoteAsset": + def get_asset_by_path(self, path: str) -> RemoteAsset: """ Fetch the asset in this version of the Dandiset whose `~RemoteAsset.path` equals ``path``. If the given asset does not @@ -1264,7 +1264,7 @@ class BaseRemoteAsset(ABC, APIBase): #: The `DandiAPIClient` instance that returned this `BaseRemoteAsset` #: and which the latter will use for API requests - client: "DandiAPIClient" + client: DandiAPIClient #: The asset identifier identifier: str = Field(alias="asset_id") #: The asset's (forward-slash-separated) path @@ -1611,9 +1611,7 @@ def get_entry_by_path(self, path: str) -> RemoteZarrEntry: else: return entry - def rmfiles( - self, files: Iterable["RemoteZarrEntry"], reingest: bool = True - ) -> None: + def rmfiles(self, files: Iterable[RemoteZarrEntry], reingest: bool = True) -> None: """ Delete one or more files from the Zarr. diff --git a/dandi/download.py b/dandi/download.py index f29328e67..fd57c930e 100644 --- a/dandi/download.py +++ b/dandi/download.py @@ -423,7 +423,7 @@ def agg_done(self, done_sizes: Iterator[int]) -> list[str]: pref += "<" if self.items_summary.has_unknown_sizes: pref += "?" - v = [naturalsize(done), "%s%.2f%%" % (pref, 100 * r)] + v = [naturalsize(done), f"{pref}{100 * r:.2f}%"] if ( done and self.items_summary.t0 is not None diff --git a/dandi/due.py b/dandi/due.py index 720b0b6ef..51a328237 100644 --- a/dandi/due.py +++ b/dandi/due.py @@ -27,7 +27,7 @@ __version__ = "0.0.8" -class InactiveDueCreditCollector(object): +class InactiveDueCreditCollector: """Just a stub at the Collector which would not do anything""" def _donothing(self, *args, **kwargs): diff --git a/dandi/organize.py b/dandi/organize.py index 06c163d0f..8e12c1437 100644 --- a/dandi/organize.py +++ b/dandi/organize.py @@ -382,9 +382,9 @@ def _assign_dandi_names(metadata): def _get_unique_values(metadata, fields, filter_=False): unique_values = {} for field in fields: - unique_values[field] = set(_get_hashable(r.get(field, None)) for r in metadata) + unique_values[field] = {_get_hashable(r.get(field, None)) for r in metadata} if filter_: - unique_values[field] = set(v for v in unique_values[field] if v) + unique_values[field] = {v for v in unique_values[field] if v} return unique_values @@ -998,7 +998,7 @@ def _get_metadata(path): if acted_upon and in_place: # We might need to cleanup a bit - e.g. prune empty directories left # by the move in in-place mode - dirs = set(op.dirname(e["path"]) for e in acted_upon) + dirs = {op.dirname(e["path"]) for e in acted_upon} for d in sorted(dirs)[::-1]: # from longest to shortest if op.exists(d): try: diff --git a/dandi/pynwb_utils.py b/dandi/pynwb_utils.py index c3a5945bf..d504f82ef 100644 --- a/dandi/pynwb_utils.py +++ b/dandi/pynwb_utils.py @@ -157,7 +157,7 @@ def get_neurodata_types_to_modalities_map() -> dict[str, str]: v_split = v_.__module__.split(".") if len(v_split) != 2: - print("Skipping %s coming from %s" % (v_, v_.__module__)) + print(f"Skipping {v_} coming from {v_.__module__}") continue modality = v_split[1] # so smth like ecephys @@ -247,7 +247,7 @@ def _get_pynwb_metadata(path: str | Path | Readable) -> dict[str, Any]: continue if not f.startswith("number_of_"): raise NotImplementedError( - "ATM can only compute number_of_ fields. Got {}".format(f) + f"ATM can only compute number_of_ fields. Got {f}" ) key = f[len("number_of_") :] out[f] = len(getattr(nwb, key, []) or []) diff --git a/dandi/support/pyout.py b/dandi/support/pyout.py index a633f7099..25719ada7 100644 --- a/dandi/support/pyout.py +++ b/dandi/support/pyout.py @@ -54,7 +54,7 @@ def summary_dates(values): def counts(values): - return ["{:d} {}".format(v, k) for k, v in Counter(values).items()] + return [f"{v:d} {k}" for k, v in Counter(values).items()] # class mapped_counts(object): @@ -148,9 +148,7 @@ def get_style(hide_if_missing=True): "errors": dict( align="center", color=dict(interval=[[0, 1, "green"], [1, None, "red"]]), - aggregate=lambda x: ( - "{} with errors".format(sum(map(bool, x))) if any(x) else "" - ), + aggregate=lambda x: (f"{sum(map(bool, x))} with errors" if any(x) else ""), ), "status": dict( color=dict(lookup={"skipped": "yellow", "done": "green", "error": "red"}), diff --git a/dandi/tests/fixtures.py b/dandi/tests/fixtures.py index 84d9fa74b..d661b8d59 100644 --- a/dandi/tests/fixtures.py +++ b/dandi/tests/fixtures.py @@ -435,7 +435,7 @@ def docker_compose_setup() -> Iterator[dict[str, str]]: ], cwd=str(LOCAL_DOCKER_DIR), env=env, - universal_newlines=True, + text=True, ) m = re.search(r"^Generated token (\w+) for user admin@nil.nil$", r, flags=re.M) if not m: diff --git a/dandi/tests/skip.py b/dandi/tests/skip.py index 7fed75839..0e08b5f99 100644 --- a/dandi/tests/skip.py +++ b/dandi/tests/skip.py @@ -181,7 +181,7 @@ class NamespaceAttributeError(AttributeError): """ -class Namespace(object, metaclass=abc.ABCMeta): +class Namespace(metaclass=abc.ABCMeta): """Provide namespace skip conditions in CONDITION_FNS.""" fns = {c.__name__: c for c in CONDITION_FNS} @@ -231,12 +231,12 @@ def attr_value(self, condition_func): def __getattr__(self, item): if item.startswith("skipif_"): try: - return super(Mark, self).__getattr__(item[len("skipif_") :]) + return super().__getattr__(item[len("skipif_") :]) except NamespaceAttributeError: # Fall back to the original item name so that the attribute # error message doesn't confusingly drop "skipif_". pass - return super(Mark, self).__getattr__(item) + return super().__getattr__(item) mark = Mark() diff --git a/dandi/tests/test_keyring.py b/dandi/tests/test_keyring.py index 1ff202898..84bae065d 100644 --- a/dandi/tests/test_keyring.py +++ b/dandi/tests/test_keyring.py @@ -36,7 +36,7 @@ def test_dandi_authenticate_no_env_var( ) DandiAPIClient(local_dandi_api.api_url).dandi_authenticate() inputmock.assert_called_once_with( - "Please provide API Key for {}: ".format(local_dandi_api.instance_id) + f"Please provide API Key for {local_dandi_api.instance_id}: " ) diff --git a/dandi/tests/test_upload.py b/dandi/tests/test_upload.py index 6ccdf8990..9326b3ad4 100644 --- a/dandi/tests/test_upload.py +++ b/dandi/tests/test_upload.py @@ -28,9 +28,9 @@ def test_upload_download( ) -> None: d = new_dandiset.dandiset dspath = new_dandiset.dspath - (nwb_file,) = [ + (nwb_file,) = ( p for p in list_paths(organized_nwb_dir) if p.name != dandiset_metadata_file - ] + ) assert nwb_file.suffix == ".nwb" parent, name = nwb_file.relative_to(organized_nwb_dir).parts (dspath / parent).mkdir() @@ -299,7 +299,7 @@ def test_upload_bids_zarr(bids_zarr_dandiset: SampleDandiset) -> None: bids_zarr_dandiset.upload() assets = list(bids_zarr_dandiset.dandiset.get_assets()) assert len(assets) > 10 # it is a bigish dataset - (asset,) = [a for a in assets if a.path.endswith(".zarr")] + (asset,) = (a for a in assets if a.path.endswith(".zarr")) assert isinstance(asset, RemoteZarrAsset) assert asset.asset_type is AssetType.ZARR assert asset.path.endswith(".zarr") diff --git a/dandi/utils.py b/dandi/utils.py index eb279d1d1..dcd9422e5 100644 --- a/dandi/utils.py +++ b/dandi/utils.py @@ -234,16 +234,15 @@ def flattened(it: Iterable) -> list: def load_jsonl(filename: AnyPath) -> list: """Load json lines formatted file""" - with open(filename, "r") as f: + with open(filename) as f: return list(map(json.loads, f)) _encoded_dirsep = re.escape(os.sep) -_VCS_REGEX = r"%s\.(?:git|gitattributes|svn|bzr|hg)(?:%s|$)" % ( - _encoded_dirsep, - _encoded_dirsep, +_VCS_REGEX = ( + rf"{_encoded_dirsep}\.(?:git|gitattributes|svn|bzr|hg)(?:{_encoded_dirsep}|$)" ) -_DATALAD_REGEX = r"%s\.(?:datalad)(?:%s|$)" % (_encoded_dirsep, _encoded_dirsep) +_DATALAD_REGEX = rf"{_encoded_dirsep}\.(?:datalad)(?:{_encoded_dirsep}|$)" def find_files( @@ -374,7 +373,7 @@ def copy_file(src: AnyPath, dst: AnyPath) -> None: ["cp", "--help"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - universal_newlines=True, + text=True, ) # Ignore command failures (e.g., if cp doesn't support --help), as the # command will still likely output its usage info.