Update icon and Add info

This commit is contained in:
Andros Fenollosa
2017-04-20 00:57:59 +02:00
parent 65f275850d
commit 014ffce8ed
182 changed files with 9338 additions and 10 deletions

View File

@ -0,0 +1,87 @@
from py2app.util import imp_find_module
import os, sys, glob
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
try:
set
except NameError:
from sets import Set as set
try:
basestring
except NameError:
basestring = str
def check(cmd, mf):
m = mf.findNode('Image') or mf.findNode('PIL.Image')
if m is None or m.filename is None:
return None
if mf.findNode('PIL.Image'):
have_PIL = True
else:
have_PIL = False
plugins = set()
visited = set()
for folder in sys.path:
if not isinstance(folder, basestring):
continue
for extra in ('', 'PIL'):
folder = os.path.realpath(os.path.join(folder, extra))
if (not os.path.isdir(folder)) or (folder in visited):
continue
for fn in os.listdir(folder):
if not fn.endswith('ImagePlugin.py'):
continue
mod, ext = os.path.splitext(fn)
try:
sys.path.insert(0, folder)
imp_find_module(mod)
del sys.path[0]
except ImportError:
pass
else:
plugins.add(mod)
visited.add(folder)
s = StringIO('_recipes_pil_prescript(%r)\n' % list(plugins))
for plugin in plugins:
if have_PIL:
mf.implyNodeReference(m, 'PIL.' + plugin)
else:
mf.implyNodeReference(m, plugin)
mf.removeReference(m, 'FixTk')
# Since Imaging-1.1.5, SpiderImagePlugin imports ImageTk conditionally.
# This is not ever used unless the user is explicitly using Tk elsewhere.
sip = mf.findNode('SpiderImagePlugin')
if sip is not None:
mf.removeReference(sip, 'ImageTk')
# The ImageQt plugin should only be usefull when using PyQt, which
# would then be explicitly imported.
# Note: this code doesn't have the right side-effect at the moment
# due to the way the PyQt5 recipe is structured.
sip = mf.findNode('PIL.ImageQt')
if sip is not None:
mf.removeReference(sip, 'PyQt5')
mf.removeReference(sip, 'PyQt5.QtGui')
mf.removeReference(sip, 'PyQt5.QtCore')
mf.removeReference(sip, 'PyQt4')
mf.removeReference(sip, 'PyQt4.QtGui')
mf.removeReference(sip, 'PyQt4.QtCore')
pass
return dict(
prescripts = ['py2app.recipes.PIL.prescript', s],
include = "PIL.JpegPresets", # Dodgy import from PIL.JpegPlugin in Pillow 2.0
flatpackages = [os.path.dirname(m.filename)],
)

View File

@ -0,0 +1,43 @@
def _recipes_pil_prescript(plugins):
try:
import Image
have_PIL = False
except ImportError:
from PIL import Image
have_PIL = True
import sys
def init():
if Image._initialized >= 2:
return
if have_PIL:
try:
import PIL.JpegPresets
sys.modules['JpegPresets'] = PIL.JpegPresets
except ImportError:
pass
for plugin in plugins:
try:
if have_PIL:
try:
# First try absolute import through PIL (for Pillow support)
# only then try relative imports
m = __import__('PIL.' + plugin, globals(), locals(), [])
m = getattr(m, plugin)
sys.modules[plugin] = m
continue
except ImportError:
pass
__import__(plugin, globals(), locals(), [])
except ImportError:
if Image.DEBUG:
print('Image: failed to import')
if Image.OPEN or Image.SAVE:
Image._initialized = 2
return 1
Image.init = init

View File

