Example #1
0
def test_supports_loading_multiple_keys_in_one_call():
    def call_fn(keys):
        return Promise.resolve(keys)

    identity_loader = DataLoader(call_fn)

    promise_all = identity_loader.load_many([1, 2])
    assert isinstance(promise_all, Promise)

    values = promise_all.get()
    assert values == [1, 2]

    promise_all = identity_loader.load_many([])
    assert isinstance(promise_all, Promise)

    values = promise_all.get()
    assert values == []
Example #2
0
def test_supports_loading_multiple_keys_in_one_call():
    def call_fn(keys):
        return Promise.resolve(keys)

    identity_loader = DataLoader(call_fn)

    promise_all = identity_loader.load_many([1, 2])
    assert isinstance(promise_all, Promise)

    values = promise_all.get()
    assert values == [1, 2]

    promise_all = identity_loader.load_many([])
    assert isinstance(promise_all, Promise)

    values = promise_all.get()
    assert values == []
Example #3
0
class ExternalRESTField(graphene.Field):

    def __init__(self, rest_object_class, source_field_name='id', filter_field_name='id', is_top_level=False, many=False, *args, **kwargs):
        assert is_top_level or not (source_field_name == 'id' and filter_field_name == 'id') 
        self.source_field_name = source_field_name
        self.filter_field_name = filter_field_name
        self.rest_object_class = rest_object_class
        self.is_top_level = is_top_level

        self.request_maker = RequestMaker(
            filter_by_parent_fields=(not is_top_level),
            filter_field_name=filter_field_name
        )

        def batch_load_fn(source_values):
            self.request_maker.filter_values = source_values
            response = self.request_maker.make_request()
            return Promise.resolve(response.json()['results'])

        self.data_loader = DataLoader(batch_load_fn)

        self.many = many
        if self.many:
            super().__init__(graphene.List(rest_object_class), *args, **kwargs)
        else:
            super().__init__(rest_object_class, *args, **kwargs)

    def get_resolver(self, parent_resolver):
        if self.resolver:
            return self.resolver
        else:
            return self.generate_resolver(get_actual_object_class(self.rest_object_class))
    
    def generate_resolver(self, rest_object_class, *class_args, **class_kwargs):

        def endpoint_resolver_promise(parent_object, results):
            
            relevant_results = list(filter(lambda h: equals_or_contains(h[self.filter_field_name], getattr(parent_object, self.source_field_name)), results))
            if not self.many:
                assert len(relevant_results) == 1
                relevant_results = relevant_results[0]
            
            obj = reduce_fields_to_objects(rest_object_class, relevant_results, is_list=self.many)
            return obj

        def endpoint_resolver(parent_object, args, context, info):

            # This is called for every parent object where we want nested objects.
            # Therefore we don't want to do unnecessary computation (ex:
            # processing query params/headers from the original request)
            # Instead, we do initial processing in request_maker.initialize_x
            # and final processing in request_maker.generate_x
            self.request_maker.headers = context.headers
            self.request_maker.data = context.data
            self.request_maker.base_url = rest_object_class.base_url
            self.request_maker.query_string = context.query_string
            self.request_maker.graphql_arguments = args
            
            if self.is_top_level:
                response = self.request_maker.make_request()
                return reduce_fields_to_objects(rest_object_class, response.json()['results'])
            else:
                source_values = getattr(parent_object, self.source_field_name)
                if not is_non_str_iterable(source_values):
                    source_values = [source_values]
                result = self.data_loader.load_many(source_values)
                return result.then(
                    functools.partial(endpoint_resolver_promise, parent_object)
                )

        return endpoint_resolver