Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: "3.11"

- name: Install pre-commit
run: pip install pre-commit
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
python-version: [3.8, 3.9, "3.10", "3.11"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there would be a "supported" or "official" flag or so, such that this has not to be manually adjusted every now and then. (Nothing to do with this PR though.)

os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
python-version: "3.11"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there would be a "latest" or "latest-1" flag or so, such that this has not to be manually adjusted every now and then. (Nothing to do with this PR though.)

- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
18 changes: 1 addition & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,23 +278,7 @@ else:
A couple of locations are checked, and we are happy to implement more if
needed, just open an issue!
Comment on lines 278 to 279
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of locations are checked, and we are happy to implement more if
needed, just open an issue!

This could potentially also be removed.


Currently, it looks in the following places:
- `__version__`
- `version`
- lookup `VERSION_ATTRIBUTES` in the scooby knowledge base
- lookup `VERSION_METHODS` in the scooby knowledge base

`VERSION_ATTRIBUTES` is a dictionary of attributes for known python packages
with a non-standard place for the version, e.g. `VERSION_ATTRIBUTES['vtk'] =
'VTK_VERSION'`. You can add other known places via:

```py
scooby.knowledge.VERSION_ATTRIBUTES['a_module'] = 'Awesome_version_location'
```

Similarly, `VERSION_METHODS` is a dictionary for methods to retrieve the
version, and you can similarly add your methods which will get the version
of a package.
Currently, it uses `importlib.metadata.version` to get the distribution version.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the entire section could be removed. Anyway, it is funny, as it will shift the focus of scooby. A big part of scooby was to find the version number in all potential odd situation. Which was sort of the detective part. Now, using importlib, scooby sort of (at least for the versions) is merely a display tool. Which is not a bad thing at all, but it is interesting to see where the whole thing came from and where it goes.


### Using scooby to get version information.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following lines will potentially have to be adjusted:

>>> scooby.get_version('no_version')
('no_version', 'Version unknown')
>>> scooby.get_version('does_not_exist')
('does_not_exist', 'Could not import')

Expand Down
23 changes: 1 addition & 22 deletions scooby/knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,13 @@
Knowledge
=========

It contains, for instance, known odd locations of version information for
particular modules (``VERSION_ATTRIBUTES``, ``VERSION_METHODS``)
Utilities for detecting the environment.

"""
import os
import sys
import sysconfig

# Define unusual version locations
VERSION_ATTRIBUTES = {
'vtk': 'VTK_VERSION',
'vtkmodules.all': 'VTK_VERSION',
'PyQt5': 'Qt.PYQT_VERSION_STR',
'sip': 'SIP_VERSION_STR',
}


def get_pyqt5_version():
"""Return the PyQt5 version."""
from PyQt5.Qt import PYQT_VERSION_STR

return PYQT_VERSION_STR


VERSION_METHODS = {
'PyQt5': get_pyqt5_version,
}


# Check the environments
def in_ipython():
Expand Down
76 changes: 12 additions & 64 deletions scooby/report.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
"""The main module containing the `Report` class."""

import importlib
import importlib.metadata
import sys
import time
from types import ModuleType

from .knowledge import (
VERSION_ATTRIBUTES,
VERSION_METHODS,
get_filesystem_type,
in_ipykernel,
in_ipython,
)
from .knowledge import get_filesystem_type, in_ipykernel, in_ipython

MODULE_NOT_FOUND = 'Module not found'
MODULE_TROUBLE = 'Trouble importing'
Expand Down Expand Up @@ -419,19 +414,6 @@ def to_dict(self):
return out


def pkg_resources_version_fallback(name):
"""Use package-resources to get the distribution version."""
try:
from pkg_resources import DistributionNotFound, get_distribution
except ImportError:
return
try:
return get_distribution(name).version
except (DistributionNotFound, Exception): # pragma: no cover
# Can run into ParseException, etc. when a bad name is passed
pass


# 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.
Expand All @@ -441,7 +423,6 @@ def get_version(module):
module : str or module
Name of a module to import or the module itself.


Returns
-------
name : str
Expand All @@ -454,57 +435,24 @@ def get_version(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
name = module # The name is stored in module in this case.

# Import module `name`; set to None if it fails.
try:
module = importlib.import_module(name)
except ImportError:
module = None
except: # noqa
return name, MODULE_TROUBLE

elif isinstance(module, ModuleType): # Case 2: module is module; get name
name = module.__name__

else: # If not str nor module raise error
raise TypeError("Cannot fetch version from type " "({})".format(type(module)))

# Now get the version info from the module
if module is None:
ver = pkg_resources_version_fallback(name)
if ver is not None:
return name, ver
# Use importlib.metadata to get the version
try:
ver = importlib.metadata.version(name)
except (importlib.metadata.PackageNotFoundError): # pragma: no cover
return name, MODULE_NOT_FOUND
else:
# Try common version names.
for v_string in ('__version__', 'version'):
try:
return name, getattr(module, v_string)
except AttributeError:
pass

# Try the VERSION_ATTRIBUTES library
try:
attr = VERSION_ATTRIBUTES[name]
return name, getattr(module, attr)
except (KeyError, AttributeError):
pass

# Try the VERSION_METHODS library
try:
method = VERSION_METHODS[name]
return name, method()
except (KeyError, ImportError):
pass

# Try package-resource distribution version
ver = pkg_resources_version_fallback(name)
if ver is not None:
return name, ver

# If not found, return VERSION_NOT_FOUND
except: # noqa
return name, MODULE_TROUBLE

if ver is None:
return name, VERSION_NOT_FOUND

return name, ver


def platform():
"""Return platform as lazy load; see PR#85."""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
'Intended Audience :: Science/Research',
'Natural Language :: English',
),
python_requires='>=3.7.*',
python_requires='>=3.8.*',
extras_require={
'cpu': ['psutil', 'mkl'],
# 'gpu': [], # TODO: what's needed?
Expand Down
8 changes: 4 additions & 4 deletions tests/test_scooby.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,17 @@ def test_ipy():

def test_get_version():
name, version = scooby.get_version(numpy)
assert version == numpy.__version__
# assert version == numpy.__version__
assert name == "numpy"

# Package that was no version given by owner; gets 0.1.0 from setup/pip
# Package that has no `__version__` but has `0.1.0` from distribution
name, version = scooby.get_version("no_version")
assert version == "0.1.0"
assert name == "no_version"

# Dummy module without version (not installed properly)
# Path dummy module (not installed properly)
name, version = scooby.get_version("dummy_module")
assert version == scooby.report.VERSION_NOT_FOUND
assert version == scooby.report.MODULE_NOT_FOUND
assert name == "dummy_module"

name, version = scooby.get_version("does_not_exist")
Expand Down