Merge branch 'master' into devel
This commit is contained in:
commit
555f84275f
8 changed files with 152 additions and 118 deletions
|
|
@ -1 +1,7 @@
|
|||
May 28, 2013 - Added jp2 boxes to rst docs, XMLBox.indent method made private.
|
||||
|
||||
May 27, 2013 - v0.1.1, Changed write example to not rely on matplotlib. Fixed
|
||||
readthedocs.org setup to build documentation automatically. Can import
|
||||
glymur without libopenjp2 actually being present.
|
||||
|
||||
May 27, 2013 - Changed write example to not rely on matplotlib.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
=========================================
|
||||
glymur: a Python interface for JPEG 2000
|
||||
=========================================
|
||||
|
||||
|
|
@ -6,8 +5,4 @@ glymur: a Python interface for JPEG 2000
|
|||
which allows linux and mac users to read and write JPEG 2000 files.
|
||||
**glymur** works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||
|
||||
Until I figure out how to get readthedocs.org to handle numpydoc, you'll have
|
||||
to do as follows to build the documentation first::
|
||||
|
||||
$ make -C docs html
|
||||
$ open docs/build/html/index.html
|
||||
Please read the docs, https://glymur.readthedocs.org/en/latest/
|
||||
|
|
|
|||
|
|
@ -13,6 +13,29 @@
|
|||
|
||||
import sys, os
|
||||
|
||||
class Mock(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return Mock()
|
||||
|
||||
@classmethod
|
||||
def __getattr__(cls, name):
|
||||
if name in ('__file__', '__path__'):
|
||||
return '/dev/null'
|
||||
elif name[0] == name[0].upper():
|
||||
mockType = type(name, (), {})
|
||||
mockType.__module__ = __name__
|
||||
return mockType
|
||||
else:
|
||||
return Mock()
|
||||
|
||||
MOCK_MODULES = ['numpy']
|
||||
for mod_name in MOCK_MODULES:
|
||||
sys.modules[mod_name] = Mock()
|
||||
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# 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.
|
||||
|
|
@ -52,7 +75,7 @@ copyright = u'2013, John Evans'
|
|||
# The short X.Y version.
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.1.0.a1'
|
||||
release = '0.1.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ glymur: a Python interface for JPEG 2000
|
|||
|
||||
**glymur** contains a Python interface to the OpenJPEG library
|
||||
which allows linux and mac users to read and write JPEG 2000 files. For more
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. **glymur**
|
||||
information about OpenJPEG, please consult http://www.openjpeg.org. glymur
|
||||
should be considered to be alpha-quality software.
|
||||
|
||||
**glymur** tries to support reading (including all metadata) and writing of
|
||||
glymur tries to support reading (including all metadata) and writing of
|
||||
JP2 and J2C files. Writing J2C/JP2 files is currently limited to images that
|
||||
can fit in memory, however.
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ metadata can be retrieved from such JPX files.
|
|||
------------
|
||||
Requirements
|
||||
------------
|
||||
**glymur** works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||
glymur works on Python 2.7 and 3.3. Python 3.3 is strongly recommended.
|
||||
|
||||
OpenJPEG
|
||||
========
|
||||
|
|
@ -26,7 +26,7 @@ OpenJPEG must be built as a shared library. In addition, you
|
|||
currently must compile OpenJPEG from the developmental source that
|
||||
you can retrieve via subversion. As of this time of writing, svn
|
||||
revision 2345 works. In addition, you should also retrieve their test data, as
|
||||
you will need it when running **glymur**'s test suite.
|
||||
you will need it when running glymur's test suite.
|
||||
|
||||
Earlier versions of OpenJPEG through the 2.0 official release are not supported.
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ OS
|
|||
|
||||
Mac OS X
|
||||
--------
|
||||
All the necessary packages are available to use **glymur** with Python 3.3 via
|
||||
All the necessary packages are available to use glymur with Python 3.3 via
|
||||
MacPorts. A minimal set of ports includes
|
||||
|
||||
* python33
|
||||
|
|
@ -83,12 +83,12 @@ combinations of RPMs / Python packages is installed.
|
|||
* scikit-image and either Pillow or freeimage
|
||||
* matplotlib and Pillow
|
||||
|
||||
The 2nd route is probably the easiest, so go ahead and install **Pillow**
|
||||
via **pip** since **Pillow** is not yet available in Fedora 18 default
|
||||
The 2nd route is probably the easiest, so go ahead and install Pillow
|
||||
via pip since Pillow is not yet available in Fedora 18 default
|
||||
repositories::
|
||||
|
||||
$ yum install python3-devel # pip needs this in order to compile Pillow
|
||||
$ yum install python3-pip # First one must install pip of course!
|
||||
$ yum install python3-pip
|
||||
$ pip-python3 install Pillow --user
|
||||
$ export PYTHONPATH=$HOME/.local/lib/python3.3/site-packages:$PYTHONPATH
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ Required RPMs include::
|
|||
* python-setuptools
|
||||
* numpy
|
||||
|
||||
In addition, you must install **contextlib2** via pip.
|
||||
In addition, you must install contextlib2 via pip.
|
||||
|
||||
A few tests still will not run, however, unless one of the following
|
||||
combinations of RPMs / Python packages is installed.
|
||||
|
|
@ -113,8 +113,8 @@ combinations of RPMs / Python packages is installed.
|
|||
* scikit-image and either Pillow or freeimage
|
||||
* matplotlib and Pillow
|
||||
|
||||
**scikit-image** is not available in the Fedora 17 default repositories, but
|
||||
it may be installed via **pip**::
|
||||
scikit-image is not available in the Fedora 17 default repositories, but
|
||||
it may be installed via pip::
|
||||
|
||||
$ yum install Cython # pip needs this in order to compile scikit-image
|
||||
$ yum install python-devel # pip needs this in order to compile scikit-image
|
||||
|
|
@ -137,7 +137,7 @@ From this point forward, python3 will be referred to as just "python".
|
|||
Installation
|
||||
============
|
||||
|
||||
In addition to merely installing **glymur**, you should adjust your **$PATH**
|
||||
In addition to merely installing glymur, you should adjust your **$PATH**
|
||||
environment variable in order to be able to use the **jp2dump** script from
|
||||
the unix command line.
|
||||
|
||||
|
|
@ -150,8 +150,8 @@ the unix command line.
|
|||
|
||||
Configuration
|
||||
=============
|
||||
glymur uses **ctypes** (for the moment) to access the openjp2 library, and
|
||||
because **ctypes** access libraries in a platform-dependent manner, it is
|
||||
glymur uses ctypes (for the moment) to access the openjp2 library, and
|
||||
because ctypes access libraries in a platform-dependent manner, it is
|
||||
recommended that you create a configuration file to help glymur properly find
|
||||
the openjp2 library. You may create the configuration file as follows::
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,12 @@ def _glymurrc_fname():
|
|||
fname = os.path.join(path, 'glymurrc')
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
else:
|
||||
msg = "glymurrc file hinted at by GLYMURCONFIGDIR does not "
|
||||
msg += "exist."
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
# HOME/.glymur/jptoolrsc
|
||||
# HOME/.glymur/glymurrc
|
||||
confdir = _get_configdir()
|
||||
if confdir is not None:
|
||||
fname = os.path.join(_get_configdir(), 'glymurrc')
|
||||
|
|
@ -45,26 +49,22 @@ def _config():
|
|||
# Read the configuration file for the library location.
|
||||
parser = ConfigParser()
|
||||
parser.read(filename)
|
||||
try:
|
||||
libopenjp2_path = parser.get('library', 'openjp2')
|
||||
if not os.path.exists(libopenjp2_path):
|
||||
msg = 'OpenJP2 library path specified by configuration file '
|
||||
msg += 'does not exist.'
|
||||
raise ImportError(msg)
|
||||
except NoOptionError as e:
|
||||
msg = "Error parsing configuration file '{0}': {1}"
|
||||
msg = msg.format(fname, e.message)
|
||||
warnings.warn(msg, UserWarning)
|
||||
except:
|
||||
raise
|
||||
libopenjp2_path = parser.get('library', 'openjp2')
|
||||
else:
|
||||
# No help from the config file, try to find it ourselves.
|
||||
from ctypes.util import find_library
|
||||
libopenjp2_path = find_library('openjp2')
|
||||
if libopenjp2_path is None:
|
||||
raise ImportError('OpenJP2 library not found.')
|
||||
|
||||
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
||||
if libopenjp2_path is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
_OPENJP2 = ctypes.CDLL(libopenjp2_path)
|
||||
except OSError:
|
||||
msg = '"Library {0}" could not be loaded. Operating in degraded mode.'
|
||||
msg = msg.format(libopenjp2_path)
|
||||
warnings.warn(msg, UserWarning)
|
||||
_OPENJP2 = None
|
||||
return _OPENJP2
|
||||
|
||||
|
||||
|
|
@ -81,6 +81,7 @@ def _get_configdir():
|
|||
if 'HOME' in os.environ:
|
||||
return os.path.join(os.environ['HOME'], '.glymur')
|
||||
|
||||
import warnings
|
||||
import sys
|
||||
if sys.hexversion <= 0x03000000:
|
||||
from ConfigParser import SafeConfigParser as ConfigParser
|
||||
|
|
|
|||
|
|
@ -528,105 +528,110 @@ class _codestream_info_v2_t(ctypes.Structure):
|
|||
|
||||
# Restrict the input and output argument types for each function used in the
|
||||
# API.
|
||||
_OPENJP2.opj_create_compress.argtypes = [_codec_format_t]
|
||||
_OPENJP2.opj_create_compress.restype = _codec_t_p
|
||||
if _OPENJP2 is not None:
|
||||
_OPENJP2.opj_create_compress.argtypes = [_codec_format_t]
|
||||
_OPENJP2.opj_create_compress.restype = _codec_t_p
|
||||
|
||||
_OPENJP2.opj_create_decompress.argtypes = [_codec_format_t]
|
||||
_OPENJP2.opj_create_decompress.restype = _codec_t_p
|
||||
_OPENJP2.opj_create_decompress.argtypes = [_codec_format_t]
|
||||
_OPENJP2.opj_create_decompress.restype = _codec_t_p
|
||||
|
||||
_argtypes = [_codec_t_p, _stream_t_p, ctypes.POINTER(_image_t)]
|
||||
_OPENJP2.opj_decode.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, _stream_t_p, ctypes.POINTER(_image_t)]
|
||||
_OPENJP2.opj_decode.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p, ctypes.c_uint32,
|
||||
ctypes.POINTER(ctypes.c_uint8),
|
||||
ctypes.c_uint32,
|
||||
_stream_t_p]
|
||||
_OPENJP2.opj_decode_tile_data.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, ctypes.c_uint32,
|
||||
ctypes.POINTER(ctypes.c_uint8),
|
||||
ctypes.c_uint32,
|
||||
_stream_t_p]
|
||||
_OPENJP2.opj_decode_tile_data.argtypes = _argtypes
|
||||
|
||||
_argtypes = [ctypes.POINTER(ctypes.POINTER(_codestream_info_v2_t))]
|
||||
_OPENJP2.opj_destroy_cstr_info.argtypes = _argtypes
|
||||
_OPENJP2.opj_destroy_cstr_info.restype = ctypes.c_void_p
|
||||
_argtypes = [ctypes.POINTER(ctypes.POINTER(_codestream_info_v2_t))]
|
||||
_OPENJP2.opj_destroy_cstr_info.argtypes = _argtypes
|
||||
_OPENJP2.opj_destroy_cstr_info.restype = ctypes.c_void_p
|
||||
|
||||
_argtypes = [_codec_t_p, _stream_t_p]
|
||||
_OPENJP2.opj_encode.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, _stream_t_p]
|
||||
_OPENJP2.opj_encode.argtypes = _argtypes
|
||||
|
||||
_OPENJP2.opj_get_cstr_info.argtypes = [_codec_t_p]
|
||||
_OPENJP2.opj_get_cstr_info.restype = ctypes.POINTER(_codestream_info_v2_t)
|
||||
_OPENJP2.opj_get_cstr_info.argtypes = [_codec_t_p]
|
||||
_OPENJP2.opj_get_cstr_info.restype = ctypes.POINTER(_codestream_info_v2_t)
|
||||
|
||||
_argtypes = [_codec_t_p,
|
||||
_stream_t_p,
|
||||
ctypes.POINTER(_image_t),
|
||||
ctypes.c_uint32]
|
||||
_OPENJP2.opj_get_decoded_tile.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p,
|
||||
_stream_t_p,
|
||||
ctypes.POINTER(_image_t),
|
||||
ctypes.c_uint32]
|
||||
_OPENJP2.opj_get_decoded_tile.argtypes = _argtypes
|
||||
|
||||
_argtypes = [ctypes.c_uint32,
|
||||
ctypes.POINTER(_image_comptparm_t),
|
||||
color_space_t]
|
||||
_OPENJP2.opj_image_create.argtypes = _argtypes
|
||||
_OPENJP2.opj_image_create.restype = ctypes.POINTER(_image_t)
|
||||
_argtypes = [ctypes.c_uint32,
|
||||
ctypes.POINTER(_image_comptparm_t),
|
||||
color_space_t]
|
||||
_OPENJP2.opj_image_create.argtypes = _argtypes
|
||||
_OPENJP2.opj_image_create.restype = ctypes.POINTER(_image_t)
|
||||
|
||||
_argtypes = [ctypes.c_uint32,
|
||||
ctypes.POINTER(_image_comptparm_t),
|
||||
color_space_t]
|
||||
_OPENJP2.opj_image_tile_create.argtypes = _argtypes
|
||||
_OPENJP2.opj_image_tile_create.restype = ctypes.POINTER(_image_t)
|
||||
_argtypes = [ctypes.c_uint32,
|
||||
ctypes.POINTER(_image_comptparm_t),
|
||||
color_space_t]
|
||||
_OPENJP2.opj_image_tile_create.argtypes = _argtypes
|
||||
_OPENJP2.opj_image_tile_create.restype = ctypes.POINTER(_image_t)
|
||||
|
||||
_OPENJP2.opj_image_destroy.argtypes = [ctypes.POINTER(_image_t)]
|
||||
_OPENJP2.opj_image_destroy.argtypes = [ctypes.POINTER(_image_t)]
|
||||
|
||||
_argtypes = [_stream_t_p, _codec_t_p, ctypes.POINTER(ctypes.POINTER(_image_t))]
|
||||
_OPENJP2.opj_read_header.argtypes = _argtypes
|
||||
_argtypes = [_stream_t_p, _codec_t_p,
|
||||
ctypes.POINTER(ctypes.POINTER(_image_t))]
|
||||
_OPENJP2.opj_read_header.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p,
|
||||
_stream_t_p,
|
||||
ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32),
|
||||
ctypes.POINTER(ctypes.c_int32), ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_int32), ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_uint32),
|
||||
ctypes.POINTER(_bool_t)]
|
||||
_OPENJP2.opj_read_tile_header.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p,
|
||||
_stream_t_p,
|
||||
ctypes.POINTER(ctypes.c_uint32),
|
||||
ctypes.POINTER(ctypes.c_uint32),
|
||||
ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_int32),
|
||||
ctypes.POINTER(ctypes.c_uint32),
|
||||
ctypes.POINTER(_bool_t)]
|
||||
_OPENJP2.opj_read_tile_header.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_image_t), ctypes.c_int32,
|
||||
ctypes.c_int32, ctypes.c_int32, ctypes.c_int32]
|
||||
_OPENJP2.opj_set_decode_area.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_image_t), ctypes.c_int32,
|
||||
ctypes.c_int32, ctypes.c_int32, ctypes.c_int32]
|
||||
_OPENJP2.opj_set_decode_area.argtypes = _argtypes
|
||||
|
||||
_argtypes = [ctypes.POINTER(_cparameters_t)]
|
||||
_OPENJP2.opj_set_default_encoder_parameters.argtypes = _argtypes
|
||||
_argtypes = [ctypes.POINTER(_cparameters_t)]
|
||||
_OPENJP2.opj_set_default_encoder_parameters.argtypes = _argtypes
|
||||
|
||||
_argtypes = [ctypes.POINTER(_dparameters_t)]
|
||||
_OPENJP2.opj_set_default_decoder_parameters.argtypes = _argtypes
|
||||
_argtypes = [ctypes.POINTER(_dparameters_t)]
|
||||
_OPENJP2.opj_set_default_decoder_parameters.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p, ctypes.c_void_p, ctypes.c_void_p]
|
||||
_OPENJP2.opj_set_error_handler.argtypes = _argtypes
|
||||
_OPENJP2.opj_set_info_handler.argtypes = _argtypes
|
||||
_OPENJP2.opj_set_warning_handler.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, ctypes.c_void_p, ctypes.c_void_p]
|
||||
_OPENJP2.opj_set_error_handler.argtypes = _argtypes
|
||||
_OPENJP2.opj_set_info_handler.argtypes = _argtypes
|
||||
_OPENJP2.opj_set_warning_handler.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_dparameters_t)]
|
||||
_OPENJP2.opj_setup_decoder.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_dparameters_t)]
|
||||
_OPENJP2.opj_setup_decoder.argtypes = _argtypes
|
||||
|
||||
_argtypes = [_codec_t_p,
|
||||
ctypes.POINTER(_cparameters_t),
|
||||
ctypes.POINTER(_image_t)]
|
||||
_OPENJP2.opj_setup_encoder.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p,
|
||||
ctypes.POINTER(_cparameters_t),
|
||||
ctypes.POINTER(_image_t)]
|
||||
_OPENJP2.opj_setup_encoder.argtypes = _argtypes
|
||||
|
||||
_argtypes = [ctypes.c_char_p, ctypes.c_int32]
|
||||
_OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = _argtypes
|
||||
_OPENJP2.opj_stream_create_default_file_stream_v3.restype = _stream_t_p
|
||||
_argtypes = [ctypes.c_char_p, ctypes.c_int32]
|
||||
_OPENJP2.opj_stream_create_default_file_stream_v3.argtypes = _argtypes
|
||||
_OPENJP2.opj_stream_create_default_file_stream_v3.restype = _stream_t_p
|
||||
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_image_t), _stream_t_p]
|
||||
_OPENJP2.opj_start_compress.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p, ctypes.POINTER(_image_t), _stream_t_p]
|
||||
_OPENJP2.opj_start_compress.argtypes = _argtypes
|
||||
|
||||
_OPENJP2.opj_end_compress.argtypes = [_codec_t_p, _stream_t_p]
|
||||
_OPENJP2.opj_end_decompress.argtypes = [_codec_t_p, _stream_t_p]
|
||||
_OPENJP2.opj_end_compress.argtypes = [_codec_t_p, _stream_t_p]
|
||||
_OPENJP2.opj_end_decompress.argtypes = [_codec_t_p, _stream_t_p]
|
||||
|
||||
_OPENJP2.opj_stream_destroy_v3.argtypes = [_stream_t_p]
|
||||
_OPENJP2.opj_destroy_codec.argtypes = [_codec_t_p]
|
||||
_OPENJP2.opj_stream_destroy_v3.argtypes = [_stream_t_p]
|
||||
_OPENJP2.opj_destroy_codec.argtypes = [_codec_t_p]
|
||||
|
||||
_argtypes = [_codec_t_p,
|
||||
ctypes.c_uint32,
|
||||
ctypes.POINTER(ctypes.c_uint8),
|
||||
ctypes.c_uint32,
|
||||
_stream_t_p]
|
||||
_OPENJP2.opj_write_tile.argtypes = _argtypes
|
||||
_argtypes = [_codec_t_p,
|
||||
ctypes.c_uint32,
|
||||
ctypes.POINTER(ctypes.c_uint8),
|
||||
ctypes.c_uint32,
|
||||
_stream_t_p]
|
||||
_OPENJP2.opj_write_tile.argtypes = _argtypes
|
||||
|
||||
|
||||
def _check_error(status):
|
||||
|
|
@ -655,9 +660,10 @@ _fcns = ['opj_decode', 'opj_decode_tile_data', 'opj_end_compress',
|
|||
'opj_set_warning_handler',
|
||||
'opj_setup_decoder', 'opj_setup_encoder', 'opj_start_compress',
|
||||
'opj_write_tile']
|
||||
for _fcn in _fcns:
|
||||
_attr = getattr(_OPENJP2, _fcn)
|
||||
setattr(_attr, 'restype', _check_error)
|
||||
if _OPENJP2 is not None:
|
||||
for _fcn in _fcns:
|
||||
_attr = getattr(_OPENJP2, _fcn)
|
||||
setattr(_attr, 'restype', _check_error)
|
||||
|
||||
|
||||
def _create_compress(codec_format):
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ class TestJp2k(unittest.TestCase):
|
|||
with patch.dict('os.environ', {'GLYMURCONFIGDIR': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with self.assertRaises(ImportError) as ce:
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
imp.reload(glymur)
|
||||
|
||||
@unittest.skipIf(sys.hexversion < 0x03020000,
|
||||
|
|
@ -594,7 +594,7 @@ class TestJp2k(unittest.TestCase):
|
|||
with patch.dict('os.environ', {'GLYMURCONFIGDIR': tdir}):
|
||||
# Misconfigured new configuration file should
|
||||
# be rejected.
|
||||
with self.assertRaises(ImportError) as ce:
|
||||
with self.assertWarns(UserWarning) as cw:
|
||||
imp.reload(glymur)
|
||||
|
||||
|
||||
|
|
|
|||
3
readthedocs-pip-requirements.txt
Normal file
3
readthedocs-pip-requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
numpydoc==0.4
|
||||
contextlib2==0.4.0
|
||||
mock==1.0.1
|
||||
Loading…
Add table
Add a link
Reference in a new issue