diff --git a/tests/unit/test_builder.py b/tests/unit/test_builder.py index 6c38ea60..355cbca7 100644 --- a/tests/unit/test_builder.py +++ b/tests/unit/test_builder.py @@ -167,11 +167,11 @@ class Consumer(builder.Consumer): request_method = request_definition_builder # Verify: Get request definition builder on access - assert Consumer.request_method is request_definition_builder + assert Consumer.request_method is request_definition_builder.copy() # Verify: Try again after resetting Consumer.request_method = request_definition_builder - assert Consumer.request_method is request_definition_builder + assert Consumer.request_method is request_definition_builder.copy() # Verify: We get callable on attribute access for an instance consumer = Consumer() diff --git a/uplink/arguments.py b/uplink/arguments.py index 1e7e7e79..979ec53d 100644 --- a/uplink/arguments.py +++ b/uplink/arguments.py @@ -120,6 +120,9 @@ def _process_annotation(self, name, annotation): def is_done(self): return self.remaining_args_count == 0 + def copy(self): + return self + @property def _types(self): types = self._annotations diff --git a/uplink/builder.py b/uplink/builder.py index 34b6fae6..79343197 100644 --- a/uplink/builder.py +++ b/uplink/builder.py @@ -181,7 +181,7 @@ def _build_definition(self): def __get__(self, instance, owner): if instance is None: - return self._request_definition_builder + return self._request_definition_builder.copy() else: return instance.session.create(instance, self._request_definition) diff --git a/uplink/commands.py b/uplink/commands.py index 61b58746..144bd2ad 100644 --- a/uplink/commands.py +++ b/uplink/commands.py @@ -155,6 +155,14 @@ def argument_handler_builder(self): def method_handler_builder(self): return self._method_handler_builder + def copy(self): + return RequestDefinitionBuilder( + self._method, + self._uri, + self._argument_handler_builder.copy(), + self._method_handler_builder.copy(), + ) + def _auto_fill_remaining_arguments(self): uri_vars = set(self.uri.remaining_variables) missing = list(self.argument_handler_builder.missing_arguments) diff --git a/uplink/decorators.py b/uplink/decorators.py index 62574d08..8db341e1 100644 --- a/uplink/decorators.py +++ b/uplink/decorators.py @@ -37,6 +37,12 @@ def add_annotation(self, annotation, *args_, **kwargs): super(MethodAnnotationHandlerBuilder, self).add_annotation(annotation) return annotation + def copy(self): + clone = MethodAnnotationHandlerBuilder() + clone._class_annotations = list(self._class_annotations) + clone._method_annotations = list(self._method_annotations) + return clone + def build(self): return MethodAnnotationHandler( self._class_annotations + self._method_annotations @@ -89,16 +95,18 @@ def _is_static_call(cls, *args_, **kwargs): else: return is_consumer_class and not (kwargs or args_[1:]) - def __call__(self, class_or_builder): + def __call__(self, class_or_builder, **kwargs): if self._is_consumer_class(class_or_builder): builders = helpers.get_api_definitions(class_or_builder) builders = filter(self._is_relevant_for_builder, builders) for name, b in builders: - b.method_handler_builder.add_annotation(self, is_class=True) + self(b, is_class=True) helpers.set_api_definition(class_or_builder, name, b) elif isinstance(class_or_builder, interfaces.RequestDefinitionBuilder): - class_or_builder.method_handler_builder.add_annotation(self) + class_or_builder.method_handler_builder.add_annotation( + self, **kwargs + ) return class_or_builder def modify_request(self, request_builder): diff --git a/uplink/interfaces.py b/uplink/interfaces.py index b87057b2..b610aaf7 100644 --- a/uplink/interfaces.py +++ b/uplink/interfaces.py @@ -99,6 +99,9 @@ def method_handler_builder(self): def build(self): raise NotImplementedError + def copy(self): + raise NotImplementedError + class RequestDefinition(object): def make_converter_registry(self, converters):