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. |