Anonymous avatar Anonymous committed 17f12ee

Rewrite the conversion function support, making it a
real setuptools entry-point. This makes it possible
to introduce new conversions outside of py2app.

My longer-term plan is the move the current conversion
functions to the appropriate pyobjc package.

Comments (0)

Files changed (8)

 - A new recipe for `virtualenv`_, this allows you to use py2app from 
   a virtual environment.
 
+- 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
 
 

py2app/converters/__init__.py

-#
-# Data convertors
-#
-# Interface:
-#   def convert(source, destination):
-#       pass
-#
-#   source is a file/directory name
-#   function should return True if it installed the file,
-#   False otherwise.
-#
-# TODO:
-# - Add converters for CoreData models
-import xib
+"""
+Resource data converters
+"""

py2app/converters/coredata.py

+"""
+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)

py2app/converters/nibfile.py

+"""
+Automatic compilation of XIB files
+"""
+import subprocess, os
+from py2app.decorators import converts
+
+@converts(suffix=".xib")
+def convert_xib(source, destination, dry_run=0):
+    destination = destination[:-4] + ".nib"
+
+    if dry_run:
+        return
+
+    p = subprocess.Popen(['ibtool', '--compile', destination, source])
+    xit = p.wait()
+    if xit != 0:
+        raise RuntimeError("ibtool failed, code %d"%(xit,))
+
+
+@converts(suffix=".nib")
+def convert_nib(source, destination, dry_run=0):
+    destination = destination[:-4] + ".nib"
+
+    if dry_run:
+        return
+
+    p = subprocess.Popen(['ibtool', '--compile', destination, source])
+    xit = p.wait()
+    if xit != 0:
+        raise RuntimeError("ibtool failed, code %d"%(xit,))
+

py2app/converters/xib.py

-"""
-Automatic compilation of XIB files
-"""
-import subprocess, os
-
-def convert(source, destination):
-    ext = os.path.splitext(source)[-1]
-    if ext != '.xib':
-        return False
-
-    destination = destination[:-4] + ".nib"
-
-    p = subprocess.Popen(['ibtool', '--compile', destination, source])
-    xit = p.wait()
-    if xit != 0:
-        raise RuntimeError("ibtool failed, code %d"%(xit,))
-
-    return True

py2app/decorators.py

+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
 from altgraph.compat import *
 import macholib.util
 
+import pkg_resources
+
 def os_path_islink(path):
     """
     os.path.islink with zipfile support.
             # zipfiles, but those have a lash at the end of the filename
             return False
 
+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):
     """
     Copy a resource file into the application bundle
     """
     import py2app.converters as conv
 
-    for mod in conv.__dict__.values():
-        try:
-            func = getattr(mod, 'convert')
-        except AttributeError:
-            continue
-
-        r = func(source, destination)
-        if r:
-            return
+    converter = find_converter(source)
+    if converter is not None:
+        converter(source, destination, dry_run=dry_run)
+        return
 
     if os.path.isdir(source):
         # XXX: This is wrong, need to call ourselves recursively
         'console_scripts': [
             "py2applet = py2app.script_py2applet:main",
         ],
+        'py2app.converter': [
+            "xib          = py2app.converters.nibfile:convert_xib",
+            "nib          = py2app.converters.nibfile:convert_nib",
+            "datamodel    = py2app.converters.coredata:convert_datamodel",
+            "mappingmodel = py2app.converters.coredata:convert_mappingmodel",
+        ],
     },
     zip_safe=False,
     # workaround for setuptools 0.6b4 bug
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.