diff --git a/src/neuroconv/basedatainterface.py b/src/neuroconv/basedatainterface.py index adcec89b5..32f3a3f30 100644 --- a/src/neuroconv/basedatainterface.py +++ b/src/neuroconv/basedatainterface.py @@ -70,7 +70,7 @@ def get_metadata_schema(self) -> dict: return metadata_schema def get_metadata(self) -> DeepDict: - """Child DataInterface classes should override this to match their metadata.""" + """Extract metadata from source files and return it as a DeepDict.""" metadata = DeepDict() metadata["NWBFile"]["session_description"] = "" metadata["NWBFile"]["identifier"] = str(uuid.uuid4()) diff --git a/src/neuroconv/utils/checks.py b/src/neuroconv/utils/checks.py index 3a17e4776..e38cef306 100644 --- a/src/neuroconv/utils/checks.py +++ b/src/neuroconv/utils/checks.py @@ -1,10 +1,11 @@ from numbers import Real -from typing import Optional +from typing import Optional, Union import numpy as np +from numpy.typing import ArrayLike, NDArray -def calculate_regular_series_rate(series: np.ndarray, tolerance_decimals: int = 6) -> Optional[Real]: +def calculate_regular_series_rate(series: Union[ArrayLike, NDArray], tolerance_decimals: int = 6) -> Optional[float]: """Calculates the rate of a series as the difference between all consecutive points. If the difference between all time points are all the same value, then the value of rate is a scalar otherwise it is None.""" diff --git a/src/neuroconv/utils/dict.py b/src/neuroconv/utils/dict.py index f0507b653..141869eb8 100644 --- a/src/neuroconv/utils/dict.py +++ b/src/neuroconv/utils/dict.py @@ -36,7 +36,7 @@ def remove_implicit_resolver(cls, tag_to_remove): _NoDatesSafeLoader.remove_implicit_resolver("tag:yaml.org,2002:timestamp") -def load_dict_from_file(file_path: FilePath) -> dict: +def load_dict_from_file(file_path: FilePath) -> dict[str, Any]: """Safely load metadata from .yml or .json files.""" file_path = Path(file_path) assert file_path.is_file(), f"{file_path} is not a file." @@ -51,12 +51,18 @@ def load_dict_from_file(file_path: FilePath) -> dict: return dictionary -def exist_dict_in_list(d, ls): +def exist_dict_in_list(d: dict[str, Any], ls: list[dict[str, Any]]) -> bool: """Check if an identical dictionary exists in the list.""" return any([d == i for i in ls]) -def append_replace_dict_in_list(ls, d, compare_key, list_dict_deep_update: bool = True, remove_repeats: bool = True): +def append_replace_dict_in_list( + ls: list[dict[str, Any]], + d: dict[str, Any], + compare_key: str, + list_dict_deep_update: bool = True, + remove_repeats: bool = True +) -> list[dict[str, Any]]: """ Update the list ls with the dict d. @@ -107,14 +113,14 @@ def append_replace_dict_in_list(ls, d, compare_key, list_dict_deep_update: bool def dict_deep_update( - d: collections.abc.Mapping, - u: collections.abc.Mapping, + d: dict[str, Any], + u: dict[str, Any], append_list: bool = True, remove_repeats: bool = True, copy: bool = True, compare_key: str = "name", list_dict_deep_update: bool = True, -) -> collections.abc.Mapping: +) -> dict[str, Any]: """ Perform an update to all nested keys of dictionary d(input) from dictionary u(updating dict). @@ -214,34 +220,20 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: if isinstance(value, dict): self[key] = DeepDict(value) - def deep_update(self, other: Optional[Union[dict, "DeepDict"]] = None, **kwargs) -> None: + def deep_update(self, other: Optional[Union[dict[str, Any], "DeepDict"]] = None, **kwargs: Any) -> None: for key, value in (other or kwargs).items(): if key in self and isinstance(self[key], dict) and isinstance(value, dict): self[key].deep_update(value) else: self[key] = value - def to_dict(self) -> dict: + def to_dict(self) -> dict[str, Any]: """Turn a DeepDict into a normal dictionary""" - - def _to_dict(d: Union[dict, "DeepDict"]) -> dict: + def _to_dict(d: Union[dict[str, Any], "DeepDict"]) -> dict[str, Any]: return {key: _to_dict(value) for key, value in d.items()} if isinstance(d, dict) else d - return _to_dict(self) - def __deepcopy__(self, memodict={}): - """ - - Parameters - ---------- - memodict: dict - unused - - Returns - ------- - DeepDict - - """ + def __deepcopy__(self, memodict: dict = {}) -> "DeepDict": return DeepDict(deepcopy(self.to_dict())) def __repr__(self) -> str: diff --git a/src/neuroconv/utils/json_schema.py b/src/neuroconv/utils/json_schema.py index 182558b98..bb21dfb01 100644 --- a/src/neuroconv/utils/json_schema.py +++ b/src/neuroconv/utils/json_schema.py @@ -4,7 +4,7 @@ import warnings from datetime import datetime from pathlib import Path -from typing import Any, Callable, Optional +from typing import Any, Callable, Optional, Type, Union import docstring_parser import hdmf.data_utils @@ -65,9 +65,9 @@ def get_base_schema( root: bool = False, id_: Optional[str] = None, required: Optional[list[str]] = None, - properties: Optional[dict] = None, + properties: Optional[dict[str, Any]] = None, **kwargs, -) -> dict: +) -> dict[str, Any]: """Return the base schema used for all other schemas.""" base_schema = dict( required=required or [], @@ -85,7 +85,7 @@ def get_base_schema( return base_schema -def get_schema_from_method_signature(method: Callable, exclude: Optional[list[str]] = None) -> dict: +def get_schema_from_method_signature(method: Callable, exclude: Optional[list[str]] = None) -> dict[str, Any]: """Deprecated version of `get_json_schema_from_method_signature`.""" message = ( "The method `get_schema_from_method_signature` is now named `get_json_schema_from_method_signature`." @@ -96,7 +96,7 @@ def get_schema_from_method_signature(method: Callable, exclude: Optional[list[st return get_json_schema_from_method_signature(method=method, exclude=exclude) -def get_json_schema_from_method_signature(method: Callable, exclude: Optional[list[str]] = None) -> dict: +def get_json_schema_from_method_signature(method: Callable, exclude: Optional[list[str]] = None) -> dict[str, Any]: """ Get the equivalent JSON schema for a signature of a method. @@ -179,14 +179,14 @@ def get_json_schema_from_method_signature(method: Callable, exclude: Optional[li return json_schema -def _copy_without_title_keys(d: Any, /) -> Optional[dict]: +def _copy_without_title_keys(d: Any) -> Optional[dict[str, Any]]: if not isinstance(d, dict): return d return {key: _copy_without_title_keys(value) for key, value in d.items() if key != "title"} -def fill_defaults(schema: dict, defaults: dict, overwrite: bool = True): +def fill_defaults(schema: dict[str, Any], defaults: dict[str, Any], overwrite: bool = True) -> None: """ Insert the values of the defaults dict as default values in the schema in place. @@ -211,7 +211,7 @@ def fill_defaults(schema: dict, defaults: dict, overwrite: bool = True): val["default"] = defaults[key] -def unroot_schema(schema: dict): +def unroot_schema(schema: dict[str, Any]) -> dict[str, Any]: """ Modify a json-schema dictionary to make it not root. @@ -223,7 +223,7 @@ def unroot_schema(schema: dict): return {k: v for k, v in schema.items() if k in terms} -def _is_member(types, target_types): +def _is_member(types: Union[Type, tuple[Type, ...]], target_types: Union[Type, tuple[Type, ...]]) -> bool: if not isinstance(target_types, tuple): target_types = (target_types,) if not isinstance(types, tuple): @@ -231,7 +231,7 @@ def _is_member(types, target_types): return any(t in target_types for t in types) -def get_schema_from_hdmf_class(hdmf_class): +def get_schema_from_hdmf_class(hdmf_class: Type) -> dict[str, Any]: """Get metadata schema from hdmf class.""" schema = get_base_schema() schema["tag"] = hdmf_class.__module__ + "." + hdmf_class.__name__ @@ -244,6 +244,7 @@ def get_schema_from_hdmf_class(hdmf_class): # Temporary solution before this is solved: https://github.com/hdmf-dev/hdmf/issues/475 if "device" in pynwb_children_fields: pynwb_children_fields.remove("device") + docval = hdmf_class.__init__.__docval__ for docval_arg in docval["args"]: arg_name = docval_arg["name"] @@ -298,7 +299,7 @@ def get_schema_from_hdmf_class(hdmf_class): return schema -def get_metadata_schema_for_icephys() -> dict: +def get_metadata_schema_for_icephys() -> dict[str, Any]: """ Returns the metadata schema for icephys data.