Browse files

Add Pyinstaller

We use Pyinstaller to convert Python program to Windows executable file.
  • Loading branch information...
1 parent 49b21d1 commit b7b1fff1253cdf5dd37a3b1d02f3bad69fb5a852 Hank Wang committed Apr 3, 2013
Showing with 23,850 additions and 0 deletions.
  1. +239 −0 update-app/pyinstaller-2.0/.pylintrc
  2. +1 −0 update-app/pyinstaller-2.0/MANIFEST.in
  3. +92 −0 update-app/pyinstaller-2.0/PyInstaller/__init__.py
  4. +631 −0 update-app/pyinstaller-2.0/PyInstaller/bindepend.py
  5. +1,625 −0 update-app/pyinstaller-2.0/PyInstaller/build.py
  6. +335 −0 update-app/pyinstaller-2.0/PyInstaller/compat.py
  7. +174 −0 update-app/pyinstaller-2.0/PyInstaller/configure.py
  8. 0 update-app/pyinstaller-2.0/PyInstaller/depend/__init__.py
  9. +242 −0 update-app/pyinstaller-2.0/PyInstaller/depend/dylib.py
  10. +170 −0 update-app/pyinstaller-2.0/PyInstaller/depend/impdirector.py
  11. +325 −0 update-app/pyinstaller-2.0/PyInstaller/depend/imptracker.py
  12. +156 −0 update-app/pyinstaller-2.0/PyInstaller/depend/modules.py
  13. +254 −0 update-app/pyinstaller-2.0/PyInstaller/depend/owner.py
  14. +357 −0 update-app/pyinstaller-2.0/PyInstaller/depend/utils.py
  15. 0 update-app/pyinstaller-2.0/PyInstaller/fake/__init__.py
  16. +43 −0 update-app/pyinstaller-2.0/PyInstaller/fake/fake-site.py
  17. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/__init__.py
  18. +58 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/django-import-finder.py
  19. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/enchant-datafiles-finder.py
  20. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-DateTime.mxDateTime.py
  21. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-DateTime.py
  22. +21 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-Image.py
  23. +41 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-OpenGL.py
  24. +26 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-OpenGL_accelerate.py
  25. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PIL.Image.py
  26. +21 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PIL.SpiderImagePlugin.py
  27. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PIL.py
  28. +15 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.Qt.py
  29. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.Qt3Support.py
  30. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtAssistant.py
  31. +8 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtCore.py
  32. +12 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtGui.py
  33. +26 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtHelp.py
  34. +9 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtNetwork.py
  35. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtOpenGL.py
  36. +8 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtScript.py
  37. +8 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtSql.py
  38. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtSvg.py
  39. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtTest.py
  40. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtWebKit.py
  41. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.QtXml.py
  42. +10 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.Qwt5.py
  43. +8 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.phonon.py
  44. +13 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.py
  45. +27 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.uic.port_v2.py
  46. +27 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.uic.port_v3.py
  47. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-PyQt4.uic.py
  48. +21 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-SpiderImagePlugin.py
  49. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-_elementtree.py
  50. +6 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-_mysql.py
  51. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-_sre.py
  52. +165 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-_tkinter.py
  53. +19 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-anydbm.py
  54. +10 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-babel.py
  55. +19 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-cElementTree.py
  56. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-cPickle.py
  57. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-cStringIO.py
  58. +25 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-carchive.py
  59. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-codecs.py
  60. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-cx_Oracle.py
  61. +72 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-distutils.py
  62. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.contrib.py
  63. +33 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.contrib.sessions.py
  64. +33 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.core.cache.py
  65. +31 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.core.mail.py
  66. +34 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.core.management.py
  67. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.core.py
  68. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.backends.mysql.base.py
  69. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.backends.mysql.py
  70. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.backends.oracle.base.py
  71. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.backends.oracle.py
  72. +36 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.backends.py
  73. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.db.py
  74. +49 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-django.py
  75. +21 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-dns.rdata.py
  76. +6 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-email.message.py
  77. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-email.py
  78. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-enchant.checker.py
  79. +11 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-enchant.checker.wxSpellCheckerDialog.py
  80. +10 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-enchant.py
  81. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-encodings.py
  82. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-gadfly.py
  83. +23 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-gtk.py
  84. +6 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-h5py.py
  85. +37 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-iu.py
  86. +25 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-kinterbasdb.py
  87. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-lxml.etree.py
  88. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-lxml.objectify.py
  89. +3 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-mako.codegen.py
  90. +23 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-matplotlib.backends.py
  91. +10 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-matplotlib.numerix.py
  92. +8 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-matplotlib.py
  93. +33 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-os.py
  94. +17 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-parser.py
  95. +3 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-paste.exceptions.reporter.py
  96. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-psycopg2.py
  97. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pyexpat.py
  98. +7 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pygame.py
  99. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pygments.lexers.py
  100. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pygments.styles.py
  101. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pyodbc.py
  102. +34 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pythoncom.py
  103. +27 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pyttsx.py
  104. 0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pywinauto.py
  105. +14 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pywinauto.tests.py
  106. +32 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-pywintypes.py
  107. +19 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-qt.py
  108. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-regex.py
  109. +28 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-setuptools.py
  110. +39 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-site.py
  111. +43 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-sqlalchemy.py
  112. +10 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-storm.database.py
  113. +1 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-tables.py
  114. +20 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-time.py
  115. +61 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-usb.py
  116. +23 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-vtkpython.py
  117. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-win32com.client.py
  118. +39 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-win32com.py
  119. +18 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-win32ui.py
  120. +2 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-wx.lib.activex.py
  121. +36 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-wx.lib.pubsub.core.py
  122. +25 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-wx.lib.pubsub.setuparg1.py
  123. +19 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.domreg.py
  124. +40 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.ext.py
  125. +23 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.ext.reader.py
  126. +72 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.html.HTMLDocument.py
  127. +33 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.html.py
  128. +80 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.dom.py
  129. +19 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.etree.cElementTree.py
  130. +39 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.py
  131. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.sax.py
  132. +30 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-xml.sax.saxexts.py
  133. +27 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hook-zmq.py
  134. +281 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/hookutils.py
  135. +37 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/shared_PIL_Image.py
  136. +29 −0 update-app/pyinstaller-2.0/PyInstaller/hooks/shared_PIL_SpiderImagePlugin.py
  137. +28 −0 update-app/pyinstaller-2.0/PyInstaller/lib/README.rst
  138. +1 −0 update-app/pyinstaller-2.0/PyInstaller/lib/__init__.py
  139. +1,337 −0 update-app/pyinstaller-2.0/PyInstaller/lib/__subprocess.py
  140. +300 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/Dot.py
  141. +673 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/Graph.py
  142. +147 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/GraphAlgo.py
  143. +73 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/GraphStat.py
  144. +137 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/GraphUtil.py
  145. +192 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/ObjectGraph.py
  146. +135 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/__init__.py
  147. +189 −0 update-app/pyinstaller-2.0/PyInstaller/lib/altgraph/compat.py
  148. +221 −0 update-app/pyinstaller-2.0/PyInstaller/lib/junitxml/__init__.py
  149. +16 −0 update-app/pyinstaller-2.0/PyInstaller/lib/junitxml/tests/__init__.py
  150. +327 −0 update-app/pyinstaller-2.0/PyInstaller/lib/junitxml/tests/test_junitxml.py
  151. +361 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/MachO.py
  152. +119 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/MachOGraph.py
  153. +140 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/MachOStandalone.py
  154. +95 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/SymbolTable.py
  155. +9 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/__init__.py
  156. +44 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/_cmdline.py
  157. +168 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/dyld.py
  158. +42 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/dylib.py
  159. +42 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/framework.py
  160. +73 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/itergraphreport.py
  161. +666 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/mach_o.py
  162. +43 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/macho_dump.py
  163. +16 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/macho_find.py
  164. +24 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/macho_standalone.py
  165. +290 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/ptypes.py
  166. +236 −0 update-app/pyinstaller-2.0/PyInstaller/lib/macholib/util.py
  167. +4,651 −0 update-app/pyinstaller-2.0/PyInstaller/lib/pefile.py
  168. +332 −0 update-app/pyinstaller-2.0/PyInstaller/lib/six.py
  169. +67 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/__init__.py
  170. +10 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/__main__.py
  171. +1,095 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/case.py
  172. +9 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/collector.py
  173. +64 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/compatibility.py
  174. +323 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/loader.py
  175. +241 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/main.py
  176. +184 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/result.py
  177. +206 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/runner.py
  178. +57 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/signals.py
  179. +287 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/suite.py
  180. +99 −0 update-app/pyinstaller-2.0/PyInstaller/lib/unittest2/util.py
  181. +1 −0 update-app/pyinstaller-2.0/PyInstaller/loader/__init__.py
  182. +495 −0 update-app/pyinstaller-2.0/PyInstaller/loader/archive.py
  183. +273 −0 update-app/pyinstaller-2.0/PyInstaller/loader/carchive.py
  184. +666 −0 update-app/pyinstaller-2.0/PyInstaller/loader/iu.py
  185. +59 −0 update-app/pyinstaller-2.0/PyInstaller/log.py
  186. +317 −0 update-app/pyinstaller-2.0/PyInstaller/makespec.py
  187. +1 −0 update-app/pyinstaller-2.0/PyInstaller/utils/__init__.py
  188. +32 −0 update-app/pyinstaller-2.0/PyInstaller/utils/git.py
  189. +201 −0 update-app/pyinstaller-2.0/PyInstaller/utils/icon.py
  190. +114 −0 update-app/pyinstaller-2.0/PyInstaller/utils/misc.py
  191. +536 −0 update-app/pyinstaller-2.0/PyInstaller/utils/versioninfo.py
