As you review this, please keep in mind I'm using Jython 2.1 as shipped with IBM's WebSphere 7.0 (their latest-and-greatest). I don't have decorators, properties, new style objects, or any other Python feature invented in the last decade.
Problem:
Using WebSphere's Jython interface to determine app server configuration information is not exactly fast. I had already begun work on a simple Jython module to encapsulate the convoluted WebSphere Jython API when I decided to try and cache the results of each method invocation. WebSphere configuration details tend not to change very often.
Inspired by Python 3.2's @functools.lru_cache and Python 2.2's properties I came up with:
from org.python.core import PyString, PyTuple
class Getter:
def getter(self,attr,valid_attrs):
if attr == 'valid_attrs': return valid_attrs
if attr not in valid_attrs.keys(): raise AttributeError
attr_value = None
if type(valid_attrs[attr]) == PyString:
function = getattr(self,valid_attrs[attr])
attr_value = function()
elif type(valid_attrs[attr]) == PyTuple:
function = getattr(self,valid_attrs[attr][0])
args = []
kwargs = {}
for arg in valid_attrs[attr][1:]:
if type(arg) == PyTuple:
if len(arg) > 2:
err = ('Named argument tuple %s in %s length > 2.'
% (arg, self.__class__.__name__ ))
raise NameError(err)
kwargs[arg[0]] = arg[1]
elif type(arg) == PyString:
args.append(arg)
else:
err = ('Unknown argument in %s __getattr__ dispatch list'
% self.__class__.__name__ )
raise NameError(err)
attr_value = function(*args,**kwargs)
else:
raise AttributeError
return attr_value
class App(Getter):
def __init__(self, name=None):
if name:
self.app_name = name
else:
print 'App instance requires name.'
raise NameError
def __getattr__(self,attr):
valid_attrs = { 'app_id': ('get_app_id'),
'deployed_nodes': ('get_deployed_nodes'),
'deployed_servers': ('get_deployed_servers'),
}
attr_value = Getter.getter(self,attr,valid_attrs)
setattr(self,attr,attr_value)
return attr_value
def get_app_id(self):
return AdminConfig.getid('/Deployment: %s/' % self.app_name)
def get_deployed_node(self):
### ...
def get_deployed_servers(self):
### ...
As I use this in other classes I change the function dispatch dict (valid_attrs
) as needed.
Is this an evil abuse of __getattr__
? Next to code execution speed, I'm most worried about maintainability. Does this trigger a "WTF?" Or, does it make sense when viewed against the limitations of Jython 2.1 and features, such as @property, found in newer versions?
-
4\$\begingroup\$ Were I prone to making uneducated and accusatory statements, I would venture to say that WebSphere is the WTF. Instead, I will just wonder what their rationale is in shipping such an age-old version of Jython. Maybe not very many people are using Jython with WebSphere? \$\endgroup\$intuited– intuited2011年03月18日 05:29:10 +00:00Commented Mar 18, 2011 at 5:29
1 Answer 1
I'd say calling self.setattr
from __getattr__(self, )
is borderline abuse in itself.
I guess you are trying to implement lazy attributes, right?
However in your case valid attributes are constant and their values appear constant too, so why not set them at class "declaration" time?
Also, python syntax for a tuple with 1 element is (1,)
not (1)
that you have in valid attrs extensively.