-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip * wip * include additional files to commit * remove unintended global * some debugs * debugs * mirror API docs * mirror API docs * correct test imports * correct test imports * add soft deprecation cycle to public methods * fix some autocorrections from src * fix some autocorrections from src * add stacklevel to soft deprecation warnings * fix file names * Apply suggestions from code review Co-authored-by: Cody Baker <[email protected]> * Apply suggestions from code review * pr suggestion * pr suggestion --------- Co-authored-by: CodyCBakerPhD <[email protected]> Co-authored-by: Steph Prince <[email protected]>
- Loading branch information
1 parent
6fc57e5
commit d6a13ca
Showing
55 changed files
with
747 additions
and
530 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
Core Library | ||
============ | ||
|
||
.. automodule:: nwbinspector.nwbinspector | ||
.. automodule:: nwbinspector._inspection |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,47 @@ | ||
from .version import __version__ | ||
from .register_checks import available_checks, Importance | ||
from .nwbinspector import ( | ||
InspectorOutputJSONEncoder, | ||
from ._version import __version__ | ||
from ._registration import available_checks, register_check | ||
from ._types import Importance, Severity, InspectorMessage | ||
from ._configuration import load_config, validate_config, configure_checks | ||
from ._inspection import ( | ||
inspect_all, | ||
inspect_nwbfile, | ||
inspect_nwbfile_object, | ||
run_checks, | ||
load_config, | ||
) | ||
from .nwbinspector import inspect_nwb # TODO: remove after 7/1/2023 | ||
from .checks.ecephys import * | ||
from .checks.general import * | ||
from .checks.image_series import * | ||
from .checks.images import * | ||
from .checks.nwb_containers import * | ||
from .checks.nwbfile_metadata import * | ||
from .checks.ogen import * | ||
from .checks.ophys import * | ||
from .checks.tables import * | ||
from .checks.time_series import * | ||
from .checks.icephys import * | ||
from ._inspection import inspect_nwb # TODO: remove after 7/1/2023 | ||
from ._formatting import ( | ||
format_messages, | ||
print_to_console, | ||
save_report, | ||
MessageFormatter, | ||
FormatterOptions, | ||
InspectorOutputJSONEncoder, | ||
) | ||
from ._organization import organize_messages | ||
from .checks import * | ||
|
||
default_check_registry = {check.__name__: check for check in available_checks} | ||
|
||
__all__ = [ | ||
"available_checks", | ||
"default_check_registry", | ||
"register_check", | ||
"Importance", | ||
"Severity", | ||
"InspectorMessage", | ||
"load_config", | ||
"configure_checks", | ||
"InspectorOutputJSONEncoder", | ||
"inspect_all", | ||
"inspect_nwbfile", | ||
"inspect_nwbfile_object", | ||
"inspect_nwb", # TODO: remove after 7/1/2023 | ||
"run_checks", | ||
"format_messages", | ||
"print_to_console", | ||
"save_report", | ||
"MessageFormatter", | ||
"FormatterOptions", | ||
"organize_messages", | ||
"__version__", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
"""Primary functions for inspecting NWBFiles.""" | ||
|
||
import json | ||
import jsonschema | ||
from pathlib import Path | ||
from enum import Enum | ||
from typing import Optional, List | ||
from types import FunctionType | ||
from packaging.version import Version | ||
|
||
import yaml | ||
|
||
from . import available_checks | ||
from ._registration import InspectorMessage, Importance | ||
from nwbinspector.utils._utils import ( | ||
PathType, | ||
) | ||
|
||
INTERNAL_CONFIGS = dict(dandi=Path(__file__).parent / "internal_configs" / "dandi.inspector_config.yaml") | ||
|
||
|
||
def validate_config(config: dict): | ||
"""Validate an instance of configuration against the official schema.""" | ||
with open(file=Path(__file__).parent / "config.schema.json", mode="r") as fp: | ||
schema = json.load(fp=fp) | ||
jsonschema.validate(instance=config, schema=schema) | ||
|
||
|
||
def _copy_function(function): | ||
"""Copy the core parts of a given function, excluding wrappers, then return a new function.""" | ||
copied_function = FunctionType( | ||
function.__code__, function.__globals__, function.__name__, function.__defaults__, function.__closure__ | ||
) | ||
|
||
# in case f was given attrs (note this dict is a shallow copy) | ||
copied_function.__dict__.update(function.__dict__) | ||
return copied_function | ||
|
||
|
||
def copy_check(check): | ||
""" | ||
Copy a check function so that internal attributes can be adjusted without changing the original function. | ||
Required to ensure our configuration of functions in the registry does not effect the registry itself. | ||
Also copies the wrapper for auto-parsing results, | ||
see https://github.com/NeurodataWithoutBorders/nwbinspector/pull/218 for explanation. | ||
""" | ||
copied_check = _copy_function(function=check) | ||
copied_check.__wrapped__ = _copy_function(function=check.__wrapped__) | ||
return copied_check | ||
|
||
|
||
def load_config(filepath_or_keyword: PathType) -> dict: | ||
""" | ||
Load a config dictionary either via keyword search of the internal configs, or an explicit filepath. | ||
Currently supported keywords are: | ||
- 'dandi' | ||
For all DANDI archive related practices, including validation and upload. | ||
""" | ||
file = INTERNAL_CONFIGS.get(filepath_or_keyword, filepath_or_keyword) | ||
with open(file=file, mode="r") as stream: | ||
config = yaml.load(stream=stream, Loader=yaml.Loader) | ||
return config | ||
|
||
|
||
def configure_checks( | ||
checks: list = available_checks, | ||
config: Optional[dict] = None, | ||
ignore: Optional[List[str]] = None, | ||
select: Optional[List[str]] = None, | ||
importance_threshold: Importance = Importance.BEST_PRACTICE_SUGGESTION, | ||
) -> list: | ||
""" | ||
Filter a list of check functions (the entire base registry by default) according to the configuration. | ||
Parameters | ||
---------- | ||
config : dict | ||
Dictionary valid against our JSON configuration schema. | ||
Can specify a mapping of importance levels and list of check functions whose importance you wish to change. | ||
Typically loaded via json.load from a valid .json file | ||
checks : list of check functions | ||
Defaults to all registered checks. | ||
ignore: list, optional | ||
Names of functions to skip. | ||
select: list, optional | ||
If loading all registered checks, this can be shorthand for selecting only a handful of them. | ||
importance_threshold : string, optional | ||
Ignores all tests with an post-configuration assigned importance below this threshold. | ||
Importance has three levels: | ||
CRITICAL | ||
- potentially incorrect data | ||
BEST_PRACTICE_VIOLATION | ||
- very suboptimal data representation | ||
BEST_PRACTICE_SUGGESTION | ||
- improvable data representation | ||
The default is the lowest level, BEST_PRACTICE_SUGGESTION. | ||
""" | ||
if ignore is not None and select is not None: | ||
raise ValueError("Options 'ignore' and 'select' cannot both be used.") | ||
if importance_threshold not in Importance: | ||
raise ValueError( | ||
f"Indicated importance_threshold ({importance_threshold}) is not a valid importance level! Please choose " | ||
"from [CRITICAL_IMPORTANCE, BEST_PRACTICE_VIOLATION, BEST_PRACTICE_SUGGESTION]." | ||
) | ||
if config is not None: | ||
validate_config(config=config) | ||
checks_out = [] | ||
ignore = ignore or [] | ||
for check in checks: | ||
mapped_check = copy_check(check=check) | ||
for importance_name, func_names in config.items(): | ||
if check.__name__ in func_names: | ||
if importance_name == "SKIP": | ||
ignore.append(check.__name__) | ||
continue | ||
mapped_check.importance = Importance[importance_name] | ||
# Output wrappers are apparently parsed at time of wrapping not of time of output return... | ||
# Attempting to re-wrap the copied function if the importance level is being adjusted... | ||
# From https://github.com/NeurodataWithoutBorders/nwbinspector/issues/302 | ||
# new_check_wrapper = _copy_function(function=mapped_check.__wrapped__) | ||
# new_check_wrapper.importance = Importance[importance_name] | ||
# mapped_check.__wrapped__ = new_check_wrapper | ||
checks_out.append(mapped_check) | ||
else: | ||
checks_out = checks | ||
if select: | ||
checks_out = [x for x in checks_out if x.__name__ in select] | ||
elif ignore: | ||
checks_out = [x for x in checks_out if x.__name__ not in ignore] | ||
if importance_threshold: | ||
checks_out = [x for x in checks_out if x.importance.value >= importance_threshold.value] | ||
return checks_out |
Oops, something went wrong.