473,738 Members | 6,332 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Making class attributes non-case-sensitive?

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>.lo wer() based compare?).

Any ideas or precedence?
Cheers,

- Rafe
Oct 13 '08 #1
11 6254
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>.lo wer() 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
Oct 13 '08 #2
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...@nospam.w eb.dewrote:
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>.lo wer() 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
Oct 13 '08 #3
Rafe 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?
I still don't get the full picture - anyway, what I infer is this:

- for your own sake, you want to stick with "proper" naming, whatever that
means

- you can't control what will be called.

Then I'd go with the __getattr__-way, plus maybe a meta-class (or
postprocessing) that maps all attributes to a lower-case-variant as well,
so that the lookup is efficient.

Does that help?

Diez

Oct 13 '08 #4
On Oct 13, 10:11 am, Rafe <rafesa...@gmai l.comwrote:
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>.lo wer() based compare?).

Any ideas or precedence?
If you define '__getattr__' then it will only be called for attribute
names that don't exist. So only explicitly define the names you want
in the lowercase variant and then have something like the following:

def __getattr__(sel f, name):
return object.__getatt r__(self, name.lower())

That way each name only appears once and you only get the extra
'__getattr__' in your epydoc docs.

Michael

>
Cheers,

- Rafe
--
http://www.ironpythoninaction.com/
Oct 13 '08 #5
On Mon, 13 Oct 2008 04:08:03 -0700 (PDT), Rafe <ra*******@gmai l.comwrote:
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,
[snip]
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.
[Much other stuff I didn't understand is snipped here.]

I apologize in advance if this appears unhelpful. I
couldn't make hide nor hair of the above explanation.

The apparent requirement that there be no boundary between
the software's developers (who presumably are trained and
can learn case conventions) and its users is a completely
new one to me. Can you possibly make such software
reliable? Doesn't this open you up to the mother of all SQL
injection attacks? I really would like to understand the
circumstances in which "Keep the users out of the code" (or,
pretty much equivalent, "Don't let the implementation
language drive the user interface") isn't the right answer.

--
To email me, substitute nowhere->spamcop, invalid->net.
Oct 13 '08 #6
On Oct 13, 4:08*am, Rafe <rafesa...@gmai l.comwrote:
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...@nospam.w eb.dewrote:
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>.lo wer() 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__(sel f, 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__(sel f, attr, value):
super(C, self).__setattr __(attr.lower() , value)

Matt
Oct 13 '08 #7
I really appreciate the replies. I hope you gyus will stick with me
through one more round.

super(C, self).__setattr __(attr.lower() , value)

Unfortunately, this will not work because an attribute name such as
"getObject" is legal (I'll explain the convention in a moment.) I
think I would have to loop over all attributes and force both sides of
the compare to lower case to test for a match.

just skip ahead to the example code if you don't want more confusing
background ;)
Bear with me while I try to explain.

Basically, I am working with this application like (I think) any
application would work through a COM object. That said, I can access
python from within the application as well because it is a kind of dev
environment. 3D applications are blended GUI and development
environment and users are expected to use it through both the API and
the GUI. What may seem strange to most people here, is that you will
get hard-core programmers and surface-level users (and everything in
between, like me) working and/or developing in the same environment.
These 3D software applications are quite large and complex.

The application is called "Softimage|XSI" , commonly called "XSI". It
is a 3D application. Most companies will licenses the software but
then build layers on top of it for pipeline productivity and
communication reasons. So, it is standard for a user of the
application to also write scripts or more complex OO models. I
mentioned it was written during the brief period of time where
Softimage was owned by Microsoft because I thought there might be some
precedence for the case sensitivity issues. It was not written by
Microsoft engineers directly, but they did enforce *some* standards.
The common naming convention in XSI is (using PEP008 terminology)
"CapitalizedWor ds" for objects and functions/methods, and "mixedCase"
for variables: This is from the C++ API:

C++ Example: connecting to XSI
// gets the application object, which you can use to communicate
with XSI
Application app;
app.LogMessage( "Welcome to XSI!" );

C++ Example: creating an X3DObject
// returns the reference root object
namespace XSI;
Application app;
CRef rootRef = app.GetActiveSc eneRoot();

// create object with a reference object
X3DObject rootObj(rootRef );

The python version of the above C++ example looks like this.
from win32com.client .dynamic import Dispatch
XSI = Dispatch('XSI.A pplication').Ap plication
XSI.LogMessage( "Welcome to XSI!")
root = XSI.ActiveScene Root
As for the convention I chose, it is right out of PEP008.
"Function Names

Function names should be lowercase, with words separated by
underscores
as necessary to improve readability.

mixedCase is allowed only in contexts where that's already the
prevailing style (e.g. threading.py), to retain backwards
compatibility."

Too keep my code in line with XSI's API, I took this second part to
hear. All other conventions are in line with PEP008 I believe. Lastly,
though I can see how this might sound confusing, I stick with the XSI
API convension exactly when accessing it directly("Capit alizedWords"),
but anything I write is PEP008 with mixedCase.

The most important part of all this though is my original issue. For
some reason, the XSI implementation is not case sensitive. This
works!...

from win32com.client .dynamic import Dispatch
XSI = Dispatch('XSI.A pplication').Ap plication
XSI.LogMessage( "Welcome to XSI!")
XSI.loGmeSSAGE( "Welcome to XSI!")
This is probably totally usless info for this discussion (like I
haven't already provided enough of that!), but the XSI API, or object
model, is a little like a complex XML DOM tree...

obj = XSI.Dictionary. GetObject("my3D Object")
children = obj.Children
for child in children:
XSI.LogMessage( child.Name)
To wrap and override the 'name' attribute I use this class. (Note I
had some trouble with __setattr__ but this IS stable. I welcome
comments as this is probably one of the most confusing things to work
with for new python users.)
class DelegationWrapp er(object):
"""
This is a new-style base class that allows python to extend, or
override
attributes of a given X3DObject.

:parameters:
obj : object instance
If this class (or a sub-class of this class) do not have
an
attribute, this wrapped object will be checked before
failing.
"""
def __init__(self, obj):
"""
Store the object to delegate to.
"""
self.__obj = obj
def __repr__(self):
"""
Makes the object's name the string representation of the
object, just
like XSI does.
"""
return str(self.__obj. name)
def __getattr__(sel f, name):
"""
Tries to delegate any attribute calls not found in this class
to the
X3DObject.
"""
# Try to delegate to the 3DObject.
obj = self.__dict__["__obj"]
try:
return obj.__getattr__ (name)
except:
pass

# Raise an attribute error (Python requires this to avoid
problems)
className = self.__class__. __name__
raise AttributeError( "%s has no attribute '%s'." % (className,
name))
def __setattr__(sel f, name, val):
"""
Tries to delegate any attribute assignment not found in this
class to
the X3DObject.
"""
# This allows sub-classes to add "private" attributes freely.
# dir is checked insteaf od __dict__ because it contains bound
# attributes not available in the instance __dict__.
if name in dir(self) or name.startswith ("_"):
object.__setatt r__(self, name, val)
return

# Try to delegate to the X3DObject.
try:
self.__dict__["__obj"].__setattr__(na me, val)
return
except TypeError, err:
raise TypeError(err)
except AttributeError:
pass # raised later
except Exception, err:
raise Exception(err)

# Don't allow addition of new 'public' attributes with
AttributeError
className = self.__class__. __name__
raise AttributeError( "%s has no attribute '%s'." % (className,
name))
@property
def name(self):
"""
This doesn't do anything here, but in my real code it does.
The
problem is, if the user types 'Name' this will be bypassed.
"""
return self.__obj.Name

So is iterating through dir() to force both the members of dir(), and
the requested attribute name, to lower case for a comparison, really
the easiest way?

Thanks again for sticking with me. I hope I didn't add to the
confusion. What I learn I will of course pass on.

- Rafe


On Oct 14, 12:14*am, Matimus <mccre...@gmail .comwrote:
On Oct 13, 4:08*am, Rafe <rafesa...@gmai l.comwrote:
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...@nospam.w eb.dewrote:
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__, butI
I am concerned about the overhead of every delegated attribute call
running a search and compare (<paramName>.lo wer() 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__(sel f, 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__(sel f, attr, value):
* * * * super(C, self).__setattr __(attr.lower() , value)

Matt
Oct 14 '08 #8
I'm not sure what went wrong with the formatting in my last post. my
code is under 80 characters wide. Here is a more narrow copy and
paste...

class DelegationWrapp er(object):
"""
This is a new-style base class that allows python to
extend, or override attributes of a given X3DObject.

:parameters:
obj : object instance
If this class (or a sub-class of this class) do
not have an attribute, this wrapped object will
be checked before failing.
"""
def __init__(self, obj):
"""
Store the object to delegate to.
"""
self.__obj = obj
def __repr__(self):
"""
Makes the object's name the string representation
of the object, just like XSI does.
"""
return str(self.__obj. name)
def __getattr__(sel f, name):
"""
Tries to delegate any attribute calls not found in
this class to the X3DObject.
"""
# Try to delegate to the 3DObject.
obj = self.__dict__["__obj"]
try:
return obj.__getattr__ (name)
except:
pass

# Raise an attribute error (Python requires this
# to avoid problems)
className = self.__class__. __name__
msg = "%s has no attribute '%s'." % (className, name)
raise AttributeError( msg)
def __setattr__(sel f, name, val):
"""
Tries to delegate any attribute assignment not found
in this class to the X3DObject.
"""
# This allows sub-classes to add "private" attributes
# freely. dir is checked insteaf od __dict__ because
# it contains bound attributes not available in the
# instance __dict__.
if name in dir(self) or name.startswith ("_"):
object.__setatt r__(self, name, val)
return

# Try to delegate to the X3DObject.
try:
self.__dict__["__obj"].__setattr__(na me, val)
return
except TypeError, err:
raise TypeError(err)
except AttributeError:
pass # raised later
except Exception, err:
raise Exception(err)

# Don't allow addition of new 'public' attributes
# with AttributeError
className = self.__class__. __name__
msg = "%s has no attribute '%s'." % (className, name)
raise AttributeError( msg)
@property
def name(self):
"""
This doesn't do anything here, but in my real code it
does. The problem is, if the user types 'Name' this
will be bypassed.
"""
return self.__obj.Name
- Rafe


On Oct 14, 11:29*am, Rafe <rafesa...@gmai l.comwrote:
I really appreciate the replies. I hope you gyus will stick with me
through one more round.

super(C, self).__setattr __(attr.lower() , value)

Unfortunately, this will not work because an attribute name such as
"getObject" is legal (I'll explain the convention in a moment.) I
think I would have to loop over all attributes and force both sides of
the compare to lower case to test for a match.

just skip ahead to the example code if you don't want more confusing
background ;)

Bear with me while I try to explain.

Basically, I am working with this application like (I think) any
application would work through a COM object. That said, I can access
python from within the application as well because it is a kind of dev
environment. 3D applications are blended GUI and development
environment and users are expected to use it through both the API and
the GUI. What may seem strange to most people here, is that you will
get hard-core programmers and surface-level users (and everything in
between, like me) working and/or developing in the same environment.
These 3D software applications are quite large and complex.

The application is called "Softimage|XSI" , commonly called "XSI". It
is a 3D application. Most companies will licenses the software but
then build layers on top of it for pipeline productivity and
communication reasons. So, it is standard for a user of the
application to also write scripts or more complex OO models. I
mentioned it was written during the brief period of time where
Softimage was owned by Microsoft because I thought there might be some
precedence for the case sensitivity issues. It was not written by
Microsoft engineers directly, but they did enforce *some* standards.

The common naming convention in XSI is (using PEP008 terminology)
"CapitalizedWor ds" for objects and functions/methods, and "mixedCase"
for variables: This is from the C++ API:

C++ Example: connecting to XSI
* * // gets the application object, which you can use to communicate
with XSI
* * Application app;
* * app.LogMessage( "Welcome to XSI!" );

C++ Example: creating an X3DObject
* * // returns the reference root object
* * namespace XSI;
* * Application app;
* * CRef rootRef = app.GetActiveSc eneRoot();

* * // create object with a reference object
* * X3DObject rootObj(rootRef );

The python version of the above C++ example looks like this.
* * from win32com.client .dynamic import Dispatch
* * XSI = Dispatch('XSI.A pplication').Ap plication
* * XSI.LogMessage( "Welcome to XSI!")
* * root = XSI.ActiveScene Root

As for the convention I chose, it is right out of PEP008.
"Function Names

* * * Function names should be lowercase, with words separated by
underscores
* * * as necessary to improve readability.

* * * mixedCase is allowed only in contexts where that's already the
* * * prevailing style (e.g. threading.py), to retain backwards
compatibility."

Too keep my code in line with XSI's API, I took this second part to
hear. All other conventions are in line with PEP008 I believe. Lastly,
though I can see how this might sound confusing, I stick with the XSI
API convension exactly when accessing it directly("Capit alizedWords"),
but anything I write is PEP008 with mixedCase.

The most important part of all this though is my original issue. For
some reason, the XSI implementation is not case sensitive. This
works!...

from win32com.client .dynamic import Dispatch
XSI = Dispatch('XSI.A pplication').Ap plication
XSI.LogMessage( "Welcome to XSI!")
XSI.loGmeSSAGE( "Welcome to XSI!")

This is probably totally usless info for this discussion (like I
haven't already provided enough of that!), but the XSI API, or object
model, is a little like a complex XML DOM tree...

obj = XSI.Dictionary. GetObject("my3D Object")
children = obj.Children
for child in children:
* * XSI.LogMessage( child.Name)

To wrap and override the 'name' attribute I use this class. (Note I
had some trouble with __setattr__ but this IS stable. I welcome
comments as this is probably one of the most confusing things to work
with for new python users.)

class DelegationWrapp er(object):
* * """
* * This is a new-style base class that allows python to extend, or
override
* * attributes of a given X3DObject.

* * :parameters:
* * * * obj : object instance
* * * * * * If this class (or a sub-class of this class) do not have
an
* * * * * * attribute, this wrapped object will be checked before
failing.
* * """
* * def __init__(self, obj):
* * * * """
* * * * Store the object to delegate to.
* * * * """
* * * * self.__obj = obj

* * def __repr__(self):
* * * * """
* * * * Makes the object's name the string representation of the
object, just
* * * * like XSI does.
* * * * """
* * * * return str(self.__obj. name)

* * def __getattr__(sel f, name):
* * * * """
* * * * Tries to delegate any attribute calls not found in this class
to the
* * * * X3DObject.
* * * * """
* * * * # Try to delegate to the 3DObject.
* * * * obj = self.__dict__["__obj"]
* * * * try:
* * * * * * return obj.__getattr__ (name)
* * * * except:
* * * * * * pass

* * * * # Raise an attribute error (Python requires this to avoid
problems)
* * * * className = self.__class__. __name__
* * * * raise AttributeError( "%s has no attribute '%s'." % (className,
name))

* * def __setattr__(sel f, name, val):
* * * * """
* * * * Tries to delegate any attribute assignment not found in this
class to
* * * * the X3DObject.
* * * * """
* * * * # This allows sub-classes to add "private" attributes freely.
* * * * # dir is checked insteaf od __dict__ because it contains bound
* * * * # attributes not available in the instance __dict__.
* * * * if name in dir(self) or name.startswith ("_"):
* * * * * * object.__setatt r__(self, name, val)
* * * * * * return

* * * * # Try to delegate to the X3DObject.
* * * * try:
* * * * * * self.__dict__["__obj"].__setattr__(na me, val)
* * * * * * return
* * * * except TypeError, err:
* * * * * * raise TypeError(err)
* * * * except AttributeError:
* * * * * * pass * # raised later
* * * * except Exception, err:
* * * * * * raise Exception(err)

* * * * # Don't allow addition of new 'public' attributes with
AttributeError
* * * * className = self.__class__. __name__
* * * * raise AttributeError( "%s has no attribute '%s'." % (className,
name))

* * @property
* * def name(self):
* * * * """
* * * * This doesn't do anything here, but in my real code it does.
The
* * * * problem is, if the user types 'Name' this will be bypassed.
* * * * """
* * * * return self.__obj.Name

So is iterating through dir() to force both the members of dir(), and
the requested attribute name, to lower case for a comparison, really
the easiest way?

Thanks again for sticking with me. I hope I didn't add to the
confusion. What I learn I will of course pass on.

- Rafe

On Oct 14, 12:14*am, Matimus <mccre...@gmail .comwrote:
On Oct 13, 4:08*am, Rafe <rafesa...@gmai l.comwrote:
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...@nospam.w eb.dewrote:
Rafe wrote:
Hi,
I'm working within an application (making a lot of wrappers), butthe
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 getan
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>.lo wer() based compare?)..
Any ideas or precedence?
Ideas? Don't do that...

...

read more »
Oct 14 '08 #9
[I posted a version of the following but it contained a broken
example. I deleted it through GoogleGroups, but I'm adding this
message in case the old version is still visible on the list. If it
isn't ignore this.]
I really appreciate the replies. I hope you guys will stick with me
through one more round.

super(C, self).__setattr __(attr.lower() , value)

Unfortunately, this will not work because an attribute name such as
"getObject" is legal (I'll explain the convention in a moment.) I
think I would have to loop over all attributes and force both sides of
the compare to lower case to test for a match.

just skip ahead to the example code if you don't want more confusing
background ;)

Bear with me while I try to explain.

Basically, I am working with this application like (I think) any
application would work through a COM object. That said, I can access
python from within the application as well because it is a kind of dev
environment. 3D applications are blended GUI and development
environment and users are expected to use it through both the API and
the GUI. What may seem strange to most people here, is that you will
get hard-core programmers and surface-level users (and everything in
between, like me) working and/or developing in the same environment.
These 3D software applications are quite large and complex.

The application is called "Softimage|XSI" , commonly called "XSI". It
is a 3D application. Most companies will licenses the software but
then build layers on top of it for pipeline productivity and
communication reasons. So, it is standard for a user of the
application to also write scripts or more complex OO models. I
mentioned it was written during the brief period of time where
Softimage was owned by Microsoft because I thought there might be some
precedence for the case sensitivity issues. It was not written by
Microsoft engineers directly, but they did enforce *some* standards.

The common naming convention in XSI is (using PEP008 terminology)
"CapitalizedWor ds" for objects and functions/methods, and "mixedCase"
for variables: This is from the C++ API:

C++ Example: connecting to XSI
// gets the application object, which you can use to communicate
// with XSI
Application app;
app.LogMessage( "Welcome to XSI!" );

C++ Example: creating an X3DObject
// returns the reference root object
namespace XSI;
Application app;
CRef rootRef = app.GetActiveSc eneRoot();

// create object with a reference object
X3DObject rootObj(rootRef );

The python version of the above C++ example looks like this.
from win32com.client .dynamic import Dispatch
XSI = Dispatch('XSI.A pplication').Ap plication
XSI.LogMessage( "Welcome to XSI!")
root = XSI.ActiveScene Root

As for the convention I chose, it is right out of PEP008.
"Function Names

Function names should be lowercase, with words separated by
underscores as necessary to improve readability.

mixedCase is allowed only in contexts where that's already the
prevailing style (e.g. threading.py), to retain backwards
compatibility."

Too keep my code in line with XSI's API, I took this second part to
hear. All other conventions are in line with PEP008 I believe. Lastly,
though I can see how this might sound confusing, I stick with the XSI
API convension exactly when accessing it directly("Capit alizedWords"),
but anything I write is PEP008 with mixedCase.

The most important part of all this though is my original issue. For
some reason, the XSI implementation is not case sensitive. This
works!...

from win32com.client .dynamic import Dispatch
XSI = Dispatch('XSI.A pplication').Ap plication
XSI.LogMessage( "Welcome to XSI!")
XSI.loGmeSSAGE( "Welcome to XSI!")

This is probably totally usless info for this discussion (like I
haven't already provided enough of that!), but the XSI API, or object
model, is a little like a complex XML DOM tree...

obj = XSI.Dictionary. GetObject("my3D Object")
children = obj.Children
for child in children:
XSI.LogMessage( child.Name)

To wrap and override the 'name' attribute I use this class. (Note I
had some trouble with __setattr__ but this IS stable. I welcome
comments as this is probably one of the most confusing things to work
with for new python users.)
class DelegationWrapp er(object):
"""
This is a new-style base class that allows python to
extend, or override attributes of a given X3DObject.

:parameters:
obj : object instance
If this class (or a sub-class of this class) do
not have an attribute, this wrapped object will
be checked before failing.
"""
def __init__(self, obj):
"""
Store the object to delegate to.
"""
self.__obj = obj
def __repr__(self):
"""
Makes the object's name the string representation
of the object, just like XSI does.
"""
return str(self.__obj. name)
def __getattr__(sel f, name):
"""
Tries to delegate any attribute calls not found in
this class to the X3DObject.
"""
# Try to delegate to the 3DObject.
obj = self.__dict__["_DelegationWra pper__obj"]
try:
return getattr(obj, name)
except:
pass

# Raise an attribute error (Python requires this
# to avoid problems)
className = self.__class__. __name__
msg = "%s has no attribute '%s'." % (className, name)
raise AttributeError( msg)
def __setattr__(sel f, name, val):
"""
Tries to delegate any attribute assignment not found
in this class to the X3DObject.
"""
# This allows sub-classes to add "private" attributes
# freely. dir is checked insteaf od __dict__ because
# it contains bound attributes not available in the
# instance __dict__.
if name in dir(self) or name.startswith ("_"):
super(Delegatio nWrapper, self).__setattr __(name, val)
return

# Try to delegate to the X3DObject.
obj = self.__dict__["_DelegationWra pper__obj"]
try:
obj.__setattr__ (name, val)
return
except TypeError, err:
raise TypeError(err)
except AttributeError:
pass # raised later
except Exception, err:
raise Exception(err)

# Don't allow addition of new 'public' attributes
# with AttributeError
className = self.__class__. __name__
msg = "%s has no attribute '%s'." % (className, name)
raise AttributeError( msg)
def set_name(self, val):
self.__obj.name = val

def get_name(self):
return self.__obj.name

name = property(get_na me, set_name)
# Usage...
class A(object):
name = "a name"
test = "a test"

a = A()
b = DelegationWrapp er(a)
print b.name
print b.test
b.name = "new name"
print b.name

So is iterating through dir() to force both the members of dir(), and
the requested attribute name, to lower case for a comparison, really
the easiest way?

Thanks again for sticking with me. I hope I didn't add to the
confusion. What I learn I will of course pass on.

- Rafe

On Oct 14, 12:14*am, Matimus <mccre...@gmail .comwrote:
On Oct 13, 4:08*am, Rafe <rafesa...@gmai l.comwrote:
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...@nospam.w eb.dewrote:
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__, butI
I am concerned about the overhead of every delegated attribute call
running a search and compare (<paramName>.lo wer() 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__(sel f, 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__(sel f, attr, value):
* * * * super(C, self).__setattr __(attr.lower() , value)

Matt
Oct 14 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

50
6362
by: Dan Perl | last post by:
There is something with initializing mutable class attributes that I am struggling with. I'll use an example to explain: class Father: attr1=None # this is OK attr2= # this is wrong def foo(self, data): self.attr1=data self.attr2.append(data) The initialization of attr1 is obviously OK, all instances of Father redefine it in the method foo. But the initialization of attr2 is wrong
166
8642
by: Graham | last post by:
This has to do with class variables and instances variables. Given the following: <code> class _class: var = 0 #rest of the class
10
6361
by: Paschalis Pagonidis | last post by:
Hi, I have a class which all its attributes, properties and methods are static. However, I want a method to return an object that should be non-static. Is that possible?
90
4400
by: Ben Finney | last post by:
Howdy all, How can a (user-defined) class ensure that its instances are immutable, like an int or a tuple, without inheriting from those types? What caveats should be observed in making immutable instances? -- \ "Love is the triumph of imagination over intelligence." -- |
12
2134
by: tobias.sturn | last post by:
Hi! My prof told me always to make my members private or protected cause its standard to write setter and getter methodes.. Is that in your opinion correct? Cause I dont see any adventages to write a member of a class private if there are no side effects in changing the variable. I think you only have to write more (the getter and setters) the code gets bigger... Thanks very much!
0
999
by: Slim | last post by:
I have page that takes some counties from a database and builds a table adding a cell with a button to each row. I have attached a event to each button when clicked it builds a second table that shows the states from that country. This works fine, but in turn when you click on a stateit should build a third table of golf courses from that state. but when i click on a state i dont get third table, in fact i lose the states table and end up...
84
15887
by: Peter Olcott | last post by:
Is there anyway of doing this besides making my own string from scratch? union AnyType { std::string String; double Number; };
1
2353
by: =?ISO-8859-1?Q?Ricardo_Ar=E1oz?= | last post by:
That is self.__attributes Been reading about the reasons to introduce them and am a little concerned. As far as I understand it if you have a class that inherits from two other classes which have both the same name for an attribute then you will have a name clash because all instance attributes "wind up in the single instance object at the bottom of the class tree". Now I guess this means that in any real OOP project you'd better use...
16
2412
by: Andrea Gavana | last post by:
Hi Diez & All, Do you mind explaining "why" you find it *buttugly*? I am asking just out of curiosity, obviously. I am so biased towards wxPython that I won't make any comment on this thread in particular, but I am curious to know why some people find it "ugly" or "bad" or whatever. It has its own bugs and missing features, of course, but it is one of the major GUI player in the arena, together with PyQt and PyGTK.
50
4492
by: Juha Nieminen | last post by:
I asked a long time ago in this group how to make a smart pointer which works with incomplete types. I got this answer (only relevant parts included): //------------------------------------------------------------------ template<typename Data_t> class SmartPointer { Data_t* data; void(*deleterFunc)(Data_t*);
0
8968
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8787
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9208
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8208
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6750
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6053
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4569
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3279
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2744
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.