Dear sirs,

I have been working on integrating Apache Tika (in Java) with our open source intranet application (in Python/Django) using JCC, as described here:

http://blog.aptivate.org/2012/02/01/content-indexing-in-django-using-apache-tika/

In order to make it easy to install Tika (which normally requires mystic incantations of JCC) I have packaged it up with jar files and a setup.py script. This required some changes to JCC. I hope you will consider these for inclusion in your project. I don't believe that they break backwards compatibility.

Changes implemented by the attached patch and visible online (formatted) at <https://github.com/aptivate/jcc/commits/master>:

* Allow calling cpp.jcc with a --maxheap argument to reduce the heap size, as the default doesn't fit in memory on a reasonably small virtual machine.

* Allow calling cpp.jcc with --egg-info to generate the egg_info, without doing a build.

* Allow calling cpp.jcc with --extra-setup-arg <arg> to pass additional arguments to the setup() function call.

Changes that require more work:

* Can JCC please not fail completely if setuptools hasn't been patched? Can it monkeypatch it instead, or at least fall back to non-shared mode?

* Why does JCC use non-standard command line arguments like --build and --install? Can it be modified to make it easier to invoke from a setup.py-style environment, such as exporting a setup() function as setuptools does?

* Could JCC be used to generate dynamic proxies at runtime (with a performance cost) in Python, to avoid the need for a compiler?

* Could JCC generate a source distribution (sdist) that could be uploaded to pypi?

* "setup.py develop" is still broken in the current implementation

* JCC silently skips wrapping methods whose return type it doesn't know (for example because I forgot to include a JAR file) which requires a lot of debugging to track down and fix. This is doubly hard because it only seems to work when installed, so I can't monkey patch it on the fly to investigate problems, I have to remember to "setup.py install" each time.

Thanks in advance for your consideration.

Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 760887
The Humanitarian Centre, Fenner's, Gresham Road, Cambridge CB1 2ES

Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.
Index: jcc/python.py
===================================================================
--- jcc/python.py	(revision 1238664)
+++ jcc/python.py	(working copy)
@@ -1563,7 +1563,7 @@
 def compile(env, jccPath, output, moduleName, install, dist, debug, jars,
             version, prefix, root, install_dir, home_dir, use_distutils,
             shared, compiler, modules, wininst, find_jvm_dll, arch, generics,
-            resources, imports):
+            resources, imports, egg_info, extra_setup_args):
 
     try:
         if use_distutils:
@@ -1730,7 +1730,10 @@
             if name.endswith('.cpp'):
                 sources.append(os.path.join(path, name))
 
-    script_args = ['build_ext']
+    if egg_info:
+        script_args = ['egg_info']
+    else:    
+        script_args = ['build_ext']
 
     includes[0:0] = INCLUDES
     compile_args = CFLAGS
@@ -1840,6 +1843,7 @@
         config_vars['CFLAGS'] = ' '.join(cflags)
 
     extensions = [Extension('.'.join([moduleName, extname]), **args)]
+    script_args.extend(extra_setup_args)
 
     args = {
         'name': moduleName,
@@ -1853,4 +1857,6 @@
     if with_setuptools:
         args['zip_safe'] = False
 
+    print "setup args = %s" % args
+
     setup(**args)
Index: jcc/cpp.py
===================================================================
--- jcc/cpp.py	(revision 1238664)
+++ jcc/cpp.py	(working copy)
@@ -349,6 +349,7 @@
     build = False
     install = False
     recompile = False
+    egg_info = False
     output = 'build'
     debug = False
     excludes = []
@@ -372,7 +373,9 @@
     arch = []
     resources = []
     imports = {}
-
+    extra_setup_args = []
+    initvm_args = {'maxstack': '512k'}
+    
     i = 1
     while i < len(args):
         arg = args[i]
@@ -398,6 +401,9 @@
             elif arg == '--vmarg':
                 i += 1
                 vmargs.append(args[i])
+            elif arg == '--maxheap':
+                i += 1
+                initvm_args['maxheap'] = args[i]
             elif arg == '--python':
                 from python import python, module
                 i += 1
@@ -414,6 +420,12 @@
             elif arg == '--compile':
                 from python import compile
                 recompile = True
+            elif arg == '--egg-info':
+                from python import compile
+                egg_info = True
+            elif arg == '--extra-setup-arg':
+                i += 1
+                extra_setup_args.append(args[i])
             elif arg == '--output':
                 i += 1
                 output = args[i]
@@ -492,9 +504,10 @@
     if libpath:
         vmargs.append('-Djava.library.path=' + os.pathsep.join(libpath))
 
-    env = initVM(os.pathsep.join(classpath) or None,
-                 maxstack='512k', vmargs=' '.join(vmargs))
+    initvm_args['vmargs'] = ' '.join(vmargs)
 
+    env = initVM(os.pathsep.join(classpath) or None, **initvm_args)
+
     typeset = set()
     excludes = set(excludes)
 
@@ -504,7 +517,7 @@
         else:
             raise ValueError, "--shared must be used when using --import"
 
-    if recompile or not build and (install or dist):
+    if recompile or not build and (install or dist or egg_info):
         if moduleName is None:
             raise ValueError, 'module name not specified (use --python)'
         else:
@@ -512,7 +525,8 @@
                     install, dist, debug, jars, version,
                     prefix, root, install_dir, home_dir, use_distutils,
                     shared, compiler, modules, wininst, find_jvm_dll,
-                    arch, generics, resources, imports)
+                    arch, generics, resources, imports, egg_info,
+                    extra_setup_args)
     else:
         if imports:
             def walk((include, importset), dirname, names):
@@ -647,12 +661,13 @@
             module(out, allInOne, done, imports, cppdir, moduleName,
                    shared, generics)
             out.close()
-            if build or install or dist:
+            if build or install or dist or egg_info:
                 compile(env, os.path.dirname(args[0]), output, moduleName,
                         install, dist, debug, jars, version,
                         prefix, root, install_dir, home_dir, use_distutils,
                         shared, compiler, modules, wininst, find_jvm_dll,
-                        arch, generics, resources, imports)
+                        arch, generics, resources, imports, egg_info,
+                        extra_setup_args)
 
 
 def header(env, out, cls, typeset, packages, excludes, generics, _dll_export):

Reply via email to