@ -0,0 +1,26 @@
from . import PIL
from . import ctypes
from . import docutils
from . import ftplib
from . import importlib
from . import lxml
from . import matplotlib
from . import mimetypes
from . import numpy
from . import os_module
from . import pydoc
from . import pyenchant
from . import pygame
from . import pyopengl
from . import pyside
from . import pyzmq
from . import qt5
from . import re
from . import scipy
from . import sip
from . import subprocess
from . import virtualenv
from . import wx
from . import xml
from . import setuptools
from . import uuid

View File

@ -0,0 +1,7 @@
def check(cmd, mf):
name = 'cjkcodecs'
m = mf.findNode(name)
if m is None or m.filename is None:
return None
mf.import_hook(name, m, ['*'])
return dict()

View File

@ -0,0 +1,9 @@
import os
def check(cmd, mf):
m = mf.findNode('ctypes')
if m is None or m.filename is None:
return None
return dict(
prescripts=['py2app.bootstrap.ctypes_setup'],
)

View File

@ -0,0 +1,9 @@
def check(cmd, mf):
m = mf.findNode('docutils')
if m is None or m.filename is None:
return None
for pkg in [
'languages', 'parsers', 'readers', 'writers',
'parsers.rst.directives', 'parsers.rst.languages']:
mf.import_hook('docutils.' + pkg, m, ['*'])
return dict()

View File

@ -0,0 +1,14 @@
import sys
from modulegraph.modulegraph import MissingModule
def check(cmd, mf):
if sys.version_info[0] != 2: return {}
# ftplib has an optional dependency on an external (and likely
# non-existing) SOCKS module.
f = mf.findNode('ftplib')
m = mf.findNode('SOCKS')
if m is not None and f is not None and isinstance(m, MissingModule):
mf.removeReference(f, m)
return {}

View File

@ -0,0 +1,7 @@
def check(cmd, mf):
m = mf.findNode('importlib')
if m:
return dict(expected_missing_imports=set(
['_frozen_importlib_external']))
return None

View File

@ -0,0 +1,38 @@
#
# LXML uses imports from C code (or actually Cython code)
# and those cannot be detected by modulegraph.
# The check function adds the hidden imports to the graph
#
# The dependency list was extracted from lxml 3.0.2
import sys
def check(cmd, mf):
m = mf.findNode('lxml.etree')
if m is not None and m.filename is not None:
mf.import_hook('lxml._elementpath', m)
mf.import_hook('os.path', m)
mf.import_hook('re', m)
mf.import_hook('gzip', m)
if sys.version_info[0] == 2:
mf.import_hook('StringIO', m)
else:
mf.import_hook('io', m)
m = mf.findNode('lxml.objectify')
if m is not None and m.filename is not None:
if sys.version_info[0] == 2:
mf.import_hook('copy_reg', m)
else:
mf.import_hook('copyreg', m)
m = mf.findNode('lxml.isoschematron')
if m is not None and m.filename is not None:
# Not zip-safe (see issue 118)
return dict(packages=['lxml'])
if mf.findNode('lxml') is None:
return None
return {}

View File

@ -0,0 +1,27 @@
import os
def check(cmd, mf):
m = mf.findNode('matplotlib')
if m is None or m.filename is None:
return None
if cmd.matplotlib_backends:
backends = {}
for backend in cmd.matplotlib_backends:
if backend == '-':
pass
elif backend == '*':
mf.import_hook('matplotlib.backends', m, ['*'])
else:
mf.import_hook('matplotlib.backends.backend_%s'%(backend,), m)
else:
backends = {'packages': ['matplotlib']}
return dict(
prescripts=['py2app.recipes.matplotlib_prescript'],
resources=[os.path.join(os.path.dirname(m.filename), 'mpl-data')],
**backends
)

View File

@ -0,0 +1,2 @@
import os
os.environ['MATPLOTLIBDATA'] = os.path.join(os.environ['RESOURCEPATH'], 'mpl-data')

View File

@ -0,0 +1,4 @@
def check(cmd, mf):
m = mf.findNode('mimetypes')
if m:
return dict(expected_missing_imports=set(['winreg']))

