Lib.modjy.modjy_publish.py Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
###
#
# Copyright Alan Kennedy.
#
# You may contact the copyright holder at this uri:
#
# http://www.xhaus.com/contact/modjy
#
# The licence under which this code is released is the Apache License v2.0.
#
# The terms and conditions of this license are listed in a file contained
# in the distribution that also contained this file, under the name
# LICENSE.txt.
#
# You may also read a copy of the license at the following web address.
#
# http://modjy.xhaus.com/LICENSE.txt
#
###
import sys
import synchronize
from java.io import File
from modjy_exceptions import *
class modjy_publisher:
def init_publisher(self):
self.cache = None
if self.params['app_directory']:
self.app_directory = self.expand_relative_path(self.params['app_directory'])
else:
self.app_directory = self.servlet_context.getRealPath('/')
self.params['app_directory'] = self.app_directory
if self.app_directory is not None and not self.app_directory in sys.path:
sys.path.append(self.app_directory)
def map_uri(self, req, environ):
source_uri = '%s%s%s' % (self.app_directory, File.separator, self.params['app_filename'])
callable_name = self.params['app_callable_name']
if self.params['callable_query_name']:
query_string = req.getQueryString()
if query_string:
for name_val in query_string.split('&'):
if name_val.find('=') != -1:
name, value = name_val.split('=', 1)
else:
name, value = name_val, ''
if name == self.params['callable_query_name']:
callable_name = value
else:
callable_name = ''
return source_uri, callable_name
def get_app_object(self, req, environ):
environ["SCRIPT_NAME"] = "%s%s" % (req.getContextPath(), req.getServletPath())
path_info = req.getPathInfo() or ""
environ["PATH_INFO"] = path_info
environ["PATH_TRANSLATED"] = File(self.app_directory, path_info).getPath()
if self.params['app_import_name']:
return self.get_app_object_importable(self.params['app_import_name'])
else:
if self.cache is None:
self.cache = {}
return self.get_app_object_old_style(req, environ)
get_app_object = synchronize.make_synchronized(get_app_object)
def get_app_object_importable(self, importable_name):
self.log.debug("Attempting to import application callable '%s'\n" % (importable_name, ))
# Under the importable mechanism, the cache contains a single object
if self.cache is None:
application, instantiable, method_name = self.load_importable(importable_name.strip())
if instantiable and self.params['cache_callables']:
application = application()
self.cache = application, instantiable, method_name
application, instantiable, method_name = self.cache
self.log.debug("Application is " + str(application))
if instantiable and not self.params['cache_callables']:
application = application()
self.log.debug("Instantiated application is " + str(application))
if method_name is not None:
if not hasattr(application, method_name):
self.log.fatal("Attribute error application callable '%s' as no method '%s'" % (application, method_name))
self.raise_exc(ApplicationNotFound, "Attribute error application callable '%s' as no method '%s'" % (application, method_name))
application = getattr(application, method_name)
self.log.debug("Application method is " + str(application))
return application
def load_importable(self, name):
try:
instantiable = False ; method_name = None
importable_name = name
if name.find('()') != -1:
instantiable = True
importable_name, method_name = name.split('()')
if method_name.startswith('.'):
method_name = method_name[1:]
if not method_name:
method_name = None
module_path, from_name = importable_name.rsplit('.', 1)
imported = __import__(module_path, globals(), locals(), [from_name])
imported = getattr(imported, from_name)
return imported, instantiable, method_name
except (ImportError, AttributeError), aix:
self.log.fatal("Import error import application callable '%s': %s\n" % (name, str(aix)))
self.raise_exc(ApplicationNotFound, "Failed to import app callable '%s': %s" % (name, str(aix)))
def get_app_object_old_style(self, req, environ):
source_uri, callable_name = self.map_uri(req, environ)
source_filename = source_uri
if not self.params['cache_callables']:
self.log.debug("Caching of callables disabled")
return self.load_object(source_filename, callable_name)
if not self.cache.has_key( (source_filename, callable_name) ):
self.log.debug("Callable object not in cache: %s#%s" % (source_filename, callable_name) )
return self.load_object(source_filename, callable_name)
app_callable, last_mod = self.cache.get( (source_filename, callable_name) )
self.log.debug("Callable object was in cache: %s#%s" % (source_filename, callable_name) )
if self.params['reload_on_mod']:
f = File(source_filename)
if f.lastModified() > last_mod:
self.log.info("Source file '%s' has been modified: reloading" % source_filename)
return self.load_object(source_filename, callable_name)
return app_callable
def load_object(self, path, callable_name):
try:
app_ns = {} ; execfile(path, app_ns)
app_callable = app_ns[callable_name]
f = File(path)
self.cache[ (path, callable_name) ] = (app_callable, f.lastModified())
return app_callable
except IOError, ioe:
self.raise_exc(ApplicationNotFound, "Application filename not found: %s" % path)
except KeyError, k:
self.raise_exc(NoCallable, "No callable named '%s' in %s" % (callable_name, path))
except Exception, x:
self.raise_exc(NoCallable, "Error loading jython callable '%s': %s" % (callable_name, str(x)) )