diff --git a/.eggs/README.txt b/.eggs/README.txt new file mode 100644 index 0000000..5d01668 --- /dev/null +++ b/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/.eggs/altgraph-0.13-py3.6.egg b/.eggs/altgraph-0.13-py3.6.egg new file mode 100644 index 0000000..5c6531d Binary files /dev/null and b/.eggs/altgraph-0.13-py3.6.egg differ diff --git a/.eggs/macholib-1.8-py3.6.egg b/.eggs/macholib-1.8-py3.6.egg new file mode 100644 index 0000000..0257760 Binary files /dev/null and b/.eggs/macholib-1.8-py3.6.egg differ diff --git a/.eggs/modulegraph-0.14-py3.6.egg b/.eggs/modulegraph-0.14-py3.6.egg new file mode 100644 index 0000000..90e363f Binary files /dev/null and b/.eggs/modulegraph-0.14-py3.6.egg differ diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/PKG-INFO b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/PKG-INFO new file mode 100644 index 0000000..c9d7ff2 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/PKG-INFO @@ -0,0 +1,1533 @@ +Metadata-Version: 1.1 +Name: py2app +Version: 0.12 +Summary: Create standalone Mac OS X applications with Python +Home-page: http://bitbucket.org/ronaldoussoren/py2app +Author: Ronald Oussoren +Author-email: ronaldoussoren@mac.com +License: MIT or PSF License +Download-URL: http://pypi.python.org/pypi/py2app +Description: py2app is a Python setuptools command which will allow + you to make standalone Mac OS X application bundles + and plugins from Python scripts. + + py2app is similar in purpose and design to py2exe for + Windows. + + NOTE: py2app must be used on OSX to build applications, + it cannot create Mac applications on other platforms. + + Release history + =============== + + py2app 0.12 + ----------- + + * Pull request #15 by Armin Samii: Safer symlink and file copying + + * Update recipes: a number of recipe names conflicted with toplevel + modules imported by recipes. This causes problems on Python 2.7 (without + absolute imports) + + py2app 0.11 + ----------- + + - Make sure the stdout/stderr streams of the main binary of the application + are unbuffered. + + See `issue #177 in PyObjC's repository `_ for more information. + + - Fix issue #201: py2app is not compatible with pyvenv virtualenvs + + With additional fix by Oskari Timperi. + + - Fix issue #179: the stdout/stderr streams are no longer forwarded to console.app using ASL (by default), + use "--redirect-stdout-to-asl" to enable the redirection functionality. + + Note that for unclear reasons the redirection doesn't work on OSX 10.12 at the moment. + + - Fix issue #188: Troubles with lxml.isoschematron + + The package 'lxml.isoschematron' is not zip-safe and tries to load resources using the normal + filesystem APIs, which doesn't work when the package is part of a zipfile. + + - py2applet now longer uses "argv_emulation" by default, that results in too many problems. + + - Issue #174: clean up the summary about missing modules by removing warnings about things that aren't modules. + + Also notes when an module is likely an alias for some other module. These changes should remove a lot + of false postive warnings from the output of py2app. + + - Fix issue #161: opengl recipe uses "file" function that isn't present on Python 3 + + - Add "qt5" recipe that does the right thing for the PyQt5 wheel on PyPI (tested with PyQt5 5.6) + + - Add support for "@loader_path" in the link commands of C extension. + + This makes it possible to use wheels that were processed by `delocate-listdeps `_ + when building application bundles. + + - Do not report imports that are expected to be missing + + Patch by Barry Scott. + + py2app 0.10 + ----------- + + - The recipe for virtualenv calls a modulegraph method that was made + private in a recent release and hence no longer worked with py2app 0.9. + + Update the recipe to work around this. + + + py2app 0.9 + ---------- + + - issue #146, #147: The "python" binary in MyApp.app/Contents/MacOS was + the small stub exetable from framework builds, instead of the actual + command-line interpreter. The result is that you couldn't use + ``sys.executable`` to start a new interpreter, which (amongst others) + breaks multiprocessing. + + - pull request #7: Add support for PyQt5 to the sip recipe. Patch by + Mark Montague. + + - pull request #4: Copying PySide plugins was broken due to bad + indentation. + + - pull request #5: py2app was broken for python versions that + don't use _sysconfigdata. + + - issue #135: Don't sleep for a second after compiling a XIB file + + - issue #134: Remove target location before copying files into + the bundle. + + - issue #133: Ensure that the application's "Framework" folder + is on the search path for ``ctypes.util.find_library``. + + - issue #132: Depend on modulegraph 0.12 to avoid build errors + when the python code contains references to compatibility modules + that contain SyntaxErrors for the current python version. + + - Explicitly report modules that cannot be found at the end of + the run (for non-alias builds) + + Note: This is just a warning, missing modules are not necessarily + a problem because modulegraph can detect imports for modules that + aren't used on OSX (for example) + + - Report modules that contain syntax errors at the end of + the run (for non-alias builds) + + Note: This is just a warning, syntax errors be valid when the + dependency tree contains modules for the other major release + of python (e.g a compat_py2 module that contains compatibility + code for Python 2 and contains code that isn't valid Python 3) + + py2app 0.8.1 + ------------ + + - Loading scripts didn't work when --no-chdir was used + + Reported by Barry Scott in private mail. + + py2app 0.8 + ----------- + + py2app 0.8 is a feature release + + + - Fixed argv emulator on OSX 10.9, the way the code detected that the application + was launched through the Finder didn't work on that OSX release. + + - The launcher binary is now linked with Cocoa, that should avoid some problems + with sandboxed applications (in particular: standard open panels don't seem + to work properly in a sandboxed application when the main binary is not + linked to AppKit) + + - Don't copy Python's Makefile, Setup file and the like into a bundle when + sysconfig and distutils.sysconfig don't need these files (basicly, when + using any recent python version). + + - Fix some issues with virtualenv support: + + * detection of system installs of Python didn't work properly when using + a virtualenv. Because of this py2app did not create a "semi-standalone" + bundle when using a virtualenv created with /usr/bin/python. + + * "semi-standalone" bundles created from a virtualenv included more files + when they should (in particular bits of the stdlib) + + - Issue #92: Add option '--force-system-tk' which ensures that the _tkinter + extension (used by Tkinter) is linked against the Apple build of Tcl/Tk, + even when it is linked to another framework in Python's std. library. + + This will cause a build error when tkinter is linked with a major version of + Tcl/Tk that is not present in /System/Library/Frameworks. + + - Issue #80: Add support for copying system plugins into the application + bundle. + + Py2app now supports a new option *include_plugins*. The value of this + is a list of paths to plugins that should be copied into the application + bundle. + + Items in the list are either paths, or a tuple with the plugin type + and the path:: + + include_plugins=[ + "MyPlugins/MyDocument.qlgenerator", + ("SystemConfiguration", "MyPlugins/MyConfig.plugin"), + ] + + Py2app currently knows about the following plugin suffixes: + ``.qlgenerator``, ``.mdimporter``, ``.xpc``, ``.service``, + ``.prefPane``, ``.iaplugin`` and ``.action``. These plugins + can be added without specifying the plugin type. + + - Issue #83: Setup.py now refuses to install when the current + platform is not Mac OS X. + + This makes it clear that the package is only supported on OSX and + avoids confusing errors later on. + + - Issue #39: It is now possible to have subpackages on + in the "packages" option of py2app. + + - Issue #37: Add recipe for pyEnchant + + ..note:: + + The recipe only works for installations of pyEnchant + where pyEnchant is stored in the installation (such + as the binary eggs on PyPI), not for installations + that either use the "PYENCHANT_LIBRARY_PATH" environment + variable or MacPorts. + + - Issue #90: Removed the 'email' recipe, but require a new enough version + of modulegraph instead. Because of this py2app now requires modulegraph + 0.11 or later. + + py2app 0.7.4 + ------------ + + - Issue #77: the stdout/stderr streams of application and plugin bundles did not + end up in Console.app on OSX 10.8 (as they do on earlier releases of OSX). This + is due to a change in OSX. + + With this version the application executable converts writes to the stdout + and stderr streams to the ASL logging subsystem with the options needed to + end up in the default view of Console.app. + + NOTE: The stdout and stderr streams of plugin bundles are not redirected, as it + is rather bad form to change the global environment of the host application. + + - The i386, x86_64 and intel stub binaries are now compiled with clang on OSX 10.8, + instead of an older version of GCC. The other stub versions still are compiled + on OSX 10.6. + + - Issue #111: The site.py generated by py2app now contains a USER_SITE variable + (with a default value of ``None``) because some software tries to import the + value. + + - Py2app didn't preserve timestamps for files copied into application bundles, + and this can cause a bytecompiled file to appear older than the corresponding + source file (for packages copied in the bundle using the 'packages' option). + + Related to issue #101 + + - Py2app also didn't copy file permissions for files copied into application + bundles, which isn't a problem in general but did cause binaries to lose + there executable permissions (as noted on Stackoverflow) + + - Issue #101: Set "PYTHONDONTWRITEBYTECODE" in the environment before + calling Py_Initialize to ensure that the interpreter won't try to + write bytecode files (which can cause problems when using sandboxed + applications). + + - Issue #105: py2app can now create app and plugin bundles when the main script + has an encoding other than ASCII, in particular for Python 3. + + - Issue #106: Ensure that the PIL recipe works on Python 3. PIL itself isn't + ported yet, but Pillow does work with Python 3. + + - "python setup.py install" now fails unless the machine is running Mac OS X. + + I've seen a number of reports of users that try to use py2app on Windows + or Linux to build OSX applications. That doesn't work, py2app now fails + during installation do make this clear. + + - Disabled the 'email' recipe for python 3.x as it isn't needed there. + + - Issue #91: Added a recipe for `lxml `, needed because + lxml performs a number of imports from an extension and those cannot + be detected automaticly by modulegraph. + + - Issue #94: The site-packages zipfile in the application bundle now contains + zipfile entries for directories as well. This is needed to work around + a bug in the zipimporter for Python 3.3: it won't consider 'pkg/foo.py' to be + in namespace package 'pkg' unless there is a zipfile entry for the 'pkg' + folder (or there is a 'pkg/__init__.py' entry). + + - Issue #97: Fixes a problem with the pyside and sip recipes when the 'qt_plugins' + option is used for 'image_plugins'. + + - Issue #96: py2app should work with python 2.6 again (previous releases didn't + work due to using the sysconfig module introduced in python 2.7) + + - Issue #99: appstore requires a number of symlinks in embedded frameworks. + + (Version 0.7 already added a link Python.frameworks/Versions/Current, this + versions also adds Python.framework/Python and Python.framework/Resources with + the value required by the appstore upload tool). + + - Py2app copied stdlib packages into the app bundle for semi-standalone builds + when they are mentioned in the '--packages' option (either explicitly or + by a recipe). This was unintentional, semi-standlone builds should rely on + the external Python framework for the stdlib. + + .. note:: + + Because of this bug parts of the stdlib of ``/usr/bin/python`` could be + copied into app bundles created with py2app. + + py2app 0.7.3 + ------------ + + py2app 0.7.3 is a bugfix release + + - Issue #82: Remove debug print statement from py2app.util.LOADER that + caused problems with Python 3. + + - Issue #81: Py2app now fails with an error when trying to build a bundle + for a unix-style shared library build of Python (``--enable-shared``) unless + you are using a recent enough patchlevel of python (2.7.4, 3.2.3, 3.3.1, + 3.4.0, all of them are not released yet). + + The build failure was added to avoid a very confusing error when trying + to start the generated application due to a bug in the way python reads + the environment (for shared library builds on Mac OS X). + + - Py2app will also give an error message when the python binary does not + have a shared library (or framework) at all. + + - Issue #87: Ignore '.git' and '.hg' directories while copying package data + ('.svn' and 'CVS' were already ignored). + + - Issue #65: the fix in 0.7 to avoid copying a symlinked library twice caused + problems for some users because only one of the file names ended up in the + application bundle. This release ensures that both names exist (one as a + symbolic name to the other). + + - Issue #88: Ensure that the fix for #65 won't try to create a symlink that + points to itself. This could for example occur with homebrew, where the + exposed lib directory contains symlinks to a cellar, while tye install_name + does mention the "public" lib directory:: + + $ ls -l /opt/homebrew/lib + ... + libglib-2.0.0.dylib -> ../Cellar/glib/2.32.4/lib/libglib-2.0.0.dylib + ... + + $ otool -vL /opt/homebrew/lib/libglib-2.0.0.dylib + /opt/homebrew/lib/libglib-2.0.0.dylib: + /opt/homebrew/lib/libglib-2.0.0.dylib (compatibility version 3201.0.0, current version 3201.4.0) + time stamp 1 Thu Jan 1 01:00:01 1970 + ... + + + + py2app 0.7.2 + ------------ + + py2app 0.7.2 is a bugfix release + + - Issue #75: Don't remove ``--dist-dir``, but only remove the old version + of the objects we're trying to build (if that exists). + + This once again makes it possible to have a number of setup.py files that + build plugins into the same target folder (such as the plugins folder + of an application) + + - Issue #78: Packages added using the ``--packages`` option didn't end up + on ``sys.path`` for semi-standalone applications. + + Reported by Steve Strassmann + + - Issue #76: Semi-standalone packages using extensions modules coudn't use + extensions unless they also used the ``--site-packages`` option (and + the extensions are in the site-packages directory). + + Fixes some problems with PyQt and wxWidgets when using the system installation + of Python. + + Patch by Dan Horner. + + - It is currently not possible to use a subpackage ("foo.bar") in the list + of packages for the "packages" option. Py2app now explicitly checks for this + and prints an error message instead of building an application that doesn't + work. + + Issue: #39 + + + py2app 0.7.1 + ------------ + + py2app 0.7.1 is a bugfix release + + - Always include 'pkg_resources', this is needed to correctly work with + setuptools namespace packages, the __init__.py files of those contain + ``__import__('pkg_resources')`` and that call isn't recognized as an import + by the bytecode scanner. + + - Issue #67: py2applet didn't work with python 3 due to the use of 'raw_input' + + Reported by Andrew Barnert. + + - Issue #68: the "extra-scripts" feature introduced in 0.7 couldn't copy scripts + that aren't in the same directory as "setup.py". + + Reported by Andrew Barnert. + + - For semi-standalone applications the "lib-dynload" directory inside the + application was not on "sys.path", which resulted in launch failures + when using an extension that is not in the stdlib. + + - Issue #70: application fails to launch when script uses Windows line endings + + Reported by Luc Jean. + + py2app 0.7 + ------------ + + py2app 0.7 is a bugfix release + + - Issue #65: generated bundle would crash when two libraries linked to the + same library using different names (one refering to the real name, the other + to a symlink). + + An example if this is an application using wxWidgets when wxWidgets is installed + using homebrew. + + Reported by "Bouke". + + - Issue #13: It is now possible to add helper scripts to a bundle, for + example for creating a GUI that starts a helper script in the background. + + This can be done by using the option "--extra-scripts", the value of which is a list + of script files (".py" or ".pyw" files). + + - Smarter matplotlib recipe, it is now possible to specify which backends should + be included. Issue #44, reported by Adam Kovics. + + The argument to ``--matplotlib-backends`` (or 'matplotlib_backends' in setup.py) + is a list of plugins to include. Use '-' to not include backends other than those + found by the import statement analysis, and '*' to include all backends (without + necessarily including all of matplotlib) + + As an example, use ``--matplotlib-backends=wxagg`` to include just the wxagg + backend. + + Default is to include the entire matplotlib package. + + - The packages included by a py2app recipe weren't processed by modulegraph and + hence their dependencies were not always included. + + - Fix virtualenv support: alias builds in a virtual environment failed to work. + + (There are still issues with semi-standalone and alias plugin bundles in + a virtualenv environment). + + - issue #18: improved PyQt and PySide support. + + Py2app now has a new option named "--qt-plugins" (or "qt_plugins" in setup.py), + this option specify a list of plugins that should be included in the + application bundle. The items of the list can have a number of forms: + + * "plugintype/libplugin.dylib" + + Specify one particular plugin + + * "plugintype/\*foo\*" + + Specify one or more plugins using a glob pattern + + * "plugintype" + + Include all plugins of a type, equivalent to "plugintype/\*". + + The plugins are copied into "Resources/qt_plugins" and py2app adds a "qt.conf" + file that points to that location for plugins. + + - issue #49: package data that is a zipfile is now correctly copied into + the bundle instead of extracting the archive. + + - issue #59: compile site.py to ensure that the generated bundle doesn't + change on first run. + + This is nice to have in general, and essential when using code signing + because the signature will break when a new file is added after signing. + + Reported by Michael McCracken. + + - issue #60: recipe for "email" package was not loaded + + Reported by Chris Beaumont + + - issue #46: py2app no longer warns about the Qt license. We don't warn about + other possibly GPL licensed software either and py2app is not + a license-enforcement tool. + + Reported by briank_in_la. + + - Generated bundles always started with python optimization active + (that is, as if running as 'python -O'). + + - Fix issue #53: py2app would crash if a data file happened to + be a zipfile. + + - py2app copies data files in the directory for a package into + the application bundle. It also did this for directories that + represent subpackages, which made it impossible to exclude + subpackages. + + - added recipe for wxPython because some subpackages of wxPython + use ``__path__`` trickery that confuses modulegraph. + + - recipes can now return a list of additional entries for the + 'includes' list. + + - rewritten the recipe for matplotlib. The recipe no longer includes + the entire package, but just the "mpl-data" directory. + + WARNING: This recipe has had limited testing. + + - fix mixed indentation (tabs and spaces) in argv_emulation.py, + which caused installation failures on python 3.x (issue #40) + + - Issue #43: py2app now creates a symlink named "Current" in the + 'Versions' directory of the embedded Python framework to comply + with a requirement for the Mac App-store. + + - on some OSX releases the application receives both the + "open application" and "open documents" Apple Events during startup, + which broke an assumption in argv_emulation.py. + + - py2app is more strict w.r.t. explictly closing files, this avoids + ResourceWarnings for unclosed files. + + - fix test issue with semi-standalone builds on Python 3.2 + + - added recipe for pyzmq + + - Don't use the version information from Python.framework's Info.plist, + but use ``sys.version_info``. This fixes a build problem with EPD. + + - Ignore some more files when copying package data: + + - VIM swap files (``.foo.py.swp``) + + - Backup files for a number of tools: ``foo.orig`` and ``foo~`` + + py2app 0.6.4 + ------------ + + py2app 0.6.4 is a bugfix and minor feature release + + - Issue #28: the argv emulator crashes in 64-bit mode on OSX 10.5 + + Fixing this issue required yet another rewrite of the argv_emulator + code. + + - Added option '--arch=VALUE' which can be used to select the set of + architectures for the main executable. This defaults to the set of + architectures supported by the python interpreter and can be used to + drop support for some architectures (for example when you're using a + python binary that supports both 32-bit and 64-bit code and use a + GUI library that does not yet work in 64-bit mode). + + Valid values for the argument are archectures used in the list below + and the following groups of architectures: + + * fat: i386, ppc + + * fat3: i386, x86_64, ppc + + * univeral: i386, x86_64, ppc, ppc64 + + * intel: i386, x86_64 + + + + - Issue #32: fix crash when application uses PySide + + This is partially fixed in macholib (release 1.4.3) + + - The '-O' flag of py2app now defaults to the python optimization level + when using python 2.6 or later. + + - Issue #31: honor optimze flag at runtime. + + Until now an application bundle created by py2app would also run without + the "-O" flag, even when the user specified it should. This is now fixed. + + - Issue #33: py2app's application bundle launcher now clears the environment + variable ``PYOBJC_BUNDLE_ADDRESS``, avoids a crash when using PyObjC in an + application launched from a py2app based plugin bundle. + + - py2app's bundle launcher set the environment variable ``PYOBJC_BUNDLE_ADDRESS``, + this variable is now deprecated. Use ``PYOBJC_BUNDLE_ADDRESS`` instead + (replace ```` by the process ID of the current process). + + - When using the system python we now explicitly add Apple's additional packages + (like PyObjC and Twisted) to ``sys.path``. + + This fixes and issue reported by Sean Robinson: py2app used to create a non-working + bundle when you used these packages because the packages didn't get included + (as intented), but were not available on ``sys.path`` either. + + - Fixed the recipe for sip, which in turn ensures that PyQt4 applications + work. + + As before the SIP recipe is rather crude, it will include *all* SIP-based + packages into your application bundle when it detects a module that uses + SIP. + + - The 'Resources' folder is no longer on the python search path, + it contains the scripts while Python modules and packages are located + in the site-packages directory. This change is related to issue #30. + + - The folder 'Resources/Python/site-packages' is no longer on the python + search path. This folder is not used by py2app itself, but might by + used by custom build scripts that wrap around py2app. + + - Issue #30: py2app bundles failed to launch properly when the scriptfile + has the same name as a python package used by the application. + + - Issue #15: py2app now has an option to emulate the shell environment you + get by opening a window in the Terminal. + + Usage: ``python setup.py py2app --emulate-shell-environment`` + + This option is experimental, it is far from certain that the implementation + works on all systems. + + - Issue #16: ``--argv-emulation`` now works with Python 3.x and in 64-bit + executables. + + - Issue #17: py2applet script defaults 'argv_emulation' to False when your using + a 64-bit build of python, because that option is not supported on + such builds. + + - py2app now clears the temporary directory in 'build' and the output directory + in 'dist' before doing anything. This avoids unwanted interactions between + results from a previous builds and the current build. + + - Issue #22: py2app will give an error when the specified version is invalid, + instead of causing a crash in the generated executable. + + - Issue #23: py2app failed to work when an .egg directory was implictly added + to ``sys.path`` by setuptools and the "-O" option was used (for example + ``python setup.py py2app -O2``) + + - Issue #26: py2app copied the wrong executable into the application bundle + when using virtualenv with a framework build of Python. + + py2app 0.6.3 + ------------ + + py2app 0.6.3 is a bugfix release + + - py2app failed to compile .xib files + (as reported on the pythonmac-sig mail-ing list). + + + py2app 0.6.2 + ------------ + + py2app 0.6.2 is a bugfix release + + - py2app failed to copy the iconfile into application bundle + (reported by Russel Owen) + + - py2app failed to copy resources and data files as well + (the ``resource`` key in the py2ap options dictionary and + the ``data_files`` argument to the setup function). + + Issue #19, reported by bryon(at)spideroak.com. + + - py2app failed to build application bundles when using virtualenv + due to assumptions about the relation between ``sys.prefix`` and + ``sys.executable``. + + Report and fix by Erik van Zijst. + + - Ensure that the 'examples' directory is included in the source + archive + + py2app 0.6.1 + ------------ + + py2app 0.6.1 is a bugfix release + + Bugfixes: + + - py2app failed to build the bundle when python package contained + a zipfile with data. + + This version solves most of that problem using a rough + workaround (the issue is fixed when the filename ends with '.zip'). + + - The code that recreates the stub executables when they are + older than the source code now uses ``xcode-select`` to + find the root of SDKs. + + This makes it possible to recreate these executables on machines + where both Xcode 3 and Xcode 4 are installed and Xcode 3 is + the default Xcode. + + - The stub executables were regenerated using Xcode 3 + + As a word of warning: Xcode 4 cannot be used to rebuild the + stub executables, in particular not those that have support + for the PPC architecture. + + - Don't rebuild the stub executables automaticly, that's + unsafe with Xcode 4 and could trigger accidently when + files are installed in a different order than expected. + + - Small tweaks to the testsuite to ensure that they work + on systems with both Xcode3 and Xcode4 (Xcode3 must be + the selected version). + + - Better cleanup in the testsuite when ``setupClass`` fails. + + py2app 0.6 + ---------- + + py2app 0.6 is a minor feature release + + + Features: + + - it is now possible to specify which python distributions must + be availble when building the bundle by using the + "install_requires" argument of the ``setup()`` function:: + + setup( + + ... + install_requires = [ + "pyobjc == 2.2" + ], + ) + + - py2app can now package namespace packages that were installed + using `pip ` or the + setuptools install option ``--single-version-externally-managed``. + + - the bundle template now supports python3, based on a patch + by Virgil Dupras. + + - alias builds no longer use Carbon Aliases and therefore are + supported with python3 as well (patch by Virgil Dupras) + + - argv emulation doesn't work in python 3, this release + will tell you abou this instead of silently failing to + build a working bundle. + + - add support for custom URLs to the argv emulation code + (patch by Brendan Simon). + + You will have to add a "CFBundleURLTypes" key to your Info.plist to + use this, the argv emulation code will ensure that the URL + to open will end up in ``sys.argv``. + + - ``py2app.util`` contains a number of functions that are now + deprecated an will be removed in a future version, specifically: + ``os_path_islink``, ``os_path_isdir``, ``path_to_zip``, + ``get_zip_data``, ``get_mtime``, and ``os_readlink``. + + - The module ``py2app.simpleio`` no longer exists, and should never + have been in the repository (it was part of a failed rewrite of + the I/O layer). + + Bug fixes: + + - fix problem with symlinks in copied framework, as reported + by Dan Ross. + + - py2applet didn't work in python 3.x. + + - The ``--alias`` option didn't work when building a plugin + bundle (issue #10, fix by Virgil Dupras) + + - Avoid copying the __pycache__ directory in python versions + that implement PEP 3147 (Python 3.2 and later) + + - App bundles with Python 3 now work when the application is + stored in a directory with non-ASCII characters in the full + name. + + - Do not compile ``.nib`` files, it is not strictly needed and + breaks PyObjC projects that still use the NibClassBuilder code. + + - Better error messsages when trying to include a non-existing + file as a resource. + + - Don't drop into PDB when an exception occurs. + + - Issue #5: Avoid a possible stack overflow in the bundle executable + + - Issue #9: Work with python 3.2 + + - Fix build issues with python 2.5 (due to usage of too modern distutils + command subclasses) + + - The source distribution didn't include all files that needed to be + it ever since switching to mercurial, I've added a MANIFEST.in + file rather than relying on setuptool's autoguessing of files to include. + + - Bundle template works again with semi-standalone builds (such as + when using a system python), this rewrites the fix for issue #10 + mentioned earlier. + + - Ensure py2app works correctly when the sources are located in a + directory with non-ascii characters in its name. + + + py2app 0.5.2 + ------------ + + py2app 0.5.2 is a bugfix release + + Bug fixes: + + - Ensure that the right stub executable gets found when using + the system python 2.5 + + py2app 0.5.1 + ------------ + + py2app 0.5.1 is a bugfix release + + Bug fixes: + + - Ensure stub executables get included in the egg files + + - Fix name of the bundletemplate stub executable for 32-bit builds + + + + py2app 0.5 + ---------- + + py2app 0.5 is a minor feature release. + + Features: + + - Add support for the ``--with-framework-name`` option of Python's + configure script, that is: py2app now also works when the Python + framework is not named 'Python.framework'. + + - Add support for various build flavours of Python (32bit, 3-way, ...) + + - py2app now actually works for me (ronaldoussoren@mac.com) with a + python interpreter in a virtualenv environment. + + - Experimental support for python 3 + + Bug fixes: + + - Fix recipe for matplotlib: that recipe caused an exception with + current versions of matplotlib and pytz. + + - Use modern API's in the alias-build bootstrap code, without + this 'py2app -A' will result in broken bundles on a 64-bit build + of Python. + (Patch contributed by James R Eagan) + + - Try both 'import Image' and 'from PIL import Image' in the PIL + recipe. + (Patch contributed by Christopher Barker) + + - The stub executable now works for 64-bit application bundles + + - (Lowlevel) The application stub was rewritten to use + ``dlopen`` instead of ``dyld`` APIs. This removes deprecation + warnings during compilation. + + py2app 0.4.3 + ------------ + + py2app 0.4.3 is a bugfix release + + Bug fixes: + + - A bad format string in build_app.py made it impossible to copy the + Python framework into an app bundle. + + py2app 0.4.2 + ------------ + + py2app 0.4.2 is a minor feature release + + Features: + + - When the '--strip' option is specified we now also remove '.dSYM' + directories from the bundle. + + - Remove dependency on a 'version.plist' file in the python framework + + - A new recipe for `PyQt`_ 4.x. This recipe was donated by Kevin Walzer. + + - A new recipe for `virtualenv`_, this allows you to use py2app from + a virtual environment. + + .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv + + - Adds support for converting ``.xib`` files (NIB files for + Interface Builder 3) + + - Introduces an experimental plugin API for data converters. + + A conversion plugin should be defined as an entry-point in the + ``py2app.converter`` group:: + + setup( + ... + entry_points = { + 'py2app.converter': [ + "label = some_module:converter_function", + ] + }, + ... + ) + + The conversion function should be defined like this:: + + from py2app.decorators import converts + + @converts('.png') + def optimze_png(source, proposed_destionation, dryrun=0): + # Copy 'source' to 'proposed_destination' + # The conversion is allowed to change the proposed + # destination to another name in the same directory. + pass + + .. `virtualenv`_: http://pypi.python.org/pypi/virtualenv + + Buf fixes: + + - This fixes an issue with copying a different version of Python over + to an app/plugin bundle than the one used to run py2app with. + + + py2app 0.4.0 + ------------ + + py2app 0.4.0 is a minor feature release (and was never formally released). + + Features: + + - Support for CoreData mapping models (introduced in Mac OS X 10.5) + + - Support for python packages that are stored in zipfiles (such as ``zip_safe`` + python eggs). + + Bug fixes: + + - Fix incorrect symlink target creation with an alias bundle that has included + frameworks. + + - Stuffit tends to extract archives recursively, which results in unzipped + code archives inside py2app-created bundles. This version has a workaround + for this "feature" for Stuffit. + + - Be more carefull about passing non-constant strings as the template argumenti + of string formatting functions (in the app and bundle templates), to avoid + crashes under some conditions. + + py2app 0.3.6 + ------------ + + py2app 0.3.6 is a minor bugfix release. + + Bug fixes: + + - Ensure that custom icons are copied into the output bundle + + - Solve compatibility problem with some haxies and inputmanager plugins + + + py2app 0.3.5 + ------------ + + py2app 0.3.5 is a minor bugfix release. + + Bug fixes: + + - Resolve disable_linecache issue + + - Fix Info.plist and Python path for plugins + + + py2app 0.3.4 + ------------ + + py2app 0.3.4 is a minor bugfix release. + + Bug fixes: + + - Fixed a typo in the py2applet script + + - Removed some, but not all, compiler warnings from the bundle template + (which is still probably broken anyway) + + + py2app 0.3.3 + ------------ + + py2app 0.3.3 is a minor bugfix release. + + Bug Fixes: + + - Fixed a typo in the argv emulation code + + - Removed the unnecessary py2app.install hack (setuptools does that already) + + + py2app 0.3.2 + ------------ + + py2app 0.3.2 is a major bugfix release. + + Functional changes: + + - Massively updated documentation + + - New prefer-ppc option + + - New recipes: numpy, scipy, matplotlib + + - Updated py2applet script to take options, provide --make-setup + + Bug Fixes: + + - No longer defaults to LSPrefersPPC + + - Replaced stdlib usage of argvemulator to inline version for i386 + compatibility + + + py2app 0.3.1 + ------------ + + py2app 0.3.1 is a minor bugfix release. + + Functional changes: + + - New EggInstaller example + + Bug Fixes: + + - Now ensures that the executable is +x (when installed from egg this may not + be the case) + + + py2app 0.3.0 + ------------ + + py2app 0.3.0 is a major feature enhancements release. + + Functional changes: + + - New --xref (-x) option similar to py2exe's that produces + a list of modules and their interdependencies as a HTML + file + + - sys.executable now points to a regular Python interpreter + alongside the regular executable, so spawning sub-interpreters + should work much more reliably + + - Application bootstrap now detects paths containing ":" + and will provide a "friendly" error message instead of just + crashing . + + - Application bootstrap now sets PYTHONHOME instead of + a large PYTHONPATH + + - Application bootstrap rewritten in C that links to + CoreFoundation and Cocoa dynamically as needed, + so it doesn't imply any particular version of the runtime. + + - Documentation and examples changed to use setuptools + instead of distutils.core, which removes the need for + the py2app import + + - Refactored to use setuptools, distributed as an egg. + + - macholib, bdist_mpkg, modulegraph, and altgraph are now + separately maintained packages available on PyPI as eggs + + - macholib now supports little endian architectures, + 64-bit Mach-O headers, and reading/writing of + multiple headers per file (fat / universal binaries) + + + py2app 0.2.1 + ------------ + + py2app 0.2.1 is a minor bug fix release. + + Bug Fixes: + + - macholib.util.in_system_path understands SDKs now + + - DYLD_LIBRARY_PATH searching is fixed + + - Frameworks and excludes options should work again. + + + py2app 0.2.0 + ------------ + + py2app 0.2.0 is a minor bug fix release. + + Functional changes: + + - New datamodels option to support CoreData. Compiles + .xcdatamodel files and places them in the Resources dir + (as .mom). + + - New use-pythonpath option. The py2app application bootstrap + will no longer use entries from PYTHONPATH unless this option + is used. + + - py2app now persists information about the build environment + (python version, executable, build style, etc.) in the + Info.plist and will clean the executable before rebuilding + if anything at all has changed. + + - bdist_mpkg now builds packages with the full platform info, + so that installing a package for one platform combination + will not look like an upgrade to another platform combination. + + Bug Fixes: + + - Fixed a bug in standalone building, where a rebuild could + cause an unlaunchable executable. + + - Plugin bootstrap should compile/link correctly + with gcc 4. + + - Plugin bootstrap no longer sets PYTHONHOME and will + restore PYTHONPATH after initialization. + + - Plugin bootstrap swaps out thread state upon plug-in + load if it is the first to initialize Python. This + fixes threading issues. + + py2app 0.1.9 + ------------ + + py2app 0.1.9 is a minor bug fix release. + + Bugs fixed: + + - bdist_mpkg now builds zip files that are correctly unzipped + by all known tools. + + - The behavior of the bootstrap has changed slightly such that + ``__file__`` should now point to your main script, rather than + the bootstrap. The main script has also moved to ``Resources``, + from ``Resources/Python``, so that ``__file__`` relative resource + paths should still work. + + py2app 0.1.8 + ------------ + + py2app 0.1.8 is a major enhancements release: + + Bugs fixed: + + - Symlinks in included frameworks should be preserved correctly + (fixes Tcl/Tk) + + - Fixes some minor issues with alias bundles + + - Removed implicit SpiderImagePlugin -> ImageTk reference in PIL + recipe + + - The ``--optimize`` option should work now + + - ``weakref`` is now included by default + + - ``anydbm``'s dynamic dependencies are now in the standard implies + list + + - Errors on app launch are brought to the front so the user does + not miss them + + - bdist_mpkg now compatible with pychecker (data_files had issues) + + Options changed: + + - deprecated ``--strip``, it is now on by default + + - new ``--no-strip`` option to turn off stripping of executables + + New features: + + - Looks for a hacked version of the PyOpenGL __init__.py so that + it doesn't have to include the whole package in order to get + at the stupid version file. + + - New ``loader_files`` key that a recipe can return in order to + ensure that non-code ends up in the .zip (the pygame recipe + uses this) + + - Now scans all files in the bundle and normalizes Mach-O load + commands, not just extensions. This helps out when using the + ``--package`` option, when including frameworks that have plugins, + etc. + + - An embedded Python interpreter is now included in the executable + bundle (``sys.executable`` points to it), this currently only + works for framework builds of Python + + - New ``macho_standalone`` tool + + - New ``macho_find`` tool + + - Major enhancements to the way plugins are built + + - bdist_mpkg now has a ``--zipdist`` option to build zip files + from the built package + + - The bdist_mpkg "Installed to:" description is now based on the + package install root, rather than the build root + + py2app 0.1.7 + ------------ + + `py2app`_ 0.1.7 is a bug fix release: + + - The ``bdist_mpkg`` script will now set up sys.path properly, for setup scripts + that require local imports. + + - ``bdist_mpkg`` will now correctly accept ``ReadMe``, ``License``, ``Welcome``, + and ``background`` files by parameter. + + - ``bdist_mpkg`` can now display a custom background again (0.1.6 broke this). + + - ``bdist_mpkg`` now accepts a ``build-base=`` argument, to put build files in + an alternate location. + + - ``py2app`` will now accept main scripts with a ``.pyw`` extension. + + - ``py2app``'s not_stdlib_filter will now ignore a ``site-python`` directory as + well as ``site-packages``. + + - ``py2app``'s plugin bundle template no longer displays GUI dialogs by default, + but still links to ``AppKit``. + + - ``py2app`` now ensures that the directory of the main script is now added to + ``sys.path`` when scanning modules. + + - The ``py2app`` build command has been refactored such that it would be easier + to change its behavior by subclassing. + + - ``py2app`` alias bundles can now cope with editors that do atomic saves + (write new file, swap names with existing file). + + - ``macholib`` now has minimal support for fat binaries. It still assumes big + endian and will not make any changes to a little endian header. + + - Add a warning message when using the ``install`` command rather than installing + from a package. + + - New ``simple/structured`` example that shows how you could package an + application that is organized into several folders. + + - New ``PyObjC/pbplugin`` Xcode Plug-In example. + + py2app 0.1.6 + ------------ + + Since I have been slacking and the last announcement was for 0.1.4, here are the + changes for the soft-launched releases 0.1.5 and 0.1.6: + + `py2app`_ 0.1.6 was a major feature enhancements release: + + - ``py2applet`` and ``bdist_mpkg`` scripts have been moved to Python modules + so that the functionality can be shared with the tools. + + - Generic graph-related functionality from ``py2app`` was moved to + ``altgraph.ObjectGraph`` and ``altgraph.GraphUtil``. + + - ``bdist_mpkg`` now outputs more specific plist requirements + (for future compatibility). + + - ``py2app`` can now create plugin bundles (MH_BUNDLE) as well as executables. + New recipe for supporting extensions built with `sip`_, such as `PyQt`_. Note that + due to the way that `sip`_ works, when one sip-based extension is used, *all* + sip-based extensions are included in your application. In practice, this means + anything provided by `Riverbank`_, I don't think anyone else uses `sip`_ (publicly). + + - New recipe for `PyOpenGL`_. This is very naive and simply includes the whole + thing, rather than trying to monkeypatch their brain-dead + version acquisition routine in ``__init__``. + + - Bootstrap now sets ``ARGVZERO`` and ``EXECUTABLEPATH`` environment variables, + corresponding to the ``argv[0]`` and the ``_NSGetExecutablePath(...)`` that the + bundle saw. This is only really useful if you need to relaunch your own + application. + + - More correct ``dyld`` search behavior. + + - Refactored ``macholib`` to use ``altgraph``, can now generate `GraphViz`_ graphs + and more complex analysis of dependencies can be done. + + - ``macholib`` was refactored to be easier to maintain, and the structure handling + has been optimized a bit. + + - The few tests that there are were refactored in `py.test`_ style. + + - New `PyQt`_ example. + + - New `PyOpenGL`_ example. + + + See also: + + - http://mail.python.org/pipermail/pythonmac-sig/2004-December/012272.html + + .. _`py.test`: http://codespeak.net/py/current/doc/test.html + .. _`PyOpenGL`: http://pyopengl.sourceforge.net/ + .. _`Riverbank`: http://www.riverbankcomputing.co.uk/ + .. _`sip`: http://www.riverbankcomputing.co.uk/sip/index.php + .. _`PyQt`: http://www.riverbankcomputing.co.uk/pyqt/index.php + .. _`docutils`: http://docutils.sf.net/ + .. _`setuptools`: http://cvs.eby-sarna.com/PEAK/setuptools/ + + py2app 0.1.5 + ------------ + + `py2app`_ 0.1.5 is a major feature enhancements release: + + - Added a ``bdist_mpkg`` distutils extension, for creating Installer + an metapackage from any distutils script. + + - Includes PackageInstaller tool + + - bdist_mpkg script + + - setup.py enhancements to support bdist_mpkg functionality + + - Added a ``PackageInstaller`` tool, a droplet that performs the same function + as the ``bdist_mpkg`` script. + + - Create a custom ``bdist_mpkg`` subclass for `py2app`_'s setup script. + + - Source package now includes `PJE`_'s `setuptools`_ extension to distutils. + + - Added lots of metadata to the setup script. + + - ``py2app.modulegraph`` is now a top-level package, ``modulegraph``. + + - ``py2app.find_modules`` is now ``modulegraph.find_modules``. + + - Should now correctly handle paths (and application names) with unicode characters + in them. + + - New ``--strip`` option for ``py2app`` build command, strips all Mach-O files + in output application bundle. + + - New ``--bdist-base=`` option for ``py2app`` build command, allows an alternate + build directory to be specified. + + - New `docutils`_ recipe. + Support for non-framework Python, such as the one provided by `DarwinPorts`_. + + See also: + + - http://mail.python.org/pipermail/pythonmac-sig/2004-October/011933.html + + .. _`py.test`: http://codespeak.net/py/current/doc/test.html + .. _`GraphViz`: http://www.pixelglow.com/graphviz/ + .. _`PyOpenGL`: http://pyopengl.sourceforge.net/ + .. _`Riverbank`: http://www.riverbankcomputing.co.uk/ + .. _`sip`: http://www.riverbankcomputing.co.uk/sip/index.php + .. _`PyQt`: http://www.riverbankcomputing.co.uk/pyqt/index.php + .. _`DarwinPorts`: http://darwinports.opendarwin.org/ + .. _`setuptools`: http://cvs.eby-sarna.com/PEAK/setuptools/ + .. _`PJE`: http://dirtSimple.org/ + .. _`PyObjC`: http://pyobjc.sourceforge.net/ + + py2app 0.1.4 + ------------ + + `py2app`_ 0.1.4 is a minor bugfix release: + + - The ``altgraph`` from 0.1.3 had a pretty nasty bug in it that prevented + filtering from working properly, so I fixed it and bumped to 0.1.4. + + py2app 0.1.3 + ------------ + + `py2app`_ 0.1.3 is a refactoring and new features release: + + - ``altgraph``, my fork of Istvan Albert's `graphlib`_, is now part of the + distribution + + - ``py2app.modulegraph`` has been refactored to use ``altgraph`` + + - `py2app`_ can now create `GraphViz`_ DOT graphs with the ``-g`` option + (`TinyTinyEdit example`_) + + - Moved the filter stack into ``py2app.modulegraph`` + + - Fixed a bug that may have been in 0.1.2 where explicitly included packages + would not be scanned by ``macholib`` + + - ``py2app.apptemplate`` now contains a stripped down ``site`` module as + opposed to a ``sitecustomize`` + + - Alias builds are now the only ones that contain the system and user + ``site-packages`` directory in ``sys.path`` + + - The ``pydoc`` recipe has been beefed up to also exclude ``BaseHTTPServer``, + etc. + + Known issues: + + - Commands marked with XXX in the help are not implemented + + - Includes *all* files from packages, it should be smart enough to strip + unused .py/.pyc/.pyo files (to save space, depending on which optimization + flag is used) + + - ``macholib`` should be refactored to use ``altgraph`` + + - ``py2app.build_app`` and ``py2app.modulegraph`` should be refactored to + search for dependencies on a per-application basis + + .. _`graphlib`: http://www.personal.psu.edu/staff/i/u/iua1/python/graphlib/html/ + .. _`TinyTinyEdit example`: http://undefined.org/~bob/TinyTinyEdit.pdf + + py2app 0.1.2 + ------------ + + `py2app`_ 0.2 is primarily a bugfix release: + + - The encodings package now gets included in the zip file (saves space) + + - A copy of the Python interpreter is not included anymore in standalone + builds (saves space) + + - The executable bootstrap is now stripped by default (saves a little space) + + - ``sys.argv`` is set correctly now, it used to point to the executable, now + it points to the boot script. This should enhance compatibility with some + applications. + + - Adds an "Alias" feature to modulegraph, so that ``sys.modules`` craziness + such as ``wxPython.wx -> wx`` can be accomodated (this particular craziness + is also now handled by default) + + - A ``sys.path`` alternative may be passed to ``find_modules`` now, though + this is not used yet + + - The ``Command`` instance is now passed to recipes instead of the + ``Distribution`` instance (though no recipes currently use either) + + - The post-filtering of modules and extensions is now generalized into a + stack and can be modified by recipes + + - A `wxPython`_ example demonstrating how to package `wxGlade`_ has been + added (this is a good example of how to write your own recipe, and how to + deal with complex applications that mix code and data files) + + - ``PyRuntimeLocations`` is now set to (only) the location of the current + interpreter's ``Python.framework`` for alias and semi-standalone build + modes (enhances compatibility with extensions built with an unpatched + Makefile with Mac OS X 10.3's Python 2.3.0) + + Known issues: + + - Includes *all* files from packages, it should be smart enough to strip + unused .py/.pyc/.pyo files (to save space, depending on which optimization + flag is used). + + .. _`wxGlade`: http://wxglade.sourceforge.net/ + + py2app 0.1.1 + ------------ + + `py2app`_ 0.1.1 is primarily a bugfix release: + + - Several problems related to Mac OS X 10.2 compatibility and standalone + building have been resolved + + - Scripts that are not in the same directory as setup.py now work + + - A new recipe has been added that removes the pydoc -> Tkinter dependency + + - A recipe has been added for `py2app`_ itself + + - a `wxPython`_ example (superdoodle) has been added. + Demonstrates not only how easy it is (finally!) to bundle + `wxPython`_ applications, but also how one setup.py can + deal with both `py2exe`_ and `py2app`_. + + - A new experimental tool, py2applet, has been added. + Once you've built it (``python setup.py py2app``, of course), you should + be able to build simple applications simply by dragging your main script + and optionally any packages, data files, Info.plist and icon it needs. + + Known issues: + + - Includes *all* files from packages, it should be smart enough to strip + unused .py/.pyc/.pyo files (to save space, depending on which + optimization flag is used). + + - The default ``PyRuntimeLocations`` can cause problems on machines that + have a /Library/Frameworks/Python.framework installed. Workaround is + to set a plist that has the following key: + ``PyRuntimeLocations=['/System/Library/Frameworks/Python.framework/Versions/2.3/Python']`` + (this will be resolved soon) + + + py2app 0.1 + ---------- + + (first public release) + `py2app`_ is the bundlebuilder replacement we've all been waiting + for. It is implemented as a distutils command, similar to `py2exe`_. + + .. _`wxPython`: http://www.wxpython.org/ + .. _`py2app`: http://undefined.org/python/#py2app + .. _`py2exe`: http://starship.python.net/crew/theller/py2exe/ + +Keywords: .app,standalone +Platform: MacOS X +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Console +Classifier: Environment :: MacOS X :: Cocoa +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Natural Language :: English +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Objective C +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: User Interfaces +Classifier: Topic :: Software Development :: Build Tools diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/SOURCES.txt b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/SOURCES.txt new file mode 100644 index 0000000..71d6d76 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/SOURCES.txt @@ -0,0 +1,313 @@ +LICENSE.txt +MANIFEST.in +README.txt +setup.cfg +setup.py +tox.ini +doc/Makefile +doc/changelog.rst +doc/conf.py +doc/dependencies.rst +doc/examples.rst +doc/faq.rst +doc/implementation.rst +doc/index.rst +doc/install.rst +doc/options.rst +doc/py2applet.rst +doc/recipes.rst +doc/tutorial.rst +doc/tweaking.rst +examples/EggInstaller/Egg.icns +examples/EggInstaller/EggInstaller.py +examples/EggInstaller/setup.py +examples/PIL/hello.py +examples/PIL/setup.py +examples/PyObjC/ICSharingWatcher/ICSharingWatcher.py +examples/PyObjC/ICSharingWatcher/TableModelAppDelegate.py +examples/PyObjC/ICSharingWatcher/leases.py +examples/PyObjC/ICSharingWatcher/setup.py +examples/PyObjC/ICSharingWatcher/MainMenu.nib/classes.nib +examples/PyObjC/ICSharingWatcher/MainMenu.nib/info.nib +examples/PyObjC/ICSharingWatcher/MainMenu.nib/keyedobjects.nib +examples/PyObjC/TinyTinyEdit/TinyTinyEdit.py +examples/PyObjC/TinyTinyEdit/setup.py +examples/PyObjC/TinyTinyEdit/MainMenu.nib/classes.nib +examples/PyObjC/TinyTinyEdit/MainMenu.nib/info.nib +examples/PyObjC/TinyTinyEdit/MainMenu.nib/objects.nib +examples/PyObjC/TinyTinyEdit/TinyTinyDocument.nib/classes.nib +examples/PyObjC/TinyTinyEdit/TinyTinyDocument.nib/info.nib +examples/PyObjC/TinyTinyEdit/TinyTinyDocument.nib/objects.nib +examples/PyObjC/pbplugin/PyTestPlugin.py +examples/PyObjC/pbplugin/setup.py +examples/PyObjC/pbplugin/test.py +examples/PyOpenGL/lesson5.py +examples/PyOpenGL/setup.py +examples/PyQt/hello_app/hello.py +examples/PyQt/hello_app/setup.py +examples/PyQt/view_app/main.py +examples/PyQt/view_app/setup.py +examples/PyQt/view_app/view.qml +examples/PySide/hello.py +examples/PySide/setup.py +examples/Tkinter/hello_tk/hello.py +examples/Tkinter/hello_tk/setup.py +examples/embedded_interpreter/simple/hello.py +examples/embedded_interpreter/simple/setup.py +examples/pkg_data/setup.py +examples/pkg_data/use_testpkg.py +examples/pkg_data/testpkg/__init__.py +examples/pkg_data/testpkg/data.txt +examples/pygame/aliens.py +examples/pygame/aliens_bootstrap.py +examples/pygame/setup.py +examples/pygame/English.lproj/aliens.icns +examples/pygame/English.lproj/MainMenu.nib/JavaCompiling.plist +examples/pygame/English.lproj/MainMenu.nib/_MainMenu_EOArchive_English.java +examples/pygame/English.lproj/MainMenu.nib/classes.nib +examples/pygame/English.lproj/MainMenu.nib/info.nib +examples/pygame/English.lproj/MainMenu.nib/keyedobjects.nib +examples/pygame/data/alien1.gif +examples/pygame/data/alien2.gif +examples/pygame/data/alien3.gif +examples/pygame/data/background.gif +examples/pygame/data/bomb.gif +examples/pygame/data/boom.wav +examples/pygame/data/car_door.wav +examples/pygame/data/explosion1.gif +examples/pygame/data/house_lo.wav +examples/pygame/data/player1.gif +examples/pygame/data/shot.gif +examples/simple/hello.py +examples/simple/setup.py +examples/structured/data/datafile.txt +examples/structured/python/myapp.py +examples/structured/python/needsthis.py +examples/structured/setup/setup.py +examples/wxPython/2.4/doodle/doodle.py +examples/wxPython/2.4/doodle/setup.py +examples/wxPython/2.4/doodle/superdoodle.py +examples/wxPython/2.5/doodle/doodle.py +examples/wxPython/2.5/doodle/setup.py +examples/wxPython/2.5/doodle/superdoodle.py +examples/wxPython/2.5/drpython/setup.py +examples/wxPython/2.5/wxGlade/README.txt +examples/wxPython/2.5/wxGlade/setup.py +examples/wxPython/2.5/wxGlade/wxGlade.py +py2app/__init__.py +py2app/build_app.py +py2app/create_appbundle.py +py2app/create_pluginbundle.py +py2app/decorators.py +py2app/filters.py +py2app/script_py2applet.py +py2app/util.py +py2app.egg-info/PKG-INFO +py2app.egg-info/SOURCES.txt +py2app.egg-info/dependency_links.txt +py2app.egg-info/entry_points.txt +py2app.egg-info/not-zip-safe +py2app.egg-info/requires.txt +py2app.egg-info/top_level.txt +py2app/apptemplate/__init__.py +py2app/apptemplate/plist_template.py +py2app/apptemplate/setup.py +py2app/apptemplate/lib/__error__.sh +py2app/apptemplate/lib/site.py +py2app/apptemplate/prebuilt/main-fat +py2app/apptemplate/prebuilt/main-fat3 +py2app/apptemplate/prebuilt/main-i386 +py2app/apptemplate/prebuilt/main-intel +py2app/apptemplate/prebuilt/main-ppc +py2app/apptemplate/prebuilt/main-ppc64 +py2app/apptemplate/prebuilt/main-universal +py2app/apptemplate/prebuilt/main-x86_64 +py2app/apptemplate/prebuilt/secondary-fat +py2app/apptemplate/prebuilt/secondary-fat3 +py2app/apptemplate/prebuilt/secondary-i386 +py2app/apptemplate/prebuilt/secondary-intel +py2app/apptemplate/prebuilt/secondary-ppc +py2app/apptemplate/prebuilt/secondary-ppc64 +py2app/apptemplate/prebuilt/secondary-universal +py2app/apptemplate/prebuilt/secondary-x86_64 +py2app/apptemplate/src/main.c +py2app/bootstrap/__init__.py +py2app/bootstrap/argv_emulation.py +py2app/bootstrap/argv_inject.py +py2app/bootstrap/boot_aliasapp.py +py2app/bootstrap/boot_aliasplugin.py +py2app/bootstrap/boot_app.py +py2app/bootstrap/boot_plugin.py +py2app/bootstrap/chdir_resource.py +py2app/bootstrap/ctypes_setup.py +py2app/bootstrap/disable_linecache.py +py2app/bootstrap/emulate_shell_environment.py +py2app/bootstrap/import_encodings.py +py2app/bootstrap/path_inject.py +py2app/bootstrap/reset_sys_path.py +py2app/bootstrap/semi_standalone_path.py +py2app/bootstrap/setup_included_subpackages.py +py2app/bootstrap/setup_pkgresource.py +py2app/bootstrap/site_packages.py +py2app/bootstrap/system_path_extras.py +py2app/bootstrap/virtualenv.py +py2app/bootstrap/virtualenv_site_packages.py +py2app/bundletemplate/__init__.py +py2app/bundletemplate/plist_template.py +py2app/bundletemplate/setup.py +py2app/bundletemplate/lib/__error__.sh +py2app/bundletemplate/lib/site.py +py2app/bundletemplate/prebuilt/main-fat +py2app/bundletemplate/prebuilt/main-fat3 +py2app/bundletemplate/prebuilt/main-i386 +py2app/bundletemplate/prebuilt/main-intel +py2app/bundletemplate/prebuilt/main-ppc +py2app/bundletemplate/prebuilt/main-ppc64 +py2app/bundletemplate/prebuilt/main-universal +py2app/bundletemplate/prebuilt/main-x86_64 +py2app/bundletemplate/src/main.m +py2app/converters/__init__.py +py2app/converters/coredata.py +py2app/converters/nibfile.py +py2app/recipes/__init__.py +py2app/recipes/cjkcodecs.py +py2app/recipes/ctypes.py +py2app/recipes/docutils.py +py2app/recipes/ftplib.py +py2app/recipes/importlib.py +py2app/recipes/lxml.py +py2app/recipes/matplotlib.py +py2app/recipes/matplotlib_prescript.py +py2app/recipes/mimetypes.py +py2app/recipes/numpy.py +py2app/recipes/os_module.py +py2app/recipes/pydoc.py +py2app/recipes/pyenchant.py +py2app/recipes/pygame.py +py2app/recipes/pyopengl.py +py2app/recipes/pyside.py +py2app/recipes/pyzmq.py +py2app/recipes/qt.conf +py2app/recipes/qt5.py +py2app/recipes/re.py +py2app/recipes/scipy.py +py2app/recipes/setuptools.py +py2app/recipes/sip.py +py2app/recipes/subprocess.py +py2app/recipes/uuid.py +py2app/recipes/virtualenv.py +py2app/recipes/wx.py +py2app/recipes/xml.py +py2app/recipes/PIL/__init__.py +py2app/recipes/PIL/prescript.py +py2app_tests/__init__.py +py2app_tests/bundle_loader.m +py2app_tests/test_app_resources.py +py2app_tests/test_app_with_ctypes.py +py2app_tests/test_app_with_scripts.py +py2app_tests/test_app_with_sharedlib.py +py2app_tests/test_argv_emulation.py +py2app_tests/test_basic_app.py +py2app_tests/test_basic_app_with_encoding.py +py2app_tests/test_basic_app_with_plugin.py +py2app_tests/test_basic_plugin.py +py2app_tests/test_compile_resources.py +py2app_tests/test_email_pkg.py +py2app_tests/test_explicit_includes.py +py2app_tests/test_filters.py +py2app_tests/test_lsenvironment.py +py2app_tests/test_package_data.py +py2app_tests/test_pkg_script.py +py2app_tests/test_plugin_with_scripts.py +py2app_tests/test_py2applet.py +py2app_tests/test_recipe_imports.py +py2app_tests/test_setup.py +py2app_tests/test_shell_environment.py +py2app_tests/tools.py +py2app_tests/app_with_data/main.icns +py2app_tests/app_with_data/main.py +py2app_tests/app_with_data/setup.py +py2app_tests/app_with_data/data1/file1.txt +py2app_tests/app_with_data/data1/file2.txt +py2app_tests/app_with_data/data1/file3.sh +py2app_tests/app_with_data/data2/source.c +py2app_tests/app_with_data/data3/source.c +py2app_tests/app_with_email/main-all.py +py2app_tests/app_with_email/main-compat.py +py2app_tests/app_with_email/main-plain.py +py2app_tests/app_with_email/setup-all.py +py2app_tests/app_with_email/setup-compat.py +py2app_tests/app_with_email/setup-plain.py +py2app_tests/app_with_environment/main.py +py2app_tests/app_with_environment/setup.py +py2app_tests/app_with_scripts/helper1.py +py2app_tests/app_with_scripts/main.py +py2app_tests/app_with_scripts/presetup.py +py2app_tests/app_with_scripts/setup.py +py2app_tests/app_with_scripts/build/libdir/libfoo.dylib.libtool.i386 +py2app_tests/app_with_scripts/build/libdir/libfoo.o +py2app_tests/app_with_scripts/src/libfoo.c +py2app_tests/app_with_scripts/src/libfoo.h +py2app_tests/app_with_scripts/src/modfoo.c +py2app_tests/app_with_scripts/subdir/helper2.py +py2app_tests/app_with_shared_ctypes/main.py +py2app_tests/app_with_shared_ctypes/setup.py +py2app_tests/app_with_shared_ctypes/src/sharedlib.c +py2app_tests/app_with_shared_ctypes/src/sharedlib.h +py2app_tests/app_with_sharedlib/main.py +py2app_tests/app_with_sharedlib/mod.c +py2app_tests/app_with_sharedlib/setup.py +py2app_tests/app_with_sharedlib/src/sharedlib.c +py2app_tests/app_with_sharedlib/src/sharedlib.h +py2app_tests/argv_app/main.py +py2app_tests/argv_app/setup-with-urlscheme.py +py2app_tests/argv_app/setup.py +py2app_tests/basic_app/main.py +py2app_tests/basic_app/setup.py +py2app_tests/basic_app/package1/__init__.py +py2app_tests/basic_app/package1/subpackage/__init__.py +py2app_tests/basic_app/package1/subpackage/module.py +py2app_tests/basic_app/package2/__init__.py +py2app_tests/basic_app/package2/sub/__init__.py +py2app_tests/basic_app/package2/sub/data.dat +py2app_tests/basic_app/package3/mod.py +py2app_tests/basic_app2/main-script +py2app_tests/basic_app2/setup.py +py2app_tests/basic_app2/package1/__init__.py +py2app_tests/basic_app2/package1/subpackage/__init__.py +py2app_tests/basic_app2/package1/subpackage/module.py +py2app_tests/basic_app2/package2/__init__.py +py2app_tests/basic_app2/package2/sub/__init__.py +py2app_tests/basic_app2/package2/sub/data.dat +py2app_tests/basic_app_with_encoding/main.py +py2app_tests/basic_app_with_encoding/setup.py +py2app_tests/basic_app_with_encoding/package1/__init__.py +py2app_tests/basic_app_with_encoding/package1/subpackage/__init__.py +py2app_tests/basic_app_with_encoding/package1/subpackage/module.py +py2app_tests/basic_app_with_encoding/package2/__init__.py +py2app_tests/basic_app_with_encoding/package2/sub/__init__.py +py2app_tests/basic_app_with_encoding/package2/sub/data.dat +py2app_tests/basic_app_with_encoding/package3/mod.py +py2app_tests/basic_app_with_plugin/dummy1.qlgenerator +py2app_tests/basic_app_with_plugin/dummy2.mdimporter +py2app_tests/basic_app_with_plugin/main.py +py2app_tests/basic_app_with_plugin/setup.py +py2app_tests/basic_plugin/main.py +py2app_tests/basic_plugin/setup.py +py2app_tests/bundle_loader.dSYM/Contents/Info.plist +py2app_tests/bundle_loader.dSYM/Contents/Resources/DWARF/bundle_loader +py2app_tests/pkg_script_app/quot.py +py2app_tests/pkg_script_app/setup.py +py2app_tests/pkg_script_app/quot/__init__.py +py2app_tests/pkg_script_app/quot/queue.py +py2app_tests/plugin_with_scripts/helper1.py +py2app_tests/plugin_with_scripts/helper2.py +py2app_tests/plugin_with_scripts/main.py +py2app_tests/plugin_with_scripts/setup.py +py2app_tests/resource_compile_app/MainMenu.xib +py2app_tests/resource_compile_app/main.py +py2app_tests/resource_compile_app/setup.py +py2app_tests/shell_app/main.py +py2app_tests/shell_app/setup.py +tools/py2applet/py2applet.py +tools/py2applet/setup.py \ No newline at end of file diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/dependency_links.txt b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/entry_points.txt b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/entry_points.txt new file mode 100644 index 0000000..48df508 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/entry_points.txt @@ -0,0 +1,18 @@ +[console_scripts] +py2applet = py2app.script_py2applet:main + +[distutils.commands] +py2app = py2app.build_app:py2app + +[distutils.setup_keywords] +app = py2app.build_app:validate_target +plugin = py2app.build_app:validate_target + +[py2app.converter] +datamodel = py2app.converters.coredata:convert_datamodel +mappingmodel = py2app.converters.coredata:convert_mappingmodel +xib = py2app.converters.nibfile:convert_xib + +[py2app.recipe] + + diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/not-zip-safe b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/not-zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/not-zip-safe @@ -0,0 +1 @@ + diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/requires.txt b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/requires.txt new file mode 100644 index 0000000..93699fe --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/requires.txt @@ -0,0 +1,3 @@ +altgraph>=0.13 +modulegraph>=0.14 +macholib>=1.8 diff --git a/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/top_level.txt b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/top_level.txt new file mode 100644 index 0000000..b7fc5f7 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/EGG-INFO/top_level.txt @@ -0,0 +1 @@ +py2app diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/__init__.py new file mode 100644 index 0000000..ef92fab --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/__init__.py @@ -0,0 +1,34 @@ +""" +builds Mac OS X application bundles from Python scripts + +New keywords for distutils' setup function specify what to build: + + app + list of scripts to convert into gui app bundles + +py2app options, to be specified in the options keyword to the setup function: + + optimize - string or int (0, 1, or 2) + + includes - list of module names to include + packages - list of packages to include with subpackages + ignores - list of modules to ignore if they are not found + excludes - list of module names to exclude + dylib_excludes - list of dylibs and/or frameworks to exclude + resources - list of additional files and folders to include + plist - Info.plist template file, dict, or plistlib.Plist + dist_dir - directory where to build the final files + +Items in the macosx list can also be +dictionaries to further customize the build process. The following +keys in the dictionary are recognized, most are optional: + + script (MACOSX) - list of python scripts (required) + dest_base - directory and basename for the executable + if a directory is contained, must be the same for all targets +""" +import pkg_resources +__version__ = pkg_resources.require('py2app')[0].version + +# This makes the py2app command work in the distutils.core.setup() case +import setuptools diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/__init__.py new file mode 100644 index 0000000..a7a39be --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/__init__.py @@ -0,0 +1,2 @@ +from . import setup +from . import plist_template diff --git a/dist/main.app/Contents/Resources/__error__.sh b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/lib/__error__.sh similarity index 100% rename from dist/main.app/Contents/Resources/__error__.sh rename to .eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/lib/__error__.sh diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/lib/site.py b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/lib/site.py new file mode 100644 index 0000000..354e729 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/lib/site.py @@ -0,0 +1,132 @@ +""" +Append module search paths for third-party packages to sys.path. + +This is stripped down and customized for use in py2app applications +""" + +import sys +# os is actually in the zip, so we need to do this here. +# we can't call it python24.zip because zlib is not a built-in module (!) +_libdir = '/lib/python' + sys.version[:3] +_parent = '/'.join(__file__.split('/')[:-1]) +if not _parent.endswith(_libdir): + _parent += _libdir +sys.path.append(_parent + '/site-packages.zip') + +# Stuffit decompresses recursively by default, that can mess up py2app bundles, +# add the uncompressed site-packages to the path to compensate for that. +sys.path.append(_parent + '/site-packages') + +USER_SITE=None + +import os +try: + basestring +except NameError: + basestring = str + +def makepath(*paths): + dir = os.path.abspath(os.path.join(*paths)) + return dir, os.path.normcase(dir) + +for m in sys.modules.values(): + f = getattr(m, '__file__', None) + if isinstance(f, basestring) and os.path.exists(f): + m.__file__ = os.path.abspath(m.__file__) +del m + +# This ensures that the initial path provided by the interpreter contains +# only absolute pathnames, even if we're running from the build directory. +L = [] +_dirs_in_sys_path = {} +dir = dircase = None # sys.path may be empty at this point +for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in _dirs_in_sys_path: + L.append(dir) + _dirs_in_sys_path[dircase] = 1 +sys.path[:] = L +del dir, dircase, L +_dirs_in_sys_path = None + +def _init_pathinfo(): + global _dirs_in_sys_path + _dirs_in_sys_path = d = {} + for dir in sys.path: + if dir and not os.path.isdir(dir): + continue + dir, dircase = makepath(dir) + d[dircase] = 1 + +def addsitedir(sitedir): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in _dirs_in_sys_path: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name[-4:] == os.extsep + "pth": + addpackage(sitedir, name) + if reset: + _dirs_in_sys_path = None + +def addpackage(sitedir, name): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + with open(fullname) as f: + while 1: + dir = f.readline() + if not dir: + break + if dir[0] == '#': + continue + if dir.startswith("import"): + exec(dir) + continue + if dir[-1] == '\n': + dir = dir[:-1] + dir, dircase = makepath(sitedir, dir) + if not dircase in _dirs_in_sys_path and os.path.exists(dir): + sys.path.append(dir) + _dirs_in_sys_path[dircase] = 1 + except IOError: + return + if reset: + _dirs_in_sys_path = None + + +#sys.setdefaultencoding('utf-8') + +# +# Run custom site specific code, if available. +# +try: + import sitecustomize +except ImportError: + pass + +# +# Remove sys.setdefaultencoding() so that users cannot change the +# encoding after initialization. The test for presence is needed when +# this module is run as a script, because this code is executed twice. +# +if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/plist_template.py b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/plist_template.py new file mode 100644 index 0000000..a6d6a4f --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/plist_template.py @@ -0,0 +1,46 @@ +import sys +import py2app +__all__ = ['infoPlistDict'] + +def infoPlistDict(CFBundleExecutable, plist={}): + CFBundleExecutable = CFBundleExecutable + version = sys.version[:3] + pdict = dict( + CFBundleDevelopmentRegion='English', + CFBundleDisplayName=plist.get('CFBundleName', CFBundleExecutable), + CFBundleExecutable=CFBundleExecutable, + CFBundleIconFile=CFBundleExecutable, + CFBundleIdentifier='org.pythonmac.unspecified.%s' % (''.join(CFBundleExecutable.split()),), + CFBundleInfoDictionaryVersion='6.0', + CFBundleName=CFBundleExecutable, + CFBundlePackageType='APPL', + CFBundleShortVersionString=plist.get('CFBundleVersion', '0.0'), + CFBundleSignature='????', + CFBundleVersion='0.0', + LSHasLocalizedDisplayName=False, + NSAppleScriptEnabled=False, + NSHumanReadableCopyright='Copyright not specified', + NSMainNibFile='MainMenu', + NSPrincipalClass='NSApplication', + PyMainFileNames=['__boot__'], + PyResourcePackages=[], + PyRuntimeLocations=[(s % version) for s in [ + '@executable_path/../Frameworks/Python.framework/Versions/%s/Python', + '~/Library/Frameworks/Python.framework/Versions/%s/Python', + '/Library/Frameworks/Python.framework/Versions/%s/Python', + '/Network/Library/Frameworks/Python.framework/Versions/%s/Python', + '/System/Library/Frameworks/Python.framework/Versions/%s/Python', + ]], + ) + pdict.update(plist) + pythonInfo = pdict.setdefault('PythonInfoDict', {}) + pythonInfo.update(dict( + PythonLongVersion=sys.version, + PythonShortVersion=sys.version[:3], + PythonExecutable=sys.executable, + )) + py2appInfo = pythonInfo.setdefault('py2app', {}).update(dict( + version=py2app.__version__, + template='app', + )) + return pdict diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat new file mode 100755 index 0000000..093cb42 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat3 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat3 new file mode 100755 index 0000000..04953be Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-fat3 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-i386 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-i386 new file mode 100755 index 0000000..e042b8f Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-i386 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-intel b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-intel new file mode 100755 index 0000000..3b996d4 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-intel differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc new file mode 100755 index 0000000..3304def Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc64 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc64 new file mode 100755 index 0000000..1895924 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-ppc64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-universal b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-universal new file mode 100755 index 0000000..fd959d8 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-universal differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-x86_64 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-x86_64 new file mode 100755 index 0000000..c30d969 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/main-x86_64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat new file mode 100755 index 0000000..b7f2299 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat3 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat3 new file mode 100755 index 0000000..4f5b94b Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-fat3 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-i386 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-i386 new file mode 100755 index 0000000..d59ef1c Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-i386 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-intel b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-intel new file mode 100755 index 0000000..7b6ee23 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-intel differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc new file mode 100755 index 0000000..d0579f3 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc64 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc64 new file mode 100755 index 0000000..ab1f92b Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-ppc64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-universal b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-universal new file mode 100755 index 0000000..c425a14 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-universal differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-x86_64 b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-x86_64 new file mode 100755 index 0000000..32c4faf Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/prebuilt/secondary-x86_64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/setup.py b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/setup.py new file mode 100644 index 0000000..d6bccd9 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/setup.py @@ -0,0 +1,129 @@ +import os +import re +import sys +import distutils.sysconfig +import distutils.util + +gPreBuildVariants = [ + { + 'name': 'main-universal', + 'target': '10.5', + 'cflags': '-g -isysroot /Developer/SDKs/MacOSX10.5.sdk -arch i386 -arch ppc -arch ppc64 -arch x86_64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-ppc64', + 'target': '10.5', + 'cflags': '-g -isysroot /Developer/SDKs/MacOSX10.5.sdk -arch ppc64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-x86_64', + 'target': '10.5', + 'cflags': '-g -arch x86_64', + 'cc': '/usr/bin/clang', + }, + { + 'name': 'main-fat3', + 'target': '10.5', + 'cflags': '-g -isysroot / -arch i386 -arch ppc -arch x86_64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-intel', + 'target': '10.5', + 'cflags': '-g -arch i386 -arch x86_64 -fexceptions', + 'cc': '/usr/bin/clang', + }, + { + 'name': 'main-i386', + 'target': '10.4', + 'cflags': '-g -arch i386', + 'cc': '/usr/bin/clang', + }, + { + 'name': 'main-ppc', + 'target': '10.3', + 'cflags': '-g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc', + 'cc': 'gcc-4.0', + }, + { + 'name': 'main-fat', + 'target': '10.3', + 'cflags': '-g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc', + 'cc': 'gcc-4.0', + }, +] + + +def main(all=False, arch=None, secondary=False): + basepath = os.path.dirname(__file__) + builddir = os.path.join(basepath, 'prebuilt') + if not os.path.exists(builddir): + os.makedirs(builddir) + src = os.path.join(basepath, 'src', 'main.c') + + cfg = distutils.sysconfig.get_config_vars() + + BASE_CFLAGS = cfg['CFLAGS'] + BASE_CFLAGS = BASE_CFLAGS.replace('-dynamic', '') + while True: + x = re.sub('-arch\s+\S+', '', BASE_CFLAGS) + if x == BASE_CFLAGS: + break + BASE_CFLAGS=x + + while True: + x = re.sub('-isysroot\s+\S+', '', BASE_CFLAGS) + if x == BASE_CFLAGS: + break + BASE_CFLAGS=x + + if arch is None: + arch = distutils.util.get_platform().split('-')[-1] + if sys.prefix.startswith('/System') and \ + sys.version_info[:2] == (2,5): + arch = "fat" + + name = 'main-' + arch + root = None + + if all: + for entry in gPreBuildVariants: + dest = os.path.join(builddir, entry['name']) + + for replace in (0, 1): + if replace: + dest = os.path.join(builddir, entry['name'].replace('main', 'secondary')) + + if not os.path.exists(dest) or ( + os.stat(dest).st_mtime < os.stat(src).st_mtime): + if root is None: + fp = os.popen('xcode-select -print-path', 'r') + root = fp.read().strip() + fp.close() + + print ("rebuilding %s"%(os.path.basename(dest),)) + + CC=os.path.join(root, 'usr', 'bin', entry['cc']) + CFLAGS = BASE_CFLAGS + ' ' + entry['cflags'].replace('@@XCODE_ROOT@@', root) + if replace: + CFLAGS += " -DPY2APP_SECONDARY" + os.environ['MACOSX_DEPLOYMENT_TARGET'] = entry['target'] + os.system('"%(CC)s" -o "%(dest)s" "%(src)s" %(CFLAGS)s -framework Cocoa' % locals()) + + if secondary: + name = 'secondary-' + else: + name = 'main-' + + dest = os.path.join( + builddir, + name + arch + ) + + return dest + + +if __name__ == '__main__': + main(all=True) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/src/main.c b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/src/main.c new file mode 100644 index 0000000..53e21eb --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/apptemplate/src/main.c @@ -0,0 +1,1240 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + Typedefs +*/ + +typedef int PyObject; +typedef PyObject* (*Py_BuildValuePtr)(const char*, ...); +#if 0 +typedef void (*Py_SetPathPtr)(const wchar_t*); +#endif +typedef int (*PySys_SetObjectPtr)(const char*, PyObject*); +typedef void (*Py_SetProgramNamePtr)(const char *); +typedef void (*Py_InitializePtr)(void); +typedef int (*PyRun_SimpleFilePtr)(FILE *, const char *); +typedef void (*Py_FinalizePtr)(void); +typedef PyObject *(*PySys_GetObjectPtr)(const char *); +typedef int *(*PySys_SetArgvPtr)(int argc, char **argv); +typedef PyObject *(*PyObject_GetAttrStringPtr)(PyObject *, const char *); +typedef wchar_t* (*_Py_DecodeUTF8_surrogateescapePtr)(const char *s, ssize_t size); + + +typedef CFTypeRef id; +typedef const char * SEL; +typedef signed char BOOL; +#define NSAlertAlternateReturn 0 + +/* + Forward declarations +*/ +static int report_error(const char *); +static CFTypeRef py2app_getKey(const char *key); + +/* + Strings +*/ +static const char *ERR_REALLYBADTITLE = "The application could not be launched."; +static const char *ERR_TITLEFORMAT = "%@ has encountered a fatal error, and will now terminate."; +static const char *ERR_NONAME = "The Info.plist file must have values for the CFBundleName or CFBundleExecutable strings."; +static const char *ERR_PYRUNTIMELOCATIONS = "The Info.plist file must have a PyRuntimeLocations array containing string values for preferred Python runtime locations. These strings should be \"otool -L\" style mach ids; \"@executable_stub\" and \"~\" prefixes will be translated accordingly."; +static const char *ERR_NOPYTHONRUNTIME = "A Python runtime not could be located. You may need to install a framework build of Python, or edit the PyRuntimeLocations array in this application's Info.plist file."; +static const char *ERR_NOPYTHONSCRIPT = "A main script could not be located in the Resources folder.;"; +static const char *ERR_LINKERRFMT = "An internal error occurred while attempting to link with:\r\r%s\r\rSee the Console for a detailed dyld error message"; +static const char *ERR_PYTHONEXCEPTION = "An uncaught exception was raised during execution of the main script.\r\rThis may mean that an unexpected error has occurred, or that you do not have all of the dependencies for this application.\r\rSee the Console for a detailed traceback."; +static const char *ERR_COLONPATH = "Python applications can not currently run from paths containing a '/' (or ':' from the Terminal)."; +static const char *ERR_DEFAULTURLTITLE = "Visit Website"; +static const char *ERR_CONSOLEAPP = "Console.app"; +static const char *ERR_CONSOLEAPPTITLE = "Open Console"; +static const char *ERR_TERMINATE = "Terminate"; + +/* + Globals +*/ +static CFMutableArrayRef py2app_pool; + +#define USES(NAME) static __typeof__(&NAME) py2app_ ## NAME +/* ApplicationServices */ +USES(LSOpenFSRef); +USES(LSFindApplicationForInfo); +USES(GetCurrentProcess); +USES(SetFrontProcess); +/* CoreFoundation */ +USES(CFArrayRemoveValueAtIndex); +USES(CFStringCreateFromExternalRepresentation); +USES(CFStringAppendCString); +USES(CFStringCreateMutable); +USES(kCFTypeArrayCallBacks); +USES(CFArrayCreateMutable); +USES(CFRetain); +USES(CFRelease); +USES(CFBundleGetValueForInfoDictionaryKey); +USES(CFArrayGetCount); +USES(CFStringCreateWithCString); +USES(CFArrayGetValueAtIndex); +USES(CFArrayAppendValue); +USES(CFStringFind); +USES(CFBundleCopyPrivateFrameworksURL); +USES(CFURLCreateWithFileSystemPathRelativeToBase); +USES(CFStringCreateWithSubstring); +USES(CFStringGetLength); +USES(CFURLGetFileSystemRepresentation); +USES(CFURLCreateWithFileSystemPath); +USES(CFShow); +USES(CFBundleCopyResourcesDirectoryURL); +USES(CFURLCreateFromFileSystemRepresentation); +USES(CFURLCreateFromFileSystemRepresentationRelativeToBase); +USES(CFStringGetCharacterAtIndex); +USES(CFURLCreateWithString); +USES(CFStringGetCString); +USES(CFStringCreateByCombiningStrings); +USES(CFDictionaryGetValue); +USES(CFBooleanGetValue); +USES(CFNumberGetValue); +USES(CFStringCreateArrayBySeparatingStrings); +USES(CFArrayAppendArray); +USES(CFStringCreateByCombiningStrings); +USES(CFStringCreateWithFormat); +USES(CFBundleCopyResourceURL); +USES(CFBundleCopyAuxiliaryExecutableURL); +USES(CFURLCreateCopyDeletingLastPathComponent); +USES(CFURLCreateCopyAppendingPathComponent); +USES(CFURLCopyLastPathComponent); +USES(CFStringGetMaximumSizeForEncoding); +#undef USES + +/* + objc +*/ + +static id (*py2app_objc_getClass)(const char *name); +static SEL (*py2app_sel_getUid)(const char *str); +static id (*py2app_objc_msgSend)(id self, SEL op, ...); + +/* + Cocoa +*/ +static void (*py2app_NSLog)(CFStringRef format, ...); +static BOOL (*py2app_NSApplicationLoad)(void); +static int (*py2app_NSRunAlertPanel)(CFStringRef title, CFStringRef msg, CFStringRef defaultButton, CFStringRef alternateButton, CFStringRef otherButton, ...); + +/* + Functions +*/ + +static int bind_objc_Cocoa_ApplicationServices(void) { + static Boolean bound = false; + if (bound) return 0; + bound = true; + void* cf_dylib; + cf_dylib = dlopen("/usr/lib/libobjc.dylib", RTLD_LAZY); + if (!cf_dylib) return -1; + +#define LOOKUP(NAME) do { \ + py2app_ ## NAME = (__typeof__(py2app_ ## NAME))dlsym( \ + cf_dylib, #NAME); \ + if (!py2app_ ## NAME) return -1; \ + } while (0) + + LOOKUP(objc_getClass); + LOOKUP(sel_getUid); + LOOKUP(objc_msgSend); + + cf_dylib = dlopen( + "/System/Library/Frameworks/Cocoa.framework/Cocoa", + RTLD_LAZY); + if (!cf_dylib) return -1; + LOOKUP(NSLog); + LOOKUP(NSApplicationLoad); + LOOKUP(NSRunAlertPanel); + + cf_dylib = dlopen( + "/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", + RTLD_LAZY); + if (!cf_dylib) return -1; + + LOOKUP(GetCurrentProcess); + LOOKUP(SetFrontProcess); + LOOKUP(LSOpenFSRef); + LOOKUP(LSFindApplicationForInfo); +#undef LOOKUP + return 0; +} + +static int bind_CoreFoundation(void) { + static Boolean bound = false; + void *cf_dylib; + if (bound) return 0; + bound = true; + cf_dylib = dlopen( + "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", + RTLD_LAZY); + if (!cf_dylib) return -1; + +#define LOOKUP(NAME) do { \ + py2app_ ## NAME = (__typeof__(py2app_ ## NAME))dlsym( \ + cf_dylib, #NAME); \ + if (!py2app_ ## NAME) return -1; \ + } while (0) + + LOOKUP(CFArrayRemoveValueAtIndex); + LOOKUP(CFStringCreateFromExternalRepresentation); + LOOKUP(CFStringAppendCString); + LOOKUP(CFStringCreateMutable); + LOOKUP(kCFTypeArrayCallBacks); + LOOKUP(CFArrayCreateMutable); + LOOKUP(CFRetain); + LOOKUP(CFRelease); + LOOKUP(CFBundleGetValueForInfoDictionaryKey); + LOOKUP(CFArrayGetCount); + LOOKUP(CFStringCreateWithCString); + LOOKUP(CFArrayGetValueAtIndex); + LOOKUP(CFArrayAppendValue); + LOOKUP(CFStringFind); + LOOKUP(CFBundleCopyPrivateFrameworksURL); + LOOKUP(CFURLCreateWithFileSystemPathRelativeToBase); + LOOKUP(CFStringCreateWithSubstring); + LOOKUP(CFStringGetLength); + LOOKUP(CFURLGetFileSystemRepresentation); + LOOKUP(CFURLCreateWithFileSystemPath); + LOOKUP(CFShow); + LOOKUP(CFBundleCopyResourcesDirectoryURL); + LOOKUP(CFURLCreateFromFileSystemRepresentation); + LOOKUP(CFURLCreateFromFileSystemRepresentationRelativeToBase); + LOOKUP(CFStringGetCharacterAtIndex); + LOOKUP(CFURLCreateWithString); + LOOKUP(CFStringGetCString); + LOOKUP(CFStringCreateByCombiningStrings); + LOOKUP(CFDictionaryGetValue); + LOOKUP(CFBooleanGetValue); + LOOKUP(CFNumberGetValue); + LOOKUP(CFStringCreateArrayBySeparatingStrings); + LOOKUP(CFArrayAppendArray); + LOOKUP(CFStringCreateByCombiningStrings); + LOOKUP(CFStringCreateWithFormat); + LOOKUP(CFBundleCopyResourceURL); + LOOKUP(CFBundleCopyAuxiliaryExecutableURL); + LOOKUP(CFURLCreateCopyDeletingLastPathComponent); + LOOKUP(CFURLCreateCopyAppendingPathComponent); + LOOKUP(CFURLCopyLastPathComponent); + LOOKUP(CFStringGetMaximumSizeForEncoding); + +#undef LOOKUP + + return 0; +} + +#define AUTORELEASE(obj) ((obj == NULL) ? NULL : ( \ + py2app_CFArrayAppendValue(py2app_pool, (const void *)obj), \ + py2app_CFRelease(obj), \ + obj)) + +#define py2app_CFSTR(s) AUTORELEASE( \ + py2app_CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8)) + +static int py2app_openConsole(void) { + OSStatus err; + FSRef consoleRef; + err = py2app_LSFindApplicationForInfo( + kLSUnknownCreator, + NULL, + py2app_CFSTR(ERR_CONSOLEAPP), + &consoleRef, + NULL); + if (err != noErr) return err; + return py2app_LSOpenFSRef((const FSRef *)&consoleRef, NULL); +} + +static CFTypeRef py2app_getKey(const char *key) { + CFTypeRef rval; + CFStringRef cfKey = py2app_CFStringCreateWithCString(NULL, + key, kCFStringEncodingUTF8); + if (!cfKey) return NULL; + rval = py2app_CFBundleGetValueForInfoDictionaryKey( + CFBundleGetMainBundle(), + cfKey); + py2app_CFRelease(cfKey); + return rval; +} + +static CFStringRef py2app_getApplicationName(void) { + static CFStringRef name = NULL; + if (name) return name; + name = (CFStringRef)py2app_getKey("CFBundleName"); + if (!name) name = (CFStringRef)py2app_getKey("CFBundleExecutable"); + if (!name) name = py2app_CFSTR("py2app stub executable"); + return AUTORELEASE(name); +} + + +static CFStringRef py2app_getErrorTitle(CFStringRef applicationName) { + CFStringRef res; + if (!applicationName) return py2app_CFSTR(ERR_REALLYBADTITLE); + res = py2app_CFStringCreateWithFormat( + NULL, NULL, py2app_CFSTR(ERR_TITLEFORMAT), applicationName); + (void)AUTORELEASE(res); + return res; +} + +static void ensureGUI(void) { + ProcessSerialNumber psn; + id app = ((id(*)(id, SEL))py2app_objc_msgSend)(py2app_objc_getClass("NSApplication"), py2app_sel_getUid("sharedApplication")); + py2app_NSApplicationLoad(); + ((void(*)(id, SEL, BOOL))py2app_objc_msgSend)(app, py2app_sel_getUid("activateIgnoringOtherApps:"), 1); + if (py2app_GetCurrentProcess(&psn) == noErr) { + py2app_SetFrontProcess(&psn); + } +} + +static int report_error(const char *error) { + int choice; + id releasePool; + + if (bind_objc_Cocoa_ApplicationServices()) { + fprintf(stderr, "%s\n", error); + return -1; + } + releasePool = ((id(*)(id, SEL))py2app_objc_msgSend)( + ((id(*)(id, SEL))py2app_objc_msgSend)( + py2app_objc_getClass("NSAutoreleasePool"), + py2app_sel_getUid("alloc")), + py2app_sel_getUid("init")); + py2app_NSLog(py2app_CFSTR("%@"), py2app_CFSTR(error)); + + if (!py2app_NSApplicationLoad()) { + py2app_NSLog(py2app_CFSTR("NSApplicationLoad() failed")); + } else { + ensureGUI(); + choice = py2app_NSRunAlertPanel( + py2app_getErrorTitle(py2app_getApplicationName()), + py2app_CFSTR("%@"), + py2app_CFSTR(ERR_TERMINATE), + py2app_CFSTR(ERR_CONSOLEAPPTITLE), + NULL, + py2app_CFSTR(error)); + if (choice == NSAlertAlternateReturn) py2app_openConsole(); + } + ((void(*)(id, SEL))py2app_objc_msgSend)(releasePool, py2app_sel_getUid("release")); + return -1; +} + +static CFStringRef pathFromURL(CFURLRef anURL) { + UInt8 buf[PATH_MAX]; + py2app_CFURLGetFileSystemRepresentation(anURL, true, buf, sizeof(buf)); + return py2app_CFStringCreateWithCString(NULL, (char *)buf, kCFStringEncodingUTF8); +} + +static CFStringRef pyStandardizePath(CFStringRef pyLocation) { + CFRange foundRange; + CFURLRef fmwkURL; + CFURLRef locURL; + CFStringRef subpath; + static CFStringRef prefix = NULL; + if (!prefix) prefix = py2app_CFSTR("@executable_path/"); + foundRange = py2app_CFStringFind(pyLocation, prefix, 0); + if (foundRange.location == kCFNotFound || foundRange.length == 0) { + return NULL; + } + fmwkURL = py2app_CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle()); + foundRange.location = foundRange.length; + foundRange.length = py2app_CFStringGetLength(pyLocation) - foundRange.length; + subpath = py2app_CFStringCreateWithSubstring(NULL, pyLocation, foundRange); + locURL = py2app_CFURLCreateWithFileSystemPathRelativeToBase( + NULL, + subpath, + kCFURLPOSIXPathStyle, + false, + fmwkURL); + py2app_CFRelease(subpath); + py2app_CFRelease(fmwkURL); + subpath = pathFromURL(locURL); + py2app_CFRelease(locURL); + return subpath; +} + +static Boolean doesPathExist(CFStringRef path) { + struct stat st; + CFURLRef locURL; + UInt8 buf[PATH_MAX]; + locURL = py2app_CFURLCreateWithFileSystemPath( + NULL, path, kCFURLPOSIXPathStyle, false); + py2app_CFURLGetFileSystemRepresentation(locURL, true, buf, sizeof(buf)); + py2app_CFRelease(locURL); + return (stat((const char *)buf, &st) == -1 ? false : true); +} + +static CFStringRef py2app_findPyLocation(CFArrayRef pyLocations) { + CFIndex i; + CFIndex cnt = py2app_CFArrayGetCount(pyLocations); + for (i = 0; i < cnt; i++) { + CFStringRef newLoc; + CFStringRef pyLocation = py2app_CFArrayGetValueAtIndex(pyLocations, i); + newLoc = pyStandardizePath(pyLocation); + if (!newLoc) { + newLoc = pyLocation; + py2app_CFRetain(newLoc); + } + if (doesPathExist(newLoc)) { + return newLoc; + } + if (newLoc) py2app_CFRelease(newLoc); + } + return NULL; +} + +static CFStringRef tildeExpand(CFStringRef path) { + CFURLRef pathURL; + char buf[PATH_MAX]; + CFURLRef fullPathURL; + struct passwd *pwnam; + char tmp; + char *dir = NULL; + + + py2app_CFStringGetCString(path, buf, sizeof(buf), kCFStringEncodingUTF8); + + int i; + if (buf[0] != '~') { + return py2app_CFStringCreateWithCString( + NULL, buf, kCFStringEncodingUTF8); + } + /* user in path */ + i = 1; + while (buf[i] != '\0' && buf[i] != '/') { + i++; + } + if (i == 1) { + dir = getenv("HOME"); + } else { + tmp = buf[i]; + buf[i] = '\0'; + pwnam = getpwnam((const char *)&buf[1]); + if (pwnam) dir = pwnam->pw_dir; + buf[i] = tmp; + } + if (!dir) { + return py2app_CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); + } + pathURL = py2app_CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8*)dir, strlen(dir), false); + fullPathURL = py2app_CFURLCreateFromFileSystemRepresentationRelativeToBase( + NULL, (const UInt8*)&buf[i + 1], strlen(&buf[i + 1]), false, pathURL); + py2app_CFRelease(pathURL); + path = pathFromURL(fullPathURL); + py2app_CFRelease(fullPathURL); + return path; +} + +static void setcfenv(char *name, CFStringRef value) { + char buf[PATH_MAX]; + py2app_CFStringGetCString(value, buf, sizeof(buf), kCFStringEncodingUTF8); + setenv(name, buf, 1); +} + +static void py2app_setPythonPath(void) { + CFMutableArrayRef paths; + CFURLRef resDir; + CFStringRef resPath; + CFArrayRef resPackages; + CFDictionaryRef options; + + paths = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + resDir = py2app_CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + + resPath = pathFromURL(resDir); + py2app_CFArrayAppendValue(paths, resPath); + py2app_CFRelease(resPath); + + resPackages = py2app_getKey("PyResourcePackages"); + if (resPackages) { + int i; + int cnt = py2app_CFArrayGetCount(resPackages); + for (i = 0; i < cnt; i++) { + resPath = tildeExpand(py2app_CFArrayGetValueAtIndex(resPackages, i)); + if (py2app_CFStringGetLength(resPath)) { + if (py2app_CFStringGetCharacterAtIndex(resPath, 0) != '/') { + CFURLRef absURL = py2app_CFURLCreateWithString( + NULL, resPath, resDir); + py2app_CFRelease(resPath); + resPath = pathFromURL(absURL); + py2app_CFRelease(absURL); + } + py2app_CFArrayAppendValue(paths, resPath); + } + py2app_CFRelease(resPath); + } + } + + py2app_CFRelease(resDir); + + options = py2app_getKey("PyOptions"); + if (options) { + CFBooleanRef use_pythonpath; + CFNumberRef optimize; + use_pythonpath = py2app_CFDictionaryGetValue( + options, py2app_CFSTR("use_pythonpath")); + if (use_pythonpath && py2app_CFBooleanGetValue(use_pythonpath)) { + char *ppath = getenv("PYTHONPATH"); + if (ppath) { + CFArrayRef oldPath; + oldPath = py2app_CFStringCreateArrayBySeparatingStrings( + NULL, py2app_CFSTR(ppath), py2app_CFSTR(":")); + if (oldPath) { + CFRange rng; + rng.location = 0; + rng.length = py2app_CFArrayGetCount(oldPath); + py2app_CFArrayAppendArray(paths, oldPath, rng); + py2app_CFRelease(oldPath); + } + } + } + + optimize = py2app_CFDictionaryGetValue( + options, py2app_CFSTR("optimize")); + if (optimize) { + int v = 0; + char buf[32]; + py2app_CFNumberGetValue(optimize, kCFNumberIntType, &v); + snprintf(buf, 31, "%d", v); + setenv("PYTHONOPTIMIZE", buf, 1); + } + } + + if (py2app_CFArrayGetCount(paths)) { + resPath = py2app_CFStringCreateByCombiningStrings(NULL, paths, py2app_CFSTR(":")); + setcfenv("PYTHONPATH", resPath); + py2app_CFRelease(resPath); + } else { + if (getenv("PYTHONPATH") != NULL) { + unsetenv("PYTHONPATH"); + } + } + + py2app_CFRelease(paths); +} + + + +static void setResourcePath(void) { + CFURLRef resDir; + CFStringRef resPath; + resDir = py2app_CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + resPath = pathFromURL(resDir); + py2app_CFRelease(resDir); + setcfenv("RESOURCEPATH", resPath); + py2app_CFRelease(resPath); +} + +static void setExecutablePath(void) { + char executable_path[PATH_MAX+1]; + uint32_t bufsize = PATH_MAX; + memset(executable_path, '\0', PATH_MAX+1); + if (_NSGetExecutablePath(executable_path, &bufsize) == 0) { + setenv("EXECUTABLEPATH", executable_path, 1); + } +} + +static CFStringRef getMainScript(void) { + CFMutableArrayRef possibleMains; + CFBundleRef bndl; + CFStringRef e_py, e_pyc, e_pyo, path; + int i, cnt; + possibleMains = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + CFArrayRef firstMains = py2app_getKey("PyMainFileNames"); + if (firstMains) { + CFRange rng; + rng.location = 0; + rng.length = py2app_CFArrayGetCount(firstMains); + py2app_CFArrayAppendArray(possibleMains, firstMains, rng); + } + py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("__main__")); + py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("__realmain__")); + py2app_CFArrayAppendValue(possibleMains, py2app_CFSTR("Main")); + + e_py = py2app_CFSTR("py"); + e_pyc = py2app_CFSTR("pyc"); + e_pyo = py2app_CFSTR("pyo"); + + cnt = py2app_CFArrayGetCount(possibleMains); + bndl = CFBundleGetMainBundle(); + path = NULL; + for (i = 0; i < cnt; i++) { + CFStringRef base; + CFURLRef resURL; + base = py2app_CFArrayGetValueAtIndex(possibleMains, i); + resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_py, NULL); + if (resURL == NULL) { + resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_pyc, NULL); + } + if (resURL == NULL) { + resURL = py2app_CFBundleCopyResourceURL(bndl, base, e_pyo, NULL); + } + if (resURL != NULL) { + path = pathFromURL(resURL); + py2app_CFRelease(resURL); + break; + } + } + py2app_CFRelease(possibleMains); + return path; +} + +static int report_linkEdit_error(void) { + CFStringRef errString; + const char *errorString; + char* buf; + errorString = dlerror(); + fputs(errorString, stderr); + errString = py2app_CFStringCreateWithFormat( + NULL, NULL, py2app_CFSTR(ERR_LINKERRFMT), errorString); + buf = alloca(py2app_CFStringGetMaximumSizeForEncoding( + py2app_CFStringGetLength(errString), kCFStringEncodingUTF8)); + py2app_CFStringGetCString(errString, buf, sizeof(buf), kCFStringEncodingUTF8); + py2app_CFRelease(errString); + return report_error(buf); +} + +static CFStringRef getPythonInterpreter(CFStringRef pyLocation) { + CFBundleRef bndl; + CFStringRef auxName; + CFURLRef auxURL; + CFStringRef path; + + auxName = py2app_getKey("PyExecutableName"); + if (!auxName) auxName = py2app_CFSTR("python"); + bndl = CFBundleGetMainBundle(); + auxURL = py2app_CFBundleCopyAuxiliaryExecutableURL(bndl, auxName); + if (auxURL) { + path = pathFromURL(auxURL); + py2app_CFRelease(auxURL); + return path; + } + return NULL; +} + +static CFStringRef getErrorScript(void) { + CFMutableArrayRef errorScripts; + CFBundleRef bndl; + CFStringRef path; + int i, cnt; + errorScripts = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + CFArrayRef firstErrorScripts = py2app_getKey("PyErrorScripts"); + if (firstErrorScripts) { + CFRange rng; + rng.location = 0; + rng.length = py2app_CFArrayGetCount(firstErrorScripts); + py2app_CFArrayAppendArray(errorScripts, firstErrorScripts, rng); + } + py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__")); + py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.py")); + py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.pyc")); + py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.pyo")); + py2app_CFArrayAppendValue(errorScripts, py2app_CFSTR("__error__.sh")); + + cnt = py2app_CFArrayGetCount(errorScripts); + bndl = CFBundleGetMainBundle(); + path = NULL; + for (i = 0; i < cnt; i++) { + CFStringRef base; + CFURLRef resURL; + base = py2app_CFArrayGetValueAtIndex(errorScripts, i); + resURL = py2app_CFBundleCopyResourceURL(bndl, base, NULL, NULL); + if (resURL) { + path = pathFromURL(resURL); + py2app_CFRelease(resURL); + break; + } + } + py2app_CFRelease(errorScripts); + return path; + +} + +static CFMutableArrayRef get_trimmed_lines(CFStringRef output) { + CFMutableArrayRef lines; + CFArrayRef tmp; + CFRange rng; + lines = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + tmp = py2app_CFStringCreateArrayBySeparatingStrings( + NULL, output, py2app_CFSTR("\n")); + rng.location = 0; + rng.length = py2app_CFArrayGetCount(tmp); + py2app_CFArrayAppendArray(lines, tmp, rng); + while (true) { + CFIndex cnt = py2app_CFArrayGetCount(lines); + CFStringRef last; + /* Nothing on stdout means pass silently */ + if (cnt <= 0) { + py2app_CFRelease(lines); + return NULL; + } + last = py2app_CFArrayGetValueAtIndex(lines, cnt - 1); + if (py2app_CFStringGetLength(last) > 0) break; + py2app_CFArrayRemoveValueAtIndex(lines, cnt - 1); + } + return lines; +} + +static int report_script_error(const char *msg) { + CFStringRef errorScript; + CFMutableArrayRef lines; + CFRange foundRange; + CFStringRef lastLine; + CFStringRef output = NULL; + CFIndex lineCount; + CFURLRef buttonURL = NULL; + CFStringRef buttonString = NULL; + CFStringRef title = NULL; + CFStringRef errmsg = NULL; + id releasePool; + int errBinding; + int status = 0; + + errorScript = getErrorScript(); + if (!errorScript) return report_error(msg); + + errBinding = bind_objc_Cocoa_ApplicationServices(); + if (!errBinding) { + id task, stdoutPipe, taskData; + CFMutableArrayRef argv; + releasePool = ((id(*)(id, SEL))py2app_objc_msgSend)( + ((id(*)(id, SEL))py2app_objc_msgSend)( + py2app_objc_getClass("NSAutoreleasePool"), + py2app_sel_getUid("alloc")), + py2app_sel_getUid("init")); + task = ((id(*)(id, SEL))py2app_objc_msgSend)( + ((id(*)(id, SEL))py2app_objc_msgSend)( + py2app_objc_getClass("NSTask"), + py2app_sel_getUid("alloc")), + py2app_sel_getUid("init")); + stdoutPipe = ((id(*)(id, SEL))py2app_objc_msgSend)(py2app_objc_getClass("NSPipe"), py2app_sel_getUid("pipe")); + ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setLaunchPath:"), py2app_CFSTR("/bin/sh")); + ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setStandardOutput:"), stdoutPipe); + argv = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + py2app_CFArrayAppendValue(argv, errorScript); + py2app_CFArrayAppendValue(argv, py2app_getApplicationName()); + ((void(*)(id, SEL, id))py2app_objc_msgSend)(task, py2app_sel_getUid("setArguments:"), argv); + /* This could throw, in theory, but /bin/sh should prevent that */ + ((void(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("launch")); + ((void(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("waitUntilExit")); + taskData = ((id(*)(id, SEL))py2app_objc_msgSend)( + ((id(*)(id, SEL))py2app_objc_msgSend)(stdoutPipe, py2app_sel_getUid("fileHandleForReading")), + py2app_sel_getUid("readDataToEndOfFile")); + py2app_CFRelease(argv); + + status = ((int(*)(id, SEL))py2app_objc_msgSend)(task, py2app_sel_getUid("terminationStatus")); + py2app_CFRelease(task); + if (!status && taskData) { + output = py2app_CFStringCreateFromExternalRepresentation( + NULL, taskData, kCFStringEncodingUTF8); + } + + ((void(*)(id, SEL))py2app_objc_msgSend)(releasePool, py2app_sel_getUid("release")); + } + + py2app_CFRelease(errorScript); + if (status || !output) return report_error(msg); + + lines = get_trimmed_lines(output); + py2app_CFRelease(output); + /* Nothing on stdout means pass silently */ + if (!lines) return -1; + lineCount = py2app_CFArrayGetCount(lines); + lastLine = py2app_CFArrayGetValueAtIndex(lines, lineCount - 1); + foundRange = py2app_CFStringFind(lastLine, py2app_CFSTR("ERRORURL: "), 0); + if (foundRange.location != kCFNotFound && foundRange.length != 0) { + CFMutableArrayRef buttonArr; + CFArrayRef tmp; + CFRange rng; + buttonArr = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + tmp = py2app_CFStringCreateArrayBySeparatingStrings( + NULL, lastLine, py2app_CFSTR(" ")); + lineCount -= 1; + py2app_CFArrayRemoveValueAtIndex(lines, lineCount); + rng.location = 1; + rng.length = py2app_CFArrayGetCount(tmp) - 1; + py2app_CFArrayAppendArray(buttonArr, tmp, rng); + py2app_CFRelease(tmp); + while (true) { + CFStringRef tmpstr; + if (py2app_CFArrayGetCount(buttonArr) <= 0) break; + tmpstr = py2app_CFArrayGetValueAtIndex(buttonArr, 0); + if (py2app_CFStringGetLength(tmpstr) == 0) { + py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); + } else { + break; + } + } + + buttonURL = py2app_CFURLCreateWithString( + NULL, py2app_CFArrayGetValueAtIndex(buttonArr, 0), NULL); + if (buttonURL) { + py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); + while (true) { + CFStringRef tmpstr; + if (py2app_CFArrayGetCount(buttonArr) <= 0) break; + tmpstr = py2app_CFArrayGetValueAtIndex(buttonArr, 0); + if (py2app_CFStringGetLength(tmpstr) == 0) { + py2app_CFArrayRemoveValueAtIndex(buttonArr, 0); + } else { + break; + } + } + if (py2app_CFArrayGetCount(buttonArr) > 0) { + buttonString = py2app_CFStringCreateByCombiningStrings( + NULL, buttonArr, py2app_CFSTR(" ")); + } + if (!buttonString) buttonString = py2app_CFSTR(ERR_DEFAULTURLTITLE); + } + py2app_CFRelease(buttonArr); + + } + if (lineCount <= 0 || errBinding) { + py2app_CFRelease(lines); + return report_error(msg); + } + + releasePool = ((id(*)(id, SEL))py2app_objc_msgSend)( + ((id(*)(id, SEL))py2app_objc_msgSend)( + py2app_objc_getClass("NSAutoreleasePool"), + py2app_sel_getUid("alloc")), + py2app_sel_getUid("init")); + + title = py2app_CFArrayGetValueAtIndex(lines, 0); + py2app_CFRetain(title); + (void)AUTORELEASE(title); + lineCount -= 1; + py2app_CFArrayRemoveValueAtIndex(lines, lineCount); + py2app_NSLog(py2app_CFSTR("%@"), title); + if (lineCount > 0) { + CFStringRef showerr; + errmsg = py2app_CFStringCreateByCombiningStrings( + NULL, lines, py2app_CFSTR("\r")); + (void)AUTORELEASE(errmsg); + showerr = ((id(*)(id, SEL, id))py2app_objc_msgSend)( + ((id(*)(id, SEL, id))py2app_objc_msgSend)(errmsg, py2app_sel_getUid("componentsSeparatedByString:"), py2app_CFSTR("\r")), + py2app_sel_getUid("componentsJoinedByString:"), py2app_CFSTR("\n")); + py2app_NSLog(py2app_CFSTR("%@"), showerr); + } else { + errmsg = py2app_CFSTR(""); + } + + ensureGUI(); + if (!buttonURL) { + int choice = py2app_NSRunAlertPanel( + title, py2app_CFSTR("%@"), py2app_CFSTR(ERR_TERMINATE), + py2app_CFSTR(ERR_CONSOLEAPPTITLE), NULL, errmsg); + if (choice == NSAlertAlternateReturn) py2app_openConsole(); + } else { + int choice = py2app_NSRunAlertPanel( + title, py2app_CFSTR("%@"), py2app_CFSTR(ERR_TERMINATE), + buttonString, NULL, errmsg); + if (choice == NSAlertAlternateReturn) { + id ws = ((id(*)(id, SEL))py2app_objc_msgSend)(py2app_objc_getClass("NSWorkspace"), py2app_sel_getUid("sharedWorkspace")); + ((void(*)(id, SEL, id))py2app_objc_msgSend)(ws, py2app_sel_getUid("openURL:"), buttonURL); + } + } + ((void(*)(id, SEL))py2app_objc_msgSend)(releasePool, py2app_sel_getUid("release")); + py2app_CFRelease(lines); + return -1; +} + +static int py2app_main(int argc, char * const *argv, char * const *envp) { + CFArrayRef pyLocations; + CFStringRef pyLocation; + CFStringRef mainScript; + CFStringRef pythonInterpreter; + char *resource_path; + char buf[PATH_MAX]; + char c_pythonInterpreter[PATH_MAX]; + char c_mainScript[PATH_MAX]; + char **argv_new; + struct stat sb; + void *py_dylib; + int rval; + FILE *mainScriptFile; + char* curenv = NULL; + char* curlocale = NULL; + + + if (getenv("PYTHONOPTIMIZE") != NULL) { + unsetenv("PYTHONOPTIMIZE"); + } + if (getenv("PYTHONDEBUG") != NULL) { + unsetenv("PYTHONDEBUG"); + } + if (getenv("PYTHONDONTWRITEBYTECODE") != NULL) { + unsetenv("PYTHONDONTWRITEBYTECODE"); + } + if (getenv("PYTHONIOENCODING") != NULL) { + unsetenv("PYTHONIOENCODING"); + } + if (getenv("PYTHONDUMPREFS") != NULL) { + unsetenv("PYTHONDUMPREFS"); + } + if (getenv("PYTHONMALLOCSTATS") != NULL) { + unsetenv("PYTHONMALLOCSTATS"); + } + + /* Ensure that the interpreter won't try to write bytecode files + * Two reasons: + * - Apps are often read-only for users + * - Writing byte-code will be blocked by the sandbox + * when running a sandboxed application. + */ + setenv("PYTHONDONTWRITEBYTECODE", "1", 1); + +#ifndef PY2APP_SECONDARY + /* + * Force stdout/stderr to be unbuffered, needed when using the ASL + * output redirection because Python 3's IO library won't use + * line buffering with that. + */ + setenv("PYTHONUNBUFFERED", "1", 1); +#endif + + + if (!py2app_getApplicationName()) return report_error(ERR_NONAME); + pyLocations = (CFArrayRef)py2app_getKey("PyRuntimeLocations"); + if (!pyLocations) return report_error(ERR_PYRUNTIMELOCATIONS); + pyLocation = py2app_findPyLocation(pyLocations); + if (!pyLocation) return report_error(ERR_NOPYTHONRUNTIME); + + setExecutablePath(); + setResourcePath(); + /* check for ':' in path, not compatible with Python due to Py_GetPath */ + /* XXX: Could work-around by creating something in /tmp I guess */ + resource_path = getenv("RESOURCEPATH"); + if ((resource_path == NULL) || (strchr(resource_path, ':') != NULL)) { + return report_error(ERR_COLONPATH); + } + py2app_setPythonPath(); + setenv("ARGVZERO", argv[0], 1); + + /* Clear unwanted environment variable that could be set + * by a PyObjC bundle in a parent process. Not clearing causes + * problems in PyObjC. + */ + if (getenv("PYOBJC_BUNDLE_ADDRESS") != NULL) { + unsetenv("PYOBJC_BUNDLE_ADDRESS"); + } + snprintf(buf, sizeof(buf)-1, "PYOBJC_BUNDLE_ADDRESS%ld", (long)getpid()); + if (getenv(buf) != NULL) { + unsetenv(buf); + } + + mainScript = getMainScript(); + if (!mainScript) return report_error(ERR_NOPYTHONSCRIPT); + + pythonInterpreter = getPythonInterpreter(pyLocation); + py2app_CFStringGetCString( + pythonInterpreter, c_pythonInterpreter, + sizeof(c_pythonInterpreter), kCFStringEncodingUTF8); + py2app_CFRelease(pythonInterpreter); + if (lstat(c_pythonInterpreter, &sb) == 0) { + if (!((sb.st_mode & S_IFLNK) == S_IFLNK)) { + setenv("PYTHONHOME", resource_path, 1); + } + } + + py2app_CFStringGetCString(pyLocation, buf, sizeof(buf), kCFStringEncodingUTF8); + py_dylib = dlopen(buf, RTLD_LAZY); + if (!py_dylib) return report_linkEdit_error(); + +#define LOOKUP(NAME) \ + NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME); \ + if (!py2app_ ## NAME) { \ + return report_linkEdit_error(); \ + } + +#define OPT_LOOKUP(NAME) \ + NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME); + + LOOKUP(Py_SetProgramName); + LOOKUP(Py_Initialize); + LOOKUP(PyRun_SimpleFile); + LOOKUP(Py_Finalize); + LOOKUP(PySys_GetObject); + LOOKUP(PySys_SetArgv); + LOOKUP(PyObject_GetAttrString); + LOOKUP(Py_BuildValue); +#if 0 + OPT_LOOKUP(Py_SetPath); +#endif + OPT_LOOKUP(_Py_DecodeUTF8_surrogateescape); + LOOKUP(PySys_SetObject); + + + int isPy3K = dlsym(py_dylib, "PyBytes_FromString") != NULL; + +#undef OPT_LOOKUP +#undef LOOKUP + + if (isPy3K) { + /* + * When apps are started from the Finder (or anywhere + * except from the terminal), the LANG and LC_* variables + * aren't set in the environment. This confuses Py_Initialize + * when it tries to import the codec for UTF-8, + * therefore explicitly set the locale. + * + * Also set the LC_CTYPE environment variable because Py_Initialize + * resets the locale information using the environment :-( + */ + curlocale = setlocale(LC_ALL, NULL); + if (curlocale != NULL) { + curlocale = strdup(curlocale); + if (curlocale == NULL) { + (void)report_error("cannot save locale information"); + return -1; + } + } + setlocale(LC_ALL, "en_US.UTF-8"); + + curenv = getenv("LC_CTYPE"); + if (curenv == NULL) { + setenv("LC_CTYPE", "en_US.UTF-8", 1); + } + + wchar_t w_pythonInterpreter[PATH_MAX+1]; + mbstowcs(w_pythonInterpreter, c_pythonInterpreter, PATH_MAX+1); + py2app_Py_SetProgramName((char*)w_pythonInterpreter); + + + } else { + py2app_Py_SetProgramName(c_pythonInterpreter); + } + + py2app_Py_Initialize(); + + /* + * Reset the environment and locale information + */ + if (isPy3K) { + if (curenv == NULL) { + unsetenv("LC_CTYPE"); + } + + setlocale(LC_CTYPE, curlocale); + free(curlocale); + } + + py2app_CFStringGetCString( + mainScript, c_mainScript, + sizeof(c_mainScript), kCFStringEncodingUTF8); + py2app_CFRelease(mainScript); + + if (isPy3K) { + int i; + + argv_new = alloca((argc+1) * sizeof(wchar_t)); + argv_new[argc] = NULL; + argv_new[0] = (char*)py2app__Py_DecodeUTF8_surrogateescape(c_mainScript, strlen(c_mainScript)); + + for (i = 1; i < argc; i++) { + argv_new[i] = (char*)py2app__Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i])); + } + + } else { + argv_new = alloca((argc + 1) * sizeof(char *)); + argv_new[argc] = NULL; + argv_new[0] = c_mainScript; + memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *)); + } + py2app_PySys_SetArgv(argc, argv_new); + + mainScriptFile = fopen(c_mainScript, "r"); + rval = py2app_PyRun_SimpleFile(mainScriptFile, c_mainScript); + fclose(mainScriptFile); + + if (rval) { + rval = report_script_error(ERR_PYTHONEXCEPTION); + } + + py2app_Py_Finalize(); + + return rval; +} + +void +setup_asl(const char* appname) +{ + /* + * On Mac OS X 10.8 or later the contents of stdout and stderr + * do not end up in de Console.app log (neither in de default + * view or some other view). + * + * This function detects if "asl_log_descriptor" is available + * (introduced in 10.8), and if it is configures ASL to redirect + * all writes to stdout/stderr to the ASL in such a way that + * log lines end up in the default view of Console.app. + */ + + /* Function definitions, don't use the ASL header because that + * doesn't contain all definitions when building the binaries + * with PPC support. + */ + typedef void* aslclient; + typedef void* aslmsg; + + aslclient (*do_asl_open)(const char*, const char*, int); + int (*do_asl_add_log_file)(aslclient, int); + int (*do_asl_log_descriptor)(aslclient, aslmsg, int, int, uint32_t); + int (*do_asl_set)(aslmsg, const char*, const char*); + aslmsg (*do_asl_new)(int); + + /* + * Try to resolve the ASL function's we're using. + */ + void* sys_dylib; + sys_dylib = dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY); + + do_asl_open = dlsym(sys_dylib, "asl_open"); + do_asl_add_log_file = dlsym(sys_dylib, "asl_add_log_file"); + do_asl_log_descriptor = dlsym(sys_dylib, "asl_log_descriptor"); + do_asl_set = dlsym(sys_dylib, "asl_set"); + do_asl_new = dlsym(sys_dylib, "asl_new"); + + if (do_asl_log_descriptor == NULL) { + /* asl_log_descriptor is not available: running on OSX 10.7 + * or earlier, which means we can't set up ASL and don't have to + */ + return; + } + + aslclient cl; + aslmsg msg; + int fd2; + char uidbuf[64]; + + cl = do_asl_open(appname, "com.apple.console", 2 /* ASL_OPT_NO_DELAY */); + if (cl == NULL) { + return; + } + + /* Tell ASL to write all log lines to STDERR as well, use a dup-ed file + * descriptor because we'll later replace the original one by a file descriptor + * from ASL. + */ + fd2 = dup(2); + do_asl_add_log_file(cl, fd2); + + /* + * Create an ASL template message for the STDOUT/STDERR redirection. + * All keys are required to get log messages into the default view of Console.app + * for normal users. + */ + snprintf(uidbuf, sizeof(uidbuf), "%d", getuid()); + msg = do_asl_new(0 /* ASL_TYPE_MSG */); + do_asl_set(msg, "Facility" /* ASL_KEY_FACILITY */, "com.apple.console"); + do_asl_set(msg, "Level" /* ASL_KEY_LEVEL */, "Notice" /* ASL_STRING_NOTICE */); + do_asl_set(msg, "ReadUID" /* ASL_KEY_READ_UID */, uidbuf /* or "-1" for "All users" */); + + /* + * Finally: redirect the STDOUT/STDERR file descriptors to ASL. + */ + do_asl_log_descriptor(cl, msg, 4 /* ASL_LEVEL_NOTICE */, 1, 2 /* ASL_LOG_DESCRIPTOR_WRITE */); + do_asl_log_descriptor(cl, msg, 4 /* ASL_LEVEL_NOTICE */, 2, 2 /* ASL_LOG_DESCRIPTOR_WRITE */); +} + +#ifndef PY2APP_SECONDARY +static int +have_psn_arg(int argc, char* const * argv) +{ + int i; + + for (i = 0; i < argc; i++) { + if (strncmp(argv[i], "-psn_", 5) == 0) { + if (isdigit(argv[i][5])) { + return 1; + } + } + } + return 0; +} +#endif /* !PY2APP_SECONDARY */ + + +int +main(int argc, char * const *argv, char * const *envp) +{ + int rval; + +#ifndef PY2APP_SECONDARY + /* Running as a GUI app started by launch + * services, try to redirect stdout/stderr + * to ASL. + * + * NOTE: Detecting application bundles on OSX 10.9 + * is annoyingly hard, the devnull trick is the least + * worst option I've found yet. + */ + struct stat st; + struct utsname uts; + int is_app_bundle = 1; + + if (uname(&uts) != -1) { + if (strcmp(uts.release, "13.") <= 0) { + /* OSX 10.8 or earlier */ + if (!have_psn_arg(argc, argv)) { + is_app_bundle = 0; + } + } else { + /* OSX 10.9 or later */ + if (fstat(1, &st) != -1) { + if (!S_ISCHR(st.st_mode) || + major(st.st_dev) != 3 || + minor(st.st_dev) != 2) { + + /* We appear to be launched from the + * command-line after all. + */ + is_app_bundle = st.st_dev; + } + } + } + } + + + if (is_app_bundle) { + const char *bname; + setenv("_PY2APP_LAUNCHED_", "1", 1); + + bname = strrchr(argv[0], '/'); + if (bname == NULL) { + bname = argv[0]; + } else { + bname++; + } + + setup_asl(bname); + } +#endif /* !PY2APP_SECONDARY */ + + if (bind_CoreFoundation()) { + fprintf(stderr, "CoreFoundation not found or functions missing\n"); + return -1; + } + if (!CFBundleGetMainBundle()) { + fprintf(stderr, "Not bundled, exiting\n"); + return -1; + } + py2app_pool = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks); + if (!py2app_pool) { + fprintf(stderr, "Couldn't create global pool\n"); + return -1; + } + rval = py2app_main(argc, argv, envp); + py2app_CFRelease(py2app_pool); + return rval; +} diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/__init__.py new file mode 100644 index 0000000..8415426 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/__init__.py @@ -0,0 +1 @@ +""" py2app bootstrap files """ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_emulation.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_emulation.py new file mode 100644 index 0000000..b566659 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_emulation.py @@ -0,0 +1,272 @@ +""" +sys.argv emulation + +This module starts a basic event loop to collect file- and url-open AppleEvents. Those get +converted to strings and stuffed into sys.argv. When that is done we continue starting +the application. + +This is a workaround to convert scripts that expect filenames on the command-line to work +in a GUI environment. GUI applications should not use this feature. + +NOTE: This module uses ctypes and not the Carbon modules in the stdlib because the latter +don't work in 64-bit mode and are also not available with python 3.x. +""" + +import sys +import os +import time + +import ctypes +import struct + +class AEDesc (ctypes.Structure): + _fields_ = [ + ('descKey', ctypes.c_int), + ('descContent', ctypes.c_void_p), + ] + +class EventTypeSpec (ctypes.Structure): + _fields_ = [ + ('eventClass', ctypes.c_int), + ('eventKind', ctypes.c_uint), + ] + +def _ctypes_setup(): + carbon = ctypes.CDLL('/System/Library/Carbon.framework/Carbon') + + timer_func = ctypes.CFUNCTYPE( + None, ctypes.c_void_p, ctypes.c_long) + + ae_callback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, + ctypes.c_void_p, ctypes.c_void_p) + carbon.AEInstallEventHandler.argtypes = [ + ctypes.c_int, ctypes.c_int, ae_callback, + ctypes.c_void_p, ctypes.c_char ] + carbon.AERemoveEventHandler.argtypes = [ + ctypes.c_int, ctypes.c_int, ae_callback, + ctypes.c_char ] + + carbon.AEProcessEvent.restype = ctypes.c_int + carbon.AEProcessEvent.argtypes = [ctypes.c_void_p] + + + carbon.ReceiveNextEvent.restype = ctypes.c_int + carbon.ReceiveNextEvent.argtypes = [ + ctypes.c_long, ctypes.POINTER(EventTypeSpec), + ctypes.c_double, ctypes.c_char, + ctypes.POINTER(ctypes.c_void_p) + ] + + + carbon.AEGetParamDesc.restype = ctypes.c_int + carbon.AEGetParamDesc.argtypes = [ + ctypes.c_void_p, ctypes.c_int, ctypes.c_int, + ctypes.POINTER(AEDesc)] + + carbon.AECountItems.restype = ctypes.c_int + carbon.AECountItems.argtypes = [ ctypes.POINTER(AEDesc), + ctypes.POINTER(ctypes.c_long) ] + + carbon.AEGetNthDesc.restype = ctypes.c_int + carbon.AEGetNthDesc.argtypes = [ + ctypes.c_void_p, ctypes.c_long, ctypes.c_int, + ctypes.c_void_p, ctypes.c_void_p ] + + carbon.AEGetDescDataSize.restype = ctypes.c_int + carbon.AEGetDescDataSize.argtypes = [ ctypes.POINTER(AEDesc) ] + + carbon.AEGetDescData.restype = ctypes.c_int + carbon.AEGetDescData.argtypes = [ + ctypes.POINTER(AEDesc), + ctypes.c_void_p, + ctypes.c_int, + ] + + + carbon.FSRefMakePath.restype = ctypes.c_int + carbon.FSRefMakePath.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint] + + return carbon + +def _run_argvemulator(timeout = 60): + + # Configure ctypes + carbon = _ctypes_setup() + + # Is the emulator running? + running = [True] + + timeout = [timeout] + + # Configure AppleEvent handlers + ae_callback = carbon.AEInstallEventHandler.argtypes[2] + + kAEInternetSuite, = struct.unpack('>i', b'GURL') + kAEISGetURL, = struct.unpack('>i', b'GURL') + kCoreEventClass, = struct.unpack('>i', b'aevt') + kAEOpenApplication, = struct.unpack('>i', b'oapp') + kAEOpenDocuments, = struct.unpack('>i', b'odoc') + keyDirectObject, = struct.unpack('>i', b'----') + typeAEList, = struct.unpack('>i', b'list') + typeChar, = struct.unpack('>i', b'TEXT') + typeFSRef, = struct.unpack('>i', b'fsrf') + FALSE = b'\0' + TRUE = b'\1' + eventLoopTimedOutErr = -9875 + + kEventClassAppleEvent, = struct.unpack('>i', b'eppc') + kEventAppleEvent = 1 + + + @ae_callback + def open_app_handler(message, reply, refcon): + # Got a kAEOpenApplication event, which means we can + # start up. On some OSX versions this event is even + # sent when an kAEOpenDocuments or kAEOpenURLs event + # is sent later on. + # + # Therefore don't set running to false, but reduce the + # timeout to at most two seconds beyond the current time. + timeout[0] = min(timeout[0], time.time() - start + 2) + #running[0] = False + return 0 + + carbon.AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, + open_app_handler, 0, FALSE) + + @ae_callback + def open_file_handler(message, reply, refcon): + listdesc = AEDesc() + sts = carbon.AEGetParamDesc(message, keyDirectObject, typeAEList, + ctypes.byref(listdesc)) + if sts != 0: + print("argvemulator warning: cannot unpack open document event") + running[0] = False + return + + item_count = ctypes.c_long() + sts = carbon.AECountItems(ctypes.byref(listdesc), ctypes.byref(item_count)) + if sts != 0: + print("argvemulator warning: cannot unpack open document event") + running[0] = False + return + + desc = AEDesc() + for i in range(item_count.value): + sts = carbon.AEGetNthDesc(ctypes.byref(listdesc), i+1, typeFSRef, 0, ctypes.byref(desc)) + if sts != 0: + print("argvemulator warning: cannot unpack open document event") + running[0] = False + return + + sz = carbon.AEGetDescDataSize(ctypes.byref(desc)) + buf = ctypes.create_string_buffer(sz) + sts = carbon.AEGetDescData(ctypes.byref(desc), buf, sz) + if sts != 0: + print("argvemulator warning: cannot extract open document event") + continue + + fsref = buf + + buf = ctypes.create_string_buffer(1024) + sts = carbon.FSRefMakePath(ctypes.byref(fsref), buf, 1023) + if sts != 0: + print("argvemulator warning: cannot extract open document event") + continue + + if sys.version_info[0] > 2: + sys.argv.append(buf.value.decode('utf-8')) + else: + sys.argv.append(buf.value) + + running[0] = False + return 0 + + carbon.AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + open_file_handler, 0, FALSE) + + @ae_callback + def open_url_handler(message, reply, refcon): + listdesc = AEDesc() + ok = carbon.AEGetParamDesc(message, keyDirectObject, typeAEList, + ctypes.byref(listdesc)) + if ok != 0: + print("argvemulator warning: cannot unpack open document event") + running[0] = False + return + + item_count = ctypes.c_long() + sts = carbon.AECountItems(ctypes.byref(listdesc), ctypes.byref(item_count)) + if sts != 0: + print("argvemulator warning: cannot unpack open url event") + running[0] = False + return + + desc = AEDesc() + for i in range(item_count.value): + sts = carbon.AEGetNthDesc(ctypes.byref(listdesc), i+1, typeChar, 0, ctypes.byref(desc)) + if sts != 0: + print("argvemulator warning: cannot unpack open URL event") + running[0] = False + return + + sz = carbon.AEGetDescDataSize(ctypes.byref(desc)) + buf = ctypes.create_string_buffer(sz) + sts = carbon.AEGetDescData(ctypes.byref(desc), buf, sz) + if sts != 0: + print("argvemulator warning: cannot extract open URL event") + + else: + if sys.version_info[0] > 2: + sys.argv.append(buf.value.decode('utf-8')) + else: + sys.argv.append(buf.value) + + running[0] = False + return 0 + + carbon.AEInstallEventHandler(kAEInternetSuite, kAEISGetURL, + open_url_handler, 0, FALSE) + + # Remove the funny -psn_xxx_xxx argument + if len(sys.argv) > 1 and sys.argv[1].startswith('-psn_'): + del sys.argv[1] + + start = time.time() + now = time.time() + eventType = EventTypeSpec() + eventType.eventClass = kEventClassAppleEvent + eventType.eventKind = kEventAppleEvent + + while running[0] and now - start < timeout[0]: + event = ctypes.c_void_p() + + sts = carbon.ReceiveNextEvent(1, ctypes.byref(eventType), + start + timeout[0] - now, TRUE, ctypes.byref(event)) + + if sts == eventLoopTimedOutErr: + break + + elif sts != 0: + print("argvemulator warning: fetching events failed") + break + + sts = carbon.AEProcessEvent(event) + if sts != 0: + print("argvemulator warning: processing events failed") + break + + + carbon.AERemoveEventHandler(kCoreEventClass, kAEOpenApplication, + open_app_handler, FALSE) + carbon.AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, + open_file_handler, FALSE) + carbon.AERemoveEventHandler(kAEInternetSuite, kAEISGetURL, + open_url_handler, FALSE) + +def _argv_emulation(): + import sys, os + # only use if started by LaunchServices + if os.environ.get('_PY2APP_LAUNCHED_'): + _run_argvemulator() +_argv_emulation() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_inject.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_inject.py new file mode 100644 index 0000000..498e8fe --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/argv_inject.py @@ -0,0 +1,7 @@ +def _argv_inject(argv): + import sys + # only use if started by LaunchServices + if len(sys.argv) > 1 and sys.argv[1].startswith('-psn'): + sys.argv[1:2] = argv + else: + sys.argv[1:1] = argv diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasapp.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasapp.py new file mode 100644 index 0000000..8cb377a --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasapp.py @@ -0,0 +1,42 @@ +import re, sys +cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)") +if sys.version_info[0] == 2: + default_encoding = 'ascii' +else: + default_encoding = 'utf-8' + +def guess_encoding(fp): + for i in range(2): + ln = fp.readline() + + m = cookie_re.search(ln) + if m is not None: + return m.group(1).decode('ascii') + + return default_encoding + +def _run(): + global __file__ + import os, site + sys.frozen = 'macosx_app' + + argv0 = os.path.basename(os.environ['ARGVZERO']) + script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) + + sys.argv[0] = __file__ = script + if sys.version_info[0] == 2: + with open(script, 'rU') as fp: + source = fp.read() + "\n" + else: + with open(script, 'rb') as fp: + encoding = guess_encoding(fp) + + with open(script, 'r', encoding=encoding) as fp: + source = fp.read() + '\n' + + BOM=b'\xef\xbb\xbf'.decode('utf-8') + if source.startswith(BOM): + source = source[1:] + + + exec(compile(source, script, 'exec'), globals(), globals()) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasplugin.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasplugin.py new file mode 100644 index 0000000..e961331 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_aliasplugin.py @@ -0,0 +1,45 @@ +import re, sys +cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)") +if sys.version_info[0] == 2: + default_encoding = 'ascii' +else: + default_encoding = 'utf-8' + +def guess_encoding(fp): + for i in range(2): + ln = fp.readline() + + m = cookie_re.search(ln) + if m is not None: + return m.group(1).decode('ascii') + + return default_encoding + +def _run(): + global __file__ + import os, site + sys.frozen = 'macosx_plugin' + base = os.environ['RESOURCEPATH'] + + if 'ARGVZERO' in os.environ: + argv0 = os.path.basename(os.environ['ARGVZERO']) + else: + argv0 = None + script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) + + sys.argv[0] = __file__ = path = os.path.join(base, script) + if sys.version_info[0] == 2: + with open(path, 'rU') as fp: + source = fp.read() + "\n" + else: + with open(path, 'rb') as fp: + encoding = guess_encoding(fp) + + with open(path, 'r', encoding=encoding) as fp: + source = fp.read() + '\n' + + BOM=b'\xef\xbb\xbf'.decode('utf-8') + if source.startswith(BOM): + source = source[1:] + + exec(compile(source, script, 'exec'), globals(), globals()) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_app.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_app.py new file mode 100644 index 0000000..10911dd --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_app.py @@ -0,0 +1,42 @@ +import re, sys +cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)") +if sys.version_info[0] == 2: + default_encoding = 'ascii' +else: + default_encoding = 'utf-8' + +def guess_encoding(fp): + for i in range(2): + ln = fp.readline() + + m = cookie_re.search(ln) + if m is not None: + return m.group(1).decode('ascii') + + return default_encoding + +def _run(): + global __file__ + import os, site + sys.frozen = 'macosx_app' + base = os.environ['RESOURCEPATH'] + + argv0 = os.path.basename(os.environ['ARGVZERO']) + script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) + + path = os.path.join(base, script) + sys.argv[0] = __file__ = path + if sys.version_info[0] == 2: + with open(path, 'rU') as fp: + source = fp.read() + "\n" + else: + with open(path, 'rb') as fp: + encoding = guess_encoding(fp) + + with open(path, 'r', encoding=encoding) as fp: + source = fp.read() + '\n' + + BOM=b'\xef\xbb\xbf'.decode('utf-8') + if source.startswith(BOM): + source = source[1:] + exec(compile(source, path, 'exec'), globals(), globals()) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_plugin.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_plugin.py new file mode 100644 index 0000000..cf7e760 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/boot_plugin.py @@ -0,0 +1,45 @@ +import re, sys +cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)") +if sys.version_info[0] == 2: + default_encoding = 'ascii' +else: + default_encoding = 'utf-8' + +def guess_encoding(fp): + for i in range(2): + ln = fp.readline() + + m = cookie_re.search(ln) + if m is not None: + return m.group(1).decode('ascii') + + return default_encoding + +def _run(): + global __file__ + import os, site + sys.frozen = 'macosx_plugin' + base = os.environ['RESOURCEPATH'] + + if 'ARGVZERO' in os.environ: + argv0 = os.path.basename(os.environ['ARGVZERO']) + else: + argv0 = None + script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) + + __file__ = path = os.path.join(base, script) + if sys.version_info[0] == 2: + with open(path, 'rU') as fp: + source = fp.read() + "\n" + else: + with open(path, 'rb') as fp: + encoding = guess_encoding(fp) + + with open(path, 'r', encoding=encoding) as fp: + source = fp.read() + '\n' + + BOM=b'\xef\xbb\xbf'.decode('utf-8') + if source.startswith(BOM): + source = source[1:] + + exec(compile(source, path, 'exec'), globals(), globals()) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/chdir_resource.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/chdir_resource.py new file mode 100644 index 0000000..46641c5 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/chdir_resource.py @@ -0,0 +1,4 @@ +def _chdir_resource(): + import os + os.chdir(os.environ['RESOURCEPATH']) +_chdir_resource() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/ctypes_setup.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/ctypes_setup.py new file mode 100644 index 0000000..d3e31ca --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/ctypes_setup.py @@ -0,0 +1,8 @@ +def _setup_ctypes(): + from ctypes.macholib import dyld + import os + frameworks = os.path.join(os.environ['RESOURCEPATH'], '..', 'Frameworks') + dyld.DEFAULT_FRAMEWORK_FALLBACK.insert(0, frameworks) + dyld.DEFAULT_LIBRARY_FALLBACK.insert(0, frameworks) + +_setup_ctypes() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/disable_linecache.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/disable_linecache.py new file mode 100644 index 0000000..97f091f --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/disable_linecache.py @@ -0,0 +1,7 @@ +def _disable_linecache(): + import linecache + def fake_getline(*args, **kwargs): + return '' + linecache.orig_getline = linecache.getline + linecache.getline = fake_getline +_disable_linecache() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/emulate_shell_environment.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/emulate_shell_environment.py new file mode 100644 index 0000000..47c799c --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/emulate_shell_environment.py @@ -0,0 +1,79 @@ +def _emulate_shell_environ(): + import os + import sys + import time + import subprocess + + if sys.version_info[0] > 2: + env = os.environb + else: + env = os.environ + + split_char = b'=' + + # Start 'login -qf $LOGIN' in a pseudo-tty. The pseudo-tty + # is required to get the right behavior from the shell, without + # a tty the shell won't properly initialize the environment. + # + # NOTE: The code is very carefull w.r.t. getting the login + # name, the application shouldn't crash when the shell information + # cannot be retrieved + master, slave = os.openpty() + pid = os.fork() + try: + login = os.getlogin() + except AttributeError: + try: + login = os.environ['LOGNAME'] + except KeyError: + login = None + + if login is not None: + if pid == 0: + # Child + os.close(master) + os.setsid() + os.dup2(slave, 0) + os.dup2(slave, 1) + os.dup2(slave, 2) + os.execv('/usr/bin/login', ['login', '-qf', login]) + os._exit(42) + + else: + # Parent + os.close(slave) + # Echo markers around the actual output of env, that makes it + # easier to find the real data between other data printed + # by the shell. + os.write(master, b'echo "---------";env;echo "-----------"\r\n') + os.write(master, b'exit\r\n') + time.sleep(1) + + data = [] + b = os.read(master, 2048) + while b: + data.append(b) + b = os.read(master, 2048) + data = b''.join(data) + os.waitpid(pid, 0) + + in_data = False + for ln in data.splitlines(): + if not in_data: + if ln.strip().startswith(b'--------'): + in_data = True + continue + + if ln.startswith(b'--------'): + break + + try: + key, value = ln.rstrip().split(split_char, 1) + except: + pass + + else: + env[key] = value + + +_emulate_shell_environ() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/import_encodings.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/import_encodings.py new file mode 100644 index 0000000..a52eba9 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/import_encodings.py @@ -0,0 +1,23 @@ +def _import_encodings(): + import os + import imp + import encodings + import pkgutil + import sys + del sys.path[:2] + import encodings.aliases + + encodings.__path__ = pkgutil.extend_path( + encodings.__path__, + encodings.__name__) + #imp.reload(encodings) + + import encodings.mac_roman + encodings.aliases.__file__ = os.path.join( + os.path.dirname(encodings.mac_roman.__file__), + 'aliases.py' + encodings.mac_roman.__file__[:-1]) + + imp.reload(encodings.aliases) + imp.reload(encodings) + +_import_encodings() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/path_inject.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/path_inject.py new file mode 100644 index 0000000..3f07f48 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/path_inject.py @@ -0,0 +1,3 @@ +def _path_inject(paths): + import sys + sys.path[:0] = paths diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/reset_sys_path.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/reset_sys_path.py new file mode 100644 index 0000000..63b68bc --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/reset_sys_path.py @@ -0,0 +1,7 @@ +def _reset_sys_path(): + # Clear generic sys.path[0] + import sys, os + resources = os.environ['RESOURCEPATH'] + while sys.path[0] == resources: + del sys.path[0] +_reset_sys_path() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/semi_standalone_path.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/semi_standalone_path.py new file mode 100644 index 0000000..7641207 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/semi_standalone_path.py @@ -0,0 +1,11 @@ +def _update_path(): + import os, sys + resources = os.environ['RESOURCEPATH'] + sys.path.append(os.path.join( + resources, 'lib', 'python%d.%d'%(sys.version_info[:2]), 'lib-dynload')) + sys.path.append(os.path.join( + resources, 'lib', 'python%d.%d'%(sys.version_info[:2]))) + sys.path.append(os.path.join( + resources, 'lib', 'python%d.%d'%(sys.version_info[:2]), 'site-packages.zip')) + +_update_path() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_included_subpackages.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_included_subpackages.py new file mode 100644 index 0000000..885f7d9 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_included_subpackages.py @@ -0,0 +1,20 @@ +def _included_subpackages(packages): + for pkg in packages: + pass + +class Finder (object): + def find_module(self, fullname, path=None): + if fullname in _path_hooks: + return Loader() + +class Loader (object): + def load_module(self, fullname): + import imp, os + pkg_dir = os.path.join(os.environ['RESOURCEPATH'], + 'lib', 'python%d.%d'%(sys.version_info[:2])) + return imp.load_module( + fullname, None, + os.path.join(pkg_dir, fullname), ('', '', imp.PKG_DIRECTORY)) + +import sys +sys.meta_path.insert(0, Finder()) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_pkgresource.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_pkgresource.py new file mode 100644 index 0000000..fec741a --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/setup_pkgresource.py @@ -0,0 +1,13 @@ +def _setup_pkgresources(): + import pkg_resources + import os, plistlib + + pl = plistlib.readPlist(os.path.join( + os.path.dirname(os.getenv('RESOURCEPATH')), "Info.plist")) + appname = pl.get('CFBundleIdentifier') + if appname is None: + appname = pl['CFBundleDisplayName'] + path = os.path.expanduser('~/Library/Caches/%s/python-eggs'%(appname,)) + pkg_resources.set_extraction_path(path) + +_setup_pkgresources() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/site_packages.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/site_packages.py new file mode 100644 index 0000000..81c5e32 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/site_packages.py @@ -0,0 +1,24 @@ +def _site_packages(): + import site, sys, os + paths = [] + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + paths.append(os.path.join(prefix, 'lib', 'python' + sys.version[:3], + 'site-packages')) + if os.path.join('.framework', '') in os.path.join(sys.prefix, ''): + home = os.environ.get('HOME') + if home: + paths.append(os.path.join(home, 'Library', 'Python', + sys.version[:3], 'site-packages')) + + # Work around for a misfeature in setuptools: easy_install.pth places + # site-packages way to early on sys.path and that breaks py2app bundles. + # NOTE: this is hacks into an undocumented feature of setuptools and + # might stop to work without warning. + sys.__egginsert = len(sys.path) + + for path in paths: + site.addsitedir(path) +_site_packages() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/system_path_extras.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/system_path_extras.py new file mode 100644 index 0000000..6617ed5 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/system_path_extras.py @@ -0,0 +1,9 @@ +""" Add Apple's additional packages to sys.path """ +def add_system_python_extras(): + import site, sys + + ver = '%s.%s'%(sys.version_info[:2]) + + site.addsitedir('/System/Library/Frameworks/Python.framework/Versions/%s/Extras/lib/python'%(ver,)) + +add_system_python_extras() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv.py new file mode 100644 index 0000000..c19a474 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv.py @@ -0,0 +1,33 @@ +def _fixup_virtualenv(real_prefix): + import sys, os + sys.real_prefix = real_prefix + + # NOTE: The adjustment code is based from logic in the site.py + # installed by virtualenv 1.8.2 (but simplified by removing support + # for platforms that aren't supported by py2app) + + paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])] + hardcoded_relative_dirs = paths[:] + plat_path = os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3], + 'plat-%s' % sys.platform) + if os.path.exists(plat_path): + paths.append(plat_path) + + # This is hardcoded in the Python executable, but + # relative to sys.prefix, so we have to fix up: + for path in list(paths): + tk_dir = os.path.join(path, 'lib-tk') + if os.path.exists(tk_dir): + paths.append(tk_dir) + + # These are hardcoded in the Apple's Python executable, + # but relative to sys.prefix, so we have to fix them up: + hardcoded_paths = [os.path.join(relative_dir, module) + for relative_dir in hardcoded_relative_dirs + for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')] + + for path in hardcoded_paths: + if os.path.exists(path): + paths.append(path) + + sys.path.extend(paths) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv_site_packages.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv_site_packages.py new file mode 100644 index 0000000..1f065cc --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bootstrap/virtualenv_site_packages.py @@ -0,0 +1,32 @@ +def _site_packages(prefix, real_prefix, global_site_packages): + import site, sys, os + paths = [] + prefixes = [sys.prefix] + + paths.append(os.path.join(prefix, 'lib', 'python' + sys.version[:3], + 'site-packages')) + if os.path.join('.framework', '') in os.path.join(prefix, ''): + home = os.environ.get('HOME') + if home: + paths.append(os.path.join(home, 'Library', 'Python', + sys.version[:3], 'site-packages')) + + + # Work around for a misfeature in setuptools: easy_install.pth places + # site-packages way to early on sys.path and that breaks py2app bundles. + # NOTE: this is hacks into an undocumented feature of setuptools and + # might stop to work without warning. + sys.__egginsert = len(sys.path) + + for path in paths: + site.addsitedir(path) + + + # Ensure that the global site packages get placed on sys.path after + # the site packages from the virtual environment (this functionality + # is also in virtualenv) + sys.__egginsert = len(sys.path) + + if global_site_packages: + site.addsitedir(os.path.join(real_prefix, 'lib', 'python' + sys.version[:3], + 'site-packages')) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/build_app.py b/.eggs/py2app-0.12-py3.6.egg/py2app/build_app.py new file mode 100644 index 0000000..998ab43 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/build_app.py @@ -0,0 +1,2185 @@ +""" +Mac OS X .app build command for distutils + +Originally (loosely) based on code from py2exe's build_exe.py by Thomas Heller. +""" +from __future__ import print_function + +import imp +import sys +import os +import zipfile +import plistlib +import shlex +import shutil +import textwrap +import pkg_resources +import collections +import types +from modulegraph import modulegraph + +from py2app.apptemplate.setup import main as script_executable +from py2app.util import mergecopy, make_exec + +try: + from cStringIO import StringIO +except ImportError: + from io import StringIO + +from itertools import chain + + +from setuptools import Command +from distutils.util import convert_path +from distutils import log +from distutils.errors import * + + +from modulegraph.find_modules import find_modules, parse_mf_results, find_needed_modules +from modulegraph.modulegraph import SourceModule, Package, Script +from modulegraph import zipio + +import macholib.dyld +import macholib.MachOStandalone +import macholib.MachO +from macholib.util import flipwritable + +from py2app.create_appbundle import create_appbundle +from py2app.create_pluginbundle import create_pluginbundle +from py2app.util import \ + fancy_split, byte_compile, make_loader, imp_find_module, \ + copy_tree, fsencoding, strip_files, in_system_path, makedirs, \ + iter_platform_files, find_version, skipscm, momc, copy_file, \ + copy_resource, make_symlink +from py2app.filters import \ + not_stdlib_filter, not_system_filter, has_filename_filter +from py2app import recipes + +from distutils.sysconfig import get_config_var, get_config_h_filename +PYTHONFRAMEWORK=get_config_var('PYTHONFRAMEWORK') + + +PLUGIN_SUFFIXES = { + '.qlgenerator': 'QuickLook', + '.mdimporter': 'Spotlight', + '.xpc': 'XPCServices', + '.service': 'Services', + '.prefPane': 'PreferencePanes', + '.iaplugin': 'InternetAccounts', + '.action': 'Automator', +} + +try: + basestring +except NameError: + basestring = str + +if hasattr(sys, 'real_prefix'): + sys_base_prefix = sys.real_prefix +elif hasattr(sys, 'base_prefix'): + sys_base_prefix = sys.base_prefix +else: + sys_base_prefix = sys.prefix + +def rewrite_tkinter_load_commands(tkinter_path): + print("rewrite_tk", tkinter_path) + m = macholib.MachO.MachO(tkinter_path) + tcl_path = None + tk_path = None + + rewrite_map = {} + + for header in m.headers: + for idx, name, other in header.walkRelocatables(): + if other.endswith('/Tk'): + if tk_path is not None and other != tk_path: + raise DistutilsPlatformError('_tkinter is linked to different Tk paths') + tk_path = other + elif other.endswith('/Tcl'): + if tcl_path is not None and other != tcl_path: + raise DistutilsPlatformError('_tkinter is linked to different Tcl paths') + tcl_path = other + + if tcl_path is None or 'Tcl.framework' not in tcl_path: + raise DistutilsPlatformError('_tkinter is not linked a Tcl.framework') + + if tk_path is None or 'Tk.framework' not in tk_path: + raise DistutilsPlatformError('_tkinter is not linked a Tk.framework') + + system_tcl_versions = [nm for nm in os.listdir('/System/Library/Frameworks/Tcl.framework/Versions') if nm != 'Current'] + system_tk_versions = [nm for nm in os.listdir('/System/Library/Frameworks/Tk.framework/Versions') if nm != 'Current'] + + if not tcl_path.startswith('/System/Library/Frameworks'): + # ../Versions/8.5/Tcl + ver = os.path.basename(os.path.dirname(tcl_path)) + if ver not in system_tcl_versions: + raise DistutilsPlatformError('_tkinter is linked to a version of Tcl not in /System') + + rewrite_map[tcl_path] = '/System/Library/Frameworks/Tcl.framework/Versions/%s/Tcl'%(ver,) + + if not tk_path.startswith('/System/Library/Frameworks'): + # ../Versions/8.5/Tk + ver = os.path.basename(os.path.dirname(tk_path)) + if ver not in system_tk_versions: + raise DistutilsPlatformError('_tkinter is linked to a version of Tk not in /System') + + rewrite_map[tk_path] = '/System/Library/Frameworks/Tk.framework/Versions/%s/Tk'%(ver,) + + if rewrite_map: + print("Relinking _tkinter.so to system Tcl/Tk") + rewroteAny = False + for header in m.headers: + for idx, name, other in header.walkRelocatables(): + data = rewrite_map.get(other) + if data: + if header.rewriteDataForCommand(idx, data.encode(sys.getfilesystemencoding())): + rewroteAny = True + + if rewroteAny: + old_mode = flipwritable(m.filename) + try: + with open(m.filename, 'rb+') as f: + for header in m.headers: + f.seek(0) + header.write(f) + f.seek(0, 2) + f.flush() + + finally: + flipwritable(m.filename, old_mode) + + else: + print("_tkinter already linked against system Tcl/Tk") + + +def get_zipfile(dist, semi_standalone=False): + if sys.version_info[0] == 3: + if semi_standalone: + return "python%d.%d/site-packages.zip"%(sys.version_info[:2]) + else: + return "python%d%d.zip"%(sys.version_info[:2]) + return getattr(dist, "zipfile", None) or "site-packages.zip" + +def framework_copy_condition(src): + # Skip Headers, .svn, and CVS dirs + return skipscm(src) and os.path.basename(src) != 'Headers' + +class PythonStandalone(macholib.MachOStandalone.MachOStandalone): + def __init__(self, appbuilder, ext_dir, copyexts, *args, **kwargs): + super(PythonStandalone, self).__init__(*args, **kwargs) + self.appbuilder = appbuilder + self.ext_map = {} + for e in copyexts: + fn = os.path.join(ext_dir, + (e.identifier.replace('.', os.sep) + + os.path.splitext(e.filename)[1]) + ) + self.ext_map[fn] = os.path.dirname(e.filename) + + def update_node(self, m): + if isinstance(m, macholib.MachO.MachO): + if m.filename in self.ext_map: + m.loader_path = self.ext_map[m.filename] + return m + + def copy_dylib(self, src): + dest = os.path.join(self.dest, os.path.basename(src)) + if os.path.islink(src): + dest = os.path.join(self.dest, os.path.basename(os.path.realpath(src))) + + # Ensure that the orginal name also exists, avoids problems when + # the filename is used from Python (see issue #65) + # + # NOTE: The if statement checks that the target link won't + # point to itself, needed for systems like homebrew that + # store symlinks in "public" locations that point to + # files of the same name in a per-package install location. + link_dest = os.path.join(self.dest, os.path.basename(src)) + if os.path.basename(link_dest) != os.path.basename(dest): + make_symlink(os.path.basename(dest), link_dest) + + else: + dest = os.path.join(self.dest, os.path.basename(src)) + + self.ext_map[dest] = os.path.dirname(src) + return self.appbuilder.copy_dylib(src, dest) + + def copy_framework(self, info): + destfn = self.appbuilder.copy_framework(info, self.dest) + dest = os.path.join(self.dest, info['shortname'] + '.framework') + self.pending.append((destfn, iter_platform_files(dest))) + return destfn + +def iterRecipes(module=recipes): + for name in dir(module): + if name.startswith('_'): + continue + check = getattr(getattr(module, name), 'check', None) + if check is not None: + yield (name, check) + +# A very loosely defined "target". We assume either a "script" or "modules" +# attribute. Some attributes will be target specific. +class Target(object): + def __init__(self, **kw): + self.__dict__.update(kw) + # If modules is a simple string, assume they meant list + m = self.__dict__.get("modules") + if m and isinstance(m, basestring): + self.modules = [m] + + def get_dest_base(self): + dest_base = getattr(self, "dest_base", None) + if dest_base: return dest_base + script = getattr(self, "script", None) + if script: + return os.path.basename(os.path.splitext(script)[0]) + modules = getattr(self, "modules", None) + assert modules, "no script, modules or dest_base specified" + return modules[0].split(".")[-1] + + def validate(self): + resources = getattr(self, "resources", []) + for r_filename in resources: + if not os.path.isfile(r_filename): + raise DistutilsOptionError( + "Resource filename '%s' does not exist" % (r_filename,)) + + +def validate_target(dist, attr, value): + res = FixupTargets(value, "script") + other = {"app": "plugin", "plugin": "app"} + if res and getattr(dist, other[attr]): + # XXX - support apps and plugins? + raise DistutilsOptionError( + "You must specify either app or plugin, not both") + +def FixupTargets(targets, default_attribute): + if not targets: + return targets + try: + targets = eval(targets) + except: + pass + ret = [] + for target_def in targets: + if isinstance(target_def, basestring): + # Create a default target object, with the string as the attribute + target = Target(**{default_attribute: target_def}) + else: + d = getattr(target_def, "__dict__", target_def) + if default_attribute not in d: + raise DistutilsOptionError( + "This target class requires an attribute '%s'" + % (default_attribute,)) + target = Target(**d) + target.validate() + ret.append(target) + return ret + +def normalize_data_file(fn): + if isinstance(fn, basestring): + fn = convert_path(fn) + return ('', [fn]) + return fn + +def is_system(): + prefix = sys.prefix + if os.path.exists(os.path.join(prefix, ".Python")): + fn = os.path.join(prefix, "lib", "python%d.%d"%(sys.version_info[:2]), "orig-prefix.txt") + if os.path.exists(fn): + with open(fn, 'rU') as fp: + prefix = fp.read().strip() + + return in_system_path(prefix) + +def installation_info(version=None): + if version is None: + version = sys.version + + if is_system(): + return version[:3] + " (FORCED: Using vendor Python)" + else: + return version[:3] + +class py2app(Command): + description = "create a Mac OS X application or plugin from Python scripts" + # List of option tuples: long name, short name (None if no short + # name), and help string. + + user_options = [ + ("app=", None, + "application bundle to be built"), + ("plugin=", None, + "plugin bundle to be built"), + ('optimize=', 'O', + "optimization level: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ("includes=", 'i', + "comma-separated list of modules to include"), + ("packages=", 'p', + "comma-separated list of packages to include"), + ("iconfile=", None, + "Icon file to use"), + ("excludes=", 'e', + "comma-separated list of modules to exclude"), + ("dylib-excludes=", 'E', + "comma-separated list of frameworks or dylibs to exclude"), + ("datamodels=", None, + "xcdatamodels to be compiled and copied into Resources"), + ("expected-missing-imports=", None, + "expected missing imports either a comma sperated list " + "or @ followed by file containing a list of imports, one per line"), + ("mappingmodels=", None, + "xcmappingmodels to be compiled and copied into Resources"), + ("resources=", 'r', + "comma-separated list of additional data files and folders to include (not for code!)"), + ("frameworks=", 'f', + "comma-separated list of additional frameworks and dylibs to include"), + ("plist=", 'P', + "Info.plist template file, dict, or plistlib.Plist"), + ("extension=", None, + "Bundle extension [default:.app for app, .plugin for plugin]"), + ("graph", 'g', + "output module dependency graph"), + ("xref", 'x', + "output module cross-reference as html"), + ("no-strip", None, + "do not strip debug and local symbols from output"), + #("compressed", 'c', + # "create a compressed zipfile"), + ("no-chdir", 'C', + "do not change to the data directory (Contents/Resources) [forced for plugins]"), + #("no-zip", 'Z', + # "do not use a zip file (XXX)"), + ("semi-standalone", 's', + "depend on an existing installation of Python " + installation_info()), + ("alias", 'A', + "Use an alias to current source file (for development only!)"), + ("argv-emulation", 'a', + "Use argv emulation [disabled for plugins]."), + ("argv-inject=", None, + "Inject some commands into the argv"), + ("emulate-shell-environment", None, + "Emulate the shell environment you get in a Terminal window"), + ("use-pythonpath", None, + "Allow PYTHONPATH to effect the interpreter's environment"), + ("use-faulthandler", None, + "Enable the faulthandler in the generated bundle (Python 3.3 or later)"), + ("verbose-interpreter", None, + "Start python in verbose mode"), + ('bdist-base=', 'b', + 'base directory for build library (default is build)'), + ('dist-dir=', 'd', + "directory to put final built distributions in (default is dist)"), + ('site-packages', None, + "include the system and user site-packages into sys.path"), + ("strip", 'S', + "strip debug and local symbols from output (on by default, for compatibility)"), + ("prefer-ppc", None, + "Force application to run translated on i386 (LSPrefersPPC=True)"), + ('debug-modulegraph', None, + 'Drop to pdb console after the module finding phase is complete'), + ("debug-skip-macholib", None, + "skip macholib phase (app will not be standalone!)"), + ("arch=", None, "set of architectures to use (fat, fat3, universal, intel, i386, ppc, x86_64; default is the set for the current python binary)"), + ("qt-plugins=", None, "set of Qt plugins to include in the application bundle (default None)"), + ("matplotlib-backends=", None, "set of matplotlib backends to include (default: include entire package)"), + ("extra-scripts=", None, "set of scripts to include in the application bundle, next to the main application script"), + ("include-plugins=", None, "List of plugins to include"), + ("force-system-tk", None, "Ensure that Tkinter is linked against Apple's build of Tcl/Tk"), + ("report-missing-from-imports", None, "Report the list of missing names for 'from module import name'"), + ("no-report-missing-conditional-import", None, "Don't report missing modules when they appear to be conditional imports"), + ("redirect-stdout-to-asl", None, "Forward the stdout/stderr streams to Console.app using the ASL library"), + ] + + boolean_options = [ + #"compressed", + "xref", + "strip", + "no-strip", + "site-packages", + "semi-standalone", + "alias", + "argv-emulation", + #"no-zip", + "use-pythonpath", + "use-faulthandler", + "verbose-interpreter", + "no-chdir", + "debug-modulegraph", + "debug-skip-macholib", + "graph", + "prefer-ppc", + "emulate-shell-environment", + "force-system-tk", + "report-missing-from-imports", + "no-report-missing-conditional-import", + "redirect-stdout-to-asl", + ] + + always_expected_missing_imports = set([ + 'org', 'java', # Jython only + '_frozen_importlib_external' # Seems to be side effect of py2app + ]) + + + def initialize_options (self): + self.app = None + self.plugin = None + self.bdist_base = None + self.xref = False + self.graph = False + self.no_zip = 0 + self.optimize = 0 + if hasattr(sys, 'flags'): + self.optimize = sys.flags.optimize + self.arch = None + self.strip = True + self.no_strip = False + self.iconfile = None + self.extension = None + self.alias = 0 + self.argv_emulation = 0 + self.emulate_shell_environment = 0 + self.argv_inject = None + self.no_chdir = 0 + self.site_packages = False + self.use_pythonpath = False + self.use_faulthandler = False + self.verbose_interpreter = False + self.includes = None + self.packages = None + self.excludes = None + self.dylib_excludes = None + self.frameworks = None + self.resources = None + self.datamodels = None + self.mappingmodels = None + self.plist = None + self.compressed = True + self.semi_standalone = is_system() + self.dist_dir = None + self.debug_skip_macholib = False + self.debug_modulegraph = False + self.prefer_ppc = False + self.filters = [] + self.eggs = [] + self.qt_plugins = None + self.matplotlib_backends = None + self.extra_scripts = None + self.include_plugins = None + self.force_system_tk = False + self.report_missing_from_imports = False + self.no_report_missing_conditional_import = False + self.redirect_stdout_to_asl = False + self._python_app = None + self.expected_missing_imports = None + + + def finalize_options (self): + if sys_base_prefix != sys.prefix: + self._python_app = os.path.join(sys_base_prefix, 'Resources', 'Python.app') + + elif os.path.exists(os.path.join(sys.prefix, 'pyvenv.cfg')): + with open(os.path.join(sys.prefix, 'pyvenv.cfg')) as fp: + for line in fp: + if line.startswith('home = '): + _, home_path = line.split('=', 1) + prefix = os.path.dirname(home_path.strip()) + break + + else: + raise DistutilsPlatformError('Pyvenv detected, but cannot determine base prefix') + + + self._python_app = os.path.join(prefix, 'Resources', 'Python.app') + + + elif os.path.exists(os.path.join(sys.prefix, ".Python")): + fn = os.path.join(sys.prefix, "lib", "python%d.%d"%(sys.version_info[:2]), "orig-prefix.txt") + if os.path.exists(fn): + with open(fn, 'rU') as fp: + prefix = fp.read().strip() + self._python_app = os.path.join(prefix, 'Resources', 'Python.app') + else: + raise DistutilsPlatformError('Virtualenv detected, but cannot determine base prefix') + + else: + self._python_app = os.path.join(sys.prefix, 'Resources', 'Python.app') + + if not self.strip: + self.no_strip = True + elif self.no_strip: + self.strip = False + self.optimize = int(self.optimize) + if self.argv_inject and isinstance(self.argv_inject, basestring): + self.argv_inject = shlex.split(self.argv_inject) + self.includes = set(fancy_split(self.includes)) + self.includes.add('encodings.*') + + if self.use_faulthandler: + self.includes.add('faulthandler') + #if sys.version_info[:2] >= (3, 2): + # self.includes.add('pkgutil') + # self.includes.add('imp') + self.packages = set(fancy_split(self.packages)) + + self.excludes = set(fancy_split(self.excludes)) + self.excludes.add('readline') + # included by apptemplate + self.excludes.add('site') + if getattr(self.distribution, 'install_requires', None): + self.includes.add('pkg_resources') + self.eggs = pkg_resources.require(self.distribution.install_requires) + + # Setuptools/distribute style namespace packages uses + # __import__('pkg_resources'), and that import isn't detected at the + # moment. Forcefully include pkg_resources. + self.includes.add('pkg_resources') + + dylib_excludes = fancy_split(self.dylib_excludes) + self.dylib_excludes = [] + for fn in dylib_excludes: + try: + res = macholib.dyld.framework_find(fn) + except ValueError: + try: + res = macholib.dyld.dyld_find(fn) + except ValueError: + res = fn + self.dylib_excludes.append(res) + self.resources = fancy_split(self.resources) + frameworks = fancy_split(self.frameworks) + self.frameworks = [] + for fn in frameworks: + try: + res = macholib.dyld.framework_find(fn) + except ValueError: + res = macholib.dyld.dyld_find(fn) + while res in self.dylib_excludes: + self.dylib_excludes.remove(res) + self.frameworks.append(res) + if not self.plist: + self.plist = {} + if isinstance(self.plist, basestring): + self.plist = plistlib.Plist.fromFile(self.plist) + if isinstance(self.plist, plistlib.Dict): + self.plist = dict(self.plist.__dict__) + else: + self.plist = dict(self.plist) + + self.set_undefined_options('bdist', + ('dist_dir', 'dist_dir'), + ('bdist_base', 'bdist_base')) + + if self.semi_standalone: + self.filters.append(not_stdlib_filter) + + if self.iconfile is None and 'CFBundleIconFile' not in self.plist: + # Default is the generic applet icon in the framework + iconfile = os.path.join(self._python_app, + 'Contents', 'Resources', 'PythonApplet.icns') + if os.path.exists(iconfile): + self.iconfile = iconfile + + + self.runtime_preferences = list(self.get_runtime_preferences()) + + self.qt_plugins = fancy_split(self.qt_plugins) + self.matplotlib_backends = fancy_split(self.matplotlib_backends) + self.extra_scripts = fancy_split(self.extra_scripts) + self.include_plugins = fancy_split(self.include_plugins) + + if self.expected_missing_imports is None: + self.expected_missing_imports = self.always_expected_missing_imports + else: + if self.expected_missing_imports.startswith( '@' ): + self.expected_missing_imports = self.read_expected_missing_imports_file( self.expected_missing_imports[1:] ) + else: + self.expected_missing_imports = set(fancy_split(self.expected_missing_imports)) + self.expected_missing_imports |= self.always_expected_missing_imports + + if self.datamodels: + print("WARNING: the datamodels option is deprecated, add model files to the list of resources") + + if self.mappingmodels: + print("WARNING: the mappingmodels option is deprecated, add model files to the list of resources") + + + def read_expected_missing_imports_file( self, filename ): + # + # ignore blank lines and lines that start with a '#' + # only one import per line + # + expected_missing_imports = set() + with open( filename, 'r' ) as f: + for line in f: + line = line.strip() + if line.startswith( '#' ) or line == '': + continue + expected_missing_imports.add( line ) + + return expected_missing_imports + + + def get_default_plist(self): + # XXX - this is all single target stuff + plist = {} + target = self.targets[0] + + version = self.distribution.get_version() + if version == '0.0.0': + try: + version = find_version(target.script) + except ValueError: + pass + + if not isinstance(version, basestring): + raise DistutilsOptionError("Version must be a string") + + if sys.version_info[0] > 2 and isinstance(version, type('a'.encode('ascii'))): + raise DistutilsOptionError("Version must be a string") + + plist['CFBundleVersion'] = version + + name = self.distribution.get_name() + if name == 'UNKNOWN': + base = target.get_dest_base() + name = os.path.basename(base) + plist['CFBundleName'] = name + + return plist + + def get_runtime(self, prefix=None, version=None): + # XXX - this is a bit of a hack! + # ideally we'd use dylib functions to figure this out + if prefix is None: + prefix = sys.prefix + if version is None: + version = sys.version + version = version[:3] + info = None + if sys_base_prefix != sys.prefix: + prefix = sys_base_prefix + + elif os.path.exists(os.path.join(prefix, "pyvenv.cfg")): + with open(os.path.join(prefix, "pyvenv.cfg")) as fp: + for ln in fp: + if ln.startswith('home = '): + _, home_path = ln.split('=', 1) + prefix = os.path.dirname(home_path.strip()) + break + else: + raise DistutilsPlatformError('Pyvenv detected, but cannot determine base prefix') + + elif os.path.exists(os.path.join(prefix, ".Python")): + # We're in a virtualenv environment, locate the real prefix + fn = os.path.join(prefix, "lib", "python%d.%d"%(sys.version_info[:2]), "orig-prefix.txt") + if os.path.exists(fn): + with open(fn, 'rU') as fp: + prefix = fp.read().strip() + + try: + fmwk = macholib.dyld.framework_find(prefix) + except ValueError: + info = None + else: + info = macholib.dyld.framework_info(fmwk) + + if info is not None: + dylib = info['name'] + runtime = os.path.join(info['location'], info['name']) + else: + dylib = 'libpython%s.dylib' % (sys.version[:3],) + runtime = os.path.join(prefix, 'lib', dylib) + + return dylib, runtime + + def get_runtime_preferences(self, prefix=None, version=None): + dylib, runtime = self.get_runtime(prefix=prefix, version=version) + yield os.path.join('@executable_path', '..', 'Frameworks', dylib) + if self.semi_standalone or self.alias: + yield runtime + + def run(self): + if get_config_var('PYTHONFRAMEWORK') is None: + if not get_config_var('Py_ENABLE_SHARED'): + raise DistutilsPlatformError("This python does not have a shared library or framework") + + else: + # Issue .. in py2app's tracker, and issue .. in python's tracker: a unix-style shared + # library build did not read the application environment correctly. The collection of + # if statements below gives a clean error message when py2app is started, instead of + # building a bundle that will give a confusing error message when started. + msg = "py2app is not supported for a shared library build with this version of python" + if sys.version_info[:2] < (2,7): + raise DistutilsPlatformError(msg) + elif sys.version_info[:2] == (2,7) and sys.version[3] < 4: + raise DistutilsPlatformError(msg) + elif sys.version_info[0] == 3 and sys.version_info[1] < 2: + raise DistutilsPlatformError(msg) + elif sys.version_info[0] == 3 and sys.version_info[1] == 2 and sys.version_info[3] < 3: + raise DistutilsPlatformError(msg) + elif sys.version_info[0] == 3 and sys.version_info[1] == 3 and sys.version_info[3] < 1: + raise DistutilsPlatformError(msg) + + if hasattr(self.distribution, "install_requires") \ + and self.distribution.install_requires: + + self.distribution.fetch_build_eggs(self.distribution.install_requires) + + + build = self.reinitialize_command('build') + build.build_base = self.bdist_base + build.run() + self.create_directories() + self.fixup_distribution() + self.initialize_plist() + + sys_old_path = sys.path[:] + extra_paths = [ + os.path.dirname(target.script) + for target in self.targets + ] + extra_paths.extend([build.build_platlib, build.build_lib]) + self.additional_paths = [ + os.path.abspath(p) + for p in extra_paths + if p is not None + ] + sys.path[:0] = self.additional_paths + + # this needs additional_paths + self.initialize_prescripts() + + try: + self._run() + finally: + sys.path = sys_old_path + + + def iter_datamodels(self, resdir): + for (path, files) in (normalize_data_file(fn) for fn in (self.datamodels or ())): + path = fsencoding(path) + for fn in files: + fn = fsencoding(fn) + basefn, ext = os.path.splitext(fn) + if ext != '.xcdatamodel': + basefn = fn + fn += '.xcdatamodel' + destfn = os.path.basename(basefn) + '.mom' + yield fn, os.path.join(resdir, path, destfn) + + def compile_datamodels(self, resdir): + for src, dest in self.iter_datamodels(resdir): + print("compile datamodel", src, "->", dest) + self.mkpath(os.path.dirname(dest)) + momc(src, dest) + + def iter_mappingmodels(self, resdir): + for (path, files) in (normalize_data_file(fn) for fn in (self.mappingmodels or ())): + path = fsencoding(path) + for fn in files: + fn = fsencoding(fn) + basefn, ext = os.path.splitext(fn) + if ext != '.xcmappingmodel': + basefn = fn + fn += '.xcmappingmodel' + destfn = os.path.basename(basefn) + '.cdm' + yield fn, os.path.join(resdir, path, destfn) + + def compile_mappingmodels(self, resdir): + for src, dest in self.iter_mappingmodels(resdir): + self.mkpath(os.path.dirname(dest)) + mapc(src, dest) + + def iter_extra_plugins(self): + for item in self.include_plugins: + if isinstance(item, (list, tuple)): + subdir, path = item + + else: + ext = os.path.splitext(item)[1] + try: + subdir = PLUGIN_SUFFIXES[ext] + path = item + except KeyError: + raise DistutilsOptionError("Cannot determine subdirectory for plugin %s"%(item,)) + + yield path, os.path.join(subdir, os.path.basename(path)) + + def iter_data_files(self): + dist = self.distribution + allres = chain(getattr(dist, 'data_files', ()) or (), self.resources) + for (path, files) in (normalize_data_file(fn) for fn in allres): + path = fsencoding(path) + for fn in files: + fn = fsencoding(fn) + yield fn, os.path.join(path, os.path.basename(fn)) + + def collect_scripts(self): + # these contains file names + scripts = set() + + for target in self.targets: + scripts.add(target.script) + scripts.update([ + k for k in target.prescripts if isinstance(k, basestring) + ]) + if hasattr(target, 'extra_scripts'): + scripts.update(target.extra_scripts) + + scripts.update(self.extra_scripts) + return scripts + + def get_plist_options(self): + result = dict( + PyOptions=dict( + use_pythonpath=bool(self.use_pythonpath), + site_packages=bool(self.site_packages), + alias=bool(self.alias), + argv_emulation=bool(self.argv_emulation), + emulate_shell_environment=bool(self.emulate_shell_environment), + no_chdir=bool(self.no_chdir), + prefer_ppc=self.prefer_ppc, + verbose=self.verbose_interpreter, + use_faulthandler=self.use_faulthandler, + ), + ) + if self.optimize: + result['PyOptions']['optimize'] = self.optimize + return result + + + def initialize_plist(self): + plist = self.get_default_plist() + for target in self.targets: + plist.update(getattr(target, 'plist', {})) + plist.update(self.plist) + plist.update(self.get_plist_options()) + + if self.iconfile: + iconfile = self.iconfile + if not os.path.exists(iconfile): + iconfile = iconfile + '.icns' + if not os.path.exists(iconfile): + raise DistutilsOptionError("icon file must exist: %r" + % (self.iconfile,)) + self.resources.append(iconfile) + plist['CFBundleIconFile'] = os.path.basename(iconfile) + if self.prefer_ppc: + plist['LSPrefersPPC'] = True + + self.plist = plist + return plist + + def run_alias(self): + self.app_files = [] + for target in self.targets: + + extra_scripts = list(self.extra_scripts) + if hasattr(target, 'extra_scripts'): + extra_scripts.update(extra_scripts) + + dst = self.build_alias_executable(target, target.script, extra_scripts) + self.app_files.append(dst) + + for fn in extra_scripts: + if fn.endswith('.py'): + fn = fn[:-3] + elif fn.endswith('.pyw'): + fn = fn[:-4] + + src_fn = script_executable(arch=self.arch, secondary=True) + tgt_fn = os.path.join(target.appdir, 'Contents', 'MacOS', os.path.basename(fn)) + mergecopy(src_fn, tgt_fn) + make_exec(tgt_fn) + + def collect_recipedict(self): + return dict(iterRecipes()) + + def get_modulefinder(self): + if self.debug_modulegraph: + debug = 4 + else: + debug = 0 + return find_modules( + scripts=self.collect_scripts(), + includes=self.includes, + packages=self.packages, + excludes=self.excludes, + debug=debug, + ) + + def collect_filters(self): + return [has_filename_filter] + list(self.filters) + + def process_recipes(self, mf, filters, flatpackages, loader_files): + rdict = self.collect_recipedict() + while True: + for name, check in rdict.items(): + rval = check(self, mf) + if rval is None: + print("--- Skipping recipe %s ---" % (name,)) + continue + # we can pull this off so long as we stop the iter + del rdict[name] + print('*** using recipe: %s ***' % (name,)) + + if 'expected_missing_imports' in rval: + self.expected_missing_imports |= rval.get('expected_missing_imports') + + if rval.get('packages'): + self.packages.update(rval['packages']) + find_needed_modules(mf, packages=rval['packages']) + + for pkg in rval.get('flatpackages', ()): + if isinstance(pkg, basestring): + pkg = (os.path.basename(pkg), pkg) + flatpackages[pkg[0]] = pkg[1] + filters.extend(rval.get('filters', ())) + loader_files.extend(rval.get('loader_files', ())) + newbootstraps = list(map(self.get_bootstrap, + rval.get('prescripts', ()))) + + if rval.get('includes'): + find_needed_modules(mf, includes=rval['includes']) + + if rval.get('resources'): + self.resources.extend(rval['resources']) + + for fn in newbootstraps: + if isinstance(fn, basestring): + mf.run_script(fn) + + for target in self.targets: + target.prescripts.extend(newbootstraps) + break + else: + break + + def _run(self): + try: + if self.alias: + self.run_alias() + else: + self.run_normal() + except: + raise + # XXX - remove when not debugging + # distutils sucks + import pdb, sys, traceback + traceback.print_exc() + pdb.post_mortem(sys.exc_info()[2]) + + print("Done!") + + def filter_dependencies(self, mf, filters): + print("*** filtering dependencies ***") + nodes_seen, nodes_removed, nodes_orphaned = mf.filterStack(filters) + print('%d total' % (nodes_seen,)) + print('%d filtered' % (nodes_removed,)) + print('%d orphaned' % (nodes_orphaned,)) + print('%d remaining' % (nodes_seen - nodes_removed,)) + + def get_appname(self): + return self.plist['CFBundleName'] + + def build_xref(self, mf, flatpackages): + for target in self.targets: + base = target.get_dest_base() + appdir = os.path.join(self.dist_dir, os.path.dirname(base)) + appname = self.get_appname() + dgraph = os.path.join(appdir, appname + '.html') + print("*** creating dependency html: %s ***" + % (os.path.basename(dgraph),)) + with open(dgraph, 'w') as fp: + mf.create_xref(fp) + + def build_graph(self, mf, flatpackages): + for target in self.targets: + base = target.get_dest_base() + appdir = os.path.join(self.dist_dir, os.path.dirname(base)) + appname = self.get_appname() + dgraph = os.path.join(appdir, appname + '.dot') + print("*** creating dependency graph: %s ***" + % (os.path.basename(dgraph),)) + with open(dgraph, 'w') as fp: + mf.graphreport(fp, flatpackages=flatpackages) + + def finalize_modulefinder(self, mf): + for item in mf.flatten(): + if isinstance(item, Package) and item.filename == '-': + # In python3.3 or later the default importer supports namespace + # packages without an __init__ file, don't use that funcionality + # because that causes problems with our suppport for loading + # C extensions. + #if sys.version_info[:2] <= (3,3): + if 1: + fn = os.path.join(self.temp_dir, 'empty_package', '__init__.py') + if not os.path.exists(fn): + dn = os.path.dirname(fn) + if not os.path.exists(dn): + os.makedirs(dn) + with open(fn, 'w') as fp: + pass + + item.filename = fn + + py_files, extensions = parse_mf_results(mf) + + # Remove all top-level scripts from the list of python files, + # those get treated differently. + py_files = [ item for item in py_files if not isinstance(item, Script) ] + + extensions = list(extensions) + return py_files, extensions + + def collect_packagedirs(self): + return list(filter(os.path.exists, [ + os.path.join(os.path.realpath(self.get_bootstrap(pkg)), '') + for pkg in self.packages + ])) + + def may_log_missing(self, module_name): + module_parts = module_name.split('.') + for num_parts in range(1,len(module_parts)+1): + module_id = '.'.join(module_parts[0:num_parts]) + if module_id in self.expected_missing_imports: + return False + + return True + + def run_normal(self): + mf = self.get_modulefinder() + filters = self.collect_filters() + flatpackages = {} + loader_files = [] + self.process_recipes(mf, filters, flatpackages, loader_files) + + if self.debug_modulegraph: + import pdb + pdb.Pdb().set_trace() + + self.filter_dependencies(mf, filters) + + if self.graph: + self.build_graph(mf, flatpackages) + if self.xref: + self.build_xref(mf, flatpackages) + + + py_files, extensions = self.finalize_modulefinder(mf) + pkgdirs = self.collect_packagedirs() + self.create_binaries(py_files, pkgdirs, extensions, loader_files) + + + missing = [] + syntax_error = [] + invalid_bytecode = [] + for module in mf.nodes(): + if isinstance(module, modulegraph.MissingModule): + if module.identifier != '__main__': + missing.append(module) + elif isinstance(module, modulegraph.InvalidSourceModule): + syntax_error.append(module) + elif hasattr(modulegraph, 'InvalidCompiledModule') and isinstance(module, modulegraph.InvalidCompiledModule): + invalid_bytecode.append(module) + + if missing: + missing_unconditional = collections.defaultdict(set) + missing_fromimport = collections.defaultdict(set) + missing_fromimport_conditional = collections.defaultdict(set) + missing_conditional = collections.defaultdict(set) + + log.info( 'checking for any import problems' ) + for module in sorted(missing): + for m in mf.getReferers(module): + if m is None: continue # XXX + + try: + ed = mf.edgeData(m, module) + except KeyError: + ed = None + + if hasattr(modulegraph, 'DependencyInfo') and isinstance(ed, modulegraph.DependencyInfo): + c = missing_unconditional + if ed.conditional or ed.function: + if ed.fromlist: + c = missing_fromimport_conditional + else: + c = missing_conditional + + elif ed.fromlist: + c = missing_fromimport + + c[module.identifier].add(m.identifier) + + else: + missing_unconditional[module.identifier].add(m.identifier) + + if missing_unconditional: + warnings = [] + for m in sorted(missing_unconditional): + try: + if '.' in m: + m1, m2 = m.rsplit('.', 1) + try: + o = __import__(m1, fromlist=[m2]) + o = getattr(o, m2) + except AttributeError: + if self.may_log_missing(m): + warnings.append(" * %s (%s)" % (m, ", ".join(sorted(missing_unconditional[m])))) + continue + + + else: + o = __import__(m) + + if isinstance(o, types.ModuleType): + if self.may_log_missing(m): + warnings.append(" * %s (%s) [module alias]" % (m, ", ".join(sorted(missing_unconditional[m])))) + + except ImportError: + if self.may_log_missing(m): + warnings.append(" * %s (%s)" % (m, ", ".join(sorted(missing_unconditional[m])))) + + if len(warnings) > 0: + log.warn("Modules not found (unconditional imports):") + for msg in warnings: + log.warn(msg) + log.warn("") + + + if missing_conditional and not self.no_report_missing_conditional_import: + warnings = [] + for m in sorted(missing_conditional): + try: + if '.' in m: + m1, m2 = m.rsplit('.', 1) + o = __import__(m1, fromlist=[m2]) + try: + o = getattr(o, m2) + except AttributeError: + if self.may_log_missing(m): + warnings.append(" * %s (%s)" % (m, ", ".join(sorted(missing_unconditional[m])))) + continue + + + else: + o = __import__(m) + + if isinstance(o, types.ModuleType): + if self.may_log_missing(m): + warnings.append(" * %s (%s) [module alias]" % (m, ", ".join(sorted(missing_unconditional[m])))) + except ImportError: + if self.may_log_missing(m): + warnings.append(" * %s (%s)" % (m, ", ".join(sorted(missing_conditional[m])))) + + if len(warnings) > 0: + log.warn("Modules not found (conditional imports):") + for msg in warnings: + log.warn(msg) + log.warn("") + + if self.report_missing_from_imports and ( + missing_fromimport or ( + not self.no_report_missing_conditional_import and missing_fromimport_conditional)): + log.warn("Modules not found ('from ... import y'):") + for m in sorted(missing_fromimport): + log.warn(" * %s (%s)" % (m, ", ".join(sorted(missing_fromimport[m])))) + + if not self.no_report_missing_conditional_import and missing_fromimport_conditional: + log.warn("") + log.warn("Conditional:") + for m in sorted(missing_fromimport_conditional): + log.warn(" * %s (%s)" % (m, ", ".join(sorted(missing_fromimport_conditional[m])))) + log.warn("") + + if syntax_error: + log.warn("Modules with syntax errors:") + for module in sorted(syntax_error): + log.warn(" * %s"%(module.identifier)) + + log.warn("") + + if invalid_bytecode: + log.warn("Modules with invalid bytecode:") + for module in sorted(invalid_bytecode): + log.warn(" * %s"%(module.identifier)) + + log.warn("") + + + def create_directories(self): + bdist_base = self.bdist_base + if self.semi_standalone: + self.bdist_dir = os.path.join(bdist_base, + 'python%s-semi_standalone' % (sys.version[:3],), 'app') + else: + self.bdist_dir = os.path.join(bdist_base, + 'python%s-standalone' % (sys.version[:3],), 'app') + + if os.path.exists(self.bdist_dir): + shutil.rmtree(self.bdist_dir) + + self.collect_dir = os.path.abspath( + os.path.join(self.bdist_dir, "collect")) + self.mkpath(self.collect_dir) + + self.temp_dir = os.path.abspath(os.path.join(self.bdist_dir, "temp")) + self.mkpath(self.temp_dir) + + self.dist_dir = os.path.abspath(self.dist_dir) + self.mkpath(self.dist_dir) + + self.lib_dir = os.path.join(self.bdist_dir, + os.path.dirname(get_zipfile(self.distribution, self.semi_standalone))) + self.mkpath(self.lib_dir) + + self.ext_dir = os.path.join(self.lib_dir, 'lib-dynload') + self.mkpath(self.ext_dir) + + self.framework_dir = os.path.join(self.bdist_dir, 'Frameworks') + self.mkpath(self.framework_dir) + + def create_binaries(self, py_files, pkgdirs, extensions, loader_files): + print("*** create binaries ***") + dist = self.distribution + pkgexts = [] + copyexts = [] + extmap = {} + def packagefilter(mod, pkgdirs=pkgdirs): + fn = os.path.realpath(getattr(mod, 'filename', None)) + if fn is None: + return None + for pkgdir in pkgdirs: + if fn.startswith(pkgdir): + return None + return fn + if pkgdirs: + py_files = list(filter(packagefilter, py_files)) + for ext in extensions: + fn = packagefilter(ext) + if fn is None: + fn = os.path.realpath(getattr(ext, 'filename', None)) + pkgexts.append(ext) + else: + if '.' in ext.identifier: + py_files.append(self.create_loader(ext)) + copyexts.append(ext) + extmap[fn] = ext + + # byte compile the python modules into the target directory + print("*** byte compile python files ***") + byte_compile(py_files, + target_dir=self.collect_dir, + optimize=self.optimize, + force=self.force, + verbose=self.verbose, + dry_run=self.dry_run) + + for item in py_files: + if not isinstance(item, Package): continue + self.copy_package_data(item, self.collect_dir) + + self.lib_files = [] + self.app_files = [] + + # create the shared zipfile containing all Python modules + archive_name = os.path.join(self.lib_dir, + get_zipfile(dist, self.semi_standalone)) + + for path, files in loader_files: + dest = os.path.join(self.collect_dir, path) + self.mkpath(dest) + for fn in files: + destfn = os.path.join(dest, os.path.basename(fn)) + if os.path.isdir(fn): + self.copy_tree(fn, destfn, preserve_symlinks=False) + else: + self.copy_file(fn, destfn) + + arcname = self.make_lib_archive(archive_name, + base_dir=self.collect_dir, verbose=self.verbose, + dry_run=self.dry_run) + + # XXX: this doesn't work with python3 + #self.lib_files.append(arcname) + + # build the executables + for target in self.targets: + extra_scripts = list(self.extra_scripts) + if hasattr(target, 'extra_scripts'): + extra_scripts.extend(target.extra_scripts) + + dst = self.build_executable( + target, arcname, pkgexts, copyexts, target.script, extra_scripts) + exp = os.path.join(dst, 'Contents', 'MacOS') + execdst = os.path.join(exp, 'python') + if self.semi_standalone: + make_symlink(sys.executable, execdst) + else: + if PYTHONFRAMEWORK: + # When we're using a python framework bin/python refers to a stub executable + # that we don't want use, we need the executable in Resources/Python.app + dpath = os.path.join(self._python_app, 'Contents', 'MacOS') + self.copy_file(os.path.join(dpath, PYTHONFRAMEWORK), execdst) + + elif os.path.exists(os.path.join(sys.prefix, ".Python")): + fn = os.path.join(sys.prefix, "lib", "python%d.%d"%(sys.version_info[:2]), "orig-prefix.txt") + if os.path.exists(fn): + with open(fn, 'rU') as fp: + prefix = fp.read().strip() + + rest_path = os.path.normpath(sys.executable)[len(os.path.normpath(sys.prefix))+1:] + if rest_path.startswith('.'): + rest_path = rest_path[1:] + + self.copy_file(os.path.join(prefix, rest_path), execdst) + + else: + self.copy_file(sys.executable, execdst) + + if not self.debug_skip_macholib: + if self.force_system_tk: + print("force system tk") + resdir = os.path.join(dst, 'Contents', 'Resources') + pydir = os.path.join(resdir, 'lib', 'python%s.%s'%(sys.version_info[:2])) + ext_dir = os.path.join(pydir, os.path.basename(self.ext_dir)) + tkinter_path = os.path.join(ext_dir, '_tkinter.so') + if os.path.exists(tkinter_path): + rewrite_tkinter_load_commands(tkinter_path) + else: + print("tkinter not found at", tkinter_path) + + + mm = PythonStandalone( + appbuilder=self, + base=dst, + ext_dir=os.path.join(dst, 'Contents', 'Resources', 'lib', 'python%s.%s'%(sys.version_info[:2]), 'lib-dynload'), + copyexts=copyexts, + executable_path=exp) + + dylib, runtime = self.get_runtime() + if self.semi_standalone: + mm.excludes.append(runtime) + else: + mm.mm.run_file(runtime) + for exclude in self.dylib_excludes: + info = macholib.dyld.framework_info(exclude) + if info is not None: + exclude = os.path.join( + info['location'], info['shortname'] + '.framework') + mm.excludes.append(exclude) + for fmwk in self.frameworks: + mm.mm.run_file(fmwk) + platfiles = mm.run() + if self.strip: + platfiles = self.strip_dsym(platfiles) + self.strip_files(platfiles) + self.app_files.append(dst) + + def copy_package_data(self, package, target_dir): + """ + Copy any package data in a python package into the target_dir. + + This is a bit of a hack, it would be better to identify python eggs + and copy those in whole. + """ + exts = [ i[0] for i in imp.get_suffixes() ] + exts.append('.py') + exts.append('.pyc') + exts.append('.pyo') + def datafilter(item): + for e in exts: + if item.endswith(e): + return False + return True + + target_dir = os.path.join(target_dir, *(package.identifier.split('.'))) + for dname in package.packagepath: + filenames = list(filter(datafilter, zipio.listdir(dname))) + for fname in filenames: + if fname in ('.svn', 'CVS', '.hg', '.git'): + # Scrub revision manager junk + continue + if fname in ('__pycache__',): + # Ignore PEP 3147 bytecode cache + continue + if fname.startswith('.') and fname.endswith('.swp'): + # Ignore vim(1) temporary files + continue + if fname.endswith('~') or fname.endswith('.orig'): + # Ignore backup files for common tools (hg, emacs, ...) + continue + pth = os.path.join(dname, fname) + + # Check if we have found a package, exclude those + if zipio.isdir(pth): + # XXX: the 'and not' part is wrong, need to fix zipio.isdir + for p in zipio.listdir(pth): + if p.startswith('__init__.') and p[8:] in exts: + break + + else: + if os.path.isfile(pth): + # Avoid extracting a resource file that happens + # to be zipfile. + # XXX: Need API in zipio for nicer code. + copy_file(pth, os.path.join(target_dir, fname)) + else: + copy_tree(pth, os.path.join(target_dir, fname)) + continue + + elif zipio.isdir(pth) and ( + zipio.isfile(os.path.join(pth, '__init__.py')) + or zipio.isfile(os.path.join(pth, '__init__.pyc')) + or zipio.isfile(os.path.join(pth, '__init__.pyo'))): + # Subdirectory is a python package, these will get included later on + # when the subpackage itself is included, ignore for now. + pass + + else: + copy_file(pth, os.path.join(target_dir, fname)) + + + def strip_dsym(self, platfiles): + """ Remove .dSYM directories in the bundled application """ + + # + # .dSYM directories are contain detached debugging information and + # should be completely removed when the "strip" option is specified. + # + if self.dry_run: + return platfiles + for dirpath, dnames, fnames in os.walk(self.appdir): + for nm in list(dnames): + if nm.endswith('.dSYM'): + print("removing debug info: %s/%s"%(dirpath, nm)) + shutil.rmtree(os.path.join(dirpath, nm)) + dnames.remove(nm) + return [file for file in platfiles if '.dSYM' not in file] + + def strip_files(self, files): + unstripped = 0 + stripfiles = [] + for fn in files: + unstripped += os.stat(fn).st_size + stripfiles.append(fn) + log.info('stripping %s', os.path.basename(fn)) + strip_files(stripfiles, dry_run=self.dry_run, verbose=self.verbose) + stripped = 0 + for fn in stripfiles: + stripped += os.stat(fn).st_size + log.info('stripping saved %d bytes (%d / %d)', + unstripped - stripped, stripped, unstripped) + + def copy_dylib(self, src, dst): + # will be copied from the framework? + if src != sys.executable: + force, self.force = self.force, True + self.copy_file(src, dst) + self.force = force + return dst + + def copy_versioned_framework(self, info, dst): + # XXX - Boy is this ugly, but it makes sense because the developer + # could have both Python 2.3 and 2.4, or Tk 8.4 and 8.5, etc. + # Saves a good deal of space, and I'm pretty sure this ugly + # hack is correct in the general case. + version = info['version'] + if version is None: + return self.raw_copy_framework(info, dst) + short = info['shortname'] + '.framework' + infile = os.path.join(info['location'], short) + outfile = os.path.join(dst, short) + vsplit = os.path.join(infile, 'Versions').split(os.sep) + def condition(src, vsplit=vsplit, version=version): + srcsplit = src.split(os.sep) + if ( + len(srcsplit) > len(vsplit) and + srcsplit[:len(vsplit)] == vsplit and + srcsplit[len(vsplit)] != version and + not os.path.islink(src) + ): + return False + # Skip Headers, .svn, and CVS dirs + return framework_copy_condition(src) + + return self.copy_tree(infile, outfile, + preserve_symlinks=True, condition=condition) + + def copy_framework(self, info, dst): + force, self.force = self.force, True + if info['shortname'] == PYTHONFRAMEWORK: + self.copy_python_framework(info, dst) + else: + self.copy_versioned_framework(info, dst) + self.force = force + return os.path.join(dst, info['name']) + + def raw_copy_framework(self, info, dst): + short = info['shortname'] + '.framework' + infile = os.path.join(info['location'], short) + outfile = os.path.join(dst, short) + return self.copy_tree(infile, outfile, + preserve_symlinks=True, condition=framework_copy_condition) + + def copy_python_framework(self, info, dst): + # XXX - In this particular case we know exactly what we can + # get away with.. should this be extended to the general + # case? Per-framework recipes? + includedir = get_config_var('CONFINCLUDEPY') + configdir = get_config_var('LIBPL') + + + if includedir is None: + includedir = 'python%d.%d'%(sys.version_info[:2]) + else: + includedir = os.path.basename(includedir) + + if configdir is None: + configdir = 'config' + else: + configdir = os.path.basename(configdir) + + + indir = os.path.dirname(os.path.join(info['location'], info['name'])) + outdir = os.path.dirname(os.path.join(dst, info['name'])) + if os.path.exists(outdir): + # Python framework has already been created. + return + + self.mkpath(os.path.join(outdir, 'Resources')) + pydir = 'python%s.%s'%(sys.version_info[:2]) + + # Create a symlink "for Python.frameworks/Versions/Current". This + # is required for the Mac App-store. + make_symlink( + os.path.basename(outdir), + os.path.join(os.path.dirname(outdir), "Current")) + + # Likewise for two links in the root of the framework: + make_symlink( + 'Versions/Current/Resources', + os.path.join(os.path.dirname(os.path.dirname(outdir)), 'Resources')) + make_symlink( + os.path.join('Versions/Current', PYTHONFRAMEWORK), + os.path.join(os.path.dirname(os.path.dirname(outdir)), PYTHONFRAMEWORK)) + + + # Experiment for issue 57 + if not os.path.exists(os.path.join(indir, 'include')): + alt = os.path.join(indir, 'Versions/Current') + if os.path.exists(os.path.join(alt, 'include')): + indir = alt + + # distutils looks for some files relative to sys.executable, which + # means they have to be in the framework... + self.mkpath(os.path.join(outdir, 'include')) + self.mkpath(os.path.join(outdir, 'include', includedir)) + self.mkpath(os.path.join(outdir, 'lib')) + self.mkpath(os.path.join(outdir, 'lib', pydir)) + self.mkpath(os.path.join(outdir, 'lib', pydir, configdir)) + + + fmwkfiles = [ + os.path.basename(info['name']), + 'Resources/Info.plist', + 'include/%s/pyconfig.h'%(includedir), + ] + if '_sysconfigdata' not in sys.modules: + fmwkfiles.append( + 'lib/%s/%s/Makefile'%(pydir, configdir) + ) + + for fn in fmwkfiles: + self.copy_file( + os.path.join(indir, fn), + os.path.join(outdir, fn)) + + + + def fixup_distribution(self): + dist = self.distribution + + # Trying to obtain app and plugin from dist for backward compatibility + # reasons. + app = dist.app + plugin = dist.plugin + # If we can get suitable values from self.app and self.plugin, we prefer + # them. + if self.app is not None or self.plugin is not None: + app = self.app + plugin = self.plugin + + # Convert our args into target objects. + dist.app = FixupTargets(app, "script") + dist.plugin = FixupTargets(plugin, "script") + if dist.app and dist.plugin: + # XXX - support apps and plugins? + raise DistutilsOptionError( + "You must specify either app or plugin, not both") + elif dist.app: + self.style = 'app' + self.targets = dist.app + elif dist.plugin: + self.style = 'plugin' + self.targets = dist.plugin + else: + raise DistutilsOptionError( + "You must specify either app or plugin") + if len(self.targets) != 1: + # XXX - support multiple targets? + raise DistutilsOptionError( + "Multiple targets not currently supported") + if not self.extension: + self.extension = '.' + self.style + + # make sure all targets use the same directory, this is + # also the directory where the pythonXX.dylib must reside + paths = set() + for target in self.targets: + paths.add(os.path.dirname(target.get_dest_base())) + + if len(paths) > 1: + raise DistutilsOptionError( + "all targets must use the same directory: %s" % + ([p for p in paths],)) + if paths: + app_dir = paths.pop() # the only element + if os.path.isabs(app_dir): + raise DistutilsOptionError( + "app directory must be relative: %s" % (app_dir,)) + self.app_dir = os.path.join(self.dist_dir, app_dir) + self.mkpath(self.app_dir) + else: + # Do we allow to specify no targets? + # We can at least build a zipfile... + self.app_dir = self.lib_dir + + def initialize_prescripts(self): + prescripts = [] + prescripts.append('reset_sys_path') + if self.semi_standalone: + prescripts.append('semi_standalone_path') + + if 0 and sys.version_info[:2] >= (3, 2) and not self.alias: + # Python 3.2 or later requires a more complicated + # bootstrap + prescripts.append('import_encodings') + + if os.path.exists(os.path.join(sys.prefix, ".Python")): + # We're in a virtualenv, which means sys.path + # will be broken in alias builds unless we fix + # it. + if self.alias or self.semi_standalone: + prescripts.append("virtualenv") + prescripts.append(StringIO('_fixup_virtualenv(%r)' % (sys.real_prefix,))) + + if self.site_packages or self.alias: + import site + global_site_packages = not os.path.exists( + os.path.join(os.path.dirname(site.__file__), 'no-global-site-packages.txt')) + prescripts.append('virtualenv_site_packages') + prescripts.append(StringIO('_site_packages(%r, %r, %d)' % ( + sys.prefix, sys.real_prefix, global_site_packages))) + + elif self.site_packages or self.alias: + prescripts.append('site_packages') + + if is_system(): + prescripts.append('system_path_extras') + + #if self.style == 'app': + # prescripts.append('setup_pkgresource') + + included_subpkg = [pkg for pkg in self.packages if '.' in pkg] + if included_subpkg: + prescripts.append('setup_included_subpackages') + prescripts.append(StringIO('_path_hooks = %r'%( + included_subpkg))) + + if self.emulate_shell_environment: + prescripts.append('emulate_shell_environment') + + if self.argv_emulation and self.style == 'app': + prescripts.append('argv_emulation') + if 'CFBundleDocumentTypes' not in self.plist: + self.plist['CFBundleDocumentTypes'] = [ + { + 'CFBundleTypeOSTypes' : [ + '****', + 'fold', + 'disk', + ], + 'CFBundleTypeRole': 'Viewer' + }, + ] + + if self.argv_inject is not None: + prescripts.append('argv_inject') + prescripts.append( + StringIO('_argv_inject(%r)\n' % (self.argv_inject,))) + + if self.style == 'app' and not self.no_chdir: + prescripts.append('chdir_resource') + if not self.alias: + prescripts.append('disable_linecache') + prescripts.append('boot_' + self.style) + else: + + # Add ctypes prescript because it is needed to + # find libraries in the bundle, but we don't run + # recipes and hence the ctypes recipe is not used + # for alias builds. + prescripts.append('ctypes_setup') + + if self.additional_paths: + prescripts.append('path_inject') + prescripts.append( + StringIO('_path_inject(%r)\n' % (self.additional_paths,))) + prescripts.append('boot_alias' + self.style) + newprescripts = [] + for s in prescripts: + if isinstance(s, basestring): + newprescripts.append( + self.get_bootstrap('py2app.bootstrap.' + s)) + else: + newprescripts.append(s) + + for target in self.targets: + prescripts = getattr(target, 'prescripts', []) + target.prescripts = newprescripts + prescripts + + + def get_bootstrap(self, bootstrap): + if isinstance(bootstrap, basestring): + if not os.path.exists(bootstrap): + bootstrap = imp_find_module(bootstrap)[1] + return bootstrap + + def get_bootstrap_data(self, bootstrap): + bootstrap = self.get_bootstrap(bootstrap) + if not isinstance(bootstrap, basestring): + return bootstrap.getvalue() + else: + with open(bootstrap, 'rU') as fp: + return fp.read() + + def create_pluginbundle(self, target, script, use_runtime_preference=True): + base = target.get_dest_base() + appdir = os.path.join(self.dist_dir, os.path.dirname(base)) + appname = self.get_appname() + print("*** creating plugin bundle: %s ***" % (appname,)) + if self.runtime_preferences and use_runtime_preference: + self.plist.setdefault( + 'PyRuntimeLocations', self.runtime_preferences) + appdir, plist = create_pluginbundle( + appdir, + appname, + plist=self.plist, + extension=self.extension, + arch=self.arch, + ) + appdir = fsencoding(appdir) + resdir = os.path.join(appdir, 'Contents', 'Resources') + return appdir, resdir, plist + + def create_appbundle(self, target, script, use_runtime_preference=True): + base = target.get_dest_base() + appdir = os.path.join(self.dist_dir, os.path.dirname(base)) + appname = self.get_appname() + print("*** creating application bundle: %s ***" % (appname,)) + if self.runtime_preferences and use_runtime_preference: + self.plist.setdefault( + 'PyRuntimeLocations', self.runtime_preferences) + pythonInfo = self.plist.setdefault('PythonInfoDict', {}) + py2appInfo = pythonInfo.setdefault('py2app', {}).update(dict( + alias=bool(self.alias), + )) + appdir, plist = create_appbundle( + appdir, + appname, + plist=self.plist, + extension=self.extension, + arch=self.arch, + redirect_stdout=self.redirect_stdout_to_asl + ) + appdir = fsencoding(appdir) + resdir = os.path.join(appdir, 'Contents', 'Resources') + return appdir, resdir, plist + + def create_bundle(self, target, script, use_runtime_preference=True): + fn = getattr(self, 'create_%sbundle' % (self.style,)) + return fn( + target, + script, + use_runtime_preference=use_runtime_preference + ) + + def iter_frameworks(self): + for fn in self.frameworks: + fmwk = macholib.dyld.framework_info(fn) + if fmwk is None: + yield fn + else: + basename = fmwk['shortname'] + '.framework' + yield os.path.join(fmwk['location'], basename) + + def build_alias_executable(self, target, script, extra_scripts): + # Build an alias executable for the target + appdir, resdir, plist = self.create_bundle(target, script) + + # symlink python executable + execdst = os.path.join(appdir, 'Contents', 'MacOS', 'python') + prefixPathExecutable = os.path.join(sys.prefix, 'bin', 'python') + if os.path.exists(prefixPathExecutable): + pyExecutable = prefixPathExecutable + else: + pyExecutable = sys.executable + make_symlink(pyExecutable, execdst) + + # make PYTHONHOME + pyhome = os.path.join(resdir, 'lib', 'python' + sys.version[:3]) + realhome = os.path.join(sys.prefix, 'lib', 'python' + sys.version[:3]) + makedirs(pyhome) + if self.optimize: + make_symlink('../../site.pyo', os.path.join(pyhome, 'site.pyo')) + else: + make_symlink('../../site.pyc', os.path.join(pyhome, 'site.pyc')) + make_symlink( + os.path.join(realhome, 'config'), + os.path.join(pyhome, 'config')) + + + # symlink data files + # XXX: fixme: need to integrate automatic data conversion + for src, dest in self.iter_data_files(): + dest = os.path.join(resdir, dest) + if src == dest: + continue + makedirs(os.path.dirname(dest)) + try: + copy_resource(src, dest, dry_run=self.dry_run, symlink=1) + except: + import traceback + traceback.print_exc() + raise + + plugindir = os.path.join(appdir, 'Contents', 'Library') + for src, dest in self.iter_extra_plugins(): + dest = os.path.join(plugindir, dest) + if src == dest: + continue + + makedirs(os.path.dirname(dest)) + try: + copy_resource(src, dest, dry_run=self.dry_run) + except: + import traceback + traceback.print_exc() + raise + + # symlink frameworks + for src in self.iter_frameworks(): + dest = os.path.join( + appdir, 'Contents', 'Frameworks', os.path.basename(src)) + if src == dest: + continue + makedirs(os.path.dirname(dest)) + make_symlink(os.path.abspath(src), dest) + + self.compile_datamodels(resdir) + self.compile_mappingmodels(resdir) + + bootfn = '__boot__' + bootfile = open(os.path.join(resdir, bootfn + '.py'), 'w') + for fn in target.prescripts: + bootfile.write(self.get_bootstrap_data(fn)) + bootfile.write('\n\n') + bootfile.write("DEFAULT_SCRIPT=%r\n"%(os.path.realpath(script),)) + script_map = {} + for fn in extra_scripts: + tgt = os.path.realpath(fn) + fn = os.path.basename(fn) + if fn.endswith('.py'): + script_map[fn[:-3]] = tgt + elif fn.endswith('.py'): + script_map[fn[:-4]] = tgt + else: + script_map[fn] = tgt + + bootfile.write("SCRIPT_MAP=%r\n"%(script_map,)) + bootfile.write('try:\n') + bootfile.write(' _run()\n') + bootfile.write('except KeyboardInterrupt:\n') + bootfile.write(' pass\n') + bootfile.close() + + target.appdir = appdir + return appdir + + def build_executable(self, target, arcname, pkgexts, copyexts, script, extra_scripts): + # Build an executable for the target + appdir, resdir, plist = self.create_bundle(target, script) + self.appdir = appdir + self.resdir = resdir + self.plist = plist + + for fn in extra_scripts: + if fn.endswith('.py'): + fn = fn[:-3] + elif fn.endswith('.pyw'): + fn = fn[:-4] + + src_fn = script_executable(arch=self.arch, secondary=True) + tgt_fn = os.path.join(self.appdir, 'Contents', 'MacOS', os.path.basename(fn)) + mergecopy(src_fn, tgt_fn) + make_exec(tgt_fn) + + + site_path = os.path.join(resdir, 'site.py') + byte_compile([ + SourceModule('site', site_path), + ], + target_dir=resdir, + optimize=self.optimize, + force=self.force, + verbose=self.verbose, + dry_run=self.dry_run) + if not self.dry_run: + os.unlink(site_path) + + + includedir = get_config_var('CONFINCLUDEPY') + configdir = get_config_var('LIBPL') + + + if includedir is None: + includedir = 'python%d.%d'%(sys.version_info[:2]) + else: + includedir = os.path.basename(includedir) + + if configdir is None: + configdir = 'config' + else: + configdir = os.path.basename(configdir) + + self.compile_datamodels(resdir) + self.compile_mappingmodels(resdir) + + bootfn = '__boot__' + bootfile = open(os.path.join(resdir, bootfn + '.py'), 'w') + for fn in target.prescripts: + bootfile.write(self.get_bootstrap_data(fn)) + bootfile.write('\n\n') + + bootfile.write("DEFAULT_SCRIPT=%r\n"%(os.path.basename(script),)) + + script_map = {} + for fn in extra_scripts: + fn = os.path.basename(fn) + if fn.endswith('.py'): + script_map[fn[:-3]] = fn + elif fn.endswith('.py'): + script_map[fn[:-4]] = fn + else: + script_map[fn] = fn + + bootfile.write("SCRIPT_MAP=%r\n"%(script_map,)) + bootfile.write('_run()\n') + bootfile.close() + + self.copy_file(script, resdir) + for fn in extra_scripts: + self.copy_file(fn, resdir) + + pydir = os.path.join(resdir, 'lib', 'python%s.%s'%(sys.version_info[:2])) + if sys.version_info[0] == 2 or self.semi_standalone: + arcdir = os.path.join(resdir, 'lib', 'python' + sys.version[:3]) + else: + arcdir = os.path.join(resdir, 'lib') + realhome = os.path.join(sys.prefix, 'lib', 'python' + sys.version[:3]) + self.mkpath(pydir) + + # The site.py file needs to be a two locations + # 1) in lib/pythonX.Y, to be found during normal startup and + # by the 'python' executable + # 2) in the resources directory next to the script for + # semistandalone builds (the lib/pythonX.Y directory is too + # late on sys.path to be found in that case). + # + if self.optimize: + make_symlink('../../site.pyo', os.path.join(pydir, 'site.pyo')) + else: + make_symlink('../../site.pyc', os.path.join(pydir, 'site.pyc')) + cfgdir = os.path.join(pydir, configdir) + realcfg = os.path.join(realhome, configdir) + real_include = os.path.join(sys.prefix, 'include') + if self.semi_standalone: + make_symlink(realcfg, cfgdir) + make_symlink(real_include, os.path.join(resdir, 'include')) + else: + self.mkpath(cfgdir) + if '_sysconfigdata' not in sys.modules: + # Recent enough versions of Python 2.7 and 3.x have + # an _sysconfigdata module and don't need the Makefile + # to provide the sysconfig data interface. Don't copy + # them. + for fn in 'Makefile', 'Setup', 'Setup.local', 'Setup.config': + rfn = os.path.join(realcfg, fn) + if os.path.exists(rfn): + self.copy_file(rfn, os.path.join(cfgdir, fn)) + + inc_dir = os.path.join(resdir, 'include', includedir) + self.mkpath(inc_dir) + self.copy_file(get_config_h_filename(), + os.path.join(inc_dir, 'pyconfig.h')) + + + self.copy_file(arcname, arcdir) + if sys.version_info[0] != 2: + import zlib + self.copy_file(zlib.__file__, os.path.dirname(arcdir)) + + ext_dir = os.path.join(pydir, os.path.basename(self.ext_dir)) + self.copy_tree(self.ext_dir, ext_dir, preserve_symlinks=True) + self.copy_tree(self.framework_dir, + os.path.join(appdir, 'Contents', 'Frameworks'), + preserve_symlinks=True) + for pkg_name in self.packages: + pkg = self.get_bootstrap(pkg_name) + print('XXXX', pkg_name, pkg) + + if self.semi_standalone: + # For semi-standalone builds don't copy packages + # from the stdlib into the app bundle, even when + # they are mentioned in self.packages. + p = Package(pkg_name, pkg) + if not not_stdlib_filter(p): + continue + + dst = os.path.join(pydir, pkg_name) + if os.path.isdir(pkg): + self.mkpath(dst) + self.copy_tree(pkg, dst) + else: + self.copy_file(pkg, dst + '.py') + + # FIXME: The python files should be bytecompiled + # here (see issue 101) + + for copyext in copyexts: + fn = os.path.join(ext_dir, + (copyext.identifier.replace('.', os.sep) + + os.path.splitext(copyext.filename)[1]) + ) + self.mkpath(os.path.dirname(fn)) + copy_file(copyext.filename, fn, dry_run=self.dry_run) + + for src, dest in self.iter_data_files(): + dest = os.path.join(resdir, dest) + if src == dest: + continue + makedirs(os.path.dirname(dest)) + copy_resource(src, dest, dry_run=self.dry_run) + + plugindir = os.path.join(appdir, 'Contents', 'Library') + for src, dest in self.iter_extra_plugins(): + dest = os.path.join(plugindir, dest) + if src == dest: + continue + + makedirs(os.path.dirname(dest)) + copy_resource(src, dest, dry_run=self.dry_run) + + + target.appdir = appdir + return appdir + + def create_loader(self, item): + # Hm, how to avoid needless recreation of this file? + slashname = item.identifier.replace('.', os.sep) + pathname = os.path.join(self.temp_dir, "%s.py" % slashname) + if os.path.exists(pathname): + if self.verbose: + print("skipping python loader for extension %r" + % (item.identifier,)) + else: + self.mkpath(os.path.dirname(pathname)) + # and what about dry_run? + if self.verbose: + print("creating python loader for extension %r" + % (item.identifier,)) + + fname = slashname + os.path.splitext(item.filename)[1] + source = make_loader(fname) + if not self.dry_run: + with open(pathname, "w") as fp: + fp.write(source) + else: + return + return SourceModule(item.identifier, pathname) + + def make_lib_archive(self, zip_filename, base_dir, verbose=0, + dry_run=0): + # Like distutils "make_archive", except we can specify the + # compression to use - default is ZIP_STORED to keep the + # runtime performance up. + # Also, we don't append '.zip' to the filename. + from distutils.dir_util import mkpath + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + + if self.compressed: + compression = zipfile.ZIP_DEFLATED + else: + compression = zipfile.ZIP_STORED + if not dry_run: + z = zipfile.ZipFile(zip_filename, "w", + compression=compression) + save_cwd = os.getcwd() + os.chdir(base_dir) + for dirpath, dirnames, filenames in os.walk('.'): + if filenames: + # Ensure that there are directory entries for + # all directories in the zipfile. This is a + # workaround for : + # zipimport won't consider 'pkg/foo.py' to be in + # namespace package 'pkg' unless there is an + # entry for the directory (or there is a + # pkg/__init__.py file as well) + z.write(dirpath, dirpath) + + for fn in filenames: + path = os.path.normpath(os.path.join(dirpath, fn)) + if os.path.isfile(path): + z.write(path, path) + + os.chdir(save_cwd) + z.close() + + return zip_filename + + def copy_tree(self, infile, outfile, + preserve_mode=1, preserve_times=1, preserve_symlinks=0, + level=1, condition=None): + """Copy an entire directory tree respecting verbose, dry-run, + and force flags. + + This version doesn't bork on existing symlinks + """ + return copy_tree( + infile, outfile, + preserve_mode,preserve_times,preserve_symlinks, + not self.force, + dry_run=self.dry_run, + condition=condition) + + def copy_file(self, infile, outfile): + """ + This version doesn't bork on existing symlinks + """ + return copy_file(infile, outfile) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/__init__.py new file mode 100644 index 0000000..a7a39be --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/__init__.py @@ -0,0 +1,2 @@ +from . import setup +from . import plist_template diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/__error__.sh b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/__error__.sh new file mode 100755 index 0000000..b3fc73d --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/__error__.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This is the default bundletemplate error script +# Note that this DOES NOT present a GUI dialog, because +# it has no output on stdout, and has a return value of 0. +# +if ( test -n "$2" ) ; then + echo "[$1] Unexpected Exception:" 1>&2 + echo "$2: $3" 1>&2 +else + echo "[$1] Could not find a suitable Python runtime" 1>&2 +fi diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/site.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/site.py new file mode 100644 index 0000000..354e729 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/lib/site.py @@ -0,0 +1,132 @@ +""" +Append module search paths for third-party packages to sys.path. + +This is stripped down and customized for use in py2app applications +""" + +import sys +# os is actually in the zip, so we need to do this here. +# we can't call it python24.zip because zlib is not a built-in module (!) +_libdir = '/lib/python' + sys.version[:3] +_parent = '/'.join(__file__.split('/')[:-1]) +if not _parent.endswith(_libdir): + _parent += _libdir +sys.path.append(_parent + '/site-packages.zip') + +# Stuffit decompresses recursively by default, that can mess up py2app bundles, +# add the uncompressed site-packages to the path to compensate for that. +sys.path.append(_parent + '/site-packages') + +USER_SITE=None + +import os +try: + basestring +except NameError: + basestring = str + +def makepath(*paths): + dir = os.path.abspath(os.path.join(*paths)) + return dir, os.path.normcase(dir) + +for m in sys.modules.values(): + f = getattr(m, '__file__', None) + if isinstance(f, basestring) and os.path.exists(f): + m.__file__ = os.path.abspath(m.__file__) +del m + +# This ensures that the initial path provided by the interpreter contains +# only absolute pathnames, even if we're running from the build directory. +L = [] +_dirs_in_sys_path = {} +dir = dircase = None # sys.path may be empty at this point +for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in _dirs_in_sys_path: + L.append(dir) + _dirs_in_sys_path[dircase] = 1 +sys.path[:] = L +del dir, dircase, L +_dirs_in_sys_path = None + +def _init_pathinfo(): + global _dirs_in_sys_path + _dirs_in_sys_path = d = {} + for dir in sys.path: + if dir and not os.path.isdir(dir): + continue + dir, dircase = makepath(dir) + d[dircase] = 1 + +def addsitedir(sitedir): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in _dirs_in_sys_path: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name[-4:] == os.extsep + "pth": + addpackage(sitedir, name) + if reset: + _dirs_in_sys_path = None + +def addpackage(sitedir, name): + global _dirs_in_sys_path + if _dirs_in_sys_path is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + with open(fullname) as f: + while 1: + dir = f.readline() + if not dir: + break + if dir[0] == '#': + continue + if dir.startswith("import"): + exec(dir) + continue + if dir[-1] == '\n': + dir = dir[:-1] + dir, dircase = makepath(sitedir, dir) + if not dircase in _dirs_in_sys_path and os.path.exists(dir): + sys.path.append(dir) + _dirs_in_sys_path[dircase] = 1 + except IOError: + return + if reset: + _dirs_in_sys_path = None + + +#sys.setdefaultencoding('utf-8') + +# +# Run custom site specific code, if available. +# +try: + import sitecustomize +except ImportError: + pass + +# +# Remove sys.setdefaultencoding() so that users cannot change the +# encoding after initialization. The test for presence is needed when +# this module is run as a script, because this code is executed twice. +# +if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/plist_template.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/plist_template.py new file mode 100644 index 0000000..04ebf16 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/plist_template.py @@ -0,0 +1,51 @@ +import sys +import py2app +__all__ = ['infoPlistDict'] + +def infoPlistDict(CFBundleExecutable, plist={}): + CFBundleExecutable = CFBundleExecutable + NSPrincipalClass = ''.join(CFBundleExecutable.split()) + version = sys.version[:3] + pdict = dict( + CFBundleDevelopmentRegion='English', + CFBundleDisplayName=plist.get('CFBundleName', CFBundleExecutable), + CFBundleExecutable=CFBundleExecutable, + CFBundleIconFile=CFBundleExecutable, + CFBundleIdentifier='org.pythonmac.unspecified.%s' % (NSPrincipalClass,), + CFBundleInfoDictionaryVersion='6.0', + CFBundleName=CFBundleExecutable, + CFBundlePackageType='BNDL', + CFBundleShortVersionString=plist.get('CFBundleVersion', '0.0'), + CFBundleSignature='????', + CFBundleVersion='0.0', + LSHasLocalizedDisplayName=False, + NSAppleScriptEnabled=False, + NSHumanReadableCopyright='Copyright not specified', + NSMainNibFile='MainMen', + NSPrincipalClass=NSPrincipalClass, + PyMainFileNames=['__boot__'], + PyResourcePackages=[ (s % version) for s in [ + 'lib/python%s', + 'lib/python%s/lib-dynload', + 'lib/python%s/site-packages.zip', + ]] + [ 'lib/python%s.zip' % version.replace('.', '') ], + PyRuntimeLocations=[(s % version) for s in [ + '@executable_path/../Frameworks/Python.framework/Versions/%s/Python', + '~/Library/Frameworks/Python.framework/Versions/%s/Python', + '/Library/Frameworks/Python.framework/Versions/%s/Python', + '/Network/Library/Frameworks/Python.framework/Versions/%s/Python', + '/System/Library/Frameworks/Python.framework/Versions/%s/Python', + ]], + ) + pdict.update(plist) + pythonInfo = pdict.setdefault('PythonInfoDict', {}) + pythonInfo.update(dict( + PythonLongVersion=sys.version, + PythonShortVersion=sys.version[:3], + PythonExecutable=sys.executable, + )) + py2appInfo = pythonInfo.setdefault('py2app', {}).update(dict( + version=py2app.__version__, + template='bundle', + )) + return pdict diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat new file mode 100755 index 0000000..1743cc7 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat3 b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat3 new file mode 100755 index 0000000..933c3b7 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-fat3 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-i386 b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-i386 new file mode 100755 index 0000000..0b8145b Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-i386 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-intel b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-intel new file mode 100755 index 0000000..7b87a2e Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-intel differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc new file mode 100755 index 0000000..8098fc3 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc64 b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc64 new file mode 100755 index 0000000..786dc62 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-ppc64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-universal b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-universal new file mode 100755 index 0000000..c3f55c0 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-universal differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-x86_64 b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-x86_64 new file mode 100755 index 0000000..cc692e6 Binary files /dev/null and b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/prebuilt/main-x86_64 differ diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/setup.py b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/setup.py new file mode 100644 index 0000000..d32bb4b --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/setup.py @@ -0,0 +1,122 @@ +import os +import re +import sys +import distutils.sysconfig +import distutils.util + +gPreBuildVariants = [ + { + 'name': 'main-universal', + 'target': '10.5', + 'cflags': '-isysroot @@XCODE_ROOT@@/SDKs/MacOSX10.5.sdk -arch i386 -arch ppc -arch ppc64 -arch x86_64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-ppc64', + 'target': '10.5', + 'cflags': '-isysroot @@XCODE_ROOT@@/SDKs/MacOSX10.5.sdk -arch ppc64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-x86_64', + 'target': '10.5', + 'cflags': '-isysroot / -arch x86_64', + 'cc': 'clang', + }, + { + 'name': 'main-fat3', + 'target': '10.5', + 'cflags': '-isysroot / -arch i386 -arch ppc -arch x86_64', + 'cc': 'gcc-4.2', + }, + { + 'name': 'main-intel', + 'target': '10.5', + 'cflags': '-isysroot / -arch i386 -arch x86_64', + 'cc': 'clang', + }, + { + 'name': 'main-i386', + 'target': '10.3', + #'cflags': '-isysroot @@XCODE_ROOT@@/SDKs/MacOSX10.4u.sdk -arch i386', + 'cflags': '-arch i386 -isysroot /', + 'cc': 'clang', + }, + { + 'name': 'main-ppc', + 'target': '10.3', + 'cflags': '-isysroot @@XCODE_ROOT@@/SDKs/MacOSX10.4u.sdk -arch ppc', + 'cc': 'gcc-4.0', + }, + { + 'name': 'main-fat', + 'target': '10.3', + 'cflags': '-isysroot @@XCODE_ROOT@@/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc', + 'cc': 'gcc-4.0', + }, +] + + +def main(all=False, arch=None): + basepath = os.path.dirname(__file__) + builddir = os.path.join(basepath, 'prebuilt') + if not os.path.exists(builddir): + os.makedirs(builddir) + src = os.path.join(basepath, 'src', 'main.m') + + cfg = distutils.sysconfig.get_config_vars() + + BASE_CFLAGS = cfg['CFLAGS'] + BASE_CFLAGS = BASE_CFLAGS.replace('-dynamic', '') + BASE_CFLAGS += ' -bundle -framework Foundation -framework AppKit' + while True: + x = re.sub('-arch\s+\S+', '', BASE_CFLAGS) + if x == BASE_CFLAGS: + break + BASE_CFLAGS=x + + while True: + x = re.sub('-isysroot\s+\S+', '', BASE_CFLAGS) + if x == BASE_CFLAGS: + break + BASE_CFLAGS=x + + if arch is None: + arch = distutils.util.get_platform().split('-')[-1] + if sys.prefix.startswith('/System') and \ + sys.version_info[:2] == (2,5): + arch = "fat" + + name = 'main-' + arch + root = None + + if all: + for entry in gPreBuildVariants: + if (not all) and entry['name'] != name: continue + + dest = os.path.join(builddir, entry['name']) + if not os.path.exists(dest) or ( + os.stat(dest).st_mtime < os.stat(src).st_mtime): + if root is None: + fp = os.popen('xcode-select -print-path', 'r') + root = fp.read().strip() + fp.close() + + print ("rebuilding %s"%(entry['name'])) + + #CC=os.path.join(root, 'usr', 'bin', entry['cc']) + CC=entry['cc'] + CFLAGS = BASE_CFLAGS + ' ' + entry['cflags'].replace('@@XCODE_ROOT@@', root) + os.environ['MACOSX_DEPLOYMENT_TARGET'] = entry['target'] + os.system('"%(CC)s" -o "%(dest)s" "%(src)s" %(CFLAGS)s' % locals()) + + dest = os.path.join( + builddir, + 'main-' + arch + ) + + return dest + + +if __name__ == '__main__': + main(all=True) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/src/main.m b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/src/main.m new file mode 100644 index 0000000..79e9ea4 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/bundletemplate/src/main.m @@ -0,0 +1,692 @@ +// +// main.m +// apptemplate +// +// Created by Bob Ippolito on Mon September 20 2004. +// Copyright (c) 2004 Bob Ippolito. All rights reserved. +// + +#import +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Constants +// +NSString *ERR_CANNOT_SAVE_LOCALE = @"Cannot save locale information"; +NSString *ERR_REALLYBADTITLE = @"The bundle could not be launched."; +NSString *ERR_TITLEFORMAT = @"%@ has encountered a fatal error, and will now terminate."; +NSString *ERR_PYRUNTIMELOCATIONS = @"The Info.plist file must have a PyRuntimeLocations array containing string values for preferred Python runtime locations. These strings should be \"otool -L\" style mach ids; \"@executable_stub\" and \"~\" prefixes will be translated accordingly."; +NSString *ERR_NOPYTHONRUNTIME = @"A Python runtime could be located. You may need to install a framework build of Python, or edit the PyRuntimeLocations array in this bundle's Info.plist file.\rThese runtime locations were attempted:\r\r"; +NSString *ERR_NOPYTHONSCRIPT = @"A main script could not be located in the Resources folder.\rThese files were tried:\r\r"; +NSString *ERR_LINKERRFMT = @"An internal error occurred while attempting to link with:\r\r%s\r\rSee the Console for a detailed dyld error message"; +NSString *ERR_PYTHONEXCEPTION = @"An uncaught exception was raised during execution of the main script:\r\r%@: %@\r\rThis may mean that an unexpected error has occurred, or that you do not have all of the dependencies for this bundle."; +NSString *ERR_COLONPATH = @"Python bundles can not currently run from paths containing a '/' (or ':' from the Terminal)."; + +#define PYMACAPP_NSIMAGEFLAGS (NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING) +#define PYMACAPP_NSLOOKUPSYMBOLINIMAGEFLAGS (NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) + +// +// Typedefs +// + +#define Py_file_input 257 +typedef int PyObject; +typedef int PyThreadState; +typedef enum {PyGILState_LOCKED, PyGILState_UNLOCKED} PyGILState_STATE; +typedef PyGILState_STATE (*PyGILState_EnsurePtr)(void); +typedef void (*PyGILState_ReleasePtr)(PyGILState_STATE); +typedef PyThreadState *(*PyThreadState_SwapPtr)(PyThreadState *); +typedef void (*PyEval_ReleaseLockPtr)(void); +typedef void (*PyErr_ClearPtr)(void); +typedef void (*PyErr_PrintPtr)(void); +typedef int (*PyErr_OccurredPtr)(void); +typedef PyObject *(*PyBytes_FromStringPtr)(const char *); +typedef int (*PyList_InsertPtr)(PyObject *, int, PyObject *); +typedef void (*Py_DecRefPtr)(PyObject *); +typedef void (*Py_SetProgramNamePtr)(const wchar_t *); +typedef int (*Py_IsInitializedPtr)(void); +typedef void (*Py_InitializePtr)(void); +typedef void (*PyEval_InitThreadsPtr)(void); +typedef PyObject *(*PyRun_FilePtr)(FILE *, const char *, int, PyObject *, PyObject *); +typedef PyObject *(*PySys_GetObjectPtr)(const char *); +typedef int *(*PySys_SetArgvPtr)(int argc, char **argv); +typedef PyObject *(*PyObject_StrPtr)(PyObject *); +typedef const char *(*PyBytes_AsStringPtr)(PyObject *); +typedef PyObject *(*PyObject_GetAttrStringPtr)(PyObject *, const char *); +typedef PyObject *(*PyObject_CallMethodPtr)(PyObject *, const char *, const char *, ...); +typedef PyObject *(*PyImport_ImportModulePtr)(char *); +typedef PyObject *(*PyImport_AddModulePtr)(char *); +typedef PyObject *(*PyModule_AddStringConstantPtr)(PyObject *, char *, char *); +typedef PyObject *(*PyModule_AddObjectPtr)(PyObject *, char *, PyObject *); +typedef PyObject *(*PyModule_GetDictPtr)(PyObject *); +typedef void (*PyObject_SetItemPtr)(PyObject *, PyObject *, PyObject *); +typedef wchar_t* (*_Py_DecodeUTF8_surrogateescapePtr)(const char *s, ssize_t size); + + +// +// Signatures +// + +static void DefaultDecRef(PyObject *op); +static int report_error(NSString *err); +static int report_linkEdit_error(const char* name); +static int report_script_error(NSString *err, NSString *errClassName, NSString *errName); +static NSString *pyStandardizePath(NSString *pyLocation); +static BOOL doesPathExist(NSString *path); +static NSString *getBundleName(void); +static NSString *getErrorTitle(NSString *bundleName); +static const char *bundlePath(void); +static NSBundle *bundleBundle(void); +static int pyobjc_main(int argc, char * const *argv, char * const *envp); + +// +// Mach-O Constructor +// + +static void __attribute__ ((constructor)) _py2app_bundle_load(void); + +// +// Implementation +// + +static +const char *bundlePath(void) { + int i; + const struct mach_header *myHeader = _dyld_get_image_header_containing_address(&bundlePath); + int count = _dyld_image_count(); + for (i = 0; i < count; i++) { + if (_dyld_get_image_header(i) == myHeader) { + return _dyld_get_image_name(i); + } + } + abort(); + return NULL; +} + +static +NSBundle *bundleBundle(void) { + static NSBundle *myBundle = NULL; + if (!myBundle) { + int i; + NSString *path = [NSString stringWithUTF8String:bundlePath()]; + // strip Contents/MacOS/App + for (i = 0; i < 3; i++) { + path = [path stringByDeletingLastPathComponent]; + } + myBundle = [[NSBundle alloc] initWithPath:path]; + } + return myBundle; +} + +// +// THIS WILL NOT WORK WITH Py_TRACE_REFS / Py_DEBUG ON UNLESS USING 2.4 OR LATER! +// +static +void DefaultDecRef(PyObject *op) { + if (op != NULL) { + --(*op); + } +} + +static +int report_script_error(NSString *err, NSString *errClassName, NSString *errName) { + return report_error(err); +} + +static +int report_error(NSString *err) { + NSLog(@"%@", getErrorTitle(getBundleName())); + NSLog(@"%@", err); + return -1; +} + +static +int report_linkEdit_error(const char* name) { + NSLinkEditErrors errorClass; + int errorNumber; + const char *fileName; + const char *errorString; + NSLinkEditError(&errorClass, &errorNumber, &fileName, &errorString); + NSLog(@"%s: %s", name, errorString); + printf("<<>>> %s: %s\n", name, errorString); + return report_error([NSString stringWithFormat:ERR_LINKERRFMT, fileName]); +} + +static +NSString *pyStandardizePath(NSString *pyLocation) { + if ([pyLocation hasPrefix:@"@executable_path/"]) { + NSMutableArray *newComponents = [[pyLocation pathComponents] mutableCopy]; + [newComponents replaceObjectAtIndex:0 withObject:[bundleBundle() privateFrameworksPath]]; + pyLocation = [NSString pathWithComponents: newComponents]; + } + return [pyLocation stringByStandardizingPath]; +}; + +static +BOOL doesPathExist(NSString *path) { + struct stat sb; + return (stat([path fileSystemRepresentation], &sb) == -1) ? NO : YES; +} + +static +NSString *getBundleName(void) { + NSDictionary *infoDictionary = [bundleBundle() infoDictionary]; + NSString *bundleName = [infoDictionary objectForKey:@"CFBundleName"]; + if (!bundleName) { + bundleName = [infoDictionary objectForKey:@"CFBundleExecutable"]; + } + return bundleName; +} + +static +NSString *getErrorTitle(NSString *bundleName) { + if (!bundleName) { + return ERR_REALLYBADTITLE; + } + return [NSString stringWithFormat:ERR_TITLEFORMAT,bundleName]; +} + +static +NSString *getPythonLocation(NSArray *pyLocations) { + // get the runtime locations from the Info.plist + + // *does not* inspect DYLD environment variables for overrides, fallbacks, suffixes, etc. + // I don't really consider that a very bad thing, as it makes this search extremely deterministic. + // Note that I use the env variables when the image is actually linked, so what you find here + // may not be what gets linked. If this is the case, you deserve it :) + + // find a Python runtime + NSString *pyLocation; + NSEnumerator *pyLocationsEnumerator = [pyLocations objectEnumerator]; + while ((pyLocation = [pyLocationsEnumerator nextObject])) { + pyLocation = pyStandardizePath(pyLocation); + if (doesPathExist(pyLocation)) { + return pyLocation; + } + } + return nil; +} + +static NSString* getPythonInterpreter(NSString* pyLocation) { + NSBundle* bndl; + NSString* auxName; + + bndl = bundleBundle(); + + auxName = [[bndl infoDictionary] objectForKey:@"PyExecutableName"]; + if (!auxName) { + auxName = @"python"; + } + return [bndl pathForAuxiliaryExecutable:auxName]; +} + + +static +NSArray *getPythonPathArray(NSDictionary *infoDictionary, NSString *resourcePath) { + NSMutableArray *pythonPathArray = [NSMutableArray arrayWithObject: resourcePath]; + NSArray *pyResourcePackages = [infoDictionary objectForKey:@"PyResourcePackages"]; + if (pyResourcePackages != nil) { + NSString *pkg; + NSEnumerator *pyResourcePackageEnumerator = [pyResourcePackages objectEnumerator]; + while ((pkg = [pyResourcePackageEnumerator nextObject])) { + pkg = [pkg stringByExpandingTildeInPath]; + if (![@"/" isEqualToString: [pkg substringToIndex:1]]) { + pkg = [resourcePath stringByAppendingPathComponent:pkg]; + } + [pythonPathArray addObject:pkg]; + } + } + return pythonPathArray; +} + +static +NSString *getMainPyPath(NSDictionary *infoDictionary) { + NSArray *possibleMains = [infoDictionary objectForKey:@"PyMainFileNames"]; + if ( !possibleMains ) + possibleMains = [NSArray array]; + // find main python file. __main__.py seems to be a standard, so we'll go ahead and add defaults. + possibleMains = [possibleMains arrayByAddingObjectsFromArray:[NSArray arrayWithObjects: + @"__main__", + @"__realmain__", + @"Main", + nil]]; + NSEnumerator *possibleMainsEnumerator = [possibleMains objectEnumerator]; + NSString *mainPyPath = nil; + NSString *nextFileName = nil; + NSString *nextExtension = nil; + NSArray *extensions = [NSArray arrayWithObjects:@".py", @".pyc", @".pyo", @"", nil]; + + NSMutableArray *runtimeAttempts = [NSMutableArray array]; + while ((nextFileName = [possibleMainsEnumerator nextObject])) { + NSEnumerator *nextExtensionEnumerator = [extensions objectEnumerator]; + while ((nextExtension = [nextExtensionEnumerator nextObject])) { + [runtimeAttempts addObject:[nextFileName stringByAppendingString:nextExtension]]; + } + } + possibleMainsEnumerator = [runtimeAttempts objectEnumerator]; + while ((nextFileName = [possibleMainsEnumerator nextObject]) && !mainPyPath) { + mainPyPath = [bundleBundle() pathForResource:nextFileName ofType:nil]; + } + if (!mainPyPath) { + NSString *components = [runtimeAttempts componentsJoinedByString:@"\r"]; + report_error([ERR_NOPYTHONSCRIPT stringByAppendingString:components]); + } + return mainPyPath; +} + + +int pyobjc_main(int argc, char * const *argv, char * const *envp) { + char* curenv; + char* curlocale; + NSDictionary *infoDictionary = [bundleBundle() infoDictionary]; + + if (getenv("PYTHONOPTIMIZE") != NULL) { + unsetenv("PYTHONOPTIMIZE"); + } + if (getenv("PYTHONDEBUG") != NULL) { + unsetenv("PYTHONDEBUG"); + } + if (getenv("PYTHONDONTWRITEBYTECODE") != NULL) { + unsetenv("PYTHONDONTWRITEBYTECODE"); + } + if (getenv("PYTHONIOENCODING") != NULL) { + unsetenv("PYTHONIOENCODING"); + } + if (getenv("PYTHONDUMPREFS") != NULL) { + unsetenv("PYTHONDUMPREFS"); + } + if (getenv("PYTHONMALLOCSTATS") != NULL) { + unsetenv("PYTHONMALLOCSTATS"); + } + + /* Disable writing of bytecode files */ + setenv("PYTHONDONTWRITEBYTECODE", "1", 1); + + NSString *pyLocation = nil; + while (NSIsSymbolNameDefined("_Py_Initialize")) { + // Python is already in-process + NSSymbol sym = NSLookupAndBindSymbol("_Py_Initialize"); + if (!sym) { + break; + } + NSModule mod = NSModuleForSymbol(sym); + if (!mod) { + break; + } + const char *python_dylib_path = NSLibraryNameForModule(mod); + if (python_dylib_path) { + pyLocation = [NSString stringWithUTF8String:python_dylib_path]; + } + break; + } + NSArray *pyLocations = [infoDictionary objectForKey:@"PyRuntimeLocations"]; + if (!pyLocation) { + // Python is not in-process + if (!pyLocations) { + return report_error(ERR_PYRUNTIMELOCATIONS); + } + pyLocation = getPythonLocation(pyLocations); + } + if (!pyLocation) { + NSString *components = [pyLocations componentsJoinedByString:@"\r\r"]; + return report_script_error([ERR_NOPYTHONRUNTIME stringByAppendingString:components], nil, nil); + } + + // Find our resource path and possible PYTHONPATH + NSString *resourcePath = [bundleBundle() resourcePath]; + NSArray *pythonPathArray = getPythonPathArray(infoDictionary, resourcePath); + + // find the main script + NSString *mainPyPath = getMainPyPath(infoDictionary); + if (!mainPyPath) { + // error already reported + return -1; + } + + // Load the Python dylib (may have already been loaded, that is OK) + const struct mach_header *py_dylib = NSAddImage([pyLocation fileSystemRepresentation], PYMACAPP_NSIMAGEFLAGS); + if (!py_dylib) { + return report_linkEdit_error([pyLocation fileSystemRepresentation]); + } + + // Load the symbols we need from Python. We avoid lookups of unicode methods because their + // names are mangled by Python (because of UCS2/UCS4 stuff) and looking them up reliably is + // problematic. + NSSymbol tmpSymbol; +#define LOOKUP_SYMBOL(NAME) \ + tmpSymbol = NSLookupSymbolInImage(py_dylib, "_" #NAME, PYMACAPP_NSLOOKUPSYMBOLINIMAGEFLAGS) +#define LOOKUP_DEFINEADDRESS(NAME, ADDRESS) \ + NAME ## Ptr NAME = (NAME ## Ptr)ADDRESS +#define LOOKUP_DEFINE(NAME) \ + LOOKUP_DEFINEADDRESS(NAME, NSAddressOfSymbol(tmpSymbol)) +#define LOOKUP(NAME) \ + LOOKUP_SYMBOL(NAME); \ + if ( !tmpSymbol ) \ + return report_linkEdit_error(#NAME); \ + LOOKUP_DEFINE(NAME) + +#define OPT_LOOKUP(NAME) \ + LOOKUP_SYMBOL(NAME); \ + NAME ## Ptr NAME = NULL; \ + if (tmpSymbol) { \ + NAME = (NAME ## Ptr)NSAddressOfSymbol(tmpSymbol); \ + } + + LOOKUP_SYMBOL(Py_DecRef); + LOOKUP_DEFINEADDRESS(Py_DecRef, (tmpSymbol ? NSAddressOfSymbol(tmpSymbol) : &DefaultDecRef)); + LOOKUP(Py_SetProgramName); + LOOKUP(Py_IsInitialized); + LOOKUP(Py_Initialize); + LOOKUP(PyErr_Clear); + LOOKUP(PyErr_Print); + LOOKUP(PyErr_Occurred); + LOOKUP(PyEval_ReleaseLock); + LOOKUP(PyGILState_Ensure); + LOOKUP(PyGILState_Release); + LOOKUP(PyEval_InitThreads); + LOOKUP(PyRun_File); + LOOKUP(PySys_GetObject); + LOOKUP(PySys_SetArgv); + LOOKUP(PyObject_Str); + LOOKUP(PyList_Insert); + LOOKUP(PyObject_GetAttrString); + LOOKUP(PyObject_CallMethod); + LOOKUP(PyImport_ImportModule); + LOOKUP(PyImport_AddModule); + LOOKUP(PyObject_SetItem); + LOOKUP(PyModule_AddStringConstant); + LOOKUP(PyModule_AddObject); + LOOKUP(PyModule_GetDict); + LOOKUP(PyThreadState_Swap); + OPT_LOOKUP(_Py_DecodeUTF8_surrogateescape); + + + /* PyBytes / PyString lookups depend of if we're on py3k or not */ + PyBytes_AsStringPtr PyBytes_AsString = NULL; + PyBytes_FromStringPtr PyBytes_FromString = NULL; + LOOKUP_SYMBOL(PyBytes_AsString); + int isPy3k = tmpSymbol != NULL; + if (isPy3k) { + PyBytes_AsString = (PyBytes_AsStringPtr)NSAddressOfSymbol(tmpSymbol); + LOOKUP_SYMBOL(PyBytes_FromString); + PyBytes_FromString = (PyBytes_FromStringPtr)NSAddressOfSymbol(tmpSymbol); + } + else { + LOOKUP_SYMBOL(PyString_AsString); + PyBytes_AsString = (PyBytes_AsStringPtr)NSAddressOfSymbol(tmpSymbol); + LOOKUP_SYMBOL(PyString_FromString); + PyBytes_FromString = (PyBytes_FromStringPtr)NSAddressOfSymbol(tmpSymbol); + } + +#undef LOOKUP +#undef LOOKUP_DEFINE +#undef LOOKUP_DEFINEADDRESS +#undef LOOKUP_SYMBOL + + int was_initialized = Py_IsInitialized(); + + /* + * When apps are started from the Finder (or anywhere + * except from the terminal), the LANG and LC_* variables + * aren't set in the environment. This confuses Py_Initialize + * when it tries to import the codec for UTF-8, + * therefore explicitly set the locale. + * + * Also set the LC_CTYPE environment variable because Py_Initialize + * reset the locale information using the environment :-( + */ + if (isPy3k) { + curlocale = setlocale(LC_ALL, NULL); + if (curlocale != NULL) { + curlocale = strdup(curlocale); + if (curlocale == NULL) { + (void)report_error(ERR_CANNOT_SAVE_LOCALE); + return -1; + } + } + setlocale(LC_ALL, "en_US.UTF-8"); + + curenv = getenv("LC_CTYPE"); + if (!curenv) { + setenv("LC_CTYPE", "en_US.UTF-8", 1); + } + } + + + // Set up the environment variables to be transferred + NSMutableDictionary *newEnviron = [NSMutableDictionary dictionary]; + [newEnviron setObject:[NSString stringWithFormat:@"%p", bundleBundle()] forKey:@"PYOBJC_BUNDLE_ADDRESS"]; + [newEnviron setObject:[NSString stringWithFormat:@"%p", bundleBundle()] forKey:[NSString + stringWithFormat:@"PYOBJC_BUNDLE_ADDRESS%ld", (long)getpid()]]; + [newEnviron setObject:resourcePath forKey:@"RESOURCEPATH"]; + NSMutableDictionary *oldEnviron = [NSMutableDictionary dictionary]; + + // bootstrap Python with information about how to find what it needs + // if it is not already initialized + if (!was_initialized) { + // $PREFIX/Python -> $PREFIX + NSString *pythonProgramName = [pyLocation stringByDeletingLastPathComponent]; + NSString* interpreter = getPythonInterpreter(pyLocation); + struct stat sb; + + if (lstat([interpreter fileSystemRepresentation], &sb) == 0) { + if(!((sb.st_mode & S_IFLNK) == S_IFLNK)) { + setenv("PYTHONHOME", [resourcePath fileSystemRepresentation], 1); + } + } else { + setenv("PYTHONHOME", [resourcePath fileSystemRepresentation], 1); + } + + NSString *pyExecutableName = [infoDictionary objectForKey:@"PyExecutableName"]; + if ( !pyExecutableName ) { + pyExecutableName = @"python"; + } + + pythonProgramName = [[pythonProgramName stringByAppendingPathComponent:@"bin"] stringByAppendingPathComponent:pyExecutableName]; + + wchar_t wPythonName[PATH_MAX+1]; + if (isPy3k) { + mbstowcs(wPythonName, [pythonProgramName fileSystemRepresentation], PATH_MAX+1); + } + else { + const char *cPythonName = [pythonProgramName fileSystemRepresentation]; + memcpy(wPythonName, cPythonName, strlen(cPythonName)); + } + Py_SetProgramName(wPythonName); + } + + // Set new environment variables and save older ones (for nested plugin loading) + NSEnumerator *envEnumerator = [newEnviron keyEnumerator]; + NSString *envKey; + while ((envKey = [envEnumerator nextObject])) { + char *keyString = (char *)[envKey UTF8String]; + char *oldValue = getenv(keyString); + if (oldValue) { + [oldEnviron setObject:[NSString stringWithUTF8String:oldValue] forKey:envKey]; + } + setenv(keyString, (char *)[[newEnviron objectForKey:envKey] UTF8String], 1); + } + + + int rval = 0; + FILE *mainPyFile = NULL; + Py_Initialize(); + PyEval_InitThreads(); + + if (isPy3k) { + /* + * Reset the environment and locale information + */ + setlocale(LC_CTYPE, curlocale); + free(curlocale); + + if (!curenv) { + unsetenv("LC_CTYPE"); + } + } + + + PyGILState_STATE gilState = PyGILState_Ensure(); + + if (was_initialized) { + // transfer path into existing Python process + PyObject *path = PySys_GetObject("path"); + NSEnumerator *pathEnumerator = [pythonPathArray reverseObjectEnumerator]; + NSString *curPath; + while ((curPath = [pathEnumerator nextObject])) { + PyObject *b = PyBytes_FromString([curPath UTF8String]); + PyObject *s = PyObject_CallMethod(b, "decode", "s", "utf-8"); + PyList_Insert(path, 0, s); + Py_DecRef(b);Py_DecRef(s); + } + + // transfer environment variables into existing Python process + PyObject *osModule = PyImport_ImportModule("os"); + PyObject *pyenv = PyObject_GetAttrString(osModule, "environ"); + Py_DecRef(osModule); + envEnumerator = [newEnviron keyEnumerator]; + while ((envKey = [envEnumerator nextObject])) { + char *keyString = (char *)[envKey UTF8String]; + PyObject *b_key = PyBytes_FromString(keyString); + PyObject *b_value = PyBytes_FromString(getenv(keyString)); + PyObject *key = PyObject_CallMethod(b_key, "decode", "s", "utf-8"); + PyObject *value = PyObject_CallMethod(b_value, "decode", "s", "utf-8"); + PyObject_SetItem(pyenv, key, value); + Py_DecRef(b_key);Py_DecRef(key); + Py_DecRef(b_value);Py_DecRef(value); + } + Py_DecRef(pyenv); + } + + char *c_mainPyPath = (char *)[mainPyPath fileSystemRepresentation]; + mainPyFile = fopen(c_mainPyPath, "r"); + if (!mainPyFile) { + rval = report_error([NSString stringWithFormat:@"Could not open main script %@",mainPyPath]); + goto cleanup; + } + if (!was_initialized) { + int i; + NSMutableData *data_argv = [NSMutableData dataWithCapacity:(sizeof(char *) * argc)]; + char **argv_new = [data_argv mutableBytes]; + if (isPy3k) { + argv_new[0] = (char*)_Py_DecodeUTF8_surrogateescape(c_mainPyPath, strlen(c_mainPyPath)); + } else { + argv_new[0] = c_mainPyPath; + } + for (i = 1; i < argc; i++) { + if (isPy3k) { + argv_new[i] = (char*)_Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i])); + } else { + argv_new[i] = argv[i]; + } + } + argv_new[argc] = NULL; + PySys_SetArgv(argc, argv_new); + } + + // create a unique moduleName by CFBundleIdentifier replacing . with _ and prepending __main__ + NSString *moduleName = [NSString stringWithFormat:@"__main__%@", [[[infoDictionary objectForKey:@"CFBundleIdentifier"] componentsSeparatedByString:@"."] componentsJoinedByString:@"_"]]; + PyObject *module = PyImport_AddModule((char *)[moduleName UTF8String]); + if (!module) { + rval = report_error([NSString stringWithFormat:@"Could not create module '%@'",moduleName]); + goto cleanup; + } + PyModule_AddStringConstant(module, "__file__", c_mainPyPath); + char * builtinsName = isPy3k ? "builtins" : "__builtin__"; + PyObject *builtins = PyImport_ImportModule(builtinsName); + PyModule_AddObject(module, "__builtins__", builtins); + PyObject *module_dict = PyModule_GetDict(module); + if (PyErr_Occurred()) { + goto cleanup; + } + + PyObject *res = PyRun_File(mainPyFile, c_mainPyPath, Py_file_input, module_dict, module_dict); + if (res) { + Py_DecRef(res); + } + +cleanup: + // un-transfer the environment variables + envEnumerator = [newEnviron keyEnumerator]; + while ((envKey = [envEnumerator nextObject])) { + char *keyString = (char *)[envKey UTF8String]; + NSString *newValue = [oldEnviron objectForKey:envKey]; + if (newValue) { + setenv(keyString, [newValue UTF8String], 1); + } else { + unsetenv(keyString); + } + } + + if (mainPyFile) { + fclose(mainPyFile); + } + if (PyErr_Occurred()) { + rval = -1; + PyErr_Print(); + } + while ( rval ) { + PyObject *exc = PySys_GetObject("last_type"); + if ( !exc ) { + rval = report_error([NSString stringWithFormat:ERR_PYTHONEXCEPTION,"<>","The exception went away?"]); + break; + } + + PyObject *exceptionClassName = PyObject_GetAttrString(exc, "__name__"); + if ( !exceptionClassName ) { + rval = report_error([NSString stringWithFormat:ERR_PYTHONEXCEPTION,"<>","Could not get exception class name?"]); + break; + } + + PyObject *v = PySys_GetObject("last_value"); + PyObject *exceptionName = NULL; + if ( v ) + exceptionName = PyObject_Str(v); + + PyObject *b = PyObject_CallMethod(exceptionClassName, "encode", "s", "utf-8"); + NSString *nsExceptionClassName = [NSString stringWithCString:PyBytes_AsString(b) encoding:NSUTF8StringEncoding]; + Py_DecRef(exceptionClassName);Py_DecRef(b); + NSString *nsExceptionName; + if ( exceptionName ) { + PyObject *b = PyObject_CallMethod(exceptionName, "encode", "s", "utf-8"); + nsExceptionName = [NSString stringWithCString:PyBytes_AsString(b) encoding:NSUTF8StringEncoding]; + Py_DecRef(exceptionName);Py_DecRef(b); + } else { + nsExceptionName = @""; + } + rval = report_script_error([NSString stringWithFormat:ERR_PYTHONEXCEPTION, nsExceptionClassName, nsExceptionName], nsExceptionClassName, nsExceptionName); + break; + } + PyErr_Clear(); + PyGILState_Release(gilState); + if (gilState == PyGILState_LOCKED) { + PyThreadState_Swap(NULL); + PyEval_ReleaseLock(); + } + + return rval; +} + + +static +void _py2app_bundle_load(void) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + int argc = 1; + char * const argv[] = { (char *)bundlePath(), NULL }; + char * const *envp = *_NSGetEnviron(); + (void)pyobjc_main(argc, argv, envp); + [pool release]; +} + + diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/converters/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/__init__.py new file mode 100644 index 0000000..6c10c53 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/__init__.py @@ -0,0 +1,3 @@ +""" +Resource data converters +""" diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/converters/coredata.py b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/coredata.py new file mode 100644 index 0000000..ebc4bc3 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/coredata.py @@ -0,0 +1,24 @@ +""" +Automatic compilation of CoreData model files +""" +import subprocess, os +from py2app.decorators import converts +from py2app.util import momc, mapc + +@converts(suffix=".xcdatamodel") +def convert_datamodel(source, destination, dry_run=0): + destination = os.path.splitext(destination)[0] + ".mom" + + if dry_run: + return + + momc(source, destination) + +@converts(suffix=".xcmappingmodel") +def convert_mappingmodel(source, destination, dry_run=0): + destination = destination[:-4] + ".cdm" + + if dry_run: + return + + mapc(source, destination) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/converters/nibfile.py b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/nibfile.py new file mode 100644 index 0000000..898aaff --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/converters/nibfile.py @@ -0,0 +1,72 @@ +""" +Automatic compilation of XIB files +""" +from __future__ import print_function +import subprocess, os +from py2app.decorators import converts +from py2app.util import check_output +import time + +# XXX: _run_nibtool is an experiment while researching an odd +# failure of py2app: when _run_nibtool is None py2app will often +# (but for from everytime) fail when there are NIB files in the +# project. The failure is very odd: writing to sys.stderr fails +# with EGAIN as the errno, and subsequently the interpreter basicly +# crashes. +# +# This workaround seems to fix that issue for now. +# +def _run_nibtool(source, destination): + pid = os.fork() + if pid == 0: + os.setsid() + xit = subprocess.call([_get_ibtool(), '--compile', destination, source]) + os._exit(xit) + else: + pid, status = os.waitpid(pid, 0) + if os.WEXITSTATUS(status) != 0: + raise RuntimeError("ibtool failed (%r -> %r)"%(source, destination)) + +#_run_nibtool = None + +gTool = None +def _get_ibtool(): + global gTool + if gTool is None: + if os.path.exists('/usr/bin/xcrun'): + try: + gTool = check_output(['/usr/bin/xcrun', '-find', 'ibtool'])[:-1] + except subprocess.CalledProcessError: + raise IOError("Tool 'ibtool' not found") + else: + gTool = 'ibtool' + + return gTool + +@converts(suffix=".xib") +def convert_xib(source, destination, dry_run=0): + destination = destination[:-4] + ".nib" + + print("compile %s -> %s"%(source, destination)) + if dry_run: + return + + if _run_nibtool is None: + subprocess.check_call([_get_ibtool(), '--compile', destination, source]) + else: + _run_nibtool(source, destination) + #time.sleep(1) + +@converts(suffix=".nib") +def convert_nib(source, destination, dry_run=0): + destination = destination[:-4] + ".nib" + print("compile %s -> %s"%(source, destination)) + + if dry_run: + return + + if _run_nibtool is None: + subprocess.check_call([_get_ibtool, '--compile', destination, source]) + else: + _run_nibtool(source, destination) + #time.sleep(1) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/create_appbundle.py b/.eggs/py2app-0.12-py3.6.egg/py2app/create_appbundle.py new file mode 100644 index 0000000..6a21b95 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/create_appbundle.py @@ -0,0 +1,55 @@ +import os +import plistlib +import shutil +import sys +from pkg_resources import resource_filename +import py2app.apptemplate +from py2app.util import makedirs, mergecopy, mergetree, skipscm, make_exec + +def create_appbundle(destdir, name, extension='.app', module=py2app.apptemplate, + platform='MacOS', copy=mergecopy, mergetree=mergetree, + condition=skipscm, plist={}, arch=None, redirect_stdout=False): + kw = module.plist_template.infoPlistDict( + plist.get('CFBundleExecutable', name), plist) + app = os.path.join(destdir, kw['CFBundleName'] + extension) + if os.path.exists(app): + # Remove any existing build artifacts to ensure that + # we're getting a clean build + shutil.rmtree(app) + contents = os.path.join(app, 'Contents') + resources = os.path.join(contents, 'Resources') + platdir = os.path.join(contents, platform) + dirs = [contents, resources, platdir] + plist = plistlib.Plist() + plist.update(kw) + plistPath = os.path.join(contents, 'Info.plist') + if os.path.exists(plistPath): + if plist != plistlib.Plist.fromFile(plistPath): + for d in dirs: + shutil.rmtree(d, ignore_errors=True) + for d in dirs: + makedirs(d) + plist.write(plistPath) + srcmain = module.setup.main(arch=arch, secondary=not redirect_stdout) + if sys.version_info[0] == 2 and isinstance(kw['CFBundleExecutable'], unicode): + destmain = os.path.join(platdir, kw['CFBundleExecutable'].encode('utf-8')) + else: + destmain = os.path.join(platdir, kw['CFBundleExecutable']) + + with open(os.path.join(contents, 'PkgInfo'), 'w') as fp: + fp.write( + kw['CFBundlePackageType'] + kw['CFBundleSignature'] + ) + copy(srcmain, destmain) + make_exec(destmain) + mergetree( + resource_filename(module.__name__, 'lib'), + resources, + condition=condition, + copyfn=copy, + ) + return app, plist + +if __name__ == '__main__': + import sys + create_appbundle('build', sys.argv[1]) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/create_pluginbundle.py b/.eggs/py2app-0.12-py3.6.egg/py2app/create_pluginbundle.py new file mode 100644 index 0000000..83fe38b --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/create_pluginbundle.py @@ -0,0 +1,55 @@ +import os +import plistlib +import shutil +import sys +from pkg_resources import resource_filename + +import py2app.bundletemplate +from py2app.util import makedirs, mergecopy, mergetree, skipscm, make_exec + +def create_pluginbundle(destdir, name, extension='.plugin', module=py2app.bundletemplate, + platform='MacOS', copy=mergecopy, mergetree=mergetree, + condition=skipscm, plist={}, arch=None): + kw = module.plist_template.infoPlistDict( + plist.get('CFBundleExecutable', name), plist) + plugin = os.path.join(destdir, kw['CFBundleName'] + extension) + if os.path.exists(plugin): + # Remove any existing build artifacts to ensure + # we're getting a clean build + shutil.rmtree(plugin) + contents = os.path.join(plugin, 'Contents') + resources = os.path.join(contents, 'Resources') + platdir = os.path.join(contents, platform) + dirs = [contents, resources, platdir] + plist = plistlib.Plist() + plist.update(kw) + plistPath = os.path.join(contents, 'Info.plist') + if os.path.exists(plistPath): + if plist != plistlib.Plist.fromFile(plistPath): + for d in dirs: + shutil.rmtree(d, ignore_errors=True) + for d in dirs: + makedirs(d) + plist.write(plistPath) + srcmain = module.setup.main(arch=arch) + if sys.version_info[0] == 2 and isinstance(kw['CFBundleExecutable'], unicode): + destmain = os.path.join(platdir, kw['CFBundleExecutable'].encode('utf-8')) + else: + destmain = os.path.join(platdir, kw['CFBundleExecutable']) + with open(os.path.join(contents, 'PkgInfo'), 'w') as fp: + fp.write( + kw['CFBundlePackageType'] + kw['CFBundleSignature'] + ) + copy(srcmain, destmain) + make_exec(destmain) + mergetree( + resource_filename(module.__name__, 'lib'), + resources, + condition=condition, + copyfn=copy, + ) + return plugin, plist + +if __name__ == '__main__': + import sys + create_pluginbundle('build', sys.argv[1]) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/decorators.py b/.eggs/py2app-0.12-py3.6.egg/py2app/decorators.py new file mode 100644 index 0000000..df47d1d --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/decorators.py @@ -0,0 +1,14 @@ +def converts(suffix): + """ + Use the following convention when writing a file converter:: + + from py2app.decorators import converts + + @converts(suffix=".png") + def convert_png(source_file, destination_file): + pass + """ + def wrapper(func): + func.py2app_suffix=suffix + return func + return wrapper diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/filters.py b/.eggs/py2app-0.12-py3.6.egg/py2app/filters.py new file mode 100644 index 0000000..c6124e0 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/filters.py @@ -0,0 +1,61 @@ +import os +import sys +from modulegraph import modulegraph +from macholib.util import in_system_path + +def has_filename_filter(module): + if isinstance(module, modulegraph.MissingModule): + return True + return getattr(module, 'filename', None) is not None + +def not_stdlib_filter(module, prefix=None): + """ + Return False if the module is located in the standard library + """ + if prefix is None: + prefix = sys.prefix + if module.filename is None: + return True + + prefix = os.path.join(os.path.realpath(prefix), '') + + rp = os.path.realpath(module.filename) + if rp.startswith(prefix): + rest = rp[len(prefix):] + if '/site-python/' in rest: + return True + elif '/site-packages/' in rest: + return True + else: + return False + + if os.path.exists(os.path.join(prefix, ".Python")): + # Virtualenv + fn = os.path.join(prefix, "lib", "python%d.%d"%(sys.version_info[:2]), "orig-prefix.txt") + if os.path.exists(fn): + with open(fn, 'rU') as fp: + prefix = fp.read().strip() + + if rp.startswith(prefix): + rest = rp[len(prefix):] + if '/site-python/' in rest: + return True + elif '/site-packages/' in rest: + return True + else: + return False + + return True + +def not_system_filter(module): + """ + Return False if the module is located in a system directory + """ + return not in_system_path(module.filename) + +def bundle_or_dylib_filter(module): + """ + Return False if the module does not have a filetype attribute + corresponding to a Mach-O bundle or dylib + """ + return getattr(module, 'filetype', None) in ('bundle', 'dylib') diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/__init__.py new file mode 100644 index 0000000..a03a164 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/__init__.py @@ -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)], + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/prescript.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/prescript.py new file mode 100644 index 0000000..f1a9153 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/PIL/prescript.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/__init__.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/__init__.py new file mode 100644 index 0000000..8377480 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/__init__.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/cjkcodecs.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/cjkcodecs.py new file mode 100644 index 0000000..4c57951 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/cjkcodecs.py @@ -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() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ctypes.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ctypes.py new file mode 100644 index 0000000..c4fa0f1 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ctypes.py @@ -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'], + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/docutils.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/docutils.py new file mode 100644 index 0000000..db7e39f --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/docutils.py @@ -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() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ftplib.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ftplib.py new file mode 100644 index 0000000..514fd75 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/ftplib.py @@ -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 {} diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/importlib.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/importlib.py new file mode 100644 index 0000000..26850b4 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/importlib.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/lxml.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/lxml.py new file mode 100644 index 0000000..be9d2b3 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/lxml.py @@ -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 {} + diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib.py new file mode 100644 index 0000000..d857f9d --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib.py @@ -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 + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib_prescript.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib_prescript.py new file mode 100644 index 0000000..c065a19 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/matplotlib_prescript.py @@ -0,0 +1,2 @@ +import os +os.environ['MATPLOTLIBDATA'] = os.path.join(os.environ['RESOURCEPATH'], 'mpl-data') diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/mimetypes.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/mimetypes.py new file mode 100644 index 0000000..1101349 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/mimetypes.py @@ -0,0 +1,4 @@ +def check(cmd, mf): + m = mf.findNode('mimetypes') + if m: + return dict(expected_missing_imports=set(['winreg'])) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/numpy.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/numpy.py new file mode 100644 index 0000000..8ee424e --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/numpy.py @@ -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'] + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/os_module.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/os_module.py new file mode 100644 index 0000000..bf66186 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/os_module.py @@ -0,0 +1,4 @@ +def check(cmd, mf): + m = mf.findNode('os') + if m: + return dict(expected_missing_imports=set(['nt'])) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pydoc.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pydoc.py new file mode 100644 index 0000000..37ae192 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pydoc.py @@ -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() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyenchant.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyenchant.py new file mode 100644 index 0000000..56ccad0 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyenchant.py @@ -0,0 +1,28 @@ +""" +Recipe for 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']) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pygame.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pygame.py new file mode 100644 index 0000000..1adc498 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pygame.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyopengl.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyopengl.py new file mode 100644 index 0000000..e240b7f --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyopengl.py @@ -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'], + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyside.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyside.py new file mode 100644 index 0000000..e97e091 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyside.py @@ -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) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyzmq.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyzmq.py new file mode 100644 index 0000000..117d163 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/pyzmq.py @@ -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'] + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt.conf b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt.conf new file mode 100644 index 0000000..bf0b535 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt.conf @@ -0,0 +1,3 @@ +; Qt Configuration file +[Paths] +Plugins = Resources/qt_plugins diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt5.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt5.py new file mode 100644 index 0000000..c2c4e86 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/qt5.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/re.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/re.py new file mode 100644 index 0000000..6c7c836 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/re.py @@ -0,0 +1,4 @@ +def check(cmd, mf): + m = mf.findNode('re') + if m: + return dict(expected_missing_imports=set(['sys.getwindowsversion'])) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/scipy.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/scipy.py new file mode 100644 index 0000000..d030f12 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/scipy.py @@ -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'] + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/setuptools.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/setuptools.py new file mode 100644 index 0000000..c6b8b06 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/setuptools.py @@ -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)) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/sip.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/sip.py new file mode 100644 index 0000000..1a93161 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/sip.py @@ -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 diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/subprocess.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/subprocess.py new file mode 100644 index 0000000..55445ac --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/subprocess.py @@ -0,0 +1,4 @@ +def check(cmd, mf): + m = mf.findNode('subprocess') + if m: + return dict(expected_missing_imports=set(['_winapi'])) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/uuid.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/uuid.py new file mode 100644 index 0000000..df6cc51 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/uuid.py @@ -0,0 +1,4 @@ +def check(cmd, mf): + m = mf.findNode('uuid') + if m: + return dict(expected_missing_imports=set(['netbios', 'win32wnet'])) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/virtualenv.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/virtualenv.py new file mode 100644 index 0000000..9341646 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/virtualenv.py @@ -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() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/wx.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/wx.py new file mode 100644 index 0000000..7b16a49 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/wx.py @@ -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 + ) diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/xml.py b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/xml.py new file mode 100644 index 0000000..2923a37 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/recipes/xml.py @@ -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 {} diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/script_py2applet.py b/.eggs/py2app-0.12-py3.6.egg/py2app/script_py2applet.py new file mode 100644 index 0000000..4399f3c --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/script_py2applet.py @@ -0,0 +1,205 @@ +""" +Create an applet from a Python script. + +You can drag in packages, Info.plist files, icons, etc. + +It's expected that only one Python script is dragged in. +""" +from __future__ import print_function + +import os, sys +from distutils.core import setup +from plistlib import Plist +import py2app +import tempfile +import shutil +import imp +import pprint +from py2app.util import copy_tree +from py2app import build_app +try: + set +except NameError: + from sets import Set as set + +if sys.version_info[0] == 3: + raw_input = input + +HELP_TEXT = """ +usage: py2applet --make-setup [options...] script.py [data files...] + or: py2applet [options...] script.py [data files...] + or: py2applet --help +""" + +SETUP_TEMPLATE = '''""" +This is a setup.py script generated by py2applet + +Usage: + python setup.py py2app +""" + +from setuptools import setup + +APP = %s +DATA_FILES = %s +OPTIONS = %s + +setup( + app=APP, + data_files=DATA_FILES, + options={'py2app': OPTIONS}, + setup_requires=['py2app'], +) +''' + +def get_option_map(): + optmap = {} + for option in build_app.py2app.user_options: + opt_long, opt_short = option[:2] + if opt_short: + optmap['-' + opt_short] = opt_long.rstrip('=') + return optmap + +def get_cmd_options(): + options = set() + for option in build_app.py2app.user_options: + opt_long, opt_short = option[:2] + if opt_long.endswith('=') and opt_short: + options.add('-' + opt_short) + return options + +def main(): + if not sys.argv[1:]: + print(HELP_TEXT) + return + + scripts = [] + data_files = [] + packages = [] + args = [] + plist = {} + iconfile = None + parsing_options = True + next_is_option = False + cmd_options = get_cmd_options() + is_make_setup = False + for fn in sys.argv[1:]: + if parsing_options: + if next_is_option: + args.append(fn) + next_is_option = False + continue + elif fn == '--make-setup': + is_make_setup = True + continue + elif fn.startswith('-'): + args.append(fn) + if fn in cmd_options: + next_is_option = True + continue + parsing_options = False + if not is_make_setup: + fn = os.path.abspath(fn) + if fn.endswith('.py'): + if scripts: + data_files.append(fn) + else: + scripts.append(fn) + elif os.path.basename(fn) == 'Info.plist': + plist = Plist.fromFile(fn) + elif fn.endswith('.icns') and not iconfile: + iconfile = os.path.abspath(fn) + elif os.path.isdir(fn): + sys.path.insert(0, [os.path.dirname(fn)]) + try: + path = imp.find_module(os.path.basename(fn))[0] + except ImportError: + path = '' + del sys.path[0] + if os.path.realpath(path) == os.path.realpath(fn): + packages.append(os.path.basename(fn)) + else: + data_files.append(fn) + else: + data_files.append(fn) + + options = dict( + packages=packages, + plist=plist, + iconfile=iconfile, + ) + for k,v in list(options.items()): + if not v: + del options[k] + if is_make_setup: + make_setup(args, scripts, data_files, options) + else: + build(args, scripts, data_files, options) + +def make_setup(args, scripts, data_files, options): + optmap = get_option_map() + cmd_options = get_cmd_options() + + while args: + cmd = args.pop(0) + if cmd in cmd_options: + cmd = optmap[cmd] + options[cmd.replace('-', '_')] = args.pop(0) + elif '=' in cmd: + cmd, val = cmd.split('=', 1) + options[cmd.lstrip('-').replace('-', '_')] = val + else: + cmd = optmap.get(cmd, cmd) + options[cmd.lstrip('-').replace('-', '_')] = True + + if os.path.exists('setup.py'): + res = '' + while res.lower() not in ('y', 'n'): + res = raw_input('Existing setup.py detected, replace? [Y/n] ') + if not res: + break + if res == 'n': + print('aborted!') + return + f = open('setup.py', 'w') + tvars = tuple(map(pprint.pformat, (scripts, data_files, options))) + f.write(SETUP_TEMPLATE % tvars) + f.flush() + f.close() + print('Wrote setup.py') + +def build(args, scripts, data_files, options): + old_argv = sys.argv + sys.argv = [sys.argv[0], 'py2app'] + args + old_path = sys.path + path_insert = set() + for script in scripts: + path_insert.add(os.path.dirname(script)) + sys.path = list(path_insert) + old_path + old_dir = os.getcwd() + tempdir = tempfile.mkdtemp() + os.chdir(tempdir) + try: + d = setup( + app=scripts, + data_files=data_files, + options={'py2app': options}, + ) + for target in d.app: + copy_tree( + target.appdir, + os.path.join( + os.path.dirname(target.script), + os.path.basename(target.appdir), + ), + preserve_symlinks=True, + ) + + finally: + os.chdir(old_dir) + shutil.rmtree(tempdir, ignore_errors=True) + sys.argv = old_argv + sys.path = old_path + +if __name__ == '__main__': + main() diff --git a/.eggs/py2app-0.12-py3.6.egg/py2app/util.py b/.eggs/py2app-0.12-py3.6.egg/py2app/util.py new file mode 100644 index 0000000..4fab8f3 --- /dev/null +++ b/.eggs/py2app-0.12-py3.6.egg/py2app/util.py @@ -0,0 +1,653 @@ +from __future__ import print_function + +import os, sys, imp, time, errno, stat, filecmp +from modulegraph.find_modules import PY_SUFFIXES, C_SUFFIXES +from modulegraph.util import * +from modulegraph import zipio +import macholib.util +import warnings +from distutils import log + +import pkg_resources +import subprocess + +# Deprecated functionality +def os_path_islink(path): + warnings.warn("Use zipio.islink instead of os_path_islink", + DeprecationWarning) + return zipio.islink(path) + +def os_path_isdir(path): + warnings.warn("Use zipio.isdir instead of os_path_isdir", + DeprecationWarning) + return zipio.islink(path) + +def os_readlink(path): + warnings.warn("Use zipio.readlink instead of os_readlink", + DeprecationWarning) + return zipio.islink(path) + +import zipfile +def get_zip_data(path_to_zip, path_in_zip): + warnings.warn("Use zipio.open instead of get_zip_data", + DeprecationWarning) + zf = zipfile.ZipFile(path_to_zip) + return zf.read(path_in_zip) + +def path_to_zip(path): + """ + Returns (pathtozip, pathinzip). If path isn't in a zipfile pathtozip + will be None + """ + warnings.warn("Don't use this function", DeprecationWarning) + zf = zipfile.ZipFile(path_to_zip) + orig_path = path + from distutils.errors import DistutilsFileError + if os.path.exists(path): + return (None, path) + + else: + rest = '' + while not os.path.exists(path): + path, r = os.path.split(path) + if not path: + raise DistutilsFileError("File doesn't exist: %s"%(orig_path,)) + rest = os.path.join(r, rest) + + if not os.path.isfile(path): + # Directory really doesn't exist + raise DistutilsFileError("File doesn't exist: %s"%(orig_path,)) + + try: + zf = zipfile.ZipFile(path) + except zipfile.BadZipfile: + raise DistutilsFileError("File doesn't exist: %s"%(orig_path,)) + + if rest.endswith('/'): + rest = rest[:-1] + + return path, rest + +def get_mtime(path, mustExist=True): + """ + Get mtime of a path, even if it is inside a zipfile + """ + warnings.warn("Don't use this function", DeprecationWarning) + try: + return zipio.getmtime(target) + + except IOError: + if not mustExist: + return -1 + + raise + +# End deprecated functionality + +gConverterTab = {} +def find_converter(source): + if not gConverterTab: + for ep in pkg_resources.iter_entry_points('py2app.converter'): + function = ep.load() + if not hasattr(function, "py2app_suffix"): + print("WARNING: %s does not have 'py2app_suffix' attribute"%(function)) + continue + gConverterTab[function.py2app_suffix] = function + + basename, suffix = os.path.splitext(source) + try: + return gConverterTab[suffix] + + except KeyError: + return None + +def copy_resource(source, destination, dry_run=0, symlink=0): + """ + Copy a resource file into the application bundle + """ + import py2app.converters as conv + + converter = find_converter(source) + if converter is not None: + converter(source, destination, dry_run=dry_run) + return + + if os.path.isdir(source): + if not dry_run: + if not os.path.exists(destination): + os.mkdir(destination) + for fn in zipio.listdir(source): + copy_resource(os.path.join(source, fn), + os.path.join(destination, fn), dry_run=dry_run, symlink=symlink) + + else: + if symlink: + if not dry_run: + make_symlink(os.path.abspath(source), destination) + + else: + copy_file(source, destination, dry_run=dry_run, preserve_mode=True) + + + +def copy_file(source, destination, preserve_mode=False, preserve_times=False, update=False, dry_run=0): + while True: + try: + _copy_file(source, destination, preserve_mode, preserve_times, update, dry_run) + return + except IOError as exc: + if exc.errno != errno.EAGAIN: + raise + + log.info("copying file %s failed due to spurious EAGAIN, retrying in 2 seconds", source) + time.sleep(2) + +def _copy_file(source, destination, preserve_mode=False, preserve_times=False, update=False, dry_run=0): + log.info("copying file %s -> %s", source, destination) + with zipio.open(source, 'rb') as fp_in: + if not dry_run: + if os.path.isdir(destination): + destination = os.path.join(destination, os.path.basename(source)) + if os.path.exists(destination): + os.unlink(destination) + + with open(destination, 'wb') as fp_out: + data = fp_in.read() + fp_out.write(data) + + if preserve_mode: + mode = None + if hasattr(zipio, 'getmode'): + mode = zipio.getmode(source) + + elif os.path.isfile(source): + mode = os.stat(source).st_mode + + if mode is not None: + os.chmod(destination, mode) + + if preserve_times: + mtime = zipio.getmtime(source) + os.utime(destination, (mtime, mtime)) + +def make_symlink(source, target): + if os.path.islink(target): + os.unlink(target) + + os.symlink(source, target) + +def newer(source, target): + """ + distutils.dep_utils.newer with zipfile support + """ + try: + return zipio.getmtime(source) > zipio.getmtime(target) + except IOError: + return True + + +def find_version(fn): + """ + Try to find a __version__ assignment in a source file + """ + return "0.0.0" + import compiler + from compiler.ast import Module, Stmt, Assign, AssName, Const + ast = compiler.parseFile(fn) + if not isinstance(ast, Module): + raise ValueError("expecting Module") + statements = ast.getChildNodes() + if not (len(statements) == 1 and isinstance(statements[0], Stmt)): + raise ValueError("expecting one Stmt") + for node in statements[0].getChildNodes(): + if not isinstance(node, Assign): + continue + if not len(node.nodes) == 1: + continue + assName = node.nodes[0] + if not ( + isinstance(assName, AssName) and + isinstance(node.expr, Const) and + assName.flags == 'OP_ASSIGN' and + assName.name == '__version__' + ): + continue + return node.expr.value + else: + raise ValueError("Version not found") + +def in_system_path(filename): + """ + Return True if the file is in a system path + """ + return macholib.util.in_system_path(filename) + +if sys.version_info[0] == 2: + def fsencoding(s, encoding=sys.getfilesystemencoding()): + return macholib.util.fsencoding(s, encoding=encoding) +else: + def fsencoding(s, encoding=sys.getfilesystemencoding()): + return s + +def make_exec(path): + mask = os.umask(0) + os.umask(mask) + os.chmod(path, os.stat(path).st_mode | (0o111 & ~mask)) + +def makedirs(path): + path = fsencoding(path) + if not os.path.exists(path): + os.makedirs(path) + +def mergecopy(src, dest): + return macholib.util.mergecopy(src, dest) + +def mergetree(src, dst, condition=None, copyfn=mergecopy): + """Recursively merge a directory tree using mergecopy().""" + return macholib.util.mergetree(src, dst, condition=condition, copyfn=copyfn) + +def move(src, dst): + return macholib.util.move(src, dst) + +def copy2(src, dst): + return macholib.util.copy2(src, dst) + +def fancy_split(s, sep=","): + # a split which also strips whitespace from the items + # passing a list or tuple will return it unchanged + if s is None: + return [] + if hasattr(s, "split"): + return [item.strip() for item in s.split(sep)] + return s + +class FileSet(object): + # A case insensitive but case preserving set of files + def __init__(self, iterable=None): + self._dict = {} + if iterable is not None: + for arg in iterable: + self.add(arg) + + def __repr__(self): + return "" % (self._dict.values(), id(self)) + + def add(self, fname): + self._dict[fname.upper()] = fname + + def remove(self, fname): + del self._dict[fname.upper()] + + def __contains__(self, fname): + return fname.upper() in self._dict.keys() + + def __getitem__(self, index): + key = self._dict.keys()[index] + return self._dict[key] + + def __len__(self): + return len(self._dict) + + def copy(self): + res = FileSet() + res._dict.update(self._dict) + return res + +LOADER = """ +def __load(): + import imp, os, sys + ext = %r + for path in sys.path: + if not path.endswith('lib-dynload'): + continue + ext_path = os.path.join(path, ext) + if os.path.exists(ext_path): + mod = imp.load_dynamic(__name__, ext_path) + break + else: + raise ImportError(repr(ext) + " not found") +__load() +del __load +""" + +def make_loader(fn): + return LOADER % fn + +def byte_compile(py_files, optimize=0, force=0, + target_dir=None, verbose=1, dry_run=0, + direct=None): + + if direct is None: + direct = (__debug__ and optimize == 0) + + # "Indirect" byte-compilation: write a temporary script and then + # run it with the appropriate flags. + if not direct: + from tempfile import mktemp + from distutils.util import execute, spawn + script_name = mktemp(".py") + if verbose: + print("writing byte-compilation script '%s'" % script_name) + if not dry_run: + with open(script_name, "w") as script: + script.write(""" +from py2app.util import byte_compile +from modulegraph.modulegraph import * +files = [ +""") + + for f in py_files: + script.write(repr(f) + ",\n") + script.write("]\n") + script.write(""" +byte_compile(files, optimize=%r, force=%r, + target_dir=%r, + verbose=%r, dry_run=0, + direct=1) +""" % (optimize, force, target_dir, verbose)) + + # Ensure that py2app is on PYTHONPATH, this ensures that + # py2app.util can be found even when we're running from + # an .egg that was downloaded by setuptools + import py2app + pp = os.path.dirname(os.path.dirname(py2app.__file__)) + if 'PYTHONPATH' in os.environ: + pp = '%s:%s'%(pp, os.environ['PYTHONPATH']) + + cmd = ['/usr/bin/env', 'PYTHONPATH=%s'%(pp,), sys.executable, script_name] + if optimize == 1: + cmd.insert(3, "-O") + elif optimize == 2: + cmd.insert(3, "-OO") + spawn(cmd, verbose=verbose, dry_run=dry_run) + execute(os.remove, (script_name,), "removing %s" % script_name, + verbose=verbose, dry_run=dry_run) + + + else: + from py_compile import compile + from distutils.dir_util import mkpath + + for mod in py_files: + # Terminology from the py_compile module: + # cfile - byte-compiled file + # dfile - purported source filename (same as 'file' by default) + if mod.filename == mod.identifier: + cfile = os.path.basename(mod.filename) + dfile = cfile + (__debug__ and 'c' or 'o') + else: + cfile = mod.identifier.replace('.', os.sep) + + if sys.version_info[:2] <= (3, 4): + if mod.packagepath: + dfile = cfile + os.sep + '__init__.py' + (__debug__ and 'c' or 'o') + else: + dfile = cfile + '.py' + (__debug__ and 'c' or 'o') + else: + if mod.packagepath: + dfile = cfile + os.sep + '__init__.pyc' + else: + dfile = cfile + '.pyc' + if target_dir: + cfile = os.path.join(target_dir, dfile) + + if force or newer(mod.filename, cfile): + if verbose: + print("byte-compiling %s to %s" % (mod.filename, dfile)) + + if not dry_run: + mkpath(os.path.dirname(cfile)) + suffix = os.path.splitext(mod.filename)[1] + + if suffix in ('.py', '.pyw'): + fn = cfile + '.py' + + with zipio.open(mod.filename, 'rb') as fp_in: + with open(fn, 'wb') as fp_out: + fp_out.write(fp_in.read()) + + compile(fn, cfile, dfile) + os.unlink(fn) + + elif suffix in PY_SUFFIXES: + # Minor problem: This will happily copy a file + # .pyo to .pyc or .pyc to + # .pyo, but it does seem to work. + copy_file(mod.filename, cfile, preserve_times=True) + + else: + raise RuntimeError \ + ("Don't know how to handle %r" % mod.filename) + else: + if verbose: + print("skipping byte-compilation of %s to %s" % + (mod.filename, dfile)) + +SCMDIRS = ['CVS', '.svn', '.hg', '.git'] +def skipscm(ofn): + ofn = fsencoding(ofn) + fn = os.path.basename(ofn) + if fn in SCMDIRS: + return False + return True + +def skipfunc(junk=(), junk_exts=(), chain=()): + junk = set(junk) + junk_exts = set(junk_exts) + chain = tuple(chain) + def _skipfunc(fn): + if os.path.basename(fn) in junk: + return False + elif os.path.splitext(fn)[1] in junk_exts: + return False + for func in chain: + if not func(fn): + return False + else: + return True + return _skipfunc + +JUNK = ['.DS_Store', '.gdb_history', 'build', 'dist'] + SCMDIRS +JUNK_EXTS = ['.pbxuser', '.pyc', '.pyo', '.swp'] +skipjunk = skipfunc(JUNK, JUNK_EXTS) + +def get_magic(platform=sys.platform): + if platform == 'darwin': + import struct + import macholib.mach_o + return [ + struct.pack('!L', macholib.mach_o.MH_MAGIC), + struct.pack('!L', macholib.mach_o.MH_CIGAM), + struct.pack('!L', macholib.mach_o.MH_MAGIC_64), + struct.pack('!L', macholib.mach_o.MH_CIGAM_64), + struct.pack('!L', macholib.mach_o.FAT_MAGIC), + ] + elif platform == 'linux2': + return ['\x7fELF'] + elif platform == 'win32': + return ['MZ'] + return None + +def iter_platform_files(path, is_platform_file=macholib.util.is_platform_file): + """ + Iterate over all of the platform files in a directory + """ + for root, dirs, files in os.walk(path): + for fn in files: + fn = os.path.join(root, fn) + if is_platform_file(fn): + yield fn + +def strip_files(files, dry_run=0, verbose=0): + """ + Strip the given set of files + """ + if dry_run: + return + return macholib.util.strip_files(files) + +def copy_tree(src, dst, + preserve_mode=1, + preserve_times=1, + preserve_symlinks=0, + update=0, + verbose=0, + dry_run=0, + condition=None): + + """ + Copy an entire directory tree 'src' to a new location 'dst'. Both + 'src' and 'dst' must be directory names. If 'src' is not a + directory, raise DistutilsFileError. If 'dst' does not exist, it is + created with 'mkpath()'. The end result of the copy is that every + file in 'src' is copied to 'dst', and directories under 'src' are + recursively copied to 'dst'. Return the list of files that were + copied or might have been copied, using their output name. The + return value is unaffected by 'update' or 'dry_run': it is simply + the list of all files under 'src', with the names changed to be + under 'dst'. + + 'preserve_mode' and 'preserve_times' are the same as for + 'copy_file'; note that they only apply to regular files, not to + directories. If 'preserve_symlinks' is true, symlinks will be + copied as symlinks (on platforms that support them!); otherwise + (the default), the destination of the symlink will be copied. + 'update' and 'verbose' are the same as for 'copy_file'. + """ + assert isinstance(src, (str, unicode)), repr(src) + assert isinstance(dst, (str, unicode)), repr(dst) + + + from distutils.dir_util import mkpath + from distutils.dep_util import newer + from distutils.errors import DistutilsFileError + from distutils import log + + src = fsencoding(src) + dst = fsencoding(dst) + + if condition is None: + condition = skipscm + + if not dry_run and not zipio.isdir(src): + raise DistutilsFileError( + "cannot copy tree '%s': not a directory" % src) + try: + names = zipio.listdir(src) + except os.error as exc: + (errno, errstr) = exc.args + if dry_run: + names = [] + else: + raise DistutilsFileError( + "error listing files in '%s': %s" % (src, errstr)) + + if not dry_run: + mkpath(dst) + + outputs = [] + + for n in names: + src_name = os.path.join(src, n) + dst_name = os.path.join(dst, n) + if (condition is not None) and (not condition(src_name)): + continue + + # Note: using zipio's internal _locate function throws an IOError on + # dead symlinks, so handle it here. + if os.path.islink(src_name) and not os.path.exists(os.readlink(src_name)): + continue + + if preserve_symlinks and zipio.islink(src_name): + link_dest = zipio.readlink(src_name) + log.info("linking %s -> %s", dst_name, link_dest) + if not dry_run: + if update and not newer(src, dst_name): + pass + else: + make_symlink(link_dest, dst_name) + outputs.append(dst_name) + + elif zipio.isdir(src_name) and not os.path.isfile(src_name): + # ^^^ this odd tests ensures that resource files that + # happen to be a zipfile won't get extracted. + # XXX: need API in zipio to clean up this code + outputs.extend( + copy_tree(src_name, dst_name, preserve_mode, + preserve_times, preserve_symlinks, update, + dry_run=dry_run, condition=condition)) + else: + copy_file(src_name, dst_name, preserve_mode, + preserve_times, update, dry_run=dry_run) + outputs.append(dst_name) + + return outputs + + +def walk_files(path): + for root, dirs, files in os.walk(path): + for f in files: + yield f + +def find_app(app): + dpath = os.path.realpath(app) + if os.path.exists(dpath): + return dpath + if os.path.isabs(app): + return None + for path in os.environ.get('PATH', '').split(':'): + dpath = os.path.realpath(os.path.join(path, app)) + if os.path.exists(dpath): + return dpath + return None + +def check_output(command_line): + p = subprocess.Popen(command_line, + stdout=subprocess.PIPE) + stdout, _ = p.communicate() + xit = p.wait() + if xit != 0: + raise subprocess.CalledProcessError(xit, command_line) + + return stdout + + +_tools = {} +def _get_tool(toolname): + if toolname not in _tools: + if os.path.exists('/usr/bin/xcrun'): + try: + _tools[toolname] = check_output(['/usr/bin/xcrun', '-find', toolname])[:-1] + except subprocess.CalledProcessError: + raise IOError("Tool %r not found"%(toolname,)) + + else: + # Support for Xcode 3.x and earlier + if toolname == 'momc': + choices = [ + '/Library/Application Support/Apple/Developer Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc', + '/Developer/Library/Xcode/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc', + '/Developer/usr/bin/momc', + ] + elif toolname == 'mapc': + choices = [ + '/Developer/Library/Xcode/Plug-ins/XDMappingModel.xdplugin/Contents/Resources/mapc' + '/Developer/usr/bin/mapc' + ] + else: + raise IOError("Tool %r not found"%(toolname,)) + + for fn in choices: + if os.path.exists(fn): + _tools[toolname] = fn + break + else: + raise IOError("Tool %r not found"%(toolname,)) + return _tools[toolname] + + +def momc(src, dst): + subprocess.check_call([_get_tool('momc'), src, dst]) + +def mapc(src, dst): + subprocess.check_call([_get_tool('mapc'), src, dst]) diff --git a/dist/main.app/Contents/Resources/main.py b/Guetzli-R.py similarity index 96% rename from dist/main.app/Contents/Resources/main.py rename to Guetzli-R.py index 201ab52..a8eb8a7 100644 --- a/dist/main.app/Contents/Resources/main.py +++ b/Guetzli-R.py @@ -103,10 +103,13 @@ class Application(Frame): # Run guetzli for dirpath, dirnames, files in walk(self.top_dir): for name in files: + # Info + self.label_path['text'] = 'Preparing file' url = path.join(dirpath, name) - self.label_path['text'] = f'Working... {name}' # Check type if what(url) in self.TYPES: + # Info + self.label_path['text'] = f'Working... {name}' # Get urls url_out = path.join(self.top_dir, self.TEMP_FILE) # Remove temp image diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Python b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Python similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Python rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Python diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Resources b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Resources similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Resources rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Resources diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/Python b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/Python similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/Python rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/Python diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Info.plist b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Info.plist similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Info.plist rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Info.plist diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/include/python3.6m/pyconfig.h b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/include/python3.6m/pyconfig.h similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/include/python3.6m/pyconfig.h rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/include/python3.6m/pyconfig.h diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin/Makefile b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin/Makefile similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin/Makefile rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/3.6/lib/python3.6/config-3.6m-darwin/Makefile diff --git a/dist/main.app/Contents/Frameworks/Python.framework/Versions/Current b/dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/Current similarity index 100% rename from dist/main.app/Contents/Frameworks/Python.framework/Versions/Current rename to dist/Guetzli-R.app/Contents/Frameworks/Python.framework/Versions/Current diff --git a/dist/main.app/Contents/Frameworks/libcrypto.1.0.0.dylib b/dist/Guetzli-R.app/Contents/Frameworks/libcrypto.1.0.0.dylib similarity index 100% rename from dist/main.app/Contents/Frameworks/libcrypto.1.0.0.dylib rename to dist/Guetzli-R.app/Contents/Frameworks/libcrypto.1.0.0.dylib diff --git a/dist/main.app/Contents/Frameworks/liblzma.5.dylib b/dist/Guetzli-R.app/Contents/Frameworks/liblzma.5.dylib similarity index 100% rename from dist/main.app/Contents/Frameworks/liblzma.5.dylib rename to dist/Guetzli-R.app/Contents/Frameworks/liblzma.5.dylib diff --git a/dist/Guetzli-R.app/Contents/Frameworks/libpng16.16.dylib b/dist/Guetzli-R.app/Contents/Frameworks/libpng16.16.dylib new file mode 100644 index 0000000..540b633 Binary files /dev/null and b/dist/Guetzli-R.app/Contents/Frameworks/libpng16.16.dylib differ diff --git a/dist/main.app/Contents/Frameworks/libssl.1.0.0.dylib b/dist/Guetzli-R.app/Contents/Frameworks/libssl.1.0.0.dylib similarity index 100% rename from dist/main.app/Contents/Frameworks/libssl.1.0.0.dylib rename to dist/Guetzli-R.app/Contents/Frameworks/libssl.1.0.0.dylib diff --git a/dist/main.app/Contents/Info.plist b/dist/Guetzli-R.app/Contents/Info.plist similarity index 88% rename from dist/main.app/Contents/Info.plist rename to dist/Guetzli-R.app/Contents/Info.plist index cbc0431..d81b4d8 100644 --- a/dist/main.app/Contents/Info.plist +++ b/dist/Guetzli-R.app/Contents/Info.plist @@ -5,17 +5,17 @@ CFBundleDevelopmentRegion English CFBundleDisplayName - main + Guetzli-R CFBundleExecutable - main + Guetzli-R CFBundleIconFile - PythonApplet.icns + icon.icns CFBundleIdentifier - org.pythonmac.unspecified.main + org.pythonmac.unspecified.Guetzli-R CFBundleInfoDictionaryVersion 6.0 CFBundleName - main + Guetzli-R CFBundlePackageType APPL CFBundleShortVersionString @@ -68,7 +68,7 @@ PythonInfoDict PythonExecutable - /Users/androsfenollosa/www/guetzli-recursively/venv/bin/python3 + /Users/androsfenollosa/www/guetzli-recursively-gui/venv/bin/python3 PythonLongVersion 3.6.1 (default, Mar 23 2017, 16:49:06) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] diff --git a/dist/main.app/Contents/MacOS/main b/dist/Guetzli-R.app/Contents/MacOS/Guetzli-R similarity index 100% rename from dist/main.app/Contents/MacOS/main rename to dist/Guetzli-R.app/Contents/MacOS/Guetzli-R diff --git a/dist/main.app/Contents/MacOS/python b/dist/Guetzli-R.app/Contents/MacOS/python similarity index 100% rename from dist/main.app/Contents/MacOS/python rename to dist/Guetzli-R.app/Contents/MacOS/python diff --git a/dist/main.app/Contents/PkgInfo b/dist/Guetzli-R.app/Contents/PkgInfo similarity index 100% rename from dist/main.app/Contents/PkgInfo rename to dist/Guetzli-R.app/Contents/PkgInfo diff --git a/main.py b/dist/Guetzli-R.app/Contents/Resources/Guetzli-R.py similarity index 96% rename from main.py rename to dist/Guetzli-R.app/Contents/Resources/Guetzli-R.py index 201ab52..a8eb8a7 100644 --- a/main.py +++ b/dist/Guetzli-R.app/Contents/Resources/Guetzli-R.py @@ -103,10 +103,13 @@ class Application(Frame): # Run guetzli for dirpath, dirnames, files in walk(self.top_dir): for name in files: + # Info + self.label_path['text'] = 'Preparing file' url = path.join(dirpath, name) - self.label_path['text'] = f'Working... {name}' # Check type if what(url) in self.TYPES: + # Info + self.label_path['text'] = f'Working... {name}' # Get urls url_out = path.join(self.top_dir, self.TEMP_FILE) # Remove temp image diff --git a/dist/main.app/Contents/Resources/__boot__.py b/dist/Guetzli-R.app/Contents/Resources/__boot__.py similarity index 98% rename from dist/main.app/Contents/Resources/__boot__.py rename to dist/Guetzli-R.app/Contents/Resources/__boot__.py index 2c03e8f..cc47b36 100644 --- a/dist/main.app/Contents/Resources/__boot__.py +++ b/dist/Guetzli-R.app/Contents/Resources/__boot__.py @@ -76,6 +76,6 @@ def _setup_ctypes(): _setup_ctypes() -DEFAULT_SCRIPT='main.py' +DEFAULT_SCRIPT='Guetzli-R.py' SCRIPT_MAP={} _run() diff --git a/dist/Guetzli-R.app/Contents/Resources/__error__.sh b/dist/Guetzli-R.app/Contents/Resources/__error__.sh new file mode 100755 index 0000000..f1122a6 --- /dev/null +++ b/dist/Guetzli-R.app/Contents/Resources/__error__.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# This is the default apptemplate error script +# +if ( test -n "$2" ) ; then + echo "$1 Error" + echo "An unexpected error has occurred during execution of the main script" + echo "" + echo "$2: $3" + echo "" + echo "See the Console for a detailed traceback." +else + echo "$1 Error" + + # Usage: ERRORURL , this is used by the + # bundle runner to put up a dialog. + #echo "ERRORURL: http://www.python.org/ Visit the Python Website +# echo "ERRORURL: http://homepages.cwi.nl/~jack/macpython/index.html Visit the MacPython Website" +fi diff --git a/dist/Guetzli-R.app/Contents/Resources/guetzli-osx b/dist/Guetzli-R.app/Contents/Resources/guetzli-osx new file mode 100755 index 0000000..36550e3 Binary files /dev/null and b/dist/Guetzli-R.app/Contents/Resources/guetzli-osx differ diff --git a/dist/Guetzli-R.app/Contents/Resources/icon.icns b/dist/Guetzli-R.app/Contents/Resources/icon.icns new file mode 100644 index 0000000..decad9c Binary files /dev/null and b/dist/Guetzli-R.app/Contents/Resources/icon.icns differ diff --git a/dist/main.app/Contents/Resources/include/python3.6m/pyconfig.h b/dist/Guetzli-R.app/Contents/Resources/include/python3.6m/pyconfig.h similarity index 100% rename from dist/main.app/Contents/Resources/include/python3.6m/pyconfig.h rename to dist/Guetzli-R.app/Contents/Resources/include/python3.6m/pyconfig.h diff --git a/dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Makefile b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Makefile similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Makefile rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Makefile diff --git a/dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup diff --git a/dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.config b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.config similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.config rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.config diff --git a/dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.local b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.local similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.local rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/config-3.6m-darwin/Setup.local diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_bisect.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_bisect.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_bisect.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_bisect.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_blake2.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_blake2.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_blake2.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_blake2.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_bz2.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_bz2.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_bz2.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_bz2.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_cn.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_cn.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_cn.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_cn.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_hk.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_hk.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_hk.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_hk.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_iso2022.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_iso2022.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_iso2022.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_iso2022.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_jp.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_jp.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_jp.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_jp.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_kr.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_kr.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_kr.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_kr.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_tw.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_tw.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_tw.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_codecs_tw.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_ctypes.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_ctypes.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_ctypes.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_ctypes.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_datetime.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_datetime.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_datetime.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_datetime.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_decimal.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_decimal.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_decimal.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_decimal.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_hashlib.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_hashlib.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_hashlib.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_hashlib.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_heapq.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_heapq.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_heapq.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_heapq.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_lzma.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_lzma.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_lzma.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_lzma.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_md5.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_md5.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_md5.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_md5.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_multibytecodec.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_multibytecodec.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_multibytecodec.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_multibytecodec.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_multiprocessing.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_multiprocessing.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_multiprocessing.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_multiprocessing.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_opcode.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_opcode.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_opcode.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_opcode.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_pickle.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_pickle.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_pickle.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_pickle.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_posixsubprocess.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_posixsubprocess.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_posixsubprocess.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_posixsubprocess.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_random.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_random.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_random.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_random.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha1.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha1.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha1.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha1.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha256.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha256.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha256.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha256.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha3.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha3.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha3.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha3.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha512.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha512.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_sha512.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_sha512.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_socket.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_socket.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_socket.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_socket.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_ssl.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_ssl.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_ssl.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_ssl.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_struct.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_struct.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_struct.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_struct.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_tkinter.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_tkinter.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/_tkinter.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/_tkinter.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/array.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/array.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/array.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/array.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/binascii.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/binascii.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/binascii.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/binascii.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/grp.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/grp.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/grp.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/grp.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/math.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/math.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/math.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/math.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/mmap.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/mmap.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/mmap.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/mmap.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/pyexpat.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/pyexpat.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/pyexpat.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/pyexpat.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/resource.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/resource.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/resource.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/resource.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/select.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/select.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/select.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/select.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/unicodedata.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/unicodedata.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/unicodedata.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/unicodedata.so diff --git a/dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/zlib.so b/dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/zlib.so similarity index 100% rename from dist/main.app/Contents/Resources/lib/python3.6/lib-dynload/zlib.so rename to dist/Guetzli-R.app/Contents/Resources/lib/python3.6/lib-dynload/zlib.so diff --git a/dist/main.app/Contents/Resources/lib/python36.zip b/dist/Guetzli-R.app/Contents/Resources/lib/python36.zip similarity index 50% rename from dist/main.app/Contents/Resources/lib/python36.zip rename to dist/Guetzli-R.app/Contents/Resources/lib/python36.zip index 87798d9..2782785 100644 Binary files a/dist/main.app/Contents/Resources/lib/python36.zip and b/dist/Guetzli-R.app/Contents/Resources/lib/python36.zip differ diff --git a/dist/main.app/Contents/Resources/zlib.cpython-36m-darwin.so b/dist/Guetzli-R.app/Contents/Resources/zlib.cpython-36m-darwin.so similarity index 100% rename from dist/main.app/Contents/Resources/zlib.cpython-36m-darwin.so rename to dist/Guetzli-R.app/Contents/Resources/zlib.cpython-36m-darwin.so diff --git a/dist/main.app/Contents/Resources/PythonApplet.icns b/dist/main.app/Contents/Resources/PythonApplet.icns deleted file mode 100644 index c8aad9f..0000000 Binary files a/dist/main.app/Contents/Resources/PythonApplet.icns and /dev/null differ diff --git a/guetzli-osx b/guetzli-osx new file mode 100755 index 0000000..9390d2c Binary files /dev/null and b/guetzli-osx differ diff --git a/icon.icns b/icon.icns new file mode 100644 index 0000000..decad9c Binary files /dev/null and b/icon.icns differ diff --git a/setup.py b/setup.py index 651ee6d..bda6545 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,12 @@ from setuptools import setup + +OPTIONS = { + 'iconfile': 'icon.icns' + } +DATA_FILES = ['guetzli-osx'] setup( - app=["main.py"], + app=["Guetzli-R.py"], + options={'py2app': OPTIONS}, + data_files=DATA_FILES, setup_requires=["py2app"], )