View File

@ -0,0 +1,7 @@
def check(cmd, mf):
m = mf.findNode('numpy')
if m is None or m.filename is None:
return None
return dict(
packages = ['numpy']
)

View File

@ -0,0 +1,4 @@
def check(cmd, mf):
m = mf.findNode('os')
if m:
return dict(expected_missing_imports=set(['nt']))

View File

@ -0,0 +1,12 @@
import sys
def check(cmd, mf):
m = mf.findNode('pydoc')
if m is None or m.filename is None:
return None
refs = [
'Tkinter', 'tty', 'BaseHTTPServer', 'mimetools', 'select',
'threading', 'ic', 'getopt', 'tkinter', 'win32',
]
for ref in refs:
mf.removeReference(m, ref)
return dict()

View File

@ -0,0 +1,28 @@
"""
Recipe for pyEnchant <http://pypi.python.org/pypi/pyenchant>
PyEnchant is a python library that wraps a C library
using ctypes, hence the usual way to find the library
won't work.
"""
import os
def check(cmd, mf):
m = mf.findNode('enchant')
if m is None or m.filename is None:
return None
if 'PYENCHANT_LIBRARY_PATH' in os.environ:
libpath = os.environ['PYENCHANT_LIBRARY_PATH']
print("WARNING: using pyEnchant without embedding")
print("WARNING: this is not supported at the moment")
else:
path = os.path.dirname(m.filename)
if not os.path.exists(os.path.join(path, "lib", "libenchant.1.dylib")):
print("WARNING: using pyEnchant without embedding")
print("WARNING: this is not supported at the moment")
# Include the entire package outside of site-packages.zip,
# mostly to avoid trying to extract the C code from the package
return dict(packages=['enchant'])

View File

@ -0,0 +1,14 @@
import os
def check(cmd, mf):
m = mf.findNode('pygame')
if m is None or m.filename is None:
return None
def addpath(f):
return os.path.join(os.path.dirname(m.filename), f)
RESOURCES = ['freesansbold.ttf', 'pygame_icon.tiff', 'pygame_icon.icns']
result = dict(
loader_files = [
('pygame', map(addpath, RESOURCES)),
],
)
return result

View File

@ -0,0 +1,16 @@
from __future__ import absolute_import
import os
def check(cmd, mf):
m = mf.findNode('OpenGL')
if m is None or m.filename is None:
return None
p = os.path.splitext(m.filename)[0] + '.py'
# check to see if it's a patched version that doesn't suck
if os.path.exists(p):
for line in open(p, 'rU'):
if line.startswith('__version__ = '):
return dict()
# otherwise include the whole damned thing
return dict(
packages = ['OpenGL'],
)

View File

@ -0,0 +1,48 @@
# since pkg_resources.py lives next to this file, we need to disambiguate the import
from __future__ import absolute_import
import glob
import os
import pkg_resources
def check(cmd, mf):
name = 'PySide'
m = mf.findNode(name)
if m is None or m.filename is None:
return None
try:
from PySide import QtCore
except ImportError:
print("WARNING: macholib found PySide, but cannot import")
return {}
plugin_dir = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.PluginsPath)
resources = [pkg_resources.resource_filename('py2app', 'recipes/qt.conf')]
for item in cmd.qt_plugins:
if '/' not in item:
item = item + '/*'
if '*' in item:
for path in glob.glob(os.path.join(plugin_dir, item)):
resources.append((os.path.dirname('qt_plugins' + path[len(plugin_dir):]), [path]))
else:
resources.append((os.path.dirname(os.path.join('qt_plugins', item)), [os.path.join(plugin_dir, item)]))
# PySide dumps some of its shared files
# into /usr/lib, which is a system location
# and those files are therefore not included
# into the app bundle by default.
from macholib.util import NOT_SYSTEM_FILES
import sys
for fn in os.listdir('/usr/lib'):
add=False
if fn.startswith('libpyside-python'):
add=True
elif fn.startswith('libshiboken-python'):
add=True
if add:
NOT_SYSTEM_FILES.append(os.path.join('/usr/lib', fn))
return dict(resources=resources)

