[SAGA-RG] Python Bindings: method overloading

Andre Merzky andre at merzky.net
Wed Feb 20 08:07:58 EST 2013


On Wed, Feb 20, 2013 at 1:53 PM, Steve Fisher <dr.s.m.fisher at gmail.com> wrote:
> I have been thinking about this proposal and it will clearly work - however
> it is not beautiful.

Not beautiful on API level, or on implementation level?  On
implementation level, I agree - but that is a pain we have to deal
with only once, and while ugly, it is not difficult.  On API level, we
get an API which is rather close to what we have in GFD.90 and the
other languages -- that can't be bad, right? ;)


> Would it be acceptable to not implement these directory
> operations but tell people to move to the src object and then use the
> operation on the entry.

IMHO: possible, certainly yes -- elegant, not really, no...


Cheers, Andre.


> Steve
>
>
> On 12 February 2013 21:28, Andre Merzky <andre at merzky.net> wrote:
>>
>> Hi all,
>>
>> we have been rethinking the method overloading problem for the Python
>> bindings again.  As a reminder, this is the problem:
>>
>>   - A namespace entry has a method 'entry.copy (tgt, flags)'
>>
>>   - A namespace directory inherits from the entry, and adds another
>> copy method: 'dir.copy (src, tgt, flags)'
>>
>>   - Python though does not do method overloading, but only method
>> *overwriting*.  For that reasons, based on a suggestion of Paul, we
>> renamed the conflicting methods on entry level with a '_self' postfix:
>> 'entry.copy_self (tgt, flags)'.
>>
>>
>> It seems we found a way to implement real method overloading thouhg --
>> and since the code overhead is not too bad, we would like to propose
>> that mechanism for the SAGA Python bindings.
>>
>> First, these are the methods we are talking about, sorted by signature
>> types:
>>
>>     def copy      (self,      tgt, flags=None, ttype=None) : pass
>>     def copy      (self, src, tgt, flags=None, ttype=None) : pass
>>     def link      (self,      tgt, flags=None, ttype=None) : pass
>>     def link      (self, src, tgt, flags=None, ttype=None) : pass
>>     def move      (self,      tgt, flags=None, ttype=None) : pass
>>     def move      (self, src, tgt, flags=None, ttype=None) : pass
>>
>>     def get_size  (self,           flags=None, ttype=None) : pass
>>     def get_size  (self,      tgt, flags=None, ttype=None) : pass
>>     def remove    (self,           flags=None, ttype=None) : pass
>>     def remove    (self,      tgt, flags=None, ttype=None) : pass
>>
>>     def is_dir    (self,                       ttype=None) : pass
>>     def is_dir    (self,      tgt,             ttype=None) : pass
>>     def is_entry  (self,                       ttype=None) : pass
>>     def is_entry  (self,      tgt,             ttype=None) : pass
>>     def is_file   (self,                       ttype=None) : pass
>>     def is_file   (self,      tgt,             ttype=None) : pass
>>     def is_link   (self,                       ttype=None) : pass
>>     def is_link   (self,      tgt,             ttype=None) : pass
>>     def read_link (self,                       ttype=None) : pass
>>     def read_link (self,      tgt,             ttype=None) : pass
>>
>> So, the differences are never in the keyword args (kwargs), but always
>> in the args w/o keyword.  The kwargs are always flags, i.e. integers,
>> or enums, which we can also define as integers.
>>
>> As said: Python does not allow method overloading, only method
>> replacement.  But it *does* allow for variable parameter lists (*args,
>> **kwargs).  We can deselect the int types from the args, and count the
>> remaining arguments:
>>
>>   d = {'src' : 'src', 'tgt' : 'tgt', 'flags' : 3, 'ttype' : 2}
>>   l = list (v for v in d.values () if not isinstance (v, int))
>>
>>   print len(l) # 2
>>
>>
>> So, one can code the following:
>>
>>
>>   class ns.entry :
>>
>>   # def copy  (self,        tgt, flags=None, ttype=None) : pass
>>   # def copy  (self, src,   tgt, flags=None, ttype=None) : pass
>>     def copy  (self,      *args,               **kwargs) :
>>
>>       non_int_args = args + list (v  for v in kwargs.values () \
>>                                   if not v == None and not isinstance (v,
>> int))
>>       if  len (non_int_args) == 2 :
>>           return self._adaptor.copy_self (args, kwargs)
>>       if  len (non_int_args) == 3 :
>>           return self._adaptor.copy      (args, kwargs)
>>
>>       raise BadParameter ("signature mismatch: copy (url, [url], flags,
>> ttype)")
>>
>>
>> All further signature checks are automatically done on CPI / adaptor
>> level -- although one could here add type checking for flags and
>> ttypes at this point.
>>
>> We think this makes the API significantly cleaner and easier to use --
>> so please let us know what you think...
>>
>> Best, Andre.
>>
>>
>> --
>> There are only two hard things in Computer Science: cache invalidation
>> and naming things.
>>
>> -- Phil Karlton
>> --
>>   saga-rg mailing list
>>   saga-rg at ogf.org
>>   https://www.ogf.org/mailman/listinfo/saga-rg
>
>



-- 
There are only two hard things in Computer Science: cache invalidation
and naming things.

-- Phil Karlton


More information about the saga-rg mailing list