-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
π§ππβ»οΈ Shape up for release (#40)
π Prepare pyglotaran-extras for a release on PyPI π * π§Ήπ©Ή Only include pyglotaran_extras folder itself to setup package lookup * π Added integration tests * β¨ Added basic deprecation functionality Slightly adjusted copy paste from pyglotaran https://github.com/glotaran/pyglotaran/blob/d1e36a93d2c75ec1a93d4eacea5eba2d49b6f130/glotaran/deprecation/deprecation_utils.py#L1 * β»οΈ Renamed 'boilerplate' -> 'setup_case_study' and export load_data from io * β»οΈπ Reexport overview plot functions from plotting package * ππ Use new 'install_extras: false' option in itegration test workflow * β»οΈ Renamed 'plotting.data' -> 'plotting.plot_data' * π Improved typing * π Added 'figsize' argument to all functions which create figues And adjusted res arg for 'plot_simple_overview' to be DatasetConvertible, to be consistent with 'plot_overview' * π§Ή Added cylcer arg to plot functions so users have more control over style This should also prevent style resetting * π§Ή Changed package version to '0.5.0rc1' Ref.: https://www.python.org/dev/peps/pep-0440/#pre-releases * ποΈ First step deprecation of plot functions only returning the Figure * π Export commonly used functions from package top level * β¬οΈπ§ Update pre-commit config
- Loading branch information
Showing
28 changed files
with
903 additions
and
242 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
name: "Run Examples" | ||
|
||
on: | ||
push: | ||
pull_request: | ||
workflow_dispatch: | ||
|
||
jobs: | ||
run-examples: | ||
name: "Run Example: " | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
example_name: | ||
[ | ||
quick-start, | ||
fluorescence, | ||
transient-absorption, | ||
transient-absorption-two-datasets, | ||
spectral-constraints, | ||
spectral-guidance, | ||
two-datasets, | ||
sim-3d-disp, | ||
sim-3d-nodisp, | ||
sim-3d-weight, | ||
sim-6d-disp, | ||
] | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python 3.8 | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: 3.8 | ||
- name: Install pyglotaran-extras | ||
run: | | ||
pip install wheel | ||
pip install . | ||
- name: ${{ matrix.example_name }} | ||
id: example-run | ||
uses: glotaran/pyglotaran-examples@main | ||
with: | ||
example_name: ${{ matrix.example_name }} | ||
install_extras: false | ||
- name: Upload Example Plots Artifact | ||
uses: actions/upload-artifact@v2 | ||
with: | ||
name: example-plots | ||
path: ${{ steps.example-run.outputs.plots-path }} |
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 +1,19 @@ | ||
__version__ = "0.3.3" | ||
from pyglotaran_extras.io.load_data import load_data | ||
from pyglotaran_extras.io.setup_case_study import setup_case_study | ||
from pyglotaran_extras.plotting.plot_data import plot_data_overview | ||
from pyglotaran_extras.plotting.plot_overview import plot_overview | ||
from pyglotaran_extras.plotting.plot_overview import plot_simple_overview | ||
from pyglotaran_extras.plotting.plot_traces import plot_fitted_traces | ||
from pyglotaran_extras.plotting.plot_traces import select_plot_wavelengths | ||
|
||
__all__ = [ | ||
"load_data", | ||
"setup_case_study", | ||
"plot_data_overview", | ||
"plot_overview", | ||
"plot_simple_overview", | ||
"plot_fitted_traces", | ||
"select_plot_wavelengths", | ||
] | ||
|
||
__version__ = "0.5.0rc1" |
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,4 @@ | ||
"""Module containing deprecation functionality.""" | ||
from pyglotaran_extras.deprecation.deprecation_utils import warn_deprecated | ||
|
||
__all__ = ["warn_deprecated"] |
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,152 @@ | ||
from __future__ import annotations | ||
|
||
from importlib.metadata import distribution | ||
from warnings import warn | ||
|
||
FIG_ONLY_WARNING = ( | ||
"In the future plot functions which create figures, will return a tuple " | ||
"of Figure AND the Axes. Please set ``figure_only=False`` and adjust your code.\n" | ||
"This usage will be an error in version: 0.7.0." | ||
) | ||
|
||
|
||
class OverDueDeprecation(Exception): | ||
"""Error thrown when a deprecation should have been removed. | ||
See Also | ||
-------- | ||
deprecate | ||
warn_deprecated | ||
deprecate_module_attribute | ||
deprecate_submodule | ||
deprecate_dict_entry | ||
""" | ||
|
||
|
||
class PyglotaranExtrasApiDeprecationWarning(UserWarning): | ||
"""Warning to give users about API changes. | ||
See Also | ||
-------- | ||
warn_deprecated | ||
""" | ||
|
||
|
||
def pyglotaran_extras_version() -> str: | ||
"""Version of the distribution. | ||
This is basically the same as ``pyglotaran_extras.__version__`` but independent | ||
from pyglotaran_extras. | ||
This way all of the deprecation functionality can be used even in | ||
``pyglotaran_extras.__init__.py`` without moving the import below the definition of | ||
``__version__`` or causeing a circular import issue. | ||
Returns | ||
------- | ||
str | ||
The version string. | ||
""" | ||
return distribution("pyglotaran-extras").version | ||
|
||
|
||
def parse_version(version_str: str) -> tuple[int, int, int]: | ||
"""Parse version string to tuple of three ints for comparison. | ||
Parameters | ||
---------- | ||
version_str : str | ||
Fully qualified version string of the form 'major.minor.patch'. | ||
Returns | ||
------- | ||
tuple[int, int, int] | ||
Version as tuple. | ||
Raises | ||
------ | ||
ValueError | ||
If ``version_str`` has less that three elements separated by ``.``. | ||
ValueError | ||
If ``version_str`` 's first three elements can not be casted to int. | ||
""" | ||
error_message = ( | ||
"version_str needs to be a fully qualified version consisting of " | ||
f"int parts (e.g. '0.0.1'), got {version_str!r}" | ||
) | ||
split_version = version_str.partition("-")[0].split(".") | ||
if len(split_version) < 3: | ||
raise ValueError(error_message) | ||
try: | ||
return tuple( | ||
map(int, (*split_version[:2], split_version[2].partition("rc")[0])) | ||
) # type:ignore[return-value] | ||
except ValueError: | ||
raise ValueError(error_message) | ||
|
||
|
||
def check_overdue(deprecated_qual_name_usage: str, to_be_removed_in_version: str) -> None: | ||
"""Check if a deprecation is overdue for removal. | ||
Parameters | ||
---------- | ||
deprecated_qual_name_usage : str | ||
Old usage with fully qualified name e.g.: | ||
``'glotaran.read_model_from_yaml(model_yml_str)'`` | ||
to_be_removed_in_version : str | ||
Version the support for this usage will be removed. | ||
Raises | ||
------ | ||
OverDueDeprecation | ||
If the current version is greater or equal to ``to_be_removed_in_version``. | ||
""" | ||
if ( | ||
parse_version(pyglotaran_extras_version()) >= parse_version(to_be_removed_in_version) | ||
and "dev" not in pyglotaran_extras_version() | ||
): | ||
raise OverDueDeprecation( | ||
f"Support for {deprecated_qual_name_usage.partition('(')[0]!r} was " | ||
f"supposed to be dropped in version: {to_be_removed_in_version!r}.\n" | ||
f"Current version is: {pyglotaran_extras_version()!r}" | ||
) | ||
|
||
|
||
def warn_deprecated( | ||
*, | ||
deprecated_qual_name_usage: str, | ||
new_qual_name_usage: str, | ||
to_be_removed_in_version: str, | ||
stacklevel: int = 2, | ||
) -> None: | ||
"""Raise deprecation warning with change information. | ||
The change information are old / new usage information and end of support version. | ||
Parameters | ||
---------- | ||
deprecated_qual_name_usage : str | ||
Old usage with fully qualified name e.g.: | ||
``'glotaran.read_model_from_yaml(model_yml_str)'`` | ||
new_qual_name_usage : str | ||
New usage as fully qualified name e.g.: | ||
``'glotaran.io.load_model(model_yml_str, format_name="yml_str")'`` | ||
to_be_removed_in_version : str | ||
Version the support for this usage will be removed. | ||
stacklevel: int | ||
Stack at which the warning should be shown as raise. Default: 2 | ||
Raises | ||
------ | ||
OverDueDeprecation | ||
If the current version is greater or equal to ``to_be_removed_in_version``. | ||
""" | ||
check_overdue(deprecated_qual_name_usage, to_be_removed_in_version) | ||
warn( | ||
PyglotaranExtrasApiDeprecationWarning( | ||
f"Usage of {deprecated_qual_name_usage!r} was deprecated, " | ||
f"use {new_qual_name_usage!r} instead.\n" | ||
f"This usage will be an error in version: {to_be_removed_in_version!r}." | ||
), | ||
stacklevel=stacklevel, | ||
) |
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,2 +1,5 @@ | ||
""" pyglotaran-extras io package """ | ||
from pyglotaran_extras.io.boilerplate import setup_case_study | ||
from pyglotaran_extras.io.load_data import load_data | ||
from pyglotaran_extras.io.setup_case_study import setup_case_study | ||
|
||
__all__ = ["setup_case_study", "load_data"] |
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,81 +1,12 @@ | ||
from __future__ import annotations | ||
|
||
import inspect | ||
from os import PathLike | ||
from pathlib import Path | ||
|
||
|
||
def setup_case_study( | ||
output_folder_name: str = "pyglotaran_results", | ||
results_folder_root: None | str | PathLike[str] = None, | ||
) -> tuple[Path, Path]: | ||
"""Convenience function to to quickly get folders for a case study. | ||
This is an execution environment independent (works in python script files | ||
and notebooks, independent of where the python runtime was called from) | ||
way to get the folder the analysis code resides in and also creates the | ||
``results_folder`` in case it didn't exist before. | ||
Parameters | ||
---------- | ||
output_folder_name : str | ||
Name of the base folder for the results., by default "pyglotaran_results" | ||
results_folder_root : None | ||
Parent folder the ``output_folder_name`` should be put in | ||
, by default None which results in the users Home folder being used | ||
Returns | ||
------- | ||
tuple[Path, Path] | ||
results_folder, script_folder: | ||
results_folder: | ||
Folder to be used to save results in of the pattern | ||
(``results_folder_root`` / ``output_folder_name`` / ``analysis_folder.parent``). | ||
analysis_folder: | ||
Folder the script or Notebook resides in. | ||
""" | ||
analysis_folder = get_script_dir(nesting=1) | ||
print(f"Setting up case study for folder: {analysis_folder}") | ||
if results_folder_root is None: | ||
results_folder_root = Path.home() / output_folder_name | ||
else: | ||
results_folder_root = Path(str(results_folder_root)) | ||
script_folder_rel = analysis_folder.relative_to(analysis_folder.parent) | ||
results_folder = (results_folder_root / script_folder_rel).resolve() | ||
results_folder.mkdir(parents=True, exist_ok=True) | ||
print(f"Results will be saved in: {results_folder}") | ||
return results_folder, analysis_folder.resolve() | ||
|
||
|
||
def get_script_dir(*, nesting: int = 0) -> Path: | ||
"""Gets parent folder a script is executed in. | ||
This is a helper function for cross compatibility with jupyter notebooks. | ||
In notebooks the global ``__file__`` variable isn't set, thus we need different | ||
means to get the folder a script is defined in, which doesn't change with the | ||
current working director the ``python interpreter`` was called from. | ||
Parameters | ||
---------- | ||
nesting : int | ||
Number to go up in the call stack to get to the initially calling function. | ||
This is only needed for library code and not for user code. | ||
, by default 0 (direct call) | ||
Returns | ||
------- | ||
Path | ||
Path to the folder the script was resides in. | ||
See Also | ||
-------- | ||
setup_case_study | ||
""" | ||
calling_frame = inspect.stack()[nesting + 1].frame | ||
file_var = calling_frame.f_globals.get("__file__", ".") | ||
file_path = Path(file_var).resolve() | ||
if file_var == ".": # pragma: no cover | ||
return file_path | ||
else: | ||
return file_path.parent | ||
"""Deprecated module.""" | ||
from pyglotaran_extras.deprecation import warn_deprecated | ||
from pyglotaran_extras.io.setup_case_study import setup_case_study | ||
|
||
__all__ = ["setup_case_study"] | ||
|
||
warn_deprecated( | ||
deprecated_qual_name_usage="pyglotaran_extras.io.boilerplate", | ||
new_qual_name_usage="pyglotaran_extras.io", | ||
to_be_removed_in_version="0.7.0", | ||
stacklevel=3, | ||
) |
Oops, something went wrong.