View File

@ -0,0 +1,15 @@
def check(cmd, mf):
m = mf.findNode('zmq')
if m is None or m.filename is None:
return None
# PyZMQ is a package that contains
# a shared library. This recipe
# is mostly a workaround for a bug
# in py2app: it copies the dylib into
# the site-packages zipfile and builds
# a non-functionaly application.
return dict(
packages=['zmq']
)

View File

@ -0,0 +1,3 @@
; Qt Configuration file
[Paths]
Plugins = Resources/qt_plugins

View File

@ -0,0 +1,28 @@
import sys
from modulegraph.modulegraph import MissingModule
def check(cmd, mf):
m = mf.findNode('PyQt5')
if m and not isinstance(m, MissingModule):
try:
# PyQt5 with sipconfig module, handled
# by sip recipe
import sipconfig
return None
except ImportError:
pass
# All imports are done from C code, hence not visible
# for modulegraph
# 1. Use of 'sip'
# 2. Use of other modules, datafiles and C libraries
# in the PyQt5 package.
mf.import_hook('sip', m)
if sys.version[0] != 2:
return dict(packages=['PyQt5'],
expected_missing_imports=set(['copy_reg', 'cStringIO', 'StringIO']))
else:
return dict(packages=['PyQt5'])
return None

View File

@ -0,0 +1,4 @@
def check(cmd, mf):
m = mf.findNode('re')
if m:
return dict(expected_missing_imports=set(['sys.getwindowsversion']))

View File

@ -0,0 +1,7 @@
def check(cmd, mf):
m = mf.findNode('scipy')
if m is None or m.filename is None:
return None
return dict(
packages = ['scipy', 'numpy']
)

View File

@ -0,0 +1,18 @@
import sys
def check(cmd, mf):
m = mf.findNode('pkg_resources')
if m is None or m.filename is None:
return None
for pkg in [
'packaging', 'pyparsing', 'six', 'appdirs' ]:
mf.import_hook('pkg_resources._vendor.' + pkg, m, ['*'])
expected_missing_imports=['__main__.__requires__',
'pkg_resources.extern.pyparsing',
'pkg_resources.extern.six',
'pkg_resources._vendor.appdirs']
if sys.version[0] != 2:
expected_missing_imports.append( '__builtin__' )
return dict(expected_missing_imports=set(expected_missing_imports))

View File

