I am writing an API client for a RESTful web service. The problem I am having is one of the objects returned by the API has many subtypes. In total, there are over 200 properties across the subtypes, some being duplicates.
Those that are used by all subtypes I've defined in the parent class. However, there are some properties that only get used by, let's say, 5 of the children. In a normal case, I would just add another layer to the parent/child model, but children mix and match which properties they have in common. Here's an example
class Parent(object):
@property
def apiLinks(self):
pass
@apiLinks.setter
def apiLinks(self, value):
pass
class Child1(Parent):
@property
def interval(self):
pass
@interval.setter
def interval(self, value):
pass
@property
def duration(self):
pass
@apiLinks.setter
def duration(self, value):
pass
class Child2(Parent):
@property
def interval(self):
pass
@interval.setter
def interval(self, value):
pass
@property
def prefix(self):
pass
@prefix.setter
def prefix(self, value):
pass
class Child3(Parent):
@property
def duration(self):
pass
@duration.setter
def duration(self, value):
pass
@property
def prefix(self):
pass
@prefix.setter
def prefix(self, value):
pass
As you can see:
- apiLinks - Child1, Child2, Child3
- interval - Child1, Child2
- duration - Child1, Child3
- prefix - Child2, Child3
I don't want to define the same setter/getter functions more than once and same with the docstrings.
I've looked into importing properties, but that doesn't seem to be an option since they are by design members of an instance.
I've considered defining them all in the parent and looking up the instance type to decide whether or not it becomes available to instantiated children. Such as:
class Parent(object):
if isinstance(self, (Child1, Child2)):
@property
def interval(self):
pass
@interval.setter
def interval(self, value):
pass
I suppose I could save the property getter/setter methods as strings in another module and exec them into the functions and define the docstrings there as well.
interval_get = """@property
def interval(self):
\"\"\"
The interval at which the test should run.
Parameters
----------
value : int
Testing interval, allowed options: [300, 600, 900, 1800, 3600]
Returns
-------
value : int
Configured test interval
Raises
------
ValueError
If value is not one of [300, 600, 900, 1800, 3600]
TypeError
If type provided is not of type int
\"\"\"
return self._interval
"""
interval_set = """@interval.setter
def interval(self, value):
print('works')
self._interval = value
"""
class TestProp(object):
exec(interval_get)
exec(interval_set)
I'm looking for the recommended approach though. Also, I'm not interested in supporting python2.x so this code is for python3.x only. I'm fine with solutions specific to python3.7 even.