Thread: Re: [Orbit-python-list] Uploaded patch
Status: Inactive
Brought to you by:
tack
|
From: Duncan G. <dg...@uk...> - 2000-08-16 12:32:56
|
On Tuesday 15 August, Jason Tackaberry wrote: I was the one who asked about standards compliance in comp.lang.python. I'm also the author of omniORBpy, which fully adheres to the mapping. I think the value of the standard is being severely weakened by the fact that none of the other Python ORBs support it. I believe that this disagreement between ORBs will put people off from using Python with CORBA. Please don't interpret this email as an attempt to get people to use omniORBpy. I would genuinely like to see ORBit-Python improve in all ways, including its standards support. The more good Python ORBs there are, the more incentive there is for all of us to keep improving them. > I do address this (somewhat) in my thesis document. In short, yes I do > wish to make the mappings OMG compliant where it makes sense. I seem to > recall some of the mappings in the specification not making sense for the > approach I took (dynamic IDL). The only thing I can see that potentially causes difficulty is the mapping requirement that IDL module "M" can be accessed from Python with "import M". One way around this is to write small modules which do nothing but call CORBA.load_idl(). A simple IDL compiler fragment which just wrote such modules would comply with the mapping requirement, while keeping the general dynamic IDL approach. > Some things will be easy to implement, such as the attribute accessor > pairs. I read some discussions on why one should favor accessor functions > versus operator overloading, but these arguments just don't apply to > ORBit-Python because of its dynamic approach. I do discuss this in my > thesis paper, so it may be worth reading (the latter two chapters) for > my rationale. In the end, I wish to have both methods. I can imagine > there are pretty good arguments for just using the accessor pairs, but > the current method is just damn cool and just as efficient. I've read your thesis, and I think you have slightly missed the intention of IDL attributes. Attributes in IDL are explicitly _not_ simply data members of the object -- they are a shorthand for specifying a get/set pair of operations (or just a get in the case of readonly attributes). It should be possible for a servant to do anything it likes in response to the getting or setting of an attribute. That is not (easily) possible to do with the current ORBit-Python mapping. It is also my personal opinion that it's confusing to the programmer that an innocent-looking piece of Python code like obj.value = 10 involves a remote call, and can raise any of the CORBA system exceptions. I think it's far better to make it look like what it is: a method invocation. Cheers, Duncan. -- -- Duncan Grisby \ Research Engineer -- -- AT&T Laboratories Cambridge -- -- http://www.uk.research.att.com/~dpg1 -- |
|
From: Duncan G. <dg...@uk...> - 2000-08-16 15:44:12
|
On Wednesday 16 August, Jason Tackaberry wrote:
> But it also means you have to carry around excess baggage, which is one of
> the nicely avoided by dynamic IDL. While I'll concede this is going to
> require some hack, I'd prefer whatever hack we choose to be simple and
> minimally intrusive.
Why are Python modules considered excess baggage when the IDL itself
isn't? As Martin von Loewis (the main author of the Python mapping)
asks in comp.lang.python, how do you find the IDL file referenced by
CORBA.load_idl("naming.idl")
Do you look on PYTHONPATH? Some other IDL search path? Just the
current directory? What about files #included in the file you load?
I'm not saying that dynamic loading of IDL is always wrong (I've
implemented it for omniORBpy after all), just that it isn't always
ideal.
> A small degree of source editing is required to use a different ORB
> anyway (for example by changing the 'from ORB import CORBA' line), so I
> could require that CORBA.load_idl be invoked immediately after importing
> the CORBA module, and then override import (using __import__) to ignore
> modules that exist from the IDLs. So, something like:
The mapping standard says that it must be possible to do just "import
CORBA", and get the default CORBA installation, so with compliant ORBs
you do not need to change any code at all. This is one aspect of the
Python mapping which caused headaches for me with omniORBpy, since
it's geared towards the "from omniORB import CORBA" style. I have to
do a bit of cunning module manipulation to support "import CORBA".
That aside, you don't need to modify import's behaviour at all. As
long as load_idl puts the modules in sys.modules, future imports for
those modules will use the ones which have already been loaded.
[...attributes...]
> > involves a remote call, and can raise any of the CORBA system
> > exceptions. I think it's far better to make it look like what it is: a
> > method invocation.
>
> Well I'd considered this, but I think the elegance, simplicity, and
> readability of the 'interface.attr = foo' approach are good arguments as
> well, and I would favor this when using ORBit-Python for situations where
> using ORBit makes sense (in a Gnome application, say). All the arguments
> are perfectly legit, and I admit I'm a little torn about the issue.
My argument is that "interface.attr = foo" is _less_ readable than
"interface._set_attr(foo)", since the former does not make it clear
that an operation invocation is being made.
Take the following piece of code:
obj.foo = 1
obj.foo = obj.foo + 2
print obj.foo
What does it do? At first glance, most people would assume that it
prints 3. But if obj is a CORBA object, there is no way of telling,
because the get and set operations underlying the attribute may not be
treating it like a genuine data member. Even if it is just a data
member, some other client might concurrently modify the attribute at
any stage between the four remote calls.
Of course, Python is flexible enough that all the same problems can
arise in a single non-CORBA program, if you design classes which are
sufficiently perverse and use threads. But people don't do that --
it's not the Python way. It just makes code hard to understand. Now
consider the following code:
obj._set_foo(1)
obj._set_foo(obj._get_foo() + 2)
print obj._get_foo()
Much more ugly, I agree. But how many people would assume that it
prints 3? It's much more obvious that something other than simple
assignment is going on. I think that is a good thing, and worth the
uglifying syntax.
Anyway, enough of my ranting.
Cheers,
Duncan.
--
-- Duncan Grisby \ Research Engineer --
-- AT&T Laboratories Cambridge --
-- http://www.uk.research.att.com/~dpg1 --
|
|
From: Jason T. <ta...@li...> - 2000-08-16 16:43:57
|
> Why are Python modules considered excess baggage when the IDL itself
> isn't?
Well, better worded as "seemingly unnecessary excess baggage." I think
there might be a cleaner solution to the problem, that's all. In case
there isn't, though, I'm willing to do whatever's necessary to adhere to
the mapping specification. I do think it's important.
> As Martin von Loewis (the main author of the Python mapping)
> asks in comp.lang.python, how do you find the IDL file referenced by
>
> CORBA.load_idl("naming.idl")
>
> Do you look on PYTHONPATH? Some other IDL search path? Just the
> current directory? What about files #included in the file you load?
This is one of those unresolved issues that I decided to worry about
"later" while writing it. I knew right away that load_idl() was a hack,
but it seemed the most obvious approach for dynamic IDL loading, and it's
also the way Owen Taylor's CORBA::ORBit (perl bindings) implemented it,
from which ORBit-Python was heavily based.
> I'm not saying that dynamic loading of IDL is always wrong (I've
> implemented it for omniORBpy after all), just that it isn't always
> ideal.
Well, ORBit-Python has no idl compiler, and I don't see that changing
soon (I've no motivation to write one), so I'll have to find some way to
massage this approach into complying with a specification that was written
with other intentions.
It does sound as though some magic is going to have to happen when importing
the CORBA module. Suppose it fetches some sort of dictionary of IDL
modules that maps module and interface names to IDL files. Then when
importing a module, it could first check this dictionary and call load_idl()
if such a mapping exists. Of course there's lots of problems with this sort
of approach. Either it means some sort of specific registry that users
will have to add IDL files to, or it means some overhead to scan through
known IDL directories to generate this mapping at runtime.
> The mapping standard says that it must be possible to do just "import
> CORBA", and get the default CORBA installation, so with compliant ORBs
I suppose that means installing a new ORB will clobber the existing CORBA
module?
> you do not need to change any code at all. This is one aspect of the
> Python mapping which caused headaches for me with omniORBpy, since
> it's geared towards the "from omniORB import CORBA" style. I have to
What headaches has it caused? Why wouldn't just a simple wrapper to import
omniORB.CORBA work?
> Much more ugly, I agree. But how many people would assume that it
> prints 3? It's much more obvious that something other than simple
> assignment is going on. I think that is a good thing, and worth the
> uglifying syntax.
Since ORBit-Python implements the accessor pairs now, users will have a
choice. And your arguments are strong ones in favor of using that style,
but so long as both methods are available, I think everyone will be happy.
:)
Anyway, it may be worth it for me to post these issues to comp.lang.python
and spark a discussion. I'm humble enough to take advice from people who
know much more than I do. :)
Jason.
|
|
From: Duncan G. <dg...@uk...> - 2000-08-18 11:35:41
|
> > The mapping standard says that it must be possible to do just "import > > CORBA", and get the default CORBA installation, so with compliant ORBs > > I suppose that means installing a new ORB will clobber the existing CORBA > module? Yes, to the extent that "import CORBA" will now get the new ORB. If all the ORBs stick to the "from foo import CORBA" practice, and use a wrapper module to support "import CORBA", all installed ORBs will still be available for programs which care. > > you do not need to change any code at all. This is one aspect of the > > Python mapping which caused headaches for me with omniORBpy, since > > it's geared towards the "from omniORB import CORBA" style. I have to > > What headaches has it caused? Why wouldn't just a simple wrapper to import > omniORB.CORBA work? Maybe "headache" is too strong a word. It isn't a good idea for CORBA.py to just say "from omniORB.CORBA import *", firstly because omniORB.CORBA contains some important items prefixed with underscores, which do not get imported with import *. Secondly, that approach wastes memory since it fills a second dictionary with the names of the module's contents. omniORBpy's CORBA.py actually looks like import sys, omniORB.CORBA sys.modules["CORBA"] = omniORB.CORBA which is a bit of a dirty hack. It's a module which replaces itself while it's still being imported. > Anyway, it may be worth it for me to post these issues to comp.lang.python > and spark a discussion. I'm humble enough to take advice from people who > know much more than I do. :) Maybe. It might be better to discuss it in do...@py.... Unfortunately, now that the Python mapping is an official CORBA standard, it's pretty much set in stone. It can be extended or fixed for bugs, but it will be very hard to have it changed. Cheers, Duncan. -- -- Duncan Grisby \ Research Engineer -- -- AT&T Laboratories Cambridge -- -- http://www.uk.research.att.com/~dpg1 -- |
|
From: Duncan G. <dg...@uk...> - 2000-08-18 15:41:24
|
On Friday 18 August, Jason Tackaberry wrote:
> First, for interfaces that are not encompassed in modules, I notice that
> you use a _GlobalIDL module. I didn't see this point addressed in the
> mapping specification, so I assume this is a solution specific to omniORBpy?
Well, the specification actually says
"Other global definitions (except modules) appear in a module whose
name is implementation dependent. Implementations are encouraged to
use the name of the IDL file when defining the name for that
module."
As you say, omniORBpy uses "_GlobalIDL", not the name of the IDL file.
The second sentence I've quoted above was not in drafts of the
mapping, so I followed the precedent set by Fnorb, which also uses
_GlobalIDL.
There is also a technical reason for not doing what it says. I should
probably submit an issue about it to the OMG. Consider two IDL files:
// a.idl
struct S {
long l; string z;
};
// b.idl
#include "a.idl"
interface I {
S op();
};
Now, if we follow the "encouraged" mapping, the definition of struct S
lives in Python module "a", while the definition of interface I lives
in Python module "b". But the definition of interface I relies on the
definition of struct S, which it expects to be in the same module. The
advantage of using a fake module name like "_GlobalIDL" is that
definitions which are in the same IDL scope are always in the same
Python scope.
omniORBpy's IDL compiler has an option to change the global module
name, so you can force it to follow the "encouraged" mapping if you
want to.
> The way I would want to approach the problem is to use the same scoping
> rules as regular modules. So,
>
> interface Echo {
> // ...
> };
>
> I would favor simply:
>
> import Echo
That can't work, since the result of import has to be a Python module.
In the example of an interface declared at global scope, that doesn't
necessarily matter (since the Python mapping for interfaces is
flexible enough that Echo could be a module), but with the struct in
a.idl above, the mapping says that S must be a Python class. I don't
think you can reconcile that with the use of import for things in
global scope.
> Also, the specification seems a little vague about inheritance vs.
> delegation. In particular, I'm not sure if implementing interfaces
> through inheritance is required while delegation is optional, or if you
> can get away with one or the other (or both). I chose delegation because
> inheritance was just too tricky. Deriving a class object created from C
> is impossible, and achieving that functionality would require using something
> like Jim Fulton's ExtensionClass. Delegation was the clear winner for the
> dynamic IDL approach I took. So, if I want to adhere to the specifications,
> is implementation through inheritance required, strongly recommended, or
> optional?
I had always read the mapping as saying that inheritance was
mandatory. However, looking at it again, it does indeed look like it
makes it optional. In fact, it seems to make everything about the
server side mapping optional, which is a bit silly. I think the
_intention_ of the mapping is that inheritance is mandatory, but I'm
not at all sure. At the very least, I would say that it's strongly
recommended. Perhaps you should submit an issue to the OMG (email to
is...@om...) to get it clarified. If you email to do...@py...
too, the people who wrote the mapping will be able to comment.
If the mapping is intended to allow delegation, it fails to specify
the naming scheme for the tie class (or types in your case). That
should be standardised, just as the scheme for skeleton class names is
standardised.
If it turns out that inheritance _is_ mandatory, I don't think it will
be too much of a problem for you. The skeleton class does not have to
be very complicated. My guess is that it wouldn't be too hard to
dynamically create a new class with PyClass_New(), and fill in the
bits you need with the PyObject_... functions, all from C code.
If that's too hairy, you can write Python functions to create classes
for you, and call those functions from C code. omniORBpy does
something similar when it is unmarshalling TypeCodes for structs and
unions which is does not have stubs for -- the C++ code calls the
Python omniORB.createUnknownStruct() and omniORB.createUnknownUnion()
functions. Those functions create new classes and return them back to
C++.
I'm afraid you're discovering that complying with standards is a
rather painful process...
Cheers,
Duncan.
--
-- Duncan Grisby \ Research Engineer --
-- AT&T Laboratories Cambridge --
-- http://www.uk.research.att.com/~dpg1 --
|
|
From: Duncan G. <dg...@uk...> - 2001-04-04 12:05:40
|
On Thu 4 April, Jason Tackaberry wrote:
It's good to see orbit-python back in action. For a while I've felt
that omniORBpy is the only Python ORB going anywhere. Competition is
good :-) .
> The spec defines a base, so that all code written in compliance will be
> portable between any compliant implementation. So this is a good thing.
> The trick is implementing extensions so they don't break the spec, and
> that making sure programmers who use the extensions know they're
> non-compliant. This is one point that'll have to be worked out first.
Indeed. omniORBpy has quite a few extensions to the spec, and I'm in
the process of adding more. The difficulty is, as you say, making sure
that the extensions are clearly distinguished from the standard parts.
Wherever possible, I've put extensions in the omniORB package, so it's
obvious. Other times that's not possible, so I have to resort to
documentation.
If extensions become supported by several ORBs, it will be worth going
through the motions to add them to the official spec.
I've had a quick look at the web site, and I've spotted a couple of
errors about the CORBA mapping...
First, CORBA.ORB.shutdown() should take a boolean argument:
module CORBA {
interface ORB { // PIDL
...
void shutdown(in boolean wait_for_completion);
...
};
};
That omission might well be an omission in ORBit itself, rather than
just orbit-python.
The POA._get_the_POAManager() function is part of the standard, not an
omniORBpy specific thing. The POA's IDL definition contains:
module PortableServer {
...
interface POA {
...
readonly attribute POAManager the_POAManager;
...
};
};
So the Python POA object has a _get_the_POAManager() function.
There are a few other minor things too. I recommend you download the
ORB interface and POA chapters of the CORBA spec and check all the
method signatures.
Cheers,
Duncan.
--
-- Duncan Grisby \ Research Engineer --
-- AT&T Laboratories Cambridge --
-- http://www.uk.research.att.com/~dpg1 --
|
|
From: Jason T. <ta...@li...> - 2001-04-04 12:22:57
|
> It's good to see orbit-python back in action. For a while I've felt > that omniORBpy is the only Python ORB going anywhere. Competition is > good :-) . That's definitely true, but right now I have a lot of catching up to do. :) Although at least ORBit-Python probably beats out the competition in speed and memory usage. > I've had a quick look at the web site, and I've spotted a couple of > errors about the CORBA mapping... I'm sure there are more ... ;) > First, CORBA.ORB.shutdown() should take a boolean argument: Oh right. In fact my implementation requires it. That's an error in documentation. > The POA._get_the_POAManager() function is part of the standard, not an > omniORBpy specific thing. The POA's IDL definition contains: > So the Python POA object has a _get_the_POAManager() function. I have to admit I'm a little embarrassed about that. ;) I never even made the connection. In my own defense, I've been using the transparent accessors, so the _get_/_set_ accessors look a little foreign to me. Thanks for pointing out these errors. I'll make the corrections ASAP. Regards, Jason. |
|
From: Duncan G. <dg...@uk...> - 2001-04-12 10:48:29
|
On Wednesday 11 April, Jason Tackaberry wrote:
> Right now ORBit-Python implements a few extensions, such as transparent
> accessors (through __setattr__ and __getattr__). These extensions don't
> really break the spec since they needn't be used at all. However
> recently I've had a number of requests to implement coercion between
> CORBA.Any and Python objects. This will obviously break the spec in
> the case of CORBA.Any return values.
Interesting. I can see how it's easy to return Python objects when
unmarshalling an Any, but how would you do the marshalling side? How
can you tell if something like "hello" is meant to be a string or a
sequence<octet>, or a sequence<char>, or a 5 element array of octet or
char?
> So I was wondering what the best approach would be to enable such
> proprietary enhancements in ORBit-Python. I see 3 different "modes"
> that would change the way the module behaves:
The modes seem sensible to me.
[...]
> from ORBit import enhanced
> or
> from ORBit import strict
>
> Any comments or thoughts on this approach?
Personally, I don't think that's very nice at all. I don't like the
__future__ thing either. I think it's confusing to re-use the import
mechanism to do something altogether different. I'd be inclined to go
for something like
import ORBit
ORBit.mapping_mode(ORBit.ENHANCED)
or perhaps
ORBit.mapping_mode("enhanced")
Cheers,
Duncan.
--
-- Duncan Grisby \ Research Engineer --
-- AT&T Laboratories Cambridge --
-- http://www.uk.research.att.com/~dpg1 --
|
|
From: Martin v. L. <ma...@lo...> - 2001-04-12 17:14:53
|
> On Wednesday 11 April, Jason Tackaberry wrote:
>
> > Right now ORBit-Python implements a few extensions, such as transparent
> > accessors (through __setattr__ and __getattr__). These extensions don't
> > really break the spec since they needn't be used at all. However
> > recently I've had a number of requests to implement coercion between
> > CORBA.Any and Python objects. This will obviously break the spec in
> > the case of CORBA.Any return values.
>
> Interesting. I can see how it's easy to return Python objects when
> unmarshalling an Any, but how would you do the marshalling side? How
> can you tell if something like "hello" is meant to be a string or a
> sequence<octet>, or a sequence<char>, or a 5 element array of octet or
> char?
OTOH, looking at it from a compatibility perspective, allowing
additional (types for) values as parameters is an extension to the IDL
mapping, thus less troubling than returning the "unpacked" value.
> Personally, I don't think that's very nice at all. I don't like the
> __future__ thing either. I think it's confusing to re-use the import
> mechanism to do something altogether different. I'd be inclined to go
> for something like
>
> import ORBit
> ORBit.mapping_mode(ORBit.ENHANCED)
>
> or perhaps
>
> ORBit.mapping_mode("enhanced")
Isn't that what policies are meant for? So I'd expect something like
p = orb.create_policy(ORBit.ENHANCED)
orb._set_policy_override([p],CORBA.ADD_OVERRIDE)
A specific function is easier to use, of course.
Regards,
Martin
|
|
From: Jason T. <ta...@li...> - 2000-08-16 14:18:39
|
> severely weakened by the fact that none of the other Python ORBs
> support it. I believe that this disagreement between ORBs will put
> people off from using Python with CORBA.
I'm all for working to reach standards compliance. I definitely see the
advantage being able to run python code across different ORBs with few
changes. Unfortunately I fear this is going to require some pretty
horribly ugly hacks.
> with "import M". One way around this is to write small modules which
> do nothing but call CORBA.load_idl(). A simple IDL compiler fragment
> which just wrote such modules would comply with the mapping
> requirement, while keeping the general dynamic IDL approach.
But it also means you have to carry around excess baggage, which is one of
the nicely avoided by dynamic IDL. While I'll concede this is going to
require some hack, I'd prefer whatever hack we choose to be simple and
minimally intrusive.
A small degree of source editing is required to use a different ORB
anyway (for example by changing the 'from ORB import CORBA' line), so I
could require that CORBA.load_idl be invoked immediately after importing
the CORBA module, and then override import (using __import__) to ignore
modules that exist from the IDLs. So, something like:
from ORBit import CORBA # ORB specific
CORBA.load_idls('M.idl', 'foo.idl') # ORB specific
import M # ignored by __import__
import foo # ignored by __import__
Thus, someone who switches from ORBit-Python to omniORBpy, say, can just
change the first line, and delete the second.
> involves a remote call, and can raise any of the CORBA system
> exceptions. I think it's far better to make it look like what it is: a
> method invocation.
Well I'd considered this, but I think the elegance, simplicity, and
readability of the 'interface.attr = foo' approach are good arguments as
well, and I would favor this when using ORBit-Python for situations where
using ORBit makes sense (in a Gnome application, say). All the arguments
are perfectly legit, and I admit I'm a little torn about the issue.
Although, thanks to Roland Mas' efforts, ORBit-Python supports the accessor
pairs now.
Regards,
Jason.
|