diff --git a/src/foapy/__init__.py b/src/foapy/__init__.py index e451f10..f96955e 100644 --- a/src/foapy/__init__.py +++ b/src/foapy/__init__.py @@ -14,3 +14,53 @@ __version__ = "unknown" finally: del version, PackageNotFoundError + + +# We first need to detect if we're being called as part of the numpy setup +# procedure itself in a reliable manner. +try: + __FOAPY_SETUP__ +except NameError: + __FOAPY_SETUP__ = False + +if __FOAPY_SETUP__: + sys.stderr.write("Running from numpy source directory.\n") +else: + from .alphabet import alphabet # noqa: F401 + from .constants_intervals import binding, mode # noqa: F401 + from .intervals import intervals # noqa: F401 + from .order import order # noqa: F401 + + # public submodules are imported lazily, therefore are accessible from + # __getattr__. Note that `distutils` (deprecated) and `array_api` + # (experimental label) are not added here, because `from numpy import *` + # must not raise any warnings - that's too disruptive. + __foapy_submodules__ = {"ma"} + + __all__ = list( + __foapy_submodules__ + | {"order", "intervals", "exceptions", "alphabet", "binding", "mode"} + | {"__version__", "__array_namespace_info__"} + ) + + def __getattr__(attr): + if attr == "exceptions": + from . import exceptions + + return exceptions + elif attr == "ma": + from . import ma + + return ma + + raise AttributeError( + "module {!r} has no attribute " "{!r}".format(__name__, attr) + ) + + def __dir__(): + public_symbols = globals().keys() | __foapy_submodules__ + public_symbols -= { + "ma", + "version", + } + return list(public_symbols) diff --git a/src/foapy/intervals.py b/src/foapy/intervals.py index 52f3dd9..60c81f1 100644 --- a/src/foapy/intervals.py +++ b/src/foapy/intervals.py @@ -1,6 +1,6 @@ import numpy as np -from foapy.constants_intervals import binding, mode +from foapy import binding, mode def intervals(X, bind, mod): diff --git a/src/foapy/ma/intervals.py b/src/foapy/ma/intervals.py index 60849b4..c925655 100644 --- a/src/foapy/ma/intervals.py +++ b/src/foapy/ma/intervals.py @@ -1,7 +1,7 @@ import numpy as np from numpy import ma -from foapy.constants_intervals import binding, mode +from foapy import binding, mode from foapy.exceptions import InconsistentOrderException, Not1DArrayException diff --git a/src/foapy/ma/order.py b/src/foapy/ma/order.py index a4fa10d..7220f16 100644 --- a/src/foapy/ma/order.py +++ b/src/foapy/ma/order.py @@ -1,9 +1,9 @@ import numpy as np import numpy.ma as ma +from foapy import order as general_order from foapy.exceptions import Not1DArrayException from foapy.ma.alphabet import alphabet -from foapy.order import order as general_order def order(X, return_alphabet=False) -> np.ma.MaskedArray: diff --git a/src/foapy/skeleton.py b/src/foapy/skeleton.py deleted file mode 100644 index f9b47c0..0000000 --- a/src/foapy/skeleton.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -This is a skeleton file that can serve as a starting point for a Python -console script. To run this script uncomment the following lines in the -``[options.entry_points]`` section in ``setup.cfg``:: - - console_scripts = - fibonacci = foapy.skeleton:run - -Then run ``pip install .`` (or ``pip install -e .`` for editable mode) -which will install the command ``fibonacci`` inside your current environment. - -Besides console scripts, the header (i.e. until ``_logger``...) of this file can -also be used as template for Python modules. - -Note: - This file can be renamed depending on your needs or safely removed if not needed. - -References: - - https://setuptools.pypa.io/en/latest/userguide/entry_point.html - - https://pip.pypa.io/en/stable/reference/pip_install -""" - -import argparse -import logging -import sys - -from foapy import __version__ - -__author__ = "FOARLab" -__copyright__ = "FOARLab" -__license__ = "BSD-3-Clause" - -_logger = logging.getLogger(__name__) - - -# ---- Python API ---- -# The functions defined in this section can be imported by users in their -# Python scripts/interactive interpreter, e.g. via -# `from foapy.skeleton import fib`, -# when using this Python module as a library. - - -def fib(n): - """Fibonacci example function - - Args: - n (int): integer - - Returns: - int: n-th Fibonacci number - """ - assert n > 0 - a, b = 1, 1 - for _i in range(n - 1): - a, b = b, a + b - return a - - -# ---- CLI ---- -# The functions defined in this section are wrappers around the main Python -# API allowing them to be called directly from the terminal as a CLI -# executable/script. - - -def parse_args(args): - """Parse command line parameters - - Args: - args (List[str]): command line parameters as list of strings - (for example ``["--help"]``). - - Returns: - :obj:`argparse.Namespace`: command line parameters namespace - """ - parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration") - parser.add_argument( - "--version", - action="version", - version=f"foapy {__version__}", - ) - parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT") - parser.add_argument( - "-v", - "--verbose", - dest="loglevel", - help="set loglevel to INFO", - action="store_const", - const=logging.INFO, - ) - parser.add_argument( - "-vv", - "--very-verbose", - dest="loglevel", - help="set loglevel to DEBUG", - action="store_const", - const=logging.DEBUG, - ) - return parser.parse_args(args) - - -def setup_logging(loglevel): - """Setup basic logging - - Args: - loglevel (int): minimum loglevel for emitting messages - """ - logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s" - logging.basicConfig( - level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S" - ) - - -def main(args): - """Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion - - Instead of returning the value from :func:`fib`, it prints the result to the - ``stdout`` in a nicely formatted message. - - Args: - args (List[str]): command line parameters as list of strings - (for example ``["--verbose", "42"]``). - """ - args = parse_args(args) - setup_logging(args.loglevel) - _logger.debug("Starting crazy calculations...") - print(f"The {args.n}-th Fibonacci number is {fib(args.n)}") - _logger.info("Script ends here") - - -def run(): - """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv` - - This function can be used as entry point to create console scripts with setuptools. - """ - main(sys.argv[1:]) - - -if __name__ == "__main__": - # ^ This is a guard statement that will prevent the following code from - # being executed in the case someone imports this file instead of - # executing it as a script. - # https://docs.python.org/3/library/__main__.html - - # After installing your project with pip, users can also run your Python - # modules as scripts via the ``-m`` flag, as defined in PEP 338:: - # - # python -m foapy.skeleton 42 - # - run() diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 0ce87e3..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -""" - Dummy conftest.py for foapy. - - If you don't know what this is for, just leave it empty. - Read more about conftest.py under: - - https://docs.pytest.org/en/stable/fixture.html - - https://docs.pytest.org/en/stable/writing_plugins.html -""" - -# import pytest diff --git a/tests/test_alphabet.py b/tests/test_alphabet.py index 91414b1..136d9eb 100644 --- a/tests/test_alphabet.py +++ b/tests/test_alphabet.py @@ -4,7 +4,7 @@ import pytest from numpy.testing import assert_array_equal -from foapy.alphabet import alphabet +from foapy import alphabet from foapy.exceptions import Not1DArrayException diff --git a/tests/test_intervals.py b/tests/test_intervals.py index 908972b..e389586 100644 --- a/tests/test_intervals.py +++ b/tests/test_intervals.py @@ -4,8 +4,7 @@ import pytest from numpy.testing import assert_array_equal -from foapy.constants_intervals import binding, mode -from foapy.intervals import intervals +from foapy import binding, intervals, mode class TestIntervals(TestCase): diff --git a/tests/test_order.py b/tests/test_order.py index 15be9e3..cbba4ad 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -4,8 +4,8 @@ import pytest from numpy.testing import assert_array_equal +from foapy import order from foapy.exceptions import Not1DArrayException -from foapy.order import order class TestOrder(TestCase): diff --git a/tests/test_skeleton.py b/tests/test_skeleton.py deleted file mode 100644 index e77ef43..0000000 --- a/tests/test_skeleton.py +++ /dev/null @@ -1,25 +0,0 @@ -import pytest - -from foapy.skeleton import fib, main - -__author__ = "FOARLab" -__copyright__ = "FOARLab" -__license__ = "BSD-3-Clause" - - -def test_fib(): - """API Tests""" - assert fib(1) == 1 - assert fib(2) == 1 - assert fib(7) == 13 - with pytest.raises(AssertionError): - fib(-10) - - -def test_main(capsys): - """CLI Tests""" - # capsys is a pytest fixture that allows asserts against stdout/stderr - # https://docs.pytest.org/en/stable/capture.html - main(["7"]) - captured = capsys.readouterr() - assert "The 7-th Fibonacci number is 13" in captured.out