new branch

This commit is contained in:
Will Bierbower 2015-06-25 15:44:38 -07:00
parent 181b8ada21
commit a870c43188
53 changed files with 245 additions and 0 deletions

110
exe/README.rst Normal file
View File

@ -0,0 +1,110 @@
======================
InVEST Build Framework
======================
Scripts, hooks, and instructions for creating a binary build of InVEST.
Requirements
------------
* PyInstaller (see PyInstaller project for own OS-specific dependencies)
* InVEST3
Usage
-----
Currently must call pyinstaller from same directory as spec file (b/c of spec file)
.. code:: shell
$ pyinstaller invest.spec
Distributable build stored in top-level `dist/` folder.
Planning
--------
* Support for Linux
* Support for Windows
* Support for Mac OSX
* Scripts to install InVEST dependencies
Notes on PyInstaller
--------------------
Repository: https://github.com/pyinstaller/pyinstaller
Documentation: http://pythonhosted.org/PyInstaller/
Definitions
~~~~~~~~~~~
scripts: the python scripts named at command line
pure: pure python modules needed by the scripts
binaries: non-python modules needed by the scripts
Stage 1: Dependency Analysis
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: python
a = Analysis() # contains lists of scripts, pure, and binaries
hooks.hookutils functions:
* get_package_paths(package)
* hiddenimports = collect_submodules(package)
* datas = collect_data_files(package)
.. code:: python
MERGE( [ (a, 'script_name', 'exec_name'), (b, 'b', 'b'), ... ] )
MERGE is used in multi-package bundles.
Stage 2: Python File Compression
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: python
pyz = PYZ(a.pure) # contains the modules listed in a.pure
Stage 3: Create Executable Scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: python
# contains what will be the executable file 'myscript'
exe = EXE(a.scripts, a.binaries, a.zipfiles, a.datas, pyz, name="myscript", exclude_binaries=1)
Stage 4: Collect Files into Distributable Application
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code:: python
# creates the output folder
COLLECT(exe, a.binaries, a.zipfiles, a.datas, name="dist")
Notes on Preparing InVEST Repo for PyInstaller
----------------------------------------------
In Setup.py's setup() function:
include_package_data=True,
Add MANIFEST.in with following:
recursive-include invest_natcap/
Add additional elif block to iui.executor import switch statement
from importlib import import_module
elif getattr(sys, 'frozen', False) and getattr(sys, '_MEIPASS', False):
model = import_module(module)
model_name = os.path.splitext(os.path.basename(module))[0]
LOGGER.debug('Loading %s in frozen environment', model)

2
exe/hooks/hook-ctypes.py Normal file
View File

@ -0,0 +1,2 @@
from hookutils import collect_submodules
hiddenimports = collect_submodules('ctypes')

BIN
exe/hooks/hook-ctypes.pyc Normal file

Binary file not shown.

View File

@ -0,0 +1,2 @@
from PyInstaller.hooks.hookutils import collect_data_files
datas = collect_data_files('fauxgeo')

1
exe/hooks/hook-h5py.py Normal file
View File

@ -0,0 +1 @@
hiddenimports = ['_proxy', 'utils', 'defs', 'h5ac']

View File

@ -0,0 +1,3 @@
from PyInstaller.hooks.hookutils import collect_data_files, collect_submodules
datas = collect_data_files('invest_natcap')
hiddenimports = collect_submodules('invest_natcap')

Binary file not shown.

2
exe/hooks/hook-numpy.py Normal file
View File

@ -0,0 +1,2 @@
from hookutils import collect_submodules
hiddenimports = collect_submodules('numpy')

BIN
exe/hooks/hook-numpy.pyc Normal file

Binary file not shown.

47
exe/hooks/hook-osgeo.py Normal file
View File

