Skip to content
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

Better distribution - archives with libs and images #45

Merged
merged 15 commits into from
Jan 30, 2015
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ imageio/lib
docs/_build
tests/zipped
tests/freezing/frozen
imageio/resources/images
imageio/resources/freeimage

# Files / folders that should always be ignored
__pychache__
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ install:
pip install -q coveralls;
fi;
# Install imageio, use installed version on only one machine
- python setup.py install > ${REDIRECT_TO}
- python setup.py build_with_fi install > ${REDIRECT_TO}

before_script:

Expand Down
7 changes: 7 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ To install imageio, use one of the following methods:
* If you have pip: ``pip install imageio``
* Good old ``python setup.py install``

To install imageio with the freeimage library and a few images included,
you can force downloading the libs when building, or use one of the
provided archives from pypi:

* ``python setup.py build_with_fi install``
* ``pip install https://pypi.python.org/packages/source/i/imageio/imageio-x.y-linux64.zip``

For developers, we provide a simple mechanism to allow importing
imageio from the cloned repository. See the file ``imageio.proxy.io`` for
details.
2 changes: 1 addition & 1 deletion imageio/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .util import Image, Dict, asarray, image_as_uint8, urlopen # noqa
from .util import BaseProgressIndicator, StdoutProgressIndicator # noqa
from .util import string_types, text_type, binary_type, IS_PYPY # noqa
from .util import get_platform, appdata_dir # noqa
from .util import get_platform, appdata_dir, resource_dirs # noqa
from .findlib import load_lib # noqa
from .fetching import get_remote_file # noqa
from .request import Request, read_n_bytes, RETURN_BYTES # noqa
Expand Down
66 changes: 41 additions & 25 deletions imageio/core/fetching.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
import shutil
import time

from . import appdata_dir, StdoutProgressIndicator, string_types, urlopen
from . import appdata_dir, resource_dirs
from . import StdoutProgressIndicator, string_types, urlopen


def get_remote_file(fname, directory=None, force_download=False):
Expand All @@ -24,12 +25,14 @@ def get_remote_file(fname, directory=None, force_download=False):
Parameters
----------
fname : str
The filename on the remote data repository to download. These
correspond to paths on
The relative filename on the remote data repository to download.
These correspond to paths on
``https://github.com/imageio/imageio-binaries/``.
directory : str | None
Directory to use to save the file. By default, the appdata
directory is used.
The directory where the file will be cached if a download was
required to obtain the file. By default, the appdata directory
is used. This is also the first directory that is checked for
a local version of the file.
force_download : bool | str
If True, the file will be downloaded even if a local copy exists
(and this copy will be overwritten). Can also be a YYYY-MM-DD date
Expand All @@ -43,36 +46,49 @@ def get_remote_file(fname, directory=None, force_download=False):
"""
_url_root = 'https://github.com/imageio/imageio-binaries/raw/master/'
url = _url_root + fname
fname = op.normcase(fname) # convert to native
# Get dirs to look for the resource
directory = directory or appdata_dir('imageio')

fname = op.join(directory, op.normcase(fname)) # convert to native
if op.isfile(fname):
if not force_download: # we're done
return fname
if isinstance(force_download, string_types):
ntime = time.strptime(force_download, '%Y-%m-%d')
ftime = time.gmtime(op.getctime(fname))
if ftime >= ntime:
return fname
else:
print('File older than %s, updating...' % force_download)
if not op.isdir(op.dirname(fname)):
os.makedirs(op.abspath(op.dirname(fname)))
dirs = resource_dirs()
dirs.insert(0, appdata_dir('imageio'))
dirs.insert(0, directory) # Given dir has preference
# Try to find the resource locally
for dir in dirs:
filename = op.join(dir, fname)
if op.isfile(filename):
if not force_download: # we're done
return filename
if isinstance(force_download, string_types):
ntime = time.strptime(force_download, '%Y-%m-%d')
ftime = time.gmtime(op.getctime(filename))
if ftime >= ntime:
return filename
else:
print('File older than %s, updating...' % force_download)
break

# If we get here, we're going to try to download the file
if os.getenv('IMAGEIO_NO_INTERNET', '').lower() in ('1', 'true', 'yes'):
raise IOError('Cannot download resource from the internet')
# Get filename to store to and make sure the dir exists
filename = op.join(directory, fname)
if not op.isdir(op.dirname(filename)):
os.makedirs(op.abspath(op.dirname(filename)))
# let's go get the file
if os.getenv('CONTINUOUS_INTEGRATION', False): # pragma: no cover
# On Travis, we retry a few times ...
for i in range(2):
try:
_fetch_file(url, fname)
return fname
_fetch_file(url, filename)
return filename
except IOError:
time.sleep(0.5)
else:
_fetch_file(url, fname)
return fname
_fetch_file(url, filename)
return filename
else: # pragma: no cover
_fetch_file(url, fname)
return fname
_fetch_file(url, filename)
return filename


def _fetch_file(url, file_name, print_destination=True):
Expand Down
30 changes: 27 additions & 3 deletions imageio/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import numpy as np

IS_PYPY = '__pypy__' in sys.builtin_module_names
THIS_DIR = os.path.abspath(os.path.dirname(__file__))

# Taken from six.py
PY3 = sys.version_info[0] == 3
Expand Down Expand Up @@ -160,7 +161,7 @@ def asarray(a):
function does not.
"""
if isinstance(a, np.ndarray):
if IS_PYPY:
if IS_PYPY: # pragma: no cover
a = a.copy() # pypy has issues with base views
plain = a.view(type=np.ndarray)
return plain
Expand Down Expand Up @@ -444,8 +445,31 @@ def appdata_dir(appname=None, roaming=False):

