10
\$\begingroup\$

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?

\$\endgroup\$
1
  • 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
    Mar 18, 2011 at 5:29

1 Answer 1

3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.