@ -0,0 +1,47 @@
from PyInstaller.compat import is_win
from PyInstaller.hooks.hookutils import get_package_paths, collect_data_files
# from osgeo import gdal
# import platform
# import os
# import glob
# files = []
# if is_win:
# files += [
# 'geos_c.dll',
# ]
# # If shapely is present, use that version of GEOS_C.dll
# try:
# import shapely
# pkg_dir = os.path.dirname(shapely.__file__)
# except (ImportError, AssertionError) as error:
# # ImportError is raised when we can't import shapely
# # AssertionError is raised when the package path can't be found.
# print 'Defaulting to osgeo pkg:', error
# pkg_base, pkg_dir = get_package_paths('osgeo')
# osgeo_base, osgeo_dir = get_package_paths('osgeo')
# data_dir = os.path.join(osgeo_dir, 'data', 'gdal')
# datas = [(os.path.join(pkg_dir, filename), '') for filename in files]
# datas += [(os.path.join(data_dir, filename), '') for filename in
# glob.glob(data_dir + '/*')]
# else:
# if platform.system() == 'Darwin':
# # Accommodate multiple gdal version installations
# _base_data_dir = '/usr/local/Cellar/gdal/'
# _version_glob = "%s*" % gdal.__version__
# _gdal_version_dirname = glob.glob(_base_data_dir + _version_glob)[-1]
# data_dir = os.path.join(_gdal_version_dirname, 'share', 'gdal')
# datas = [(os.path.join(pkg_dir, filename), '') for filename in files]
# datas += [(os.path.join(data_dir, filename), '') for filename in
# glob.glob(data_dir + '/*')]
# else:
# datas = collect_data_files('osgeo')
datas = collect_data_files('osgeo')

BIN
exe/hooks/hook-osgeo.pyc Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
from PyInstaller.hooks.hookutils import collect_data_files
datas = collect_data_files('pygeoprocessing')

Binary file not shown.

1
exe/hooks/hook-scipy.py Normal file
View File

@ -0,0 +1 @@
hiddenimports = ['scipy.special._ufuncs_cxx', 'scipy.io.matlab.streams', 'scipy.sparse.cgraph._validation']

BIN
exe/hooks/hook-scipy.pyc Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
import os
from hookutils import collect_submodules, collect_data_files, get_package_paths
hiddenimports = collect_submodules('shapely')
pkg_base, pkg_dir = get_package_paths('shapely')
datas = collect_data_files('shapely')
datas += [(os.path.join(pkg_dir, 'DLLs/geos_c.dll'), '')]

BIN
exe/hooks/hook-shapely.pyc Normal file

Binary file not shown.

7
exe/hooks/rthook.py Normal file
View File

@ -0,0 +1,7 @@
import sys
import os
import multiprocessing
multiprocessing.freeze_support()
os.environ['MATPLOTLIBDATA'] = os.path.join(sys._MEIPASS, 'mpl-data')

60
exe/invest.spec Normal file
View File

@ -0,0 +1,60 @@
import sys
import os
# Global Variables
current_dir = os.path.join(os.getcwd(), os.path.dirname(sys.argv[1]))
app_dir = os.path.join(current_dir, 'apps')
scripts = os.listdir(app_dir)
# Analyze Scripts for Dependencies
kwargs = {
'hookspath': [os.path.join(current_dir, 'hooks')],
'excludes': None,
'pathex': [os.getcwd()],
}
analysis_object_tuples = []
for script in scripts:
fname, _ = os.path.splitext(script)
fpath = os.path.join(app_dir, script)
a = Analysis([fpath], **kwargs)
analysis_object_tuples.append((a, fname, fname))
MERGE(*analysis_object_tuples)
# Compress pyc and pyo Files into ZlibArchive Objects
pyz_objects = []
for t in analysis_object_tuples:
pyz = PYZ(t[0].pure)
pyz_objects.append(pyz)
# Create Executable Files
exe_objects = []
for i in range(len(scripts)):
fname, _ = os.path.splitext(scripts[i])
exe = EXE(
pyz_objects[i],
analysis_object_tuples[i][0].scripts,
name=fname,
exclude_binaries=1,
debug=False,
strip=None,
upx=False,
console=False)
exe_objects.append(exe)
# Collect Files into Distributable Folder/File
binaries = []
zipfiles = []
datas = []
for i in range(len(scripts)):
binaries.append(analysis_object_tuples[i][0].binaries)
zipfiles.append(analysis_object_tuples[i][0].zipfiles)
datas.append(analysis_object_tuples[i][0].datas)
args = exe_objects + binaries + zipfiles + datas
dist = COLLECT(
*args,
name="invest_dist",
strip=None,
upx=True)