
Beste Paul, Quoting [PFA van Zoolingen] (Aug 08 2008):
All,
To agree on the naming convention for the (implementation independent) specification the Python to Saga language binding, I am starting this thread. I am not a long-time Python programmer so I would like some imput about the following.
I am very likely much less of a python programmer than you, thus please excuse the potential ignortance of my anwer! :-)
All names are taken from the GFD-R-P.90 document, "A Simple API for Grid Applications (SAGA)". Most name rules are taken from the Python Style Guide: http://www.python.org/dev/peps/pep-0008/
Module name: -saga -Examples: saga.File, saga.Flags, saga.Object -Rationale: Less keyboard strokes. Different class names do not conflict. (File.Flags, Namespace.Flags and Replica.Flags are the same. Job.State and Task.State are the same. Only Stream.State conflicts. This could become Stream.StreamState)
Less keystrokes sound great :-) But is that a scalable approach? Saga is organized into packages, with the rationale that additional packages can be defined later on. For example, the job package has the classes description, job, service, and self. We are in the process on adding a checkpoint and recovery package, which kind of extends the core job package, and has the same classes. We would then end up with saga.job_job, saga.job_service, ... saga.cpr_job, saga.cpr_service, ... same amount of typing really. Well, you probably would leave off the prefix for the core package (saga.job, saga.service, ...), but still. Also, several classes/types would sound strange without package as qualifiers: saga.state - state of SAGA? saga.service - what does it do? saga.entry - entry of what?
This means only one saga module, and no specific packages. (Could this be a problem in the future?)
Class name: -Uppercase letters or CapCase convention. Abbreviations in capitols -Example: File(), TaskContainer(), URL(), SeekMode(), NSEntry()
Exception names: -Same as for class names. -Example: NotImplemented(), IncorrectURL(), AlreadyExists()
These are certainly things which should follow the typical language conventions...
Enum types: -GFD-R-P.90 specifies a number of enum types. (Standard) Python does not have enums. So just create classes with numbers within them. -Example: The classes WaitMode, ObjectType, Permission, Flags, SeekMode, IOMode
class State(object): new = 1 running = 2 done = 3 canceled = 4 failed = 5
Function names: -Lowercase with words separated by an underscore. - Rationale: I know, seems strange, but it looks like its Python practice, in most cases. (Some Python modules like StringIO.py don't comply, but pickle.py does.) -Example: Attributes.set_attribute(self, key, value) Context.set_defaults(self) Object.get_session(self)
same here: if that is the way to go in python...
Variable names: -Same as Function names. -Example: State.done (see above), ObjectType().exception
Return types: -All the methods used have a returntype. Most are easily converted from the pseudo-code to Python code, but there are some optimalisations numbers -> int, long, float. boolean -> True, False, String -> String
array <String> -> a List/Tuple (I.E. Attributes.get_vector_attribute()) array <byte> -> String (Buffer.set_data())
I haven't found other cases yet, but the list is probably incomplete.
-Sychronous, Asynchonous, Task
In 3.10, page 142, GDF-R-P.90 states to use a template member method like: task.get_result <return_type> (void) to get a Sync, Async or Task as a return type. Since Python does not have templates (String templates are something else), I propose to add a jobType parameter to all the methods using this principle. jobType could be {sync=0, async=1, task=0}. jobType could be defaulted to jobType=sync, so:
f = saga.File(someURL) len_out = f.read (len, buffer); OR task = f.read (len, buffer, jobType=sync)
That is certainly an option. Just to give you some trouble, here are some others: len_out = f.read (len, buffer, sync); // thats your version task = f.read (len, buffer, task); len_out = f.read_sync (len, buffer); task = f.read_task (len, buffer); len_out = f.read (sync, len, buffer); task = f.read (task, len, buffer); len_out = sync_f.read (len, buffer); task = task_f.read (len, buffer); And there are more... All options have pro and cons. We had that discussion for a long time as we designed the task model. If you are interested in gazillions of mails running circles, I can dig them out of the archive ;-) Your model is nice, as it is simple. The only drawback are optional arguments: dir.copy (src, target, Overwrite, sync); What happens without flags, e.g. no Overwrite is wanted: dir.copy (src, target, 0, sync); Basically, you cannot have default args anymore, and always have to specify all arguments. Thats tedious to the programmer. No idea if python provides some clever way to solve this - most other languages don't. Thus, please do also consider to put the flag in the first place, or to use some other qualifiers (method name, etc). Can't recall at the moment what way Hartmut chose in his Python implementation, sorry. Cheers, Andre.
Well, probably more to come but this is it for now. Greetings,
Paul van Zoolingen. Student Vrije Universiteit, Amsterdam, The Netherlands === Those who can, do. Those who can't, simulate. -- Nothing is ever easy.