diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..db4c405 --- /dev/null +++ b/.flake8 @@ -0,0 +1,21 @@ +[flake8] +exclude = .git,__pycache__,build,dist +ignore = + # whitespace before ':' + E203, + # line break before binary operator + W503, + # line length too long + E501, + # do not assign a lambda expression, use a def + E731, + # too many leading '#' for block comment + E266, + # ambiguous variable name + E741, + # module level import not at top of file + E402, + # Quotes (temporary) + Q0, + # bare excepts (temporary) + B001, E722 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 798688a..83f9ce5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,22 +1,20 @@ name: Linting on: pull_request: - push: jobs: - style: + stylecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: "3.9" - - name: Install Style dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements_style.txt - - name: Run codespell - run: make codespell - - name: Run linting - run: make lint + python-version: 3.9 + + - name: Install pre-commit + run: pip install pre-commit + + - name: Run pre-commit + run: pre-commit run --all-files diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 93cc4ca..a25f64a 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -5,7 +5,6 @@ name: Tests on: push: - branches: "*" tags: "v*" pull_request: branches: "**" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a9dbedb --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,44 @@ +repos: +- repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + +- repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + +- repo: https://gitlab.com/PyCQA/flake8 + rev: 3.9.2 + hooks: + - id: flake8 + additional_dependencies: [ + "flake8-black==0.3.2", + "flake8-isort==4.1.1", + "flake8-quotes==3.3.1", + ] + +- repo: https://github.com/codespell-project/codespell + rev: v2.1.0 + hooks: + - id: codespell + args: [ + "doc examples examples_flask pyvista tests", + "*.py *.rst *.md", + ] + +- repo: https://github.com/pycqa/pydocstyle + rev: 6.1.1 + hooks: + - id: pydocstyle + additional_dependencies: [toml==0.10.2] + files: ^scooby/ + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-merge-conflict + - id: debug-statements + - id: no-commit-to-branch + args: [--branch, main] diff --git a/scooby/__init__.py b/scooby/__init__.py index 10516ad..a0e1c37 100644 --- a/scooby/__init__.py +++ b/scooby/__init__.py @@ -1,5 +1,5 @@ -# coding=utf-8 -""" +"""Scooby. + Great Dane turned Python environment detective ============================================== diff --git a/scooby/knowledge.py b/scooby/knowledge.py index 0f193c7..8f16347 100644 --- a/scooby/knowledge.py +++ b/scooby/knowledge.py @@ -1,9 +1,9 @@ """ +The knowledge base. + Knowledge ========= -The knowledge base. - It contains, for instance, known odd locations of version information for particular modules (``VERSION_ATTRIBUTES``, ``VERSION_METHODS``) @@ -59,7 +59,7 @@ def get_pyqt5_version(): - """Returns the PyQt5 version""" + """Return the PyQt5 version.""" from PyQt5.Qt import PYQT_VERSION_STR return PYQT_VERSION_STR @@ -72,11 +72,12 @@ def get_pyqt5_version(): # Check the environments def in_ipython(): - """Mystery: are we in an IPython environment? + """Check if we are in a IPython environment. Returns ------- - bool : True if in an IPython environment + bool : True + ``True`` when in an IPython environment. """ try: __IPYTHON__ @@ -86,7 +87,7 @@ def in_ipython(): def in_ipykernel(): - """Mystery: are we in a ipykernel (most likely Jupyter) environment? + """Check if in a ipykernel (most likely Jupyter) environment. Warning ------- @@ -110,7 +111,7 @@ def in_ipykernel(): def get_standard_lib_modules(): - """Returns a set of the names of all modules in the standard library""" + """Return a set of the names of all modules in the standard library.""" if getattr(sys, 'frozen', False): # within pyinstaller lib_path = os.path.join(sysconfig.get_python_lib(standard_lib=True), '..') if os.path.isdir(lib_path): diff --git a/scooby/report.py b/scooby/report.py index 409fce1..287760c 100644 --- a/scooby/report.py +++ b/scooby/report.py @@ -1,10 +1,4 @@ -""" -Report -====== - -The main routine containing the `Report` class. - -""" +"""The main module containing the `Report` class.""" import importlib import multiprocessing @@ -35,7 +29,8 @@ class PlatformInfo: @property def system(self): - """Returns the system/OS name. + """Return the system/OS name. + E.g. ``'Linux'``, ``'Windows'``, or ``'Java'``. An empty string is returned if the value cannot be determined. """ @@ -43,18 +38,20 @@ def system(self): @property def platform(self): + """Return the platform.""" return platform.platform() @property def machine(self): - """Returns the machine type, e.g. 'i386' + """Return the machine type, e.g. 'i386'. + An empty string is returned if the value cannot be determined. """ return platform.machine() @property def architecture(self): - """bit architecture used for the executable""" + """Return the bit architecture used for the executable.""" return platform.architecture()[0] @property @@ -74,11 +71,12 @@ def total_ram(self): @property def date(self): + """Return the date formatted as a string.""" return time.strftime('%a %b %d %H:%M:%S %Y %Z') @property def filesystem(self): - """Get the type of the file system at the path of the scooby package""" + """Get the type of the file system at the path of the scooby package.""" if not hasattr(self, '_filesystem'): self._filesystem = get_filesystem_type() return self._filesystem @@ -88,6 +86,7 @@ class PythonInfo: """Internal helper class to access Python info and package versions.""" def __init__(self, additional, core, optional, sort): + """Initialize python info.""" self._packages = {} # Holds name of packages and their version self._sort = sort @@ -98,7 +97,6 @@ def __init__(self, additional, core, optional, sort): def _add_packages(self, packages, optional=False): """Add all packages to list; optional ones only if available.""" - # Ensure arguments are a list if isinstance(packages, (str, ModuleType)): pckgs = [ @@ -117,10 +115,12 @@ def _add_packages(self, packages, optional=False): @property def sys_version(self): + """Return the system version.""" return sys.version @property def python_environment(self): + """Return the python environment.""" if in_ipykernel(): return 'Jupyter' elif in_ipython(): @@ -129,8 +129,10 @@ def python_environment(self): @property def packages(self): - """Return versions of all packages - (available and unavailable/unknown) + """Return versions of all packages. + + Includes available and unavailable/unknown. + """ pckg_dict = dict(self._packages) if self._sort: @@ -186,7 +188,7 @@ def __init__( sort=False, extra_meta=None, ): - + """Initialize report.""" # Set default optional packages to investigate if optional is None: optional = ['numpy', 'scipy', 'IPython', 'matplotlib', 'scooby'] @@ -208,8 +210,7 @@ def __init__( self._extra_meta = extra_meta def __repr__(self): - """Plain-text version information.""" - + """Return Plain-text version information.""" # Width for text-version text = '\n' + self.text_width * '-' + '\n' @@ -255,8 +256,7 @@ def __repr__(self): return text def _repr_html_(self): - """HTML-rendered version information.""" - + """Return HTML-rendered version information.""" # Define html-styles border = "border: 2px solid #fff;'" @@ -275,7 +275,6 @@ def colspan(html, txt, ncol, nrow): def cols(html, version, name, ncol, i): r"""Print package information in two cells.""" - # Check if we have to start a new row if i > 0 and i % ncol == 0: html += " \n" @@ -334,7 +333,6 @@ def cols(html, version, name, ncol, i): def to_dict(self): """Return report as dict for storage.""" - out = {} # Date and time info @@ -369,8 +367,7 @@ def to_dict(self): # This functionaliy might also be of interest on its own. def get_version(module): - """Get the version of `module` by passing the package or it's name. - + """Get the version of ``module`` by passing the package or it's name. Parameters ---------- @@ -386,7 +383,6 @@ def get_version(module): version : str or None Version of module. """ - # module is (1) a string or (2) a module. # If (1), we have to load it, if (2), we have to get its name. if isinstance(module, str): # Case 1: module is a string; import diff --git a/scooby/tracker.py b/scooby/tracker.py index 4431e43..1dead96 100644 --- a/scooby/tracker.py +++ b/scooby/tracker.py @@ -1,3 +1,4 @@ +"""Track imports.""" from scooby.knowledge import get_standard_lib_modules from scooby.report import Report @@ -41,7 +42,7 @@ def _criterion(name): if TRACKING_SUPPORTED: def scooby_import(name, globals=None, locals=None, fromlist=(), level=0): - """A custom override of the import method to track package names""" + """Override of the import method to track package names.""" m = CLASSIC_IMPORT(name, globals=globals, locals=locals, fromlist=fromlist, level=level) name = name.split(".")[0] if level == 0 and _criterion(name): @@ -58,8 +59,10 @@ def track_imports(): def untrack_imports(): - """Stop tracking imports and return to the builtin import method. This will - also clear the tracked imports""" + """Stop tracking imports and return to the builtin import method. + + This will also clear the tracked imports. + """ if not TRACKING_SUPPORTED: raise RuntimeError(SUPPORT_MESSAGE) builtins.__import__ = CLASSIC_IMPORT @@ -69,11 +72,14 @@ def untrack_imports(): class TrackedReport(Report): - """A class to inspect the active environment and generate a report based - on all imported modules. Simply pass the ``globals()`` dictionary. + """A class to inspect the active environment and generate a report. + + Generates a report based on all imported modules. Simply pass the + ``globals()`` dictionary. """ def __init__(self, additional=None, ncol=3, text_width=80, sort=False): + """Initialize.""" if not TRACKING_SUPPORTED: raise RuntimeError(SUPPORT_MESSAGE) if len(TRACKED_IMPORTS) < 2: