From a0d4442177daf73a929a7c24849ce8ff211ba778 Mon Sep 17 00:00:00 2001 From: Phil Starkey Date: Mon, 2 Nov 2020 16:33:49 +1100 Subject: [PATCH] Squashed commit of the following: commit 45819532ae487814fffb493a713a877caf661ee6 Merge: d6335b2 eaa13a0 Author: Phil Starkey Date: Mon Nov 2 16:27:23 2020 +1100 Merge pull request #72 from philipstarkey/feature/versions-module-docs Added API docs for versions submodule added in #65 commit eaa13a025df534ddc64e1bc963f6db07c1f52694 Author: Phil Starkey Date: Mon Nov 2 16:24:02 2020 +1100 Second attempt at fixing the missing site package functions. This time we explicitly mock the missing functions using a lambda that returns an empty version of whatever types the methods usually return (hard coded into conf.py) commit d6335b2f0f4b65b11808843ba9e20d8e2831917c Merge: f1c0962 720003b Author: Phil Starkey Date: Mon Nov 2 15:58:56 2020 +1100 Merge pull request #73 from philipstarkey/bugfix/setuptools_scm Removes setuptools_scm configuration from pyproject.toml commit 720003b362e3451a0c711540b412c9b8e4163b31 Author: Phil Starkey Date: Mon Nov 2 15:57:33 2020 +1100 Removes setuptools_scm configuration from pyproject.toml As such, I see no way to utilise pyproject.toml for these settings, and am reverting to using the configuration specified in setup.py (restored in #71) commit f1c09621242195e0115069fe4e79d6fb08d35d59 Merge: dce6ac8 fa2654c Author: Phil Starkey Date: Mon Nov 2 13:06:10 2020 +1100 Merge pull request #71 from philipstarkey/bugfix/setuptools_scm Bugfixes for the mistakes in #70 commit 83c6ded5e7c6911aaf096ef3121966e013ca9a39 Author: Phil Starkey Date: Mon Nov 2 13:04:42 2020 +1100 Attempt to fix the site module issue on readthedocs. commit 2c433e210273db548c19f54fde1c9b8b32a6dcce Author: Phil Starkey Date: Mon Nov 2 12:51:48 2020 +1100 Added API docs for versions submodule added in #65 Formatted docstrings to match sphinx Doogle style and added rst file to docs to display them. commit fa2654c5da22f0691657bc571cd877cb9d80fb98 Author: Phil Starkey Date: Mon Nov 2 11:09:10 2020 +1100 Bugfixes for the mistakes in #70 labscript-suite/labscript-suite#53 erroenously removed the env var that removed the local version (required for uploading to test PyPI). Contrary to my statements in #62, the packaging library does not seem to be a dependency of setuptools. Instead they have vendored it as an internal submodule. Rather than rely on that, packaging is now a dependency of labscript-utils directly. --- .github/workflows/release.yml | 1 + docs/source/api/index.rst | 1 + docs/source/api/versions.rst | 8 +++ docs/source/conf.py | 18 +++++ labscript_utils/modulewatcher.py | 8 +++ labscript_utils/versions.py | 111 +++++++++++++++++++++++++------ pyproject.toml | 4 -- setup.cfg | 1 + setup.py | 7 +- 9 files changed, 133 insertions(+), 26 deletions(-) create mode 100644 docs/source/api/versions.rst diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 351c460..f1c8db5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,7 @@ defaults: env: PACKAGE_NAME: labscript-utils + SCM_LOCAL_SCHEME: no-local-version ANACONDA_USER: labscript-suite # Configuration for a package with compiled extensions: diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst index 024f52a..9e9ff9a 100644 --- a/docs/source/api/index.rst +++ b/docs/source/api/index.rst @@ -60,3 +60,4 @@ Module and File Tools double_import_denier filewatcher modulewatcher + versions diff --git a/docs/source/api/versions.rst b/docs/source/api/versions.rst new file mode 100644 index 0000000..996d686 --- /dev/null +++ b/docs/source/api/versions.rst @@ -0,0 +1,8 @@ +============================ +labscript_utils.versions +============================ + +.. automodule:: labscript_utils.versions + :members: + :undoc-members: + :private-members: \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 675d806..e3df35c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,6 +10,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +import copy import os from pathlib import Path from m2r import MdInclude @@ -50,6 +51,23 @@ autodoc_typehints = 'description' +# mock missing site packages methods +import site +mock_site_methods = { + # Format: + # method name: return value + 'getusersitepackages': '', + 'getsitepackages': [] +} +__fn = None +for __name, __rval in mock_site_methods.items(): + if not hasattr(site, __name): + __fn = lambda *args, __rval=copy.deepcopy(__rval), **kwargs: __rval + setattr(site, __name, __fn) +del __name +del __rval +del __fn + # Prefix each autosectionlabel with the name of the document it is in and a colon autosectionlabel_prefix_document = True diff --git a/labscript_utils/modulewatcher.py b/labscript_utils/modulewatcher.py index 6b0be0e..7e33b6d 100644 --- a/labscript_utils/modulewatcher.py +++ b/labscript_utils/modulewatcher.py @@ -33,6 +33,14 @@ class ModuleWatcher(object): + """A watcher that reloads modules that have been modified on disk + + Only reloads modules imported after instantiation. Does not reload C extensions. + + Args: + debug (bool, optional): When :code:`True`, prints debugging information + when reloading modules. + """ def __init__(self, debug=False): self.debug = debug # A lock to hold whenever you don't want modules unloaded: diff --git a/labscript_utils/versions.py b/labscript_utils/versions.py index 0b84ed5..032bbf7 100644 --- a/labscript_utils/versions.py +++ b/labscript_utils/versions.py @@ -48,7 +48,20 @@ class BrokenInstall(RuntimeError): def get_import_path(import_name): """Get which entry in sys.path a module would be imported from, without importing - it.""" + it. + + Args: + import_name (str): The module name. + + Raises: + ModuleNotFoundError: Raised if the module is not installed. + NotImplementedError: Raised if the module is a "namespace package". + Support for namepsace packages is not currently availabled. + + Returns: + str: The path to the folder containing the module. + + """ spec = importlib.util.find_spec(import_name) if spec is None: raise ModuleNotFoundError(import_name) @@ -66,8 +79,22 @@ def get_import_path(import_name): def _get_metadata_version(project_name, import_path): - """Return the metadata version for a package with the given project name located at - the given import path, or None if there is no such package.""" + """Gets the package metadata version. + + Args: + project_name (str): The package name (e.g. the name used when pip installing + the package). + import_path (str): The path to the folder containing the installed package. + + Raises: + :exc:`BrokenInstall`: Raised if the package installation is corrupted (multiple + packages matching the given arguments were found). May occur if + (un)installation for a particular package version only partially completed. + + Returns: + The metadata version for a package with the given project name located at + the given import path, or None if there is no such package. + """ for finder in sys.meta_path: if hasattr(finder, 'find_distributions'): @@ -84,8 +111,14 @@ def _get_metadata_version(project_name, import_path): def _get_literal_version(filename): - """Tokenize a source file and return any __version__ = literal defined in - it. + """Tokenize a source file and return any :code:`__version__ = ` literal + defined in it. + + Args: + filename (str): The path to the file to tokenize. + + Returns: + Any version literal found matching the above criteria, or None. """ if not os.path.exists(filename): return None @@ -110,17 +143,34 @@ def _get_literal_version(filename): def get_version(import_name, project_name=None, import_path=None): - """Try very hard to get the version of a package without importing it. if - import_path is not given, first find where it would be imported from, without + """Try very hard to get the version of a package without importing it. + + If import_path is not given, first find where it would be imported from, without importing it. Then look for metadata in the same import path with the given project name (note: this is not always the same as the import name, it is the name for example you would ask pip to install). If that is found, return the version info - from it. Otherwise look for a __version__.py file in the package directory, or a - __version__ = literal defined in the package source (without executing - it). + from it. Otherwise look for a :code:`__version__.py` file in the package directory, + or a :code:`__version__ = ` literal defined in the package source (without + executing it). + + Args: + import_name (str): The module name. + project_name (str, optional): The package name (e.g. the name used when pip + installing the package). This must be specified if it does not match the + module name. + import_path (str, optional): The path to the folder containing the installed + package. + + Raises: + NotImplementedError: Raised if the module name contains a period. Only + top-level packages are supported at this time. - Return NotFound if the package cannot be found, and NoVersionInfo if the version - cannot be obtained in the above way, or if it was found but was None.""" + Returns: + The version literal of the package. + If the package cannot be found, :class:`NotFound` is returned. + If the version cannot be obtained in the above way, or if the version was found + but was :code:`None`, :class:`NoVersionInfo` is returned. + """ if project_name is None: project_name = import_name if '.' in import_name: @@ -162,15 +212,34 @@ def get_version(import_name, project_name=None, import_path=None): def check_version(module_name, at_least, less_than, version=None, project_name=None): - """Check that the version of the given module is at least and less than the given - version strings, and raise VersionException if not. Raise VersionException if the - module was not found or its version could not be determined. This function uses - get_version to determine version numbers without importing modules. In order to do - this, project_name must be provided if it differs from module_name. For example, - pyserial is imported as 'serial', but the project name, as passed to a 'pip install' - command, is 'pyserial'. Therefore to check the version of pyserial, pass in - module_name='serial' and project_name='pyserial'. You can also pass in a version - string yourself, in which case no inspection of packages will take place. + """Checks if a module version is within specified bounds. + + Checks that the version of the given module is at least and less than the given + version strings. This function uses :func:`get_version` to determine version + numbers without importing modules. In order to do this, :code:`project_name` must + be provided if it differs from :code:`module_name`. For example, pyserial is + imported as 'serial', but the project name, as passed to a 'pip install' command, + is 'pyserial'. Therefore to check the version of pyserial, pass in + :code:`module_name='serial'` and :code:`project_name='pyserial'`. + You can also pass in a version string yourself, in which case no inspection of + packages will take place. + + Args: + module_name (str): The name of the module to check. + at_least (str): The minimum acceptable module version. + less_than (str): The minimum unacceptable module version. Usually this would be + the next major version if the package follows + `semver `_. + version (str, optional): The current version of the installed package. Useful when the + package version is stored in a non-standard location. + project_name (str, optional): The package name (e.g. the name used when pip + installing the package). This must be specified if it does not match the + module name. + + Raises: + :exc:`VersionException`: if the module was not found or its version could not + be determined. + """ if version is None: version = get_version(module_name, project_name) diff --git a/pyproject.toml b/pyproject.toml index 3a1c62a..c72bd8d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,3 @@ [build-system] requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=4.1.0"] build-backend = "setuptools.build_meta" - -[tool.setuptools_scm] -version_scheme = "release-branch-semver" -local_scheme = "node-and-date" diff --git a/setup.cfg b/setup.cfg index 7c93c95..f77ca06 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,6 +28,7 @@ install_requires = importlib_metadata>=1.0 h5py>=2.9 numpy>=1.15 + packaging>=20.4 pyqtgraph>=0.11.0rc0 qtutils>=2.2.3 scipy diff --git a/setup.py b/setup.py index 88857b7..a12d0a0 100644 --- a/setup.py +++ b/setup.py @@ -16,4 +16,9 @@ def run(self): self.copy_file('labscript-suite.pth', path) -setup(cmdclass={'develop': develop_command}) +VERSION_SCHEME = { + "version_scheme": os.getenv("SCM_VERSION_SCHEME", "release-branch-semver"), + "local_scheme": os.getenv("SCM_LOCAL_SCHEME", "node-and-date"), +} + +setup(use_scm_version=VERSION_SCHEME, cmdclass={'develop': develop_command}) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy