-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Lazy load legacy imports in skimage
top module
#6892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
897ef27
1987eee
e9bf44f
1c944a6
b4068da
40157d0
e7e4152
8a90270
ccdbb01
0091bcc
7452969
65080cb
85c15d7
f69ba1c
f4e3218
64b5194
6d7a770
3153f89
0a275cd
f0fbfcc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,11 @@ | ||
"""Image Processing for Python | ||
|
||
``scikit-image`` (a.k.a. ``skimage``) is a collection of algorithms for image | ||
scikit-image (a.k.a. ``skimage``) is a collection of algorithms for image | ||
processing and computer vision. | ||
|
||
The main package of ``skimage`` only provides a few utilities for converting | ||
between image data types; for most features, you need to import one of the | ||
following subpackages: | ||
|
||
Subpackages | ||
----------- | ||
color | ||
Color space conversion. | ||
data | ||
Test images and example data. | ||
draw | ||
Drawing primitives (lines, text, etc.) that operate on NumPy arrays. | ||
exposure | ||
Image intensity adjustment, e.g., histogram equalization, etc. | ||
feature | ||
Feature detection and extraction, e.g., texture analysis corners, etc. | ||
filters | ||
Sharpening, edge finding, rank filters, thresholding, etc. | ||
graph | ||
Graph-theoretic operations, e.g., shortest paths. | ||
io | ||
Reading, saving, and displaying images and video. | ||
measure | ||
Measurement of image properties, e.g., region properties and contours. | ||
metrics | ||
Metrics corresponding to images, e.g. distance metrics, similarity, etc. | ||
morphology | ||
Morphological operations, e.g., opening or skeletonization. | ||
restoration | ||
Restoration algorithms, e.g., deconvolution algorithms, denoising, etc. | ||
segmentation | ||
Partitioning an image into multiple regions. | ||
transform | ||
Geometric and other transforms, e.g., rotation or the Radon transform. | ||
util | ||
Generic utilities. | ||
|
||
Utility Functions | ||
----------------- | ||
img_as_float | ||
Convert an image to floating point format, with values in [0, 1]. | ||
Is similar to `img_as_float64`, but will not convert lower-precision | ||
floating point arrays to `float64`. | ||
img_as_float32 | ||
Convert an image to single-precision (32-bit) floating point format, | ||
with values in [0, 1]. | ||
img_as_float64 | ||
Convert an image to double-precision (64-bit) floating point format, | ||
with values in [0, 1]. | ||
img_as_uint | ||
Convert an image to unsigned integer format, with values in [0, 65535]. | ||
img_as_int | ||
Convert an image to signed integer format, with values in [-32768, 32767]. | ||
img_as_ubyte | ||
Convert an image to unsigned byte format, with values in [0, 255]. | ||
img_as_bool | ||
Convert an image to boolean format, with values either True or False. | ||
dtype_limits | ||
Return intensity limits, i.e. (min, max) tuple, of the image's dtype. | ||
|
||
between image data types; for most features, you need to import one of its | ||
subpackages. | ||
lagru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
|
||
__version__ = '0.25.0rc2.dev0' | ||
|
@@ -73,7 +16,33 @@ | |
|
||
|
||
def __dir__(): | ||
return __lazy_dir__() + ['__version__'] | ||
"""Add lazy-loaded attributes to keep consistent with `__getattr__`.""" | ||
patched_dir = {*globals().keys(), *__lazy_dir__()} | ||
return sorted(patched_dir) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is fixed by this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lazy loading expands the module attributes that are available via Spelling this out, I realize that this is also a problem with our subpackages that just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why would we want to expose things like
You can use various hacks to get hold of other attributes, but these are the ones we want our users to see. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you really need to expose more (and I don't think we should), then you could:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For the reasons stated above. Hiding builtin attributes feels very magical and unexpected to me, and like something that might lead confusing bugs. I'd like tab-completion in ipython to show me everything that's available and not a curated list. Everyone is aware that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is a common problem I run into 🙃 Since you'd like to see a change in behavior, I think you should make a convincing case for (a) why this is useful (and not confusing) to the user and (b) that it does not introduce unnecessary complexity (we could improve the code to make that the case, so I'm not too worried about this part). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe more importantly, we are way overdue on the release, so a friendly request that we merge this PR without the change to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added it as a talking point to today's meeting notes. Anyway, I'm happy to iterate on this particular issue in another PR. And I'm not seeing this issue as a blocker for the release in the first place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reverted to status quo in 0a275cd with regards to hiding stuff in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Python's docs seem to be compatible with your stance @stefanv:
|
||
|
||
|
||
# `attach_stub` currently ignores __all__ inside the stub file and simply | ||
# returns every lazy-imported object, so we need to define `__all__` again. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See scientific-python/lazy-loader#133 for a proposal to address this duplication. |
||
__all__ = [ | ||
'color', | ||
'data', | ||
'draw', | ||
'exposure', | ||
'feature', | ||
'filters', | ||
'future', | ||
'graph', | ||
'io', | ||
'measure', | ||
'metrics', | ||
'morphology', | ||
'registration', | ||
'restoration', | ||
'segmentation', | ||
'transform', | ||
'util', | ||
'__version__', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see where Not sure, but I don't think we need to advertise I just put There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I wasn't referring to anything 'previously included' or not and, in the context of this PR, I should have! I was thinking 'in the absolute,' i.e., when I import skimage as ski and I run
which objects do I expect to be available? |
||
] | ||
|
||
|
||
# Logic for checking for improper install and importing while in the source | ||
|
@@ -117,68 +86,42 @@ def _raise_build_error(e): | |
import sys | ||
lagru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
sys.stderr.write('Partial import of skimage during the build process.\n') | ||
# We are not importing the rest of the scikit during the build | ||
# We are not importing the rest of the package during the build | ||
# process, as it may not be compiled yet | ||
else: | ||
try: | ||
from ._shared import geometry | ||
|
||
del geometry | ||
except ImportError as e: | ||
_raise_build_error(e) | ||
|
||
# Legacy imports into the root namespace; not advertised in __all__ | ||
from .util.dtype import ( | ||
dtype_limits, | ||
img_as_float32, | ||
img_as_float64, | ||
img_as_float, | ||
img_as_int, | ||
img_as_uint, | ||
img_as_ubyte, | ||
img_as_bool, | ||
) | ||
|
||
from .util.lookfor import lookfor | ||
|
||
from .data import data_dir | ||
|
||
|
||
if 'dev' in __version__: | ||
# Append last commit date and hash to dev version information, if available | ||
|
||
def _try_append_commit_info(version): | ||
"""Append last commit date and hash to `version`, if available.""" | ||
import subprocess | ||
import os.path | ||
from pathlib import Path | ||
|
||
try: | ||
p = subprocess.Popen( | ||
output = subprocess.check_output( | ||
['git', 'log', '-1', '--format="%h %aI"'], | ||
stdout=subprocess.PIPE, | ||
stderr=subprocess.PIPE, | ||
cwd=os.path.dirname(__file__), | ||
cwd=Path(__file__).parent, | ||
text=True, | ||
) | ||
except FileNotFoundError: | ||
if output: | ||
git_hash, git_date = ( | ||
output.strip().replace('"', '').split('T')[0].replace('-', '').split() | ||
) | ||
version = '+'.join( | ||
[tag for tag in version.split('+') if not tag.startswith('git')] | ||
) | ||
version += f'+git{git_date}.{git_hash}' | ||
|
||
except (FileNotFoundError, subprocess.CalledProcessError): | ||
pass | ||
except OSError: | ||
pass # If skimage is built with emscripten which does not support processes | ||
else: | ||
out, err = p.communicate() | ||
if p.returncode == 0: | ||
git_hash, git_date = ( | ||
out.decode('utf-8') | ||
.strip() | ||
.replace('"', '') | ||
.split('T')[0] | ||
.replace('-', '') | ||
.split() | ||
) | ||
|
||
__version__ = '+'.join( | ||
[tag for tag in __version__.split('+') if not tag.startswith('git')] | ||
) | ||
__version__ += f'+git{git_date}.{git_hash}' | ||
return version | ||
|
||
|
||
if 'dev' in __version__: | ||
__version__ = _try_append_commit_info(__version__) | ||
|
||
|
||
from skimage._shared.tester import PytestTester | ||
from skimage._shared.tester import PytestTester as _PytestTester | ||
|
||
test = PytestTester(__name__) | ||
del PytestTester | ||
test = _PytestTester(__name__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Color space conversion.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Drawing primitives that operate on NumPy arrays, e.g., lines, text, etc.""" | ||
lagru marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Image intensity adjustment, e.g., histogram equalization, etc.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Feature detection and extraction, e.g., texture analysis, corners, etc.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Sharpening, edge finding, rank filters, thresholding, etc.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Measurement of image properties, e.g., region properties, contours.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
"""Metrics corresponding to images, e.g., distance metrics, similarity, etc.""" | ||
|
||
import lazy_loader as _lazy | ||
|
||
__getattr__, __dir__, __all__ = _lazy.attach_stub(__name__, __file__) |
Uh oh!
There was an error while loading. Please reload this page.