@ -0,0 +1,148 @@
"""
Py2app support for project using sip, which basicly means PyQt and wrappers
for other Qt-based libraries.
This will include all C modules that might be used when you import a package
using sip because we have no way to fine-tune this.
The problem with SIP is that all inter-module depedencies (for example from
PyQt4.Qt to PyQt4.QtCore) are handled in C code and therefore cannot be
detected by the python code in py2app).
"""
# since pkg_resources.py lives next to this file, we need to disambiguate the import
from __future__ import absolute_import
import sys
import glob
import os
import pkg_resources
class Sip(object):
def __init__(self):
self.packages = None
self.plugin_dir = None
def config(self):
if self.packages is not None:
print("packages", self.packages)
return self.packages
import sipconfig, os
try:
from PyQt4 import pyqtconfig
cfg = pyqtconfig.Configuration()
qtdir = cfg.qt_lib_dir
sipdir = os.path.dirname(cfg.pyqt_mod_dir)
self.plugin_dir = os.path.join(cfg.qt_dir, 'plugins')
except ImportError:
from PyQt5.QtCore import QLibraryInfo
qtdir = QLibraryInfo.location(QLibraryInfo.LibrariesPath)
self.plugin_dir = QLibraryInfo.location(QLibraryInfo.PluginsPath)
sipdir = os.path.dirname(sipconfig.__file__)
if not os.path.exists(qtdir):
print("sip: Qtdir %r does not exist"%(qtdir))
# half-broken installation? ignore.
raise ImportError
# Qt is GHETTO!
dyld_library_path = os.environ.get('DYLD_LIBRARY_PATH', '').split(':')
if qtdir not in dyld_library_path:
dyld_library_path.insert(0, qtdir)
os.environ['DYLD_LIBRARY_PATH'] = ':'.join(dyld_library_path)
self.packages = set()
for fn in os.listdir(sipdir):
fullpath = os.path.join(sipdir, fn)
if os.path.isdir(fullpath):
self.packages.add(fn)
if fn in ('PyQt4', 'PyQt5'):
# PyQt4 and later has a nested structure, also import
# subpackage to ensure everything get seen.
for sub in os.listdir(fullpath):
if ".py" not in sub:
self.packages.add('%s.%s'%(fn, sub.replace(".so","")))
# Causes a python3-related syntax error (metaclass keyword),
# and you probably don't need it:
#if "PyQt4.uic" in self.packages and sys.version_info.major != 3:
# print("WARNING: PyQt uic module found.")
# print("avoid python3 metaclass syntax errors by adding 'PyQt4.uic' to your excludes option.")
print("sip: packages: %s"%(self.packages,))
return self.packages
def check(self, cmd, mf):
try:
packages = self.config()
except ImportError:
return None
if 'PyQt4.uic' in packages:
# PyQt4.uic contains subpackages with python 2 and python 3
# support. Exclude the variant that won't be ussed, this avoids
# compilation errors on Python 2 (because some of the Python 3
# code is not valid Python 2 code)
if sys.version_info[0] == 2:
ref = 'PyQt4.uic.port_v3'
else:
ref = 'PyQt4.uic.port_v2'
if 'PyQt5.uic' in packages:
# ditto
if sys.version_info[0] == 2:
ref = 'PyQt5.uic.port_v3'
else:
ref = 'PyQt5.uic.port_v2'
# Exclude...
mf.lazynodes[ref] = None
for pkg in packages:
m = mf.findNode(pkg)
if m is not None and m.filename is not None:
break
else:
print("sip: No sip package used in application")
return None
mf.import_hook('sip', m)
m = mf.findNode('sip')
# naive inclusion of ALL sip packages
# stupid C modules.. hate hate hate
for pkg in packages:
try:
mf.import_hook(pkg, m)
except ImportError as exc:
print("WARNING: ImportError in sip recipe ignored: %s"%(exc,))
print(mf.findNode("PyQt4"))
print(mf.findNode("PyQt5"))
if mf.findNode('PyQt4') is not None or mf.findNode('PyQt5') is not None:
resources = [pkg_resources.resource_filename('py2app', 'recipes/qt.conf')]
for item in cmd.qt_plugins:
if '/' not in item:
item = item + '/*'
if '*' in item:
for path in glob.glob(os.path.join(self.plugin_dir, item)):
resources.append((os.path.dirname('qt_plugins' + path[len(self.plugin_dir):]), [path]))
else:
resources.append((os.path.dirname(os.path.join('qt_plugins', item)), [os.path.join(self.plugin_dir, item)]))
print("PyQt resources", resources)
return dict(resources=resources)
print("Return {}")
return dict()
check = Sip().check

View File

@ -0,0 +1,4 @@
def check(cmd, mf):
m = mf.findNode('subprocess')
if m:
return dict(expected_missing_imports=set(['_winapi']))

View File

@ -0,0 +1,4 @@
def check(cmd, mf):
m = mf.findNode('uuid')
if m:
return dict(expected_missing_imports=set(['netbios', 'win32wnet']))

View File