Sorry, we could not display the entire diff because too many files (537) changed.
View
239 update-app/pyinstaller-2.0/.pylintrc
@@ -0,0 +1,239 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS,altgraph,junitxml,macholib,pefile.py,__subprocess.py,six.py,unittest2
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+disable=C0111
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=parseable
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
View
1 update-app/pyinstaller-2.0/MANIFEST.in
@@ -0,0 +1 @@
+exclude .hgignore
View
92 update-app/pyinstaller-2.0/PyInstaller/__init__.py
@@ -0,0 +1,92 @@
+#
+# Copyright (C) 2011 by Hartmut Goebel
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA
+
+__all__ = ('HOMEPATH', 'CONFIGDIR', 'PLATFORM',
+ 'VERSION', 'get_version',
+ 'is_py23', 'is_py24', 'is_py25', 'is_py26', 'is_py27',
+ 'is_win', 'is_cygwin', 'is_darwin', 'is_unix', 'is_linux',
+ 'is_solar', 'is_aix')
+
+import os
+import sys
+
+# Fail hard if Python does not have minimum required version
+if sys.version_info < (2, 3):
+ raise SystemExit('PyInstaller requires at least Python 2.3, sorry.')
+
+# Extend PYTHONPATH with 3rd party libraries bundled with PyInstaller.
+# (otherwise e.g. macholib won't work on Mac OS X)
+from PyInstaller import lib
+sys.path.insert(0, lib.__path__[0])
+
+from PyInstaller import compat
+from PyInstaller.utils import git
+
+VERSION = (2, 0, 0)
+
+
+is_py23 = compat.is_py23
+is_py24 = compat.is_py24
+is_py25 = compat.is_py25
+is_py26 = compat.is_py26
+is_py27 = compat.is_py27
+
+is_win = compat.is_win
+is_cygwin = compat.is_cygwin
+is_darwin = compat.is_darwin
+
+is_linux = compat.is_linux
+is_solar = compat.is_solar
+is_aix = compat.is_aix
+
+is_unix = compat.is_unix
+
+
+HOMEPATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+
+if is_win:
+ CONFIGDIR = compat.getenv('APPDATA')
+ if not CONFIGDIR:
+ CONFIGDIR = os.path.expanduser('~\\Application Data')
+elif is_darwin:
+ CONFIGDIR = os.path.expanduser('~/Library/Application Support')
+else:
+ # According to XDG specification
+ # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
+ CONFIGDIR = compat.getenv('XDG_DATA_HOME')
+ if not CONFIGDIR:
+ CONFIGDIR = os.path.expanduser('~/.local/share')
+CONFIGDIR = os.path.join(CONFIGDIR, 'pyinstaller')
+
+PLATFORM = compat.system() + '-' + compat.architecture()
+
+# path extensions for module seach
+# :fixme: this should not be a global variable
+__pathex__ = []
+
+
+def get_version():
+ version = '%s.%s' % (VERSION[0], VERSION[1])
+ if VERSION[2]:
+ version = '%s.%s' % (version, VERSION[2])
+ if len(VERSION) >= 4 and VERSION[3]:
+ version = '%s%s' % (version, VERSION[3])
+ # include git revision in version string
+ if VERSION[3] == 'dev' and VERSION[4] > 0:
+ version = '%s-%s' % (version, VERSION[4])
+ return version
View
631 update-app/pyinstaller-2.0/PyInstaller/bindepend.py
@@ -0,0 +1,631 @@
+#! /usr/bin/env python
+#
+# Find external dependencies of binary libraries.
+#
+# Copyright (C) 2005, Giovanni Bajo
+# Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+import os
+import sys
+import re
+from glob import glob
+# Required for extracting eggs.
+import zipfile
+
+from PyInstaller import is_win, is_unix, is_aix, is_cygwin, is_darwin, is_py26
+from PyInstaller.depend import dylib
+from PyInstaller.utils import winutils
+import PyInstaller.compat as compat
+from PyInstaller.compat import set
+
+
+import PyInstaller.log as logging
+logger = logging.getLogger('PyInstaller.build.bindepend')
+
+seen = {}
+
+if is_win:
+ if is_py26:
+ try:
+ import win32api
+ import pywintypes
+ except ImportError:
+ raise SystemExit("Error: PyInstaller for Python 2.6+ on Windows "
+ "needs pywin32.\r\nPlease install from "
+ "http://sourceforge.net/projects/pywin32/")
+
+ from PyInstaller.utils.winmanifest import RT_MANIFEST
+ from PyInstaller.utils.winmanifest import GetManifestResources
+ from PyInstaller.utils.winmanifest import Manifest
+
+ try:
+ from PyInstaller.utils.winmanifest import winresource
+ except ImportError, detail:
+ winresource = None
+
+
+def getfullnameof(mod, xtrapath=None):
+ """
+ Return the full path name of MOD.
+
+ MOD is the basename of a dll or pyd.
+ XTRAPATH is a path or list of paths to search first.
+ Return the full path name of MOD.
+ Will search the full Windows search path, as well as sys.path
+ """
+ # Search sys.path first!
+ epath = sys.path + winutils.get_system_path()
+ if xtrapath is not None:
+ if type(xtrapath) == type(''):
+ epath.insert(0, xtrapath)
+ else:
+ epath = xtrapath + epath
+ for p in epath:
+ npth = os.path.join(p, mod)
+ if os.path.exists(npth):
+ return npth
+ # second try: lower case filename
+ for p in epath:
+ npth = os.path.join(p, mod.lower())
+ if os.path.exists(npth):
+ return npth
+ return ''
+
+
+def _getImports_pe(pth):
+ """
+ Find the binary dependencies of PTH.
+
+ This implementation walks through the PE header
+ and uses library pefile for that and supports
+ 32/64bit Windows
+ """
+ import PyInstaller.lib.pefile as pefile
+ dlls = set()
+ # By default library pefile parses all PE information.
+ # We are only interested in the list of dependent dlls.
+ # Performance is improved by reading only needed information.
+ # https://code.google.com/p/pefile/wiki/UsageExamples
+ pe = pefile.PE(pth, fast_load=True)
+ pe.parse_data_directories(directories=[
+ pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']])
+ # Some libraries have no other binary dependencies. Use empty list
+ # in that case. Otherwise pefile would return None.
+ # e.g. C:\windows\system32\kernel32.dll on Wine
+ for entry in getattr(pe, 'DIRECTORY_ENTRY_IMPORT', []):
+ dlls.add(entry.dll)
+ return dlls
+
+
+def _extract_from_egg(toc):
+ """
+ Ensure all binary modules in zipped eggs get extracted and
+ included with the frozen executable.
+
+ The supplied toc is directly modified to make changes effective.
+
+ return modified table of content
+ """
+ for item in toc:
+ # Item is a tupple
+ # (mod_name, path, type)
+ modname, pth, typ = item
+ if not os.path.isfile(pth):
+ pth = check_extract_from_egg(pth)[0][0]
+ # Replace value in original data structure.
+ toc.remove(item)
+ toc.append((modname, pth, typ))
+ return toc
+
+
+def Dependencies(lTOC, xtrapath=None, manifest=None):
+ """
+ Expand LTOC to include all the closure of binary dependencies.
+
+ LTOC is a logical table of contents, ie, a seq of tuples (name, path).
+ Return LTOC expanded by all the binary dependencies of the entries
+ in LTOC, except those listed in the module global EXCLUDES
+
+ manifest should be a winmanifest.Manifest instance on Windows, so
+ that all dependent assemblies can be added
+ """
+ # Extract all necessary binary modules from Python eggs to be included
+ # directly with PyInstaller.
+ lTOC = _extract_from_egg(lTOC)
+
+ for nm, pth, typ in lTOC:
+ if seen.get(nm.upper(), 0):
+ continue
+ logger.debug("Analyzing %s", pth)
+ seen[nm.upper()] = 1
+ if is_win:
+ for ftocnm, fn in selectAssemblies(pth, manifest):
+ lTOC.append((ftocnm, fn, 'BINARY'))
+ for lib, npth in selectImports(pth, xtrapath):
+ if seen.get(lib.upper(), 0) or seen.get(npth.upper(), 0):
+ continue
+ seen[npth.upper()] = 1
+ lTOC.append((lib, npth, 'BINARY'))
+
+ return lTOC
+
+
+def pkg_resouces_get_default_cache():
+ """
+ Determine the default cache location
+
+ This returns the ``PYTHON_EGG_CACHE`` environment variable, if set.
+ Otherwise, on Windows, it returns a 'Python-Eggs' subdirectory of the
+ 'Application Data' directory. On all other systems, it's '~/.python-eggs'.
+ """
+ # This function borrowed from setuptools/pkg_resources
+ egg_cache = compat.getenv('PYTHON_EGG_CACHE')
+ if egg_cache is not None:
+ return egg_cache
+
+ if os.name != 'nt':
+ return os.path.expanduser('~/.python-eggs')
+
+ app_data = 'Application Data' # XXX this may be locale-specific!
+ app_homes = [
+ (('APPDATA',), None), # best option, should be locale-safe
+ (('USERPROFILE',), app_data),
+ (('HOMEDRIVE', 'HOMEPATH'), app_data),
+ (('HOMEPATH',), app_data),
+ (('HOME',), None),
+ (('WINDIR',), app_data), # 95/98/ME
+ ]
+
+ for keys, subdir in app_homes:
+ dirname = ''
+ for key in keys:
+ if key in os.environ:
+ dirname = os.path.join(dirname, compat.getenv(key))
+ else:
+ break
+ else:
+ if subdir:
+ dirname = os.path.join(dirname, subdir)
+ return os.path.join(dirname, 'Python-Eggs')
+ else:
+ raise RuntimeError(
+ "Please set the PYTHON_EGG_CACHE enviroment variable"
+ )
+
+
+def check_extract_from_egg(pth, todir=None):
+ r"""
+ Check if path points to a file inside a python egg file, extract the
+ file from the egg to a cache directory (following pkg_resources
+ convention) and return [(extracted path, egg file path, relative path
+ inside egg file)].
+ Otherwise, just return [(original path, None, None)].
+ If path points to an egg file directly, return a list with all files
+ from the egg formatted like above.
+
+ Example:
+ >>> check_extract_from_egg(r'C:\Python26\Lib\site-packages\my.egg\mymodule\my.pyd')
+ [(r'C:\Users\UserName\AppData\Roaming\Python-Eggs\my.egg-tmp\mymodule\my.pyd',
+ r'C:\Python26\Lib\site-packages\my.egg', r'mymodule/my.pyd')]
+ """
+ rv = []
+ if os.path.altsep:
+ pth = pth.replace(os.path.altsep, os.path.sep)
+ components = pth.split(os.path.sep)
+ for i, name in enumerate(components):
+ if name.lower().endswith(".egg"):
+ eggpth = os.path.sep.join(components[:i + 1])
+ if os.path.isfile(eggpth):
+ # eggs can also be directories!
+ try:
+ egg = zipfile.ZipFile(eggpth)
+ except zipfile.BadZipfile, e:
+ raise SystemExit("Error: %s %s" % (eggpth, e))
+ if todir is None:
+ # Use the same directory as setuptools/pkg_resources. So,
+ # if the specific egg was accessed before (not necessarily
+ # by pyinstaller), the extracted contents already exist
+ # (pkg_resources puts them there) and can be used.
+ todir = os.path.join(pkg_resouces_get_default_cache(),
+ name + "-tmp")
+ if components[i + 1:]:
+ members = ["/".join(components[i + 1:])]
+ else:
+ members = egg.namelist()
+ for member in members:
+ pth = os.path.join(todir, member)
+ if not os.path.isfile(pth):
+ dirname = os.path.dirname(pth)
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+ f = open(pth, "wb")
+ f.write(egg.read(member))
+ f.close()
+ rv.append((pth, eggpth, member))
+ return rv
+ return [(pth, None, None)]
+
+
+def getAssemblies(pth):
+ """
+ Return the dependent assemblies of a binary.
+ """
+ if pth.lower().endswith(".manifest"):
+ return []
+ # check for manifest file
+ manifestnm = pth + ".manifest"
+ if os.path.isfile(manifestnm):
+ fd = open(manifestnm, "rb")
+ res = {RT_MANIFEST: {1: {0: fd.read()}}}
+ fd.close()
+ elif not winresource:
+ # resource access unavailable (needs pywin32)
+ return []
+ else:
+ # check the binary for embedded manifest
+ try:
+ res = GetManifestResources(pth)
+ except winresource.pywintypes.error, exc:
+ if exc.args[0] == winresource.ERROR_BAD_EXE_FORMAT:
+ logger.info('Cannot get manifest resource from non-PE '
+ 'file %s', pth)
+ return []
+ raise
+ rv = []
+ if RT_MANIFEST in res and len(res[RT_MANIFEST]):
+ for name in res[RT_MANIFEST]:
+ for language in res[RT_MANIFEST][name]:
+ # check the manifest for dependent assemblies
+ try:
+ manifest = Manifest()
+ manifest.filename = ":".join([pth, str(RT_MANIFEST),
+ str(name), str(language)])
+ manifest.parse_string(res[RT_MANIFEST][name][language],
+ False)
+ except Exception, exc:
+ logger.error("Can not parse manifest resource %s, %s"
+ "from %s", name, language, pth)
+ logger.exception(exc)
+ else:
+ if manifest.dependentAssemblies:
+ logger.debug("Dependent assemblies of %s:", pth)
+ logger.debug(", ".join([assembly.getid()
+ for assembly in
+ manifest.dependentAssemblies]))
+ rv.extend(manifest.dependentAssemblies)
+ return rv
+
+
+def selectAssemblies(pth, manifest=None):
+ """
+ Return a binary's dependent assemblies files that should be included.
+
+ Return a list of pairs (name, fullpath)
+ """
+ rv = []
+ if manifest:
+ _depNames = set([dep.name for dep in manifest.dependentAssemblies])
+ for assembly in getAssemblies(pth):
+ if seen.get(assembly.getid().upper(), 0):
+ continue
+ if manifest and not assembly.name in _depNames:
+ # Add assembly as dependency to our final output exe's manifest
+ logger.info("Adding %s to dependent assemblies "
+ "of final executable", assembly.name)
+ manifest.dependentAssemblies.append(assembly)
+ _depNames.add(assembly.name)
+ if not dylib.include_library(assembly.name):
+ logger.debug("Skipping assembly %s", assembly.getid())
+ continue
+ if assembly.optional:
+ logger.debug("Skipping optional assembly %s", assembly.getid())
+ continue
+ files = assembly.find_files()
+ if files:
+ seen[assembly.getid().upper()] = 1
+ for fn in files:
+ fname, fext = os.path.splitext(fn)
+ if fext.lower() == ".manifest":
+ nm = assembly.name + fext
+ else:
+ nm = os.path.basename(fn)
+ ftocnm = nm
+ if assembly.language not in (None, "", "*", "neutral"):
+ ftocnm = os.path.join(assembly.getlanguage(),
+ ftocnm)
+ nm, ftocnm, fn = [item.encode(sys.getfilesystemencoding())
+ for item in
+ (nm,
+ ftocnm,
+ fn)]
+ if not seen.get(fn.upper(), 0):
+ logger.debug("Adding %s", ftocnm)
+ seen[nm.upper()] = 1
+ seen[fn.upper()] = 1
+ rv.append((ftocnm, fn))
+ else:
+ #logger.info("skipping %s part of assembly %s dependency of %s",
+ # ftocnm, assembly.name, pth)
+ pass
+ else:
+ logger.error("Assembly %s not found", assembly.getid())
+ return rv
+
+
+def selectImports(pth, xtrapath=None):
+ """
+ Return the dependencies of a binary that should be included.
+
+ Return a list of pairs (name, fullpath)
+ """
+ rv = []
+ if xtrapath is None:
+ xtrapath = [os.path.dirname(pth)]
+ else:
+ assert isinstance(xtrapath, list)
+ xtrapath = [os.path.dirname(pth)] + xtrapath # make a copy
+ dlls = getImports(pth)
+ for lib in dlls:
+ if seen.get(lib.upper(), 0):
+ continue
+ if not is_win and not is_cygwin:
+ # all other platforms
+ npth = lib
+ lib = os.path.basename(lib)
+ else:
+ # plain win case
+ npth = getfullnameof(lib, xtrapath)
+
+ # now npth is a candidate lib if found
+ # check again for excludes but with regex FIXME: split the list
+ if npth:
+ candidatelib = npth
+ else:
+ candidatelib = lib
+
+ if not dylib.include_library(candidatelib):
+ if (candidatelib.find('libpython') < 0 and
+ candidatelib.find('Python.framework') < 0):
+ # skip libs not containing (libpython or Python.framework)
+ if not seen.get(npth.upper(), 0):
+ logger.debug("Skipping %s dependency of %s",
+ lib, os.path.basename(pth))
+ continue
+ else:
+ pass
+
+ if npth:
+ if not seen.get(npth.upper(), 0):
+ logger.debug("Adding %s dependency of %s",
+ lib, os.path.basename(pth))
+ rv.append((lib, npth))
+ else:
+ logger.error("lib not found: %s dependency of %s", lib, pth)
+
+ return rv
+
+
+def _getImports_ldd(pth):
+ """
+ Find the binary dependencies of PTH.
+
+ This implementation is for ldd platforms (mostly unix).
+ """
+ rslt = set()
+ if is_aix:
+ # Match libs of the form 'archive.a(sharedobject.so)'
+ # Will not match the fake lib '/unix'
+ lddPattern = re.compile(r"\s+(.*?)(\(.*\))")
+ else:
+ lddPattern = re.compile(r"\s+(.*?)\s+=>\s+(.*?)\s+\(.*\)")
+
+ for line in compat.exec_command('ldd', pth).strip().splitlines():
+ m = lddPattern.search(line)
+ if m:
+ if is_aix:
+ lib = m.group(1)
+ name = os.path.basename(lib) + m.group(2)
+ else:
+ name, lib = m.group(1), m.group(2)
+ if name[:10] in ('linux-gate', 'linux-vdso'):
+ # linux-gate is a fake library which does not exist and
+ # should be ignored. See also:
+ # http://www.trilithium.com/johan/2005/08/linux-gate/
+ continue
+
+ if os.path.exists(lib):
+ # Add lib if it is not already found.
+ if lib not in rslt:
+ rslt.add(lib)
+ else:
+ logger.error('Can not find %s in path %s (needed by %s)',
+ name, lib, pth)
+ return rslt
+
+
+def _getImports_macholib(pth):
+ """
+ Find the binary dependencies of PTH.
+
+ This implementation is for Mac OS X and uses library macholib.
+ """
+ from PyInstaller.lib.macholib.MachO import MachO
+ from PyInstaller.lib.macholib.mach_o import LC_RPATH
+ from PyInstaller.lib.macholib.dyld import dyld_find
+ rslt = set()
+ seen = set() # Libraries read from binary headers.
+
+ ## Walk through mach binary headers.
+
+ m = MachO(pth)
+ for header in m.headers:
+ for idx, name, lib in header.walkRelocatables():
+ # Sometimes some libraries are present multiple times.
+ if lib not in seen:
+ seen.add(lib)
+
+ # Walk through mach binary headers and look for LC_RPATH.
+ # macholib can't handle @rpath. LC_RPATH has to be read
+ # from the MachO header.
+ # TODO Do we need to remove LC_RPATH from MachO load commands?
+ # Will it cause any harm to leave them untouched?
+ # Removing LC_RPATH should be implemented when getting
+ # files from the bincache if it is necessary.
+ run_paths = set()
+ for header in m.headers:
+ for command in header.commands:
+ # A command is a tupple like:
+ # (<macholib.mach_o.load_command object at 0x>,
+ # <macholib.mach_o.rpath_command object at 0x>,
+ # '../lib\x00\x00')
+ cmd_type = command[0].cmd
+ if cmd_type == LC_RPATH:
+ rpath = command[2]
+ # Remove trailing '\x00' characters.
+ # e.g. '../lib\x00\x00'
+ rpath = rpath.rstrip('\x00')
+ # Make rpath absolute. According to Apple doc LC_RPATH
+ # is always relative to the binary location.
+ rpath = os.path.normpath(os.path.join(os.path.dirname(pth), rpath))
+ run_paths.update([rpath])
+
+ ## Try to find files in file system.
+
+ # In cases with @loader_path or @executable_path
+ # try to look in the same directory as the checked binary is.
+ # This seems to work in most cases.
+ exec_path = os.path.abspath(os.path.dirname(pth))
+
+ for lib in seen:
+
+ # Suppose that @rpath is not used for system libraries and
+ # using macholib can be avoided.
+ # macholib can't handle @rpath.
+ if lib.startswith('@rpath'):
+ lib = lib.replace('@rpath', '.') # Make path relative.
+ final_lib = None # Absolute path to existing lib on disk.
+ # Try multiple locations.
+ for run_path in run_paths:
+ # @rpath may contain relative value. Use exec_path as
+ # base path.
+ if not os.path.isabs(run_path):
+ run_path = os.path.join(exec_path, run_path)
+ # Stop looking for lib when found in first location.
+ if os.path.exists(os.path.join(run_path, lib)):
+ final_lib = os.path.abspath(os.path.join(run_path, lib))
+ rslt.add(final_lib)
+ break
+ # Log error if no existing file found.
+ if not final_lib:
+ logger.error('Can not find path %s (needed by %s)', lib, pth)
+
+ # Macholib has to be used to get absolute path to libraries.
+ else:
+ # macholib can't handle @loader_path. It has to be
+ # handled the same way as @executable_path.
+ # It is also replaced by 'exec_path'.
+ if lib.startswith('@loader_path'):
+ lib = lib.replace('@loader_path', '@executable_path')
+ try:
+ lib = dyld_find(lib, executable_path=exec_path)
+ rslt.add(lib)
+ except ValueError:
+ logger.error('Can not find path %s (needed by %s)', lib, pth)
+
+ return rslt
+
+
+def getImports(pth):
+ """
+ Forwards to the correct getImports implementation for the platform.
+ """
+ if is_win or is_cygwin:
+ if pth.lower().endswith(".manifest"):
+ return []
+ try:
+ return _getImports_pe(pth)
+ except Exception, exception:
+ # Assemblies can pull in files which aren't necessarily PE,
+ # but are still needed by the assembly. Any additional binary
+ # dependencies should already have been handled by
+ # selectAssemblies in that case, so just warn, return an empty
+ # list and continue.
+ if logger.isEnabledFor(logging.WARN):
+ # logg excaption only if level >= warn
+ logger.warn('Can not get binary dependencies for file: %s', pth)
+ logger.exception(exception)
+ return []
+ elif is_darwin:
+ return _getImports_macholib(pth)
+ else:
+ return _getImports_ldd(pth)
+
+
+def findLibrary(name):
+ """
+ Look for a library in the system.
+
+ Emulate the algorithm used by dlopen.
+ `name`must include the prefix, e.g. ``libpython2.4.so``
+ """
+ assert is_unix, "Current implementation for Unix only (Linux, Solaris, AIX)"
+
+ lib = None
+
+ # Look in the LD_LIBRARY_PATH
+ lp = compat.getenv('LD_LIBRARY_PATH', '')
+ for path in lp.split(os.pathsep):
+ libs = glob(os.path.join(path, name + '*'))
+ if libs:
+ lib = libs[0]
+ break
+
+ # Look in /etc/ld.so.cache
+ if lib is None:
+ expr = r'/[^\(\)\s]*%s\.[^\(\)\s]*' % re.escape(name)
+ m = re.search(expr, compat.exec_command('/sbin/ldconfig', '-p'))
+ if m:
+ lib = m.group(0)
+
+ # Look in the known safe paths
+ if lib is None:
+ paths = ['/lib', '/usr/lib']
+ if is_aix:
+ paths.append('/opt/freeware/lib')
+ for path in paths:
+ libs = glob(os.path.join(path, name + '*'))
+ if libs:
+ lib = libs[0]
+ break
+
+ # give up :(
+ if lib is None:
+ return None
+
+ # Resolve the file name into the soname
+ dir = os.path.dirname(lib)
+ return os.path.join(dir, getSoname(lib))
+
+
+def getSoname(filename):
+ """
+ Return the soname of a library.
+ """
+ cmd = ["objdump", "-p", "-j", ".dynamic", filename]
+ m = re.search(r'\s+SONAME\s+([^\s]+)', compat.exec_command(*cmd))
+ if m:
+ return m.group(1)
View
1,625 update-app/pyinstaller-2.0/PyInstaller/build.py
@@ -0,0 +1,1625 @@
+#!/usr/bin/env python
+#
+# Build packages using spec files
+#
+# Copyright (C) 2005, Giovanni Bajo
+# Based on previous work under copyright (c) 1999, 2002 McMillan Enterprises, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+import sys
+import os
+import shutil
+import pprint
+import py_compile
+import imp
+import tempfile
+import UserList
+import bindepend
+
+from PyInstaller.loader import archive, carchive
+
+import PyInstaller.depend.imptracker
+import PyInstaller.depend.modules
+
+from PyInstaller import HOMEPATH, CONFIGDIR, PLATFORM
+from PyInstaller import is_win, is_unix, is_aix, is_darwin, is_cygwin
+from PyInstaller import is_py23, is_py24
+import PyInstaller.compat as compat
+
+from PyInstaller.compat import hashlib, set
+from PyInstaller.depend import dylib
+from PyInstaller.utils import misc
+
+
+import PyInstaller.log as logging
+if is_win:
+ from PyInstaller.utils import winmanifest
+
+
+logger = logging.getLogger('PyInstaller.build')
+
+STRINGTYPE = type('')
+TUPLETYPE = type((None,))
+UNCOMPRESSED, COMPRESSED = range(2)
+
+DEFAULT_BUILDPATH = os.path.join('SPECPATH', 'build',
+ 'pyi.TARGET_PLATFORM', 'SPECNAME')
+
+SPEC = None
+SPECPATH = None
+BUILDPATH = None
+WARNFILE = None
+NOCONFIRM = None
+
+# Some modules are included if they are detected at build-time or
+# if a command-line argument is specified. (e.g. --ascii)
+HIDDENIMPORTS = []
+
+rthooks = {}
+
+
+def _save_data(filename, data):
+ dirname = os.path.dirname(filename)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ outf = open(filename, 'w')
+ pprint.pprint(data, outf)
+ outf.close()
+
+
+def _load_data(filename):
+ return eval(open(filename, 'rU').read())
+
+
+def setupUPXFlags():
+ f = compat.getenv("UPX", "")
+ if is_win and is_py24:
+ # Binaries built with Visual Studio 7.1 require --strip-loadconf
+ # or they won't compress. Configure.py makes sure that UPX is new
+ # enough to support --strip-loadconf.
+ f = "--strip-loadconf " + f
+ # Do not compress any icon, so that additional icons in the executable
+ # can still be externally bound
+ f = "--compress-icons=0 " + f
+ f = "--best " + f
+ compat.setenv("UPX", f)
+
+
+def mtime(fnm):
+ try:
+ return os.stat(fnm)[8]
+ except:
+ return 0
+
+
+def absnormpath(apath):
+ return os.path.abspath(os.path.normpath(apath))
+
+
+def compile_pycos(toc):
+ """Given a TOC or equivalent list of tuples, generates all the required
+ pyc/pyo files, writing in a local directory if required, and returns the
+ list of tuples with the updated pathnames.
+ """
+ global BUILDPATH
+
+ # For those modules that need to be rebuilt, use the build directory
+ # PyInstaller creates during the build process.
+ basepath = os.path.join(BUILDPATH, "localpycos")
+
+ new_toc = []
+ for (nm, fnm, typ) in toc:
+ if typ != 'PYMODULE':
+ new_toc.append((nm, fnm, typ))
+ continue
+
+ # Trim the terminal "c" or "o"
+ source_fnm = fnm[:-1]
+
+ # We need to perform a build ourselves if the source is newer
+ # than the compiled, or the compiled doesn't exist, or if it
+ # has been written by a different Python version.
+ needs_compile = (mtime(source_fnm) > mtime(fnm)
+ or
+ open(fnm, 'rb').read()[:4] != imp.get_magic())
+ if needs_compile:
+ try:
+ py_compile.compile(source_fnm, fnm)
+ logger.debug("compiled %s", source_fnm)
+ except IOError:
+ # If we're compiling on a system directory, probably we don't
+ # have write permissions; thus we compile to a local directory
+ # and change the TOC entry accordingly.
+ ext = os.path.splitext(fnm)[1]
+
+ if "__init__" not in fnm:
+ # If it's a normal module, use last part of the qualified
+ # name as module name and the first as leading path
+ leading, mod_name = nm.split(".")[:-1], nm.split(".")[-1]
+ else:
+ # In case of a __init__ module, use all the qualified name
+ # as leading path and use "__init__" as the module name
+ leading, mod_name = nm.split("."), "__init__"
+
+ leading = os.path.join(basepath, *leading)
+
+ if not os.path.exists(leading):
+ os.makedirs(leading)
+
+ fnm = os.path.join(leading, mod_name + ext)
+ needs_compile = (mtime(source_fnm) > mtime(fnm)
+ or
+ open(fnm, 'rb').read()[:4] != imp.get_magic())
+ if needs_compile:
+ py_compile.compile(source_fnm, fnm)
+ logger.debug("compiled %s", source_fnm)
+
+ new_toc.append((nm, fnm, typ))
+
+ return new_toc
+
+
+def addSuffixToExtensions(toc):
+ """
+ Returns a new TOC with proper library suffix for EXTENSION items.
+ """
+ new_toc = TOC()
+ for inm, fnm, typ in toc:
+ if typ in ('EXTENSION', 'DEPENDENCY'):
+ binext = os.path.splitext(fnm)[1]
+ if not os.path.splitext(inm)[1] == binext:
+ inm = inm + binext
+ new_toc.append((inm, fnm, typ))
+ return new_toc
+
+
+#--- functons for checking guts ---
+
+def _check_guts_eq(attr, old, new, last_build):
+ """
+ rebuild is required if values differ
+ """
+ if old != new:
+ logger.info("building because %s changed", attr)
+ return True
+ return False
+
+
+def _check_guts_toc_mtime(attr, old, toc, last_build, pyc=0):
+ """
+ rebuild is required if mtimes of files listed in old toc are newer
+ than ast_build
+
+ if pyc=1, check for .py files, too
+ """
+ for (nm, fnm, typ) in old:
+ if mtime(fnm) > last_build:
+ logger.info("building because %s changed", fnm)
+ return True
+ elif pyc and mtime(fnm[:-1]) > last_build:
+ logger.info("building because %s changed", fnm[:-1])
+ return True
+ return False
+
+
+def _check_guts_toc(attr, old, toc, last_build, pyc=0):
+ """
+ rebuild is required if either toc content changed if mtimes of
+ files listed in old toc are newer than ast_build
+
+ if pyc=1, check for .py files, too
+ """
+ return (_check_guts_eq(attr, old, toc, last_build)
+ or _check_guts_toc_mtime(attr, old, toc, last_build, pyc=pyc))
+
+
+def _check_path_overlap(path):
+ """
+ Check that path does not overlap with BUILDPATH or SPECPATH (i.e.
+ BUILDPATH and SPECPATH may not start with path, which could be
+ caused by a faulty hand-edited specfile)
+
+ Raise SystemExit if there is overlap, return True otherwise
+ """
+ specerr = 0
+ if BUILDPATH.startswith(path):
+ logger.error('Specfile error: The output path "%s" contains '
+ 'BUILDPATH (%s)', path, BUILDPATH)
+ specerr += 1
+ if SPECPATH.startswith(path):
+ logger.error('Specfile error: The output path "%s" contains '
+ 'SPECPATH (%s)', path, SPECPATH)
+ specerr += 1
+ if specerr:
+ raise SystemExit('Error: Please edit/recreate the specfile (%s) '
+ 'and set a different output name (e.g. "dist").'
+ % SPEC)
+ return True
+
+
+def _rmtree(path):
+ """
+ Remove directory and all its contents, but only after user confirmation,
+ or if the -y option is set
+ """
+ if NOCONFIRM:
+ choice = 'y'
+ elif sys.stdout.isatty():
+ choice = raw_input('WARNING: The output directory "%s" and ALL ITS '
+ 'CONTENTS will be REMOVED! Continue? (y/n)' % path)
+ else:
+ raise SystemExit('Error: The output directory "%s" is not empty. '
+ 'Please remove all its contents or use the '
+ '-y option (remove output directory without '
+ 'confirmation).' % path)
+ if choice.strip().lower() == 'y':
+ logger.info('Removing dir %s', path)
+ shutil.rmtree(path)
+ else:
+ raise SystemExit('User aborted')
+
+
+def check_egg(pth):
+ """Check if path points to a file inside a python egg file (or to an egg
+ directly)."""
+ if is_py23:
+ if os.path.altsep:
+ pth = pth.replace(os.path.altsep, os.path.sep)
+ components = pth.split(os.path.sep)
+ sep = os.path.sep
+ else:
+ components = pth.replace("\\", "/").split("/")
+ sep = "/"
+ if is_win:
+ sep = "\\"
+ for i, name in zip(range(0, len(components)), components):
+ if name.lower().endswith(".egg"):
+ eggpth = sep.join(components[:i + 1])
+ if os.path.isfile(eggpth):
+ # eggs can also be directories!
+ return True
+ return False
+
+#--
+
+
+class Target:
+ invcnum = 0
+
+ def __init__(self):
+ # Get a (per class) unique number to avoid conflicts between
+ # toc objects
+ self.invcnum = self.__class__.invcnum
+ self.__class__.invcnum += 1
+ self.out = os.path.join(BUILDPATH, 'out%02d-%s.toc' %
+ (self.invcnum, self.__class__.__name__))
+ self.outnm = os.path.basename(self.out)
+ self.dependencies = TOC()
+
+ def __postinit__(self):
+ logger.info("checking %s", self.__class__.__name__)
+ if self.check_guts(mtime(self.out)):
+ self.assemble()
+
+ GUTS = []
+
+ def check_guts(self, last_build):
+ pass
+
+ def get_guts(self, last_build, missing='missing or bad'):
+ """
+ returns None if guts have changed
+ """
+ try:
+ data = _load_data(self.out)
+ except:
+ logger.info("building because %s %s", os.path.basename(self.out), missing)
+ return None
+
+ if len(data) != len(self.GUTS):
+ logger.info("building because %s is bad", self.outnm)
+ return None
+ for i, (attr, func) in enumerate(self.GUTS):
+ if func is None:
+ # no check for this value
+ continue
+ if func(attr, data[i], getattr(self, attr), last_build):
+ return None
+ return data
+
+
+class Analysis(Target):
+ _old_scripts = set((
+ absnormpath(os.path.join(HOMEPATH, "support", "_mountzlib.py")),
+ absnormpath(os.path.join(CONFIGDIR, "support", "useUnicode.py")),
+ absnormpath(os.path.join(CONFIGDIR, "support", "useTK.py")),
+ absnormpath(os.path.join(HOMEPATH, "support", "useUnicode.py")),
+ absnormpath(os.path.join(HOMEPATH, "support", "useTK.py")),
+ absnormpath(os.path.join(HOMEPATH, "support", "unpackTK.py")),
+ absnormpath(os.path.join(HOMEPATH, "support", "removeTK.py")),
+ ))
+
+ def __init__(self, scripts=None, pathex=None, hiddenimports=None,
+ hookspath=None, excludes=None):
+ Target.__init__(self)
+ # Include initialization Python code in PyInstaller analysis.
+ _init_code_path = os.path.join(HOMEPATH, 'PyInstaller', 'loader')
+ self.inputs = [
+ os.path.join(HOMEPATH, "support", "_pyi_bootstrap.py"),
+ os.path.join(_init_code_path, 'archive.py'),
+ os.path.join(_init_code_path, 'carchive.py'),
+ os.path.join(_init_code_path, 'iu.py'),
+ ]
+ for script in scripts:
+ if absnormpath(script) in self._old_scripts:
+ logger.warn('Ignoring obsolete auto-added script %s', script)
+ continue
+ if not os.path.exists(script):
+ raise ValueError("script '%s' not found" % script)
+ self.inputs.append(script)
+ self.pathex = []
+ if pathex:
+ self.pathex = [absnormpath(path) for path in pathex]
+
+ self.hiddenimports = hiddenimports or []
+ # Include modules detected at build time. Like 'codecs' and encodings.
+ self.hiddenimports.extend(HIDDENIMPORTS)
+
+ self.hookspath = hookspath
+ self.excludes = excludes
+ self.scripts = TOC()
+ self.pure = TOC()
+ self.binaries = TOC()
+ self.zipfiles = TOC()
+ self.datas = TOC()
+ self.dependencies = TOC()
+ self.__postinit__()
+
+ GUTS = (('inputs', _check_guts_eq),
+ ('pathex', _check_guts_eq),
+ ('hookspath', _check_guts_eq),
+ ('excludes', _check_guts_eq),
+ ('scripts', _check_guts_toc_mtime),
+ ('pure', lambda *args: apply(_check_guts_toc_mtime,
+ args, {'pyc': 1})),
+ ('binaries', _check_guts_toc_mtime),
+ ('zipfiles', _check_guts_toc_mtime),
+ ('datas', _check_guts_toc_mtime),
+ ('hiddenimports', _check_guts_eq),
+ )
+
+ def check_guts(self, last_build):
+ if last_build == 0:
+ logger.info("building %s because %s non existent", self.__class__.__name__, self.outnm)
+ return True
+ for fnm in self.inputs:
+ if mtime(fnm) > last_build:
+ logger.info("building because %s changed", fnm)
+ return True
+
+ data = Target.get_guts(self, last_build)
+ if not data:
+ return True
+ scripts, pure, binaries, zipfiles, datas, hiddenimports = data[-6:]
+ self.scripts = TOC(scripts)
+ self.pure = TOC(pure)
+ self.binaries = TOC(binaries)
+ self.zipfiles = TOC(zipfiles)
+ self.datas = TOC(datas)
+ self.hiddenimports = hiddenimports
+ return False
+
+ def assemble(self):
+ logger.info("running Analysis %s", os.path.basename(self.out))
+ # Reset seen variable to correctly discover dependencies
+ # if there are multiple Analysis in a single specfile.
+ bindepend.seen = {}
+
+ python = sys.executable
+ if not is_win:
+ while os.path.islink(python):
+ python = os.path.join(os.path.dirname(python), os.readlink(python))
+ depmanifest = None
+ else:
+ depmanifest = winmanifest.Manifest(type_="win32", name=specnm,
+ processorArchitecture=winmanifest.processor_architecture(),
+ version=(1, 0, 0, 0))
+ depmanifest.filename = os.path.join(BUILDPATH,
+ specnm + ".exe.manifest")
+
+ binaries = [] # binaries to bundle
+
+ # Always add Python's dependencies first
+ # This ensures that its assembly depencies under Windows get pulled in
+ # first, so that .pyd files analyzed later which may not have their own
+ # manifest and may depend on DLLs which are part of an assembly
+ # referenced by Python's manifest, don't cause 'lib not found' messages
+ binaries.extend(bindepend.Dependencies([('', python, '')],
+ manifest=depmanifest)[1:])
+
+ ###################################################
+ # Scan inputs and prepare:
+ dirs = {} # input directories
+ pynms = [] # python filenames with no extension
+ for script in self.inputs:
+ if not os.path.exists(script):
+ raise SystemExit("Error: Analysis: script %s not found!" % script)
+ d, base = os.path.split(script)
+ if not d:
+ d = os.getcwd()
+ d = absnormpath(d)
+ pynm, ext = os.path.splitext(base)
+ dirs[d] = 1
+ pynms.append(pynm)
+ ###################################################
+ # Initialize importTracker and analyze scripts
+ importTracker = PyInstaller.depend.imptracker.ImportTracker(
+ dirs.keys() + self.pathex, self.hookspath, self.excludes)
+ PyInstaller.__pathex__ = self.pathex[:]
+ scripts = [] # will contain scripts to bundle
+ for i, script in enumerate(self.inputs):
+ logger.info("Analyzing %s", script)
+ importTracker.analyze_script(script)
+ scripts.append((pynms[i], script, 'PYSOURCE'))
+ PyInstaller.__pathex__ = []
+
+ # analyze the script's hidden imports
+ for modnm in self.hiddenimports:
+ if modnm in importTracker.modules:
+ logger.info("Hidden import %r has been found otherwise", modnm)
+ continue
+ logger.info("Analyzing hidden import %r", modnm)
+ importTracker.analyze_one(modnm)
+ if not modnm in importTracker.modules:
+ logger.error("Hidden import %r not found", modnm)
+
+ ###################################################
+ # Fills pure, binaries and rthookcs lists to TOC
+ pure = [] # pure python modules
+ zipfiles = [] # zipfiles to bundle
+ datas = [] # datafiles to bundle
+ rthooks = [] # rthooks if needed
+
+ # Find rthooks.
+ logger.info("Looking for run-time hooks")
+ for modnm, mod in importTracker.modules.items():
+ rthooks.extend(_findRTHook(modnm))
+
+ # Analyze rthooks. Runtime hooks has to be also analyzed.
+ # Otherwise some dependencies could be missing.
+ # Data structure in format:
+ # ('rt_hook_mod_name', '/rt/hook/file/name.py', 'PYSOURCE')
+ for hook_mod, hook_file, mod_type in rthooks:
+ logger.info("Analyzing rthook %s", hook_file)
+ importTracker.analyze_script(hook_file)
+
+ for modnm, mod in importTracker.modules.items():
+ # FIXME: why can we have a mod == None here?
+ if mod is None:
+ continue
+
+ datas.extend(mod.datas)
+
+ if isinstance(mod, PyInstaller.depend.modules.BuiltinModule):
+ pass
+ elif isinstance(mod, PyInstaller.depend.modules.ExtensionModule):
+ binaries.append((mod.__name__, mod.__file__, 'EXTENSION'))
+ # allows hooks to specify additional dependency
+ # on other shared libraries loaded at runtime (by dlopen)
+ binaries.extend(mod.binaries)
+ elif isinstance(mod, (PyInstaller.depend.modules.PkgInZipModule, PyInstaller.depend.modules.PyInZipModule)):
+ zipfiles.append(("eggs/" + os.path.basename(str(mod.owner)),
+ str(mod.owner), 'ZIPFILE'))
+ else:
+ # mf.PyModule instances expose a list of binary
+ # dependencies, most probably shared libraries accessed
+ # via ctypes. Add them to the overall required binaries.
+ binaries.extend(mod.binaries)
+ if modnm != '__main__':
+ pure.append((modnm, mod.__file__, 'PYMODULE'))
+
+ # Add remaining binary dependencies
+ binaries.extend(bindepend.Dependencies(binaries,
+ manifest=depmanifest))
+ if is_win:
+ depmanifest.writeprettyxml()
+ self.fixMissingPythonLib(binaries)
+ if zipfiles:
+ scripts.insert(-1, ("_pyi_egg_install.py", os.path.join(HOMEPATH, "support/_pyi_egg_install.py"), 'PYSOURCE'))
+ # Add realtime hooks just before the last script (which is
+ # the entrypoint of the application).
+ scripts[-1:-1] = rthooks
+ self.scripts = TOC(scripts)
+ self.pure = TOC(pure)
+ self.binaries = TOC(binaries)
+ self.zipfiles = TOC(zipfiles)
+ self.datas = TOC(datas)
+ try: # read .toc
+ oldstuff = _load_data(self.out)
+ except:
+ oldstuff = None
+
+ self.pure = TOC(compile_pycos(self.pure))
+
+ newstuff = tuple([getattr(self, g[0]) for g in self.GUTS])
+ if oldstuff != newstuff:
+ _save_data(self.out, newstuff)
+ wf = open(WARNFILE, 'w')
+ for ln in importTracker.getwarnings():
+ wf.write(ln + '\n')
+ wf.close()
+ logger.info("Warnings written to %s", WARNFILE)
+ return 1
+ logger.info("%s no change!", self.out)
+ return 0
+
+ def fixMissingPythonLib(self, binaries):
+ """Add the Python library if missing from the binaries.
+
+ Some linux distributions (e.g. debian-based) statically build the
+ Python executable to the libpython, so bindepend doesn't include
+ it in its output.
+
+ Darwin custom builds could possibly also have non-framework style libraries,
+ so this method also checks for that variant as well.
+ """
+
+ if is_aix:
+ # Shared libs on AIX are archives with shared object members, thus the ".a" suffix.
+ names = ('libpython%d.%d.a' % sys.version_info[:2],)
+ elif is_unix:
+ # Other *nix platforms.
+ names = ('libpython%d.%d.so' % sys.version_info[:2],)
+ elif is_darwin:
+ names = ('Python', 'libpython%d.%d.dylib' % sys.version_info[:2])
+ else:
+ return
+
+ for (nm, fnm, typ) in binaries:
+ for name in names:
+ if typ == 'BINARY' and name in fnm:
+ # lib found
+ return
+
+ # Resume search using the first item in names.
+ name = names[0]
+
+ logger.info('Looking for Python library %s', name)
+
+ if is_unix:
+ lib = bindepend.findLibrary(name)
+ if lib is None:
+ raise IOError("Python library not found!")
+
+ elif is_darwin:
+ # On MacPython, Analysis.assemble is able to find the libpython with
+ # no additional help, asking for sys.executable dependencies.
+ # However, this fails on system python, because the shared library
+ # is not listed as a dependency of the binary (most probably it's
+ # opened at runtime using some dlopen trickery).
+ # This happens on Mac OS X when Python is compiled as Framework.
+
+ # Python compiled as Framework contains same values in sys.prefix
+ # and exec_prefix. That's why we can use just sys.prefix.
+ # In virtualenv PyInstaller is not able to find Python library.
+ # We need special care for this case.
+ if compat.is_virtualenv:
+ py_prefix = sys.real_prefix
+ else:
+ py_prefix = sys.prefix
+
+ logger.info('Looking for Python library in %s', py_prefix)
+
+ lib = os.path.join(py_prefix, name)
+ if not os.path.exists(lib):
+ raise IOError("Python library not found!")
+
+ binaries.append((os.path.basename(lib), lib, 'BINARY'))
+
+
+def _findRTHook(modnm):
+ rslt = []
+ for script in rthooks.get(modnm) or []:
+ nm = os.path.basename(script)
+ nm = os.path.splitext(nm)[0]
+ if os.path.isabs(script):
+ path = script
+ else:
+ path = os.path.join(HOMEPATH, script)
+ rslt.append((nm, path, 'PYSOURCE'))
+ return rslt
+
+
+class PYZ(Target):
+ typ = 'PYZ'
+
+ def __init__(self, toc, name=None, level=9, crypt=None):
+ Target.__init__(self)
+ self.toc = toc
+ self.name = name
+ if name is None:
+ self.name = self.out[:-3] + 'pyz'
+ # Level of zlib compression.
+ self.level = level
+ if config['useCrypt'] and crypt is not None:
+ self.crypt = archive.Keyfile(crypt).key
+ else:
+ self.crypt = None
+ self.dependencies = compile_pycos(config['PYZ_dependencies'])
+ self.__postinit__()
+
+ GUTS = (('name', _check_guts_eq),
+ ('level', _check_guts_eq),
+ ('crypt', _check_guts_eq),
+ ('toc', _check_guts_toc), # todo: pyc=1
+ )
+
+ def check_guts(self, last_build):
+ if not os.path.exists(self.name):
+ logger.info("rebuilding %s because %s is missing",
+ self.outnm, os.path.basename(self.name))
+ return True
+
+ data = Target.get_guts(self, last_build)
+ if not data:
+ return True
+ return False
+
+ def assemble(self):
+ logger.info("building PYZ %s", os.path.basename(self.out))
+ pyz = archive.ZlibArchive(level=self.level, crypt=self.crypt)
+ toc = self.toc - config['PYZ_dependencies']
+ pyz.build(self.name, toc)
+ _save_data(self.out, (self.name, self.level, self.crypt, self.toc))
+ return 1
+
+
+def cacheDigest(fnm):
+ data = open(fnm, "rb").read()
+ digest = hashlib.md5(data).digest()
+ return digest
+
+
+def checkCache(fnm, strip=0, upx=0, dist_nm=None):
+ """
+ Cache prevents preprocessing binary files again and again.
+
+ 'dist_nm' Filename relative to dist directory. We need it on Mac
+ to determine level of paths for @loader_path like
+ '@loader_path/../../' for qt4 plugins.
+ """
+ # On darwin a cache is required anyway to keep the libaries
+ # with relative install names. Caching on darwin does not work
+ # since we need to modify binary headers to use relative paths
+ # to dll depencies and starting with '@loader_path'.
+
+ if ((not strip and not upx and not is_darwin and not is_win)
+ or fnm.lower().endswith(".manifest")):
+ return fnm
+ if strip:
+ strip = 1
+ else:
+ strip = 0
+ if upx:
+ upx = 1
+ else:
+ upx = 0
+
+ # Load cache index
+ # Make cachedir per Python major/minor version.
+ # This allows parallel building of executables with different
+ # Python versions as one user.
+ pyver = ('py%d%s') % (sys.version_info[0], sys.version_info[1])
+ cachedir = os.path.join(CONFIGDIR, 'bincache%d%d_%s' % (strip, upx, pyver))
+ if not os.path.exists(cachedir):
+ os.makedirs(cachedir)
+ cacheindexfn = os.path.join(cachedir, "index.dat")
+ if os.path.exists(cacheindexfn):
+ cache_index = _load_data(cacheindexfn)
+ else:
+ cache_index = {}
+
+ # Verify if the file we're looking for is present in the cache.
+ basenm = os.path.normcase(os.path.basename(fnm))
+ digest = cacheDigest(fnm)
+ cachedfile = os.path.join(cachedir, basenm)
+ cmd = None
+ if basenm in cache_index:
+ if digest != cache_index[basenm]:
+ os.remove(cachedfile)
+ else:
+ # On Mac OS X we need relative paths to dll dependencies
+ # starting with @executable_path
+ if is_darwin:
+ dylib.mac_set_relative_dylib_deps(cachedfile, dist_nm)
+ return cachedfile
+ if upx:
+ if strip:
+ fnm = checkCache(fnm, 1, 0)
+ bestopt = "--best"
+ # FIXME: Linux builds of UPX do not seem to contain LZMA (they assert out)
+ # A better configure-time check is due.
+ if config["hasUPX"] >= (3,) and os.name == "nt":
+ bestopt = "--lzma"
+
+ upx_executable = "upx"
+ if config.get('upx_dir'):
+ upx_executable = os.path.join(config['upx_dir'], upx_executable)
+ cmd = [upx_executable, bestopt, "-q", cachedfile]
+ else:
+ if strip:
+ # -S = strip only debug symbols.
+ # The default strip behaviour breaks some shared libraries
+ # under Mac OSX
+ cmd = ["strip", "-S", cachedfile]
+ shutil.copy2(fnm, cachedfile)
+ os.chmod(cachedfile, 0755)
+
+ if pyasm and fnm.lower().endswith(".pyd"):
+ # If python.exe has dependent assemblies, check for embedded manifest
+ # of cached pyd file because we may need to 'fix it' for pyinstaller
+ try:
+ res = winmanifest.GetManifestResources(os.path.abspath(cachedfile))
+ except winresource.pywintypes.error, e:
+ if e.args[0] == winresource.ERROR_BAD_EXE_FORMAT:
+ # Not a win32 PE file
+ pass
+ else:
+ logger.error(os.path.abspath(cachedfile))
+ raise
+ else:
+ if winmanifest.RT_MANIFEST in res and len(res[winmanifest.RT_MANIFEST]):
+ for name in res[winmanifest.RT_MANIFEST]:
+ for language in res[winmanifest.RT_MANIFEST][name]:
+ try:
+ manifest = winmanifest.Manifest()
+ manifest.filename = ":".join([cachedfile,
+ str(winmanifest.RT_MANIFEST),
+ str(name),
+ str(language)])
+ manifest.parse_string(res[winmanifest.RT_MANIFEST][name][language],
+ False)
+ except Exception, exc:
+ logger.error("Cannot parse manifest resource %s, "
+ "%s from", name, language)
+ logger.error(cachedfile)
+ logger.exception(exc)
+ else:
+ # Fix the embedded manifest (if any):
+ # Extension modules built with Python 2.6.5 have
+ # an empty <dependency> element, we need to add
+ # dependentAssemblies from python.exe for
+ # pyinstaller
+ olen = len(manifest.dependentAssemblies)
+ _depNames = set([dep.name for dep in
+ manifest.dependentAssemblies])
+ for pydep in pyasm:
+ if not pydep.name in _depNames:
+ logger.info("Adding %r to dependent "
+ "assemblies of %r",
+ pydep.name, cachedfile)
+ manifest.dependentAssemblies.append(pydep)
+ _depNames.update(pydep.name)
+ if len(manifest.dependentAssemblies) > olen:
+ try:
+ manifest.update_resources(os.path.abspath(cachedfile),
+ [name],
+ [language])
+ except Exception, e:
+ logger.error(os.path.abspath(cachedfile))
+ raise
+
+ if cmd:
+ try:
+ compat.exec_command(*cmd)
+ except OSError, e:
+ raise SystemExit("Execution failed: %s" % e)
+
+ # update cache index
+ cache_index[basenm] = digest
+ _save_data(cacheindexfn, cache_index)
+
+ # On Mac OS X we need relative paths to dll dependencies
+ # starting with @executable_path
+ if is_darwin:
+ dylib.mac_set_relative_dylib_deps(cachedfile, dist_nm)
+ return cachedfile
+
+
+UNCOMPRESSED, COMPRESSED, ENCRYPTED = range(3)
+
+
+class PKG(Target):
+ typ = 'PKG'
+ xformdict = {'PYMODULE': 'm',
+ 'PYSOURCE': 's',
+ 'EXTENSION': 'b',
+ 'PYZ': 'z',
+ 'PKG': 'a',
+ 'DATA': 'x',
+ 'BINARY': 'b',
+ 'ZIPFILE': 'Z',
+ 'EXECUTABLE': 'b',
+ 'DEPENDENCY': 'd'}
+
+ def __init__(self, toc, name=None, cdict=None, exclude_binaries=0,
+ strip_binaries=0, upx_binaries=0, crypt=0):
+ Target.__init__(self)
+ self.toc = toc
+ self.cdict = cdict
+ self.name = name
+ self.exclude_binaries = exclude_binaries
+ self.strip_binaries = strip_binaries
+ self.upx_binaries = upx_binaries
+ self.crypt = crypt
+ if name is None:
+ self.name = self.out[:-3] + 'pkg'
+ if self.cdict is None:
+ self.cdict = {'EXTENSION': COMPRESSED,
+ 'DATA': COMPRESSED,
+ 'BINARY': COMPRESSED,
+ 'EXECUTABLE': COMPRESSED,
+ 'PYSOURCE': COMPRESSED,
+ 'PYMODULE': COMPRESSED}
+ if self.crypt:
+ self.cdict['PYSOURCE'] = ENCRYPTED
+ self.cdict['PYMODULE'] = ENCRYPTED
+ self.__postinit__()
+
+ GUTS = (('name', _check_guts_eq),
+ ('cdict', _check_guts_eq),
+ ('toc', _check_guts_toc_mtime),
+ ('exclude_binaries', _check_guts_eq),
+ ('strip_binaries', _check_guts_eq),
+ ('upx_binaries', _check_guts_eq),
+ ('crypt', _check_guts_eq),
+ )
+
+ def check_guts(self, last_build):
+ if not os.path.exists(self.name):
+ logger.info("rebuilding %s because %s is missing",
+ self.outnm, os.path.basename(self.name))
+ return 1
+
+ data = Target.get_guts(self, last_build)
+ if not data:
+ return True
+ # todo: toc equal
+ return False
+
+ def assemble(self):
+ logger.info("building PKG %s", os.path.basename(self.name))
+ trash = []
+ mytoc = []
+ seen = {}
+ toc = addSuffixToExtensions(self.toc)
+ for inm, fnm, typ in toc:
+ if not os.path.isfile(fnm) and check_egg(fnm):
+ # file is contained within python egg, it is added with the egg
+ continue
+ if typ in ('BINARY', 'EXTENSION', 'DEPENDENCY'):
+ if self.exclude_binaries and typ != 'DEPENDENCY':
+ self.dependencies.append((inm, fnm, typ))
+ else:
+ fnm = checkCache(fnm, self.strip_binaries,
+ self.upx_binaries and (is_win or is_cygwin)
+ and config['hasUPX'], dist_nm=inm)
+ # Avoid importing the same binary extension twice. This might
+ # happen if they come from different sources (eg. once from
+ # binary dependence, and once from direct import).
+ if typ == 'BINARY' and fnm in seen:
+ continue
+ seen[fnm] = 1
+ mytoc.append((inm, fnm, self.cdict.get(typ, 0),
+ self.xformdict.get(typ, 'b')))
+ elif typ == 'OPTION':
+ mytoc.append((inm, '', 0, 'o'))
+ else:
+ mytoc.append((inm, fnm, self.cdict.get(typ, 0), self.xformdict.get(typ, 'b')))
+ archive = carchive.CArchive()
+ archive.build(self.name, mytoc)
+ _save_data(self.out,
+ (self.name, self.cdict, self.toc, self.exclude_binaries,
+ self.strip_binaries, self.upx_binaries, self.crypt))
+ for item in trash:
+ os.remove(item)
+ return 1
+
+
+class EXE(Target):
+ typ = 'EXECUTABLE'
+ exclude_binaries = 0
+ append_pkg = 1
+
+ def __init__(self, *args, **kws):
+ Target.__init__(self)
+ self.console = kws.get('console', 1)
+ self.debug = kws.get('debug', 0)
+ self.name = kws.get('name', None)
+ self.icon = kws.get('icon', None)
+ self.versrsrc = kws.get('version', None)
+ self.manifest = kws.get('manifest', None)
+ self.resources = kws.get('resources', [])
+ self.strip = kws.get('strip', None)
+ self.upx = kws.get('upx', None)
+ self.crypt = kws.get('crypt', 0)
+ self.exclude_binaries = kws.get('exclude_binaries', 0)
+ self.append_pkg = kws.get('append_pkg', self.append_pkg)
+ if self.name is None:
+ self.name = self.out[:-3] + 'exe'
+ if not os.path.isabs(self.name):
+ self.name = os.path.join(SPECPATH, self.name)
+ if is_win or is_cygwin:
+ self.pkgname = self.name[:-3] + 'pkg'
+ else:
+ self.pkgname = self.name + '.pkg'
+ self.toc = TOC()
+ for arg in args:
+ if isinstance(arg, TOC):
+ self.toc.extend(arg)
+ elif isinstance(arg, Target):
+ self.toc.append((os.path.basename(arg.name), arg.name, arg.typ))
+ self.toc.extend(arg.dependencies)
+ else:
+ self.toc.extend(arg)
+ if is_win:
+ filename = os.path.join(BUILDPATH, specnm + ".exe.manifest")
+ self.manifest = winmanifest.create_manifest(filename, self.manifest,
+ self.console)
+ self.toc.append((os.path.basename(self.name) + ".manifest", filename,
+ 'BINARY'))
+ self.pkg = PKG(self.toc, cdict=kws.get('cdict', None),
+ exclude_binaries=self.exclude_binaries,
+ strip_binaries=self.strip, upx_binaries=self.upx,
+ crypt=self.crypt)
+ self.dependencies = self.pkg.dependencies
+ self.__postinit__()
+
+ GUTS = (('name', _check_guts_eq),
+ ('console', _check_guts_eq),
+ ('debug', _check_guts_eq),
+ ('icon', _check_guts_eq),
+ ('versrsrc', _check_guts_eq),
+ ('resources', _check_guts_eq),
+ ('strip', _check_guts_eq),
+ ('upx', _check_guts_eq),
+ ('crypt', _check_guts_eq),
+ ('mtm', None,), # checked bellow
+ )
+
+ def check_guts(self, last_build):
+ if not os.path.exists(self.name):
+ logger.info("rebuilding %s because %s missing",
+ self.outnm, os.path.basename(self.name))
+ return 1
+ if not self.append_pkg and not os.path.exists(self.pkgname):
+ logger.info("rebuilding because %s missing",
+ os.path.basename(self.pkgname))
+ return 1
+
+ data = Target.get_guts(self, last_build)
+ if not data:
+ return True
+
+ icon, versrsrc, resources = data[3:6]
+ if (icon or versrsrc or resources) and not config['hasRsrcUpdate']:
+ # todo: really ignore :-)
+ logger.info("ignoring icon, version, manifest and resources = platform not capable")
+
+ mtm = data[-1]
+ crypt = data[-2]
+ if crypt != self.crypt:
+ logger.info("rebuilding %s because crypt option changed", self.outnm)
+ return 1
+ if mtm != mtime(self.name):
+ logger.info("rebuilding %s because mtimes don't match", self.outnm)
+ return True
+ if mtm < mtime(self.pkg.out):
+ logger.info("rebuilding %s because pkg is more recent", self.outnm)
+ return True
+
+ return False
+
+ def _bootloader_file(self, exe):
+ if not self.console:
+ exe = exe + 'w'
+ if self.debug:
+ exe = exe + '_d'
+ return os.path.join("support", "loader", PLATFORM, exe)
+