Making class attributes non-case-sensitive?

Matimus mccredie at gmail.com
Mon Oct 13 13:14:14 EDT 2008


On Oct 13, 4:08 am, Rafe <rafesa... at gmail.com> wrote:
> Just so I don't hijack my own thread, the issue is 'how to wrap an
> object which is not case sensitive'.
>
> The reason I am stuck dealing with this?... The application's API is
> accessed through COM, so I don't know if I can do anything but react
> to what I get. The API was written while the app (Softimage|XSI - one
> of 3 leading 3D applications for high-end visual effects) was owned by
> Microsoft. I'm not sure if it is standard for Microsoft or just the
> way this app was implemented (perhaps because under-users were
> scripting in VBscript which is not case sensitive).
>
> XSI allows many languages to be used via COM, even from within the
> software (there are built-in code editors). In the early days,
> VBScript was the most common scripting language used while anything
> more hard-core was done in C++ (of course the C implementation is case
> sensitive - well as far as I know). Then JScript became the most
> common, now Python is considered standard.
>
> Anyway, the standard practice is to use mixed-case, so I need to
> adhere to it as the resulting framework I am creating needs to be
> intuitive to use (my end-user is still writing code. It's an API for
> an API I guess...)
>
> I don't *think* I need to worry too much about performance because I'm
> not doing any serious processing, this is more about convention
> enforcement and quality control rather than number crunching. I might
> try to write something generic which gets executed by the wrappers
> __getattr__ and __setattr__, but I was hoping for some nifty
> workaround, maybe in the form of a decorator or something? Again...
> any ideas?
>
> Cheers,
>
> - Rafe
>
> On Oct 13, 4:15 pm, "Diez B. Roggisch" <de... at nospam.web.de> wrote:
>
> > Rafe wrote:
> > > Hi,
>
> > > I'm working within an application (making a lot of wrappers), but the
> > > application is not case sensitive. For example, Typing obj.name,
> > > obj.Name, or even object.naMe is all fine (as far as the app is
> > > concerned). The problem is, If someone makes a typo, they may get an
> > > unexpected error due accidentally calling the original attribute
> > > instead of the wrapped version. Does anyone have a simple solution for
> > > this?
>
> > > I can protect against some cases just by making an 'alias':
> > > class AClass(object):
> > >     def name(self):
> > >         print "hello"
>
> > >     Name = name
>
> > > ...but this doesn't protect against typos, it gets more complicated
> > > with multi-word attribute names, and it makes my epydocs confusing to
> > > read since all spelling versions are shown (I AM concerned about my
> > > docs being clear, but not as much as stopping typo related errors).
>
> > > I thought about using my wrapper's __getattr__ and __setattr__, but I
> > > I am concerned about the overhead of every delegated attribute call
> > > running a search and compare (<paramName>.lower() based compare?).
>
> > > Any ideas or precedence?
>
> > Ideas? Don't do that...
>
> > Seriously: where does that code come from, who's typing it? If it is python,
> > then make people follow python's rules. If it is some sort of homebrewn
> > language you map to python, adapt the mapper to enforce lower-case and make
> > all your properties lower case.
>
> > Diez
>
>

So, this application you are writing for allows you to script/write
callbacks in python? They are then somehow accessable through a COM
interface exposed by the application? You are worried that someone
using the application will run into case-sensitivity if they access
the code written in python?

There isn't much overhead with __getattr__ since it is _only_ called
if the initial look-up didn't find the name. You can do something like
this:

class C(object):
    def __init__(self, ...):
        ...
        self._lookingup = False
        ...

    # If this is re-entered while already looking up a value,
    # then we know that there is a problem. Not thread safe.
    def __getattr__(self, attr):
        try:
            if self._lookingup:
                raise AttributeError("'C' object has no attribute
%r"%attr)
            self._lookingup = True
            return getattr(self, attr.lower())
        finally:
            self._lookingup = False


    def __setattr__(self, attr, value):
        super(C, self).__setattr__(attr.lower(), value)

Matt



More information about the Python-list mailing list