cruise-control
cruise-control copied to clipboard
Improve usability of the Python client library
The implementation of the Python client is tightly coupled to the outputs of argparse, making it difficult to instantiate the various objects within the library without passing the values in as though it was a command-line input. This in turn makes it difficult to use the library in other projects without some translation layer to transform inputs into a command-line argument string. This is documented in the wiki section for the client, from there:
endpoint = RemoveBrokerEndpoint(['broker', 'ids', 'to', 'remove'])
endpoint.add_param(parameter_name="allow_capacity_estimation", value=False)
endpoint.add_param(parameter_name="json", value=True)
A clearer instantiation would be:
endpoint = RemoveBrokerEndpoint(brokers=['ids', 'to', 'remove'], allow_capacity_estimation=False, json=True)
However, the dynamic construction of the Endpoint class implementations do make this named parameters approach more difficult. But, regardless of the difficulty, the usability of that model also seems less compatible with patterns that would arise from users leveraging this as a library; for example, a user making multiple requests to the same endpoint with different parameters. In my opinion, to maintain the dynamic model, but make it more compatible with repeated requests, I see the following as the solution:
endpoint = RemoveBrokerEndpoint()
parameters: ParameterSet = endpoint.init_parameter_set()
# tuple:
parameters.add(('allow_capactiy_estimation', False',)
# direct reference:
parameters.add(AllowCapacityEstimationParameter(False))
# or even, with named parameters:
parameters.add(allow_capacity_estimation=False)
where ParameterSet is an implementation of some abstract collections, in the example above, I'm assuming a MutableSet. This container can enforce what's allowed for the endpoint through being initialized by the instance of the endpoint type which carries all of the definitions.
In this way, the function managing the API call can reuse an Endpoint class but be passed different parameters:
def retrieve_response_from_Endpoint(self,
cc_socket_address: str,
endpoint: AbstractEndpoint,
parameters: ParameterSet,
**kwargs):
return self.retrieve_response(
method=endpoint.http_method,
url=generate_base_url_from_cc_socket_address(cc_socket_address, endpoint),
params=parameters.compose(),
**kwargs
)