# Done
return path




def resource_dirs():
""" resource_dirs()

Get a list of directories where imageio resources may be located.
The first directory in this list is the "resources" directory in
the package itself. The list further contains the application
directory (for frozen apps), and may include additional directories
in the future.
"""
dirs = []
# Resource dir baked in the package
dirs.append(os.path.abspath(os.path.join(THIS_DIR, '..', 'resources')))
# Directory where the app is located (mainly for frozen apps)
if sys.path and sys.path[0]:
# Get the path. If frozen, sys.path[0] is the name of the executable,
# otherwise it is the path to the directory that contains the script.
thepath = sys.path[0]
if getattr(sys, 'frozen', None):
thepath = os.path.dirname(thepath)
dirs.append(os.path.abspath(thepath))
return dirs


def get_platform():
""" get_platform()

Expand Down
20 changes: 10 additions & 10 deletions imageio/plugins/_freeimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,26 @@

TEST_NUMPY_NO_STRIDES = False # To test pypy fallback

FNAME_PER_PLATFORM = {
'osx32': 'libfreeimage-3.16.0-osx10.6.dylib', # universal library
'osx64': 'libfreeimage-3.16.0-osx10.6.dylib',
'win32': 'FreeImage-3.15.4-win32.dll',
'win64': 'FreeImage-3.15.1-win64.dll',
'linux32': 'libfreeimage-3.16.0-linux32.so',
'linux64': 'libfreeimage-3.16.0-linux64.so',
}


def get_freeimage_lib():
""" Ensure we have our version of the binary freeimage lib.
"""

LIBRARIES = {
'osx32': 'libfreeimage-3.16.0-osx10.6.dylib', # universal library
'osx64': 'libfreeimage-3.16.0-osx10.6.dylib',
'win32': 'FreeImage-3.15.4-win32.dll',
'win64': 'FreeImage-3.15.1-win64.dll',
'linux32': 'libfreeimage-3.16.0-linux32.so',
'linux64': 'libfreeimage-3.16.0-linux64.so',
}

# Get filename to load
# If we do not provide a binary, the system may still do ...
plat = get_platform()
if plat:
try:
return get_remote_file('freeimage/' + LIBRARIES[plat])
return get_remote_file('freeimage/' + FNAME_PER_PLATFORM[plat])
except RuntimeError as e: # pragma: no cover
print(str(e))

Expand Down
19 changes: 10 additions & 9 deletions imageio/plugins/avbin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
from ..core import Format, get_platform, get_remote_file


FNAME_PER_PLATFORM = {
'osx64': 'libavbin-11alpha4-osx.dylib',
'win32': 'avbin-10-win32.dll',
'win64': 'avbin-10-win64.dll',
'linux32': 'libavbin-10-linux32.so',
'linux64': 'libavbin-10-linux64.so',
}


AVBIN_RESULT_ERROR = -1
AVBIN_RESULT_OK = 0
#AVbinResult = ctypes.c_int
Expand Down Expand Up @@ -129,19 +138,11 @@ def timestamp_from_avbin(timestamp):
def get_avbin_lib():
""" Get avbin .dll/.dylib/.so
"""

LIBRARIES = {
'osx64': 'libavbin-11alpha4-osx.dylib',
'win32': 'avbin-10-win32.dll',
'win64': 'avbin-10-win64.dll',
'linux32': 'libavbin-10-linux32.so',
'linux64': 'libavbin-10-linux64.so',
}

platform = get_platform()

try:
lib = LIBRARIES[platform]
lib = FNAME_PER_PLATFORM[platform]
except KeyError: # pragma: no cover
raise RuntimeError('Avbin plugin is not supported on platform %s' %
platform)
Expand Down
36 changes: 19 additions & 17 deletions imageio/plugins/ffmpeg.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,36 @@
import re
import time
import threading
import struct
import subprocess as sp

import numpy as np

from .. import formats
from ..core import (Format, get_remote_file, string_types, read_n_bytes,
image_as_uint8)
image_as_uint8, get_platform)

FNAME_PER_PLATFORM = {
'osx32': 'ffmpeg.osx.snowleopardandabove',
'osx64': 'ffmpeg.osx.snowleopardandabove',
'win32': 'ffmpeg.win32.exe',
'win64': 'ffmpeg.win32.exe',
'linux32': 'ffmpeg.linux32',
'linux64': 'ffmpeg.linux64',
}


def get_exe():
""" Get ffmpeg exe
"""
NBYTES = struct.calcsize('P') * 8
if sys.platform.startswith('linux'):
fname = 'ffmpeg.linux%i' % NBYTES
elif sys.platform.startswith('win'):
fname = 'ffmpeg.win32.exe'
elif sys.platform.startswith('darwin'):
fname = 'ffmpeg.osx.snowleopardandabove'
else: # pragma: no cover
fname = 'ffmpeg' # hope for the best
#
FFMPEG_EXE = 'ffmpeg'
if fname:
FFMPEG_EXE = get_remote_file('ffmpeg/' + fname)
os.chmod(FFMPEG_EXE, os.stat(FFMPEG_EXE).st_mode | stat.S_IEXEC) # exe
return FFMPEG_EXE
plat = get_platform()

if plat and plat in FNAME_PER_PLATFORM:
exe = get_remote_file('ffmpeg/' + FNAME_PER_PLATFORM[plat])
os.chmod(exe, os.stat(exe).st_mode | stat.S_IEXEC) # executable
return exe
else:
return 'ffmpeg' # Let's hope the system has ffmpeg


# Get camera format
if sys.platform.startswith('win'):
Expand Down
2 changes: 1 addition & 1 deletion imageio/plugins/freeimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from .. import formats
from ..core import Format, image_as_uint8
from ._freeimage import fi, IO_FLAGS
from ._freeimage import fi, IO_FLAGS, FNAME_PER_PLATFORM # noqa


# todo: support files with only meta data
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions imageio/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def get_test_dir():
# Clear and create it now
clean_test_dir(True)
os.makedirs(_the_test_dir)
os.makedirs(os.path.join(_the_test_dir, 'images'))
# And later
atexit.register(clean_test_dir)
return _the_test_dir
Expand All @@ -75,6 +76,11 @@ def clean_test_dir(strict=False):
raise


def need_internet():
if os.getenv('IMAGEIO_NO_INTERNET', '').lower() in ('1', 'true', 'yes'):
pytest.skip('No internet')


## Functions to use from make

def test_unit(cov_report='term'):
Expand Down
4 changes: 3 additions & 1 deletion make/maker.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,14 @@ def test(self, arg):
sys.exit(testing.test_unit())

elif arg == 'installed':
# Like unit, but give preference to installed package
# Like unit, but give preference to installed package.
# And do not allow the use of an internet connection.
for p in list(sys.path):
if p in ('', '.'):
sys.path.remove(p)
elif p == ROOT_DIR or p == os.path.dirname(ROOT_DIR):
sys.path.remove(p)
os.environ['IMAGEIO_NO_INTERNET'] = '1'
sys.exit(testing.test_unit())

elif arg == 'cover':
Expand Down