-1
class SignedFileRequest(SignedRequest):
    def __init__(self, host, path, node_id = None, name=None, \
                 content_type=None, hash=None, ssl=False, expires=0):
        super(SignedFileRequest, self).__init__(host, path, ssl, expires)
        self.name = name
        self.content_type = content_type
        self.hash = hash
        self.node_id = node_id
    def get_name(self):
        return self.query_dict.get(NAME_KEY)
    def set_name(self, value):
        self.query_dict[NAME_KEY] = value
    def get_content_type(self):
        return self.query_dict.get(CONTENT_TYPE_KEY)
    def set_content_type(self, value):
        self.query_dict[CONTENT_TYPE_KEY] = value
    def get_hash(self):
        return self.query_dict.get(HASH_KEY)
    def set_hash(self, value):
        self.query_dict[HASH_KEY] = value
    def get_node_id(self):
        return self.query_dict.get(NODE_ID_KEY)
    def set_node_id(self, value):
        self.query_dict[NODE_ID_KEY] = value
    name = property(get_name, set_name)
    content_type = property(get_content_type, set_content_type)
    hash = property(get_hash, set_hash)
    node_id = property(get_node_id, set_node_id)
Alexandre
  • 5,035
  • 7
  • 29
  • 36
  • And what would the pattern be? Please provide more detail as to how you'd expect to map attribute to `query_dict` key, for example. – Martijn Pieters Sep 26 '12 at 10:04
  • possible duplicate of [Can anyone help condense this Python code?](http://stackoverflow.com/questions/11921320/can-anyone-help-condense-this-python-code) – Jon Clements Sep 26 '12 at 10:10

2 Answers2

2

You could use a class decorator:

def keyprop(keymap):
    def decorator(cls):
        for name, key in keymap.items():
            def getter(self):
                return self.query_dict.get(NAME_KEY)
            def setter(self, value):
                self.query_dict[NAME_KEY] = value
            setattr(cls, name, property(getter, setter))
    return decorator

keymap = {'name' : NAME_KEY,
          'content_type' : CONTENT_TYPE_KEY,
          'hash' : HASH_KEY,
          'node_id' : NODE_ID_KEY}

@keyprop(keymap)
class SignedFileRequest(SignedRequest):
    def __init__(self, host, path, node_id = None, name=None, \
                 content_type=None, hash=None, ssl=False, expires=0):
        super(SignedFileRequest, self).__init__(host, path, ssl, expires)
        self.name = name
        self.content_type = content_type
        self.hash = hash
        self.node_id = node_id
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
1

You could use the __getattr__ and __setattr__ hooks instead of a meta class:

class SignedFileRequest(SignedRequest):
    __attr_map = dict(name=NAME_KEY, content_type=CONTENT_TYPE_KEY,
                      hash=HASH_KEY, node_id=NODE_ID_KEY)

    def __init__(self, host, path, node_id = None, name=None, \
                 content_type=None, hash=None, ssl=False, expires=0):
        super(SignedFileRequest, self).__init__(host, path, ssl, expires)
        self.name = name
        self.content_type = content_type
        self.hash = hash
        self.node_id = node_id

    def __getattr__(self, attr):
        if attr in self.__attr_map:
            return self.query_dict.get(self.__attr_map[attr])
        return super(SignedFileRequest, self).__getattr__(attr)

    def __setattr__(self, attr, value):
        if attr in self.__attr_map:
            self.query_dict[self.__attr_map[attr]] = value
        super(SignedFileRequest, self).__setattr__(attr, value)

Alternatively, the same mapping can be used to create a class decorator:

def add_property(klass, name, key):
    def getter(self):
        return self.query_dict.get(key)
    def setter(self, value):
        self.query_dict[key] = value
    setattr(klass, name, property(getter, setter))

def set_properties(**mapping):
    def decorator(klass):
        for name, key in mapping.iteritems():
            add_property(klass, name, key)
        return klass
    return decorator

@set_properties(name=NAME_KEY, content_type=CONTENT_TYPE_KEY,
                hash=HASH_KEY, node_id=NODE_ID_KEY)
class SignedFileRequest(SignedRequest):
    def __init__(self, host, path, node_id = None, name=None, \
                 content_type=None, hash=None, ssl=False, expires=0):
        super(SignedFileRequest, self).__init__(host, path, ssl, expires)
        self.name = name
        self.content_type = content_type
        self.hash = hash
        self.node_id = node_id

Or you could go with a meta class approach anyway:

 def mapped_properties_meta(**mapping):
     def mapped_meta(name, bases, attrs):
         klass = type(name, bases, attrs)
         for name, key in mapping.iteritems():
             add_property(klass, name, key)
         return klass
     return mapped_meta


class SignedFileRequest(SignedRequest):
    __metaclass__ = mapped_properties_meta(
       name=NAME_KEY, content_type=CONTENT_TYPE_KEY,
       hash=HASH_KEY, node_id=NODE_ID_KEY)

    def __init__(self, host, path, node_id = None, name=None, \
                 content_type=None, hash=None, ssl=False, expires=0):
        super(SignedFileRequest, self).__init__(host, path, ssl, expires)
        self.name = name
        self.content_type = content_type
        self.hash = hash
        self.node_id = node_id

The latter reuses the add_property function from the decorator approach.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343