diff --git a/.github/workflows/ci_test-base.yml b/.github/workflows/ci_test-base.yml index 019cc747ab..53e8cec1e7 100644 --- a/.github/workflows/ci_test-base.yml +++ b/.github/workflows/ci_test-base.yml @@ -69,7 +69,7 @@ jobs: - name: Test Package [only] run: | # NOTE: run coverage on tests does not propagare faler status for Win, https://github.com/nedbat/coveragepy/issues/1003 - coverage run --source pl_bolts -m pytest pl_bolts -v --junitxml=junit/test-results-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.requires }}.xml --ignore=pl_bolts/datamodules --ignore=pl_bolts/datasets --ignore=pl_bolts/models/self_supervised/amdim/transforms.py --ignore=pl_bolts/models/rl + python -m pytest pl_bolts -v --cov=pl_bolts --junitxml=junit/test-results-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.requires }}.xml --ignore=pl_bolts/datamodules --ignore=pl_bolts/datasets --ignore=pl_bolts/models/self_supervised/amdim/transforms.py --ignore=pl_bolts/models/rl - name: Upload pytest test results uses: actions/upload-artifact@master diff --git a/docs/source/conf.py b/docs/source/conf.py index 40c14dbec7..7075b33bad 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,37 +13,38 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import m2r -import builtins import glob import inspect import os import shutil import sys +from importlib.util import module_from_spec, spec_from_file_location import pt_lightning_sphinx_theme from sphinx.ext import apidoc -PATH_HERE = os.path.abspath(os.path.dirname(__file__)) -PATH_ROOT = os.path.join(PATH_HERE, '..', '..') -sys.path.insert(0, os.path.abspath(PATH_ROOT)) - -builtins.__LIGHTNING_BOLT_SETUP__: bool = True +_PATH_HERE = os.path.abspath(os.path.dirname(__file__)) +_PATH_ROOT = os.path.join(_PATH_HERE, '..', '..') +sys.path.insert(0, os.path.abspath(_PATH_ROOT)) SPHINX_MOCK_REQUIREMENTS = int(os.environ.get('SPHINX_MOCK_REQUIREMENTS', True)) -import pl_bolts # noqa: E402 +# alternative https://stackoverflow.com/a/67692/4521646 +spec = spec_from_file_location("pl_bolts", os.path.join(_PATH_ROOT, "pl_bolts", "info.py")) +info = module_from_spec(spec) +spec.loader.exec_module(info) # -- Project information ----------------------------------------------------- # this name shall match the project name in Github as it is used for linking to code project = 'Lightning-Bolts' -copyright = pl_bolts.__copyright__ -author = pl_bolts.__author__ +copyright = info.__copyright__ +author = info.__author__ # The short X.Y version -version = pl_bolts.__version__ +version = info.__version__ # The full version, including alpha/beta/rc tags -release = pl_bolts.__version__ +release = info.__version__ # Options for the linkcode extension # ---------------------------------- @@ -63,11 +64,11 @@ # fp.write(readme) # copy all documents from GH templates like contribution guide -for md in glob.glob(os.path.join(PATH_ROOT, '.github', '*.md')): - shutil.copy(md, os.path.join(PATH_HERE, os.path.basename(md))) +for md in glob.glob(os.path.join(_PATH_ROOT, '.github', '*.md')): + shutil.copy(md, os.path.join(_PATH_HERE, os.path.basename(md))) # export the changelog -with open(os.path.join(PATH_ROOT, 'CHANGELOG.md'), 'r') as fp: +with open(os.path.join(_PATH_ROOT, 'CHANGELOG.md'), 'r') as fp: chlog_lines = fp.readlines() # enrich short subsub-titles to be unique chlog_ver = '' @@ -77,7 +78,7 @@ elif ln.startswith('### '): ln = ln.replace('###', f'### {chlog_ver} -') chlog_lines[i] = ln -with open(os.path.join(PATH_HERE, 'CHANGELOG.md'), 'w') as fp: +with open(os.path.join(_PATH_HERE, 'CHANGELOG.md'), 'w') as fp: fp.writelines(chlog_lines) # -- General configuration --------------------------------------------------- @@ -149,7 +150,8 @@ 'api/modules.rst', 'api/pl_bolts.submit.rst', 'api/pl_bolts.utils.*', - 'api/pl_bolts.setup_tools.*', + 'api/pl_bolts.info.rst', + 'api/pl_bolts.setup_tools.rst', 'PULL_REQUEST_TEMPLATE.md', ] @@ -169,8 +171,8 @@ # documentation. html_theme_options = { - 'pytorch_project': pl_bolts.__homepage__, - 'canonical_url': pl_bolts.__homepage__, + 'pytorch_project': info.__homepage__, + 'canonical_url': info.__homepage__, 'collapse_navigation': False, 'display_version': True, 'logo_only': False, @@ -288,10 +290,10 @@ # packages for which sphinx-apidoc should generate the docs (.rst files) PACKAGES = [ - pl_bolts.__name__, + info.__name__, ] -apidoc_output_folder = os.path.join(PATH_HERE, 'api') +apidoc_output_folder = os.path.join(_PATH_HERE, 'api') def run_apidoc(_): @@ -306,7 +308,7 @@ def run_apidoc(_): '-e', '-o', apidoc_output_folder, - os.path.join(PATH_ROOT, pkg), + os.path.join(_PATH_ROOT, pkg), '**/test_*', '--force', '--private', @@ -319,15 +321,15 @@ def run_apidoc(_): def setup(app): # this is for hiding doctest decoration, # see: http://z4r.github.io/python/2011/12/02/hides-the-prompts-and-output/ - app.add_javascript('copybutton.js') + app.add_js_file('copybutton.js') app.connect('builder-inited', run_apidoc) # copy all notebooks to local folder -path_nbs = os.path.join(PATH_HERE, 'notebooks') +path_nbs = os.path.join(_PATH_HERE, 'notebooks') if not os.path.isdir(path_nbs): os.mkdir(path_nbs) -for path_ipynb in glob.glob(os.path.join(PATH_ROOT, 'notebooks', '*.ipynb')): +for path_ipynb in glob.glob(os.path.join(_PATH_ROOT, 'notebooks', '*.ipynb')): path_ipynb2 = os.path.join(path_nbs, os.path.basename(path_ipynb)) shutil.copy(path_ipynb, path_ipynb2) @@ -355,9 +357,9 @@ def package_list_from_file(file): MOCK_PACKAGES = [] if SPHINX_MOCK_REQUIREMENTS: # mock also base packages when we are on RTD since we don't install them there - MOCK_PACKAGES += package_list_from_file(os.path.join(PATH_ROOT, 'requirements.txt')) - MOCK_PACKAGES += package_list_from_file(os.path.join(PATH_ROOT, 'requirements', 'models.txt')) - MOCK_PACKAGES += package_list_from_file(os.path.join(PATH_ROOT, 'requirements', 'loggers.txt')) + MOCK_PACKAGES += package_list_from_file(os.path.join(_PATH_ROOT, 'requirements.txt')) + MOCK_PACKAGES += package_list_from_file(os.path.join(_PATH_ROOT, 'requirements', 'models.txt')) + MOCK_PACKAGES += package_list_from_file(os.path.join(_PATH_ROOT, 'requirements', 'loggers.txt')) # replace PyPI packages by importing ones MOCK_PACKAGES = [PACKAGE_MAPPING.get(pkg, pkg) for pkg in MOCK_PACKAGES] diff --git a/pl_bolts/__init__.py b/pl_bolts/__init__.py index 3c95fb9bf0..83850493fb 100644 --- a/pl_bolts/__init__.py +++ b/pl_bolts/__init__.py @@ -1,60 +1,41 @@ -"""Root package info.""" +"""Root package crossroad.""" import os -__version__ = '0.3.2rc1' -__author__ = 'PyTorchLightning et al.' -__author_email__ = 'name@pytorchlightning.ai' -__license__ = 'Apache-2.0' -__copyright__ = f'Copyright (c) 2020-2021, {__author__}' -__homepage__ = 'https://github.com/PyTorchLightning/lightning-bolts' -__docs__ = "PyTorch Lightning Bolts is a community contribution for ML researchers." -__long_doc__ = """ -What is it? ------------ -Bolts is a collection of useful models and templates to bootstrap your DL research even faster. -It's designed to work with PyTorch Lightning - -Subclass Example ----------------- -Use `pl_bolts` models to remove boilerplate for common approaches and architectures. -Because it uses LightningModules under the hood, you just need to overwrite -the relevant parts to your research. - -How to add a model ------------------- -This repository is meant for model contributions from the community. -To add a model, you can start with the MNIST template (or any other model in the repo). -Please organize the functions of your lightning module. -""" +from pl_bolts.info import ( # noqa: F401 + __author__, + __author_email__, + __copyright__, + __docs__, + __homepage__, + __license__, + __version__, +) _PACKAGE_ROOT = os.path.dirname(__file__) _PROJECT_ROOT = os.path.dirname(_PACKAGE_ROOT) _HTTPS_AWS_HUB = "https://pl-bolts-weights.s3.us-east-2.amazonaws.com" -try: - # This variable is injected in the __builtins__ by the build process. - # It used to enable importing subpackages when the binaries are not built. - _ = None if __LIGHTNING_BOLT_SETUP__ else None -except NameError: - __LIGHTNING_BOLT_SETUP__: bool = False - -if __LIGHTNING_BOLT_SETUP__: # pragma: no cover - import sys - - sys.stdout.write(f'Partial import of `{__name__}` during the build process.\n') - # We are not importing the rest of the lightning during the build process, as it may not be compiled yet -else: - from pl_bolts import callbacks, datamodules, datasets, losses, metrics, models, optimizers, transforms, utils - - __all__ = [ - 'callbacks', - 'datamodules', - 'datasets', - 'losses', - 'metrics', - 'models', - 'optimizers', - 'transforms', - 'utils', - ] +from pl_bolts import ( # noqa: E402 + callbacks, + datamodules, + datasets, + losses, + metrics, + models, + optimizers, + transforms, + utils, +) + +__all__ = [ + 'callbacks', + 'datamodules', + 'datasets', + 'losses', + 'metrics', + 'models', + 'optimizers', + 'transforms', + 'utils', +] diff --git a/pl_bolts/info.py b/pl_bolts/info.py new file mode 100644 index 0000000000..aa8bfe58ac --- /dev/null +++ b/pl_bolts/info.py @@ -0,0 +1,25 @@ +__version__ = '0.3.2rc1' +__author__ = 'PyTorchLightning et al.' +__author_email__ = 'name@pytorchlightning.ai' +__license__ = 'Apache-2.0' +__copyright__ = f'Copyright (c) 2020-2021, {__author__}' +__homepage__ = 'https://github.com/PyTorchLightning/lightning-bolts' +__docs__ = "PyTorch Lightning Bolts is a community contribution for ML researchers." +__long_doc__ = """ +What is it? +----------- +Bolts is a collection of useful models and templates to bootstrap your DL research even faster. +It's designed to work with PyTorch Lightning + +Subclass Example +---------------- +Use `pl_bolts` models to remove boilerplate for common approaches and architectures. +Because it uses LightningModules under the hood, you just need to overwrite +the relevant parts to your research. + +How to add a model +------------------ +This repository is meant for model contributions from the community. +To add a model, you can start with the MNIST template (or any other model in the repo). +Please organize the functions of your lightning module. +""" diff --git a/pl_bolts/setup_tools.py b/pl_bolts/setup_tools.py index 797bccef9e..dea69e93f2 100644 --- a/pl_bolts/setup_tools.py +++ b/pl_bolts/setup_tools.py @@ -16,19 +16,7 @@ import re from typing import List -from pl_bolts import __homepage__, __version__, _PROJECT_ROOT - -_PATH_BADGES = os.path.join('.', 'docs', 'source', '_images', 'badges') -# badge to download -_DEFAULT_BADGES = ( - 'Conda', - 'DockerHub', - 'codecov', - 'ReadTheDocs', - 'Slack', - 'Discourse status', - 'license', -) +_PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__)) def _load_requirements(path_dir: str, file_name: str = 'requirements.txt', comment_char: str = '#') -> List[str]: @@ -52,10 +40,10 @@ def _load_requirements(path_dir: str, file_name: str = 'requirements.txt', comme return reqs -def _load_readme_description(path_dir: str, homepage: str = __homepage__, ver: str = __version__) -> str: +def _load_readme_description(path_dir: str, homepage: str, ver: str) -> str: """Load readme as decribtion - >>> _load_readme_description(_PROJECT_ROOT) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE + >>> _load_readme_description(_PROJECT_ROOT, "", "") # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE '
...' """ path_readme = os.path.join(path_dir, "README.md") diff --git a/requirements/test.txt b/requirements/test.txt index 4fe79f1831..84aa2bcfd7 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -2,9 +2,8 @@ codecov>=2.1 pytest>=6.0 pytest-cov>2.10 -pytest-flake8 -flake8>=3.6 -# flake8-black +# pytest-flake8 +flake8 check-manifest twine>=3.2 isort>=5.6.4 diff --git a/setup.py b/setup.py index 44a9e06380..55d427666f 100755 --- a/setup.py +++ b/setup.py @@ -1,36 +1,40 @@ #!/usr/bin/env python import os +import sys # Always prefer setuptools over distutils from setuptools import find_packages, setup +_PATH_ROOT = os.path.realpath(os.path.dirname(__file__)) +_PATH_REQUIRE = os.path.join(_PATH_ROOT, 'requirements') + try: - import builtins + from pl_bolts import info, setup_tools except ImportError: - import __builtin__ as builtins - -# https://packaging.python.org/guides/single-sourcing-package-version/ -# http://blog.ionelmc.ro/2014/05/25/python-packaging/ - -_PATH_ROOT = os.path.dirname(__file__) -builtins.__LIGHTNING_BOLT_SETUP__: bool = True - -import pl_bolts # noqa: E402 -from pl_bolts.setup_tools import _load_readme_description, _load_requirements # noqa: E402 + # alternative https://stackoverflow.com/a/67692/4521646 + sys.path.append("pl_bolts") + import info + import setup_tools def _prepare_extras(): extras = { - 'loggers': _load_requirements(path_dir=os.path.join(_PATH_ROOT, 'requirements'), file_name='loggers.txt'), - 'models': _load_requirements(path_dir=os.path.join(_PATH_ROOT, 'requirements'), file_name='models.txt'), - 'test': _load_requirements(path_dir=os.path.join(_PATH_ROOT, 'requirements'), file_name='test.txt'), + 'loggers': setup_tools._load_requirements(path_dir=_PATH_REQUIRE, file_name='loggers.txt'), + 'models': setup_tools._load_requirements(path_dir=_PATH_REQUIRE, file_name='models.txt'), + 'test': setup_tools._load_requirements(path_dir=_PATH_REQUIRE, file_name='test.txt'), } extras['extra'] = extras['models'] + extras['loggers'] extras['dev'] = extras['extra'] + extras['test'] return extras +long_description = setup_tools._load_readme_description( + _PATH_ROOT, + homepage=info.__homepage__, + ver=info.__version__, +) + # https://packaging.python.org/discussions/install-requires-vs-requirements / # keep the meta-data here for simplicity in reading this file... it's not obvious # what happens and to non-engineers they won't know to look in init ... @@ -38,22 +42,22 @@ def _prepare_extras(): # engineer specific practices setup( name='lightning-bolts', - version=pl_bolts.__version__, - description=pl_bolts.__docs__, - author=pl_bolts.__author__, - author_email=pl_bolts.__author_email__, - url=pl_bolts.__homepage__, + version=info.__version__, + description=info.__docs__, + author=info.__author__, + author_email=info.__author_email__, + url=info.__homepage__, download_url='https://github.com/PyTorchLightning/lightning-bolts', - license=pl_bolts.__license__, + license=info.__license__, packages=find_packages(exclude=['tests', 'docs']), - long_description=_load_readme_description(_PATH_ROOT), + long_description=long_description, long_description_content_type='text/markdown', include_package_data=True, zip_safe=False, keywords=['deep learning', 'pytorch', 'AI'], python_requires='>=3.6', setup_requires=['wheel'], - install_requires=_load_requirements(_PATH_ROOT), + install_requires=setup_tools._load_requirements(_PATH_ROOT), extras_require=_prepare_extras(), project_urls={ "Bug Tracker": "https://github.com/PyTorchLightning/lightning-bolts/issues",