@ -0,0 +1,106 @@
"""
virtualenv installs a wrapper for the real distutils into the
virtual environment. Ignore that wrapper, but go for the real
distutils instead
This recipe is rather compilicated and definitely not a
good model for other recipes!!!
"""
from __future__ import absolute_import
import sys, os, imp
from modulegraph.modulegraph import MissingModule, \
Package, SourceModule, CompiledModule, find_module
def retry_import(mf, m):
"""
Try to reimport 'm', which should be a MissingModule
"""
if '.' in m.identifier:
pname, partname = m.identifier.rsplit('.', 1)
parent = mf.findNode(pname)
else:
parent = None
partname = m.identifier
# This is basicly mf.find_module inlined and with a
# check disabled.
def fmod(name, path, parent):
if path is None:
if name in sys.builtin_module_names:
return (None, None, ("", "", imp.C_BUILTIN))
path = mf.path
fp, buf, stuff = find_module(name, path)
if buf:
buf = os.path.realpath(buf)
return (fp, buf, stuff)
try:
fp, pathname, stuff = fmod(partname,
parent and parent.packagepath, parent)
except ImportError as e:
return
if stuff[-1] == imp.PKG_DIRECTORY:
m.__class__ = Package
elif stuff[-1] == imp.PY_SOURCE:
m.__class__ = SourceModule
else:
m.__class__ = CompiledModule
#making this match the code later on that checks whether scan_code needs a leading _
if hasattr(mf, 'load_module'):
m = mf.load_module(m.identifier, fp, pathname, stuff)
else:
m = mf._load_module(m.identifier, fp, pathname, stuff)
if parent:
mf.createReference(m, parent)
parent[partname] = m
return m
def check(cmd, mf):
m = mf.findNode('distutils')
if m is None or m.filename is None:
return None
with open(m.filename, 'rU') as fp:
contents = fp.read()
if 'virtualenv' in contents:
# This is the virtualenv version
mos = mf.findNode('os')
if mos is None or mos.filename is None:
raise ValueError("Where is the os module")
m.filename = os.path.join(os.path.dirname(mos.filename), 'distutils', '__init__.py')
with open(m.filename) as fp:
source = fp.read() + '\n'
m.code = co = compile(source, m.filename, 'exec')
m.packagepath = [os.path.dirname(m.filename)]
if mf.replace_paths:
co = mf.replace_paths_in_code(co)
# XXX: Recent versions of modulegraph made scan_code private,
# temporarily call the private version.
if hasattr(mf, 'scan_code'):
mf.scan_code(co, m)
else:
mf._scan_code(co, m)
# That's not all there is to this, we need to look for
# MissingModules in the distutils namespace as well and
# try to import these again.
for m in mf.flatten():
if isinstance(m, MissingModule):
if m.identifier.startswith('distutils.'):
# A missing distutils package, retry
# importing it.
#
retry_import(mf, m)
return dict()

View File

@ -0,0 +1,20 @@
def check(cmd, mf):
# wx.lib.pubsub tries to be too smart w.r.t.
# the __path__ it uses, include all of it when
# found.
m = mf.findNode('wx.lib.pubsub')
if m is None or m.filename is None:
return None
include_packages = [
'wx.lib.pubsub.*',
'wx.lib.pubsub.core.*',
'wx.lib.pubsub.core.arg1.*',
'wx.lib.pubsub.core.kwargs.*',
'wx.lib.pubsub.pubsub1.*',
'wx.lib.pubsub.pubsub2.*',
'wx.lib.pubsub.utils.*',
]
return dict(
includes = include_packages
)

View File

@ -0,0 +1,13 @@
import sys
from modulegraph.modulegraph import MissingModule
def check(cmd, mf):
if sys.version_info[0] != 2: return {}
# Optional dependency on XML+ package in the stdlib, ignore
# this when the package isn't present.
m = mf.findNode('_xmlplus')
if m is not None and isinstance(m, MissingModule):
mf.removeReference(mf.findNode('xml'), m)
return {}