Exemple #1
0
    def mutate(self, info, resource_data=None):
        # We must merge in existing resource.data if we are updating
        if R.has('id', resource_data):
            # New data gets priority, but this is a deep merge.
            resource_data['data'] = R.merge_deep(
                Resource.objects.get(id=resource_data['id']).data,
                R.prop_or({}, 'data', resource_data))
            # Modifies defaults value to add .data.graph
            # We could decide in the future to generate this derived data on the client, but it's easy enough to do here

        modified_resource_data = enforce_unique_props(resource_fields,
                                                      resource_data)
        # Make sure that all props are unique that must be, either by modifying values or erring.
        update_or_create_values = input_type_parameters_for_update_or_create(
            resource_fields, modified_resource_data)

        # Add the sankey data unless we are updating the instance without updating instance.data
        update_or_create_values_with_sankey_data = R.merge(
            update_or_create_values,
            dict(defaults=add_sankey_graph_to_resource_dict(
                update_or_create_values['defaults']))) if R.has(
                    'defaults',
                    update_or_create_values) else update_or_create_values

        resource, created = update_or_create_with_revision(
            Resource, update_or_create_values_with_sankey_data)
        return UpsertResource(resource=resource)
 def mutate(self, info, group_state_data=None):
     """
         Update or create the group state
     :param info:
     :param group_state_data:
     :return:
     """
     update_or_create_values = input_type_parameters_for_update_or_create(group_state_fields, group_state_data)
     # We can do update_or_create since we have a unique group_id in addition to the unique id
     group_state, created = update_or_create_with_revision(GroupState, update_or_create_values)
     return UpsertGroupState(group_state=group_state)
 def mutate(self, info, group_data=None):
     group_model = Group()
     data = R.merge(
         group_data,
         dict(password=make_password(R.prop('password', group_data),
                                     salt='not_random'))
         if R.prop_or(False, 'password', group_data) else {})
     update_or_create_values = input_type_parameters_for_update_or_create(
         group_fields, data)
     group, created = update_or_create_with_revision(
         group_model, update_or_create_values)
     return UpsertGroup(group=group)
    def mutate(self, info, search_location_data=None):
        deleted_search_location_response = delete_if_marked_for_delete(
            SearchLocation, UpsertSearchLocation, 'search_location',
            search_location_data)
        if deleted_search_location_response:
            return deleted_search_location_response

        modified_search_location_data = R.compose(
            # Make sure that all props are unique that must be, either by modifying values or erring.
            lambda data: enforce_unique_props(search_location_fields, data),
            # Remove the many to many values. They are saved separately
            lambda data: R.omit(['jurisdictions'], data))(search_location_data)

        update_or_create_values = input_type_parameters_for_update_or_create(
            search_location_fields, modified_search_location_data)
        search_location, created = update_or_create_with_revision(
            SearchLocation, update_or_create_values)

        # SearchJurisdictions can be created during the creation of search_locations
        if R.prop_or(False, 'jurisdictions', search_location_data):
            existing_search_intersections_by_id = R.index_by(
                R.prop('id'), search_location.jurisdictions.all())
            for search_jurisdiction_unsaved in R.prop('intersections',
                                                      search_location_data):
                # existing instances have an id
                search_jursidiction_id = R.prop_or(
                    None, 'id', search_jurisdiction_unsaved)
                search_jurisdiction, created = update_or_create_with_revision(
                    SearchJurisdiction,
                    R.merge(
                        R.prop(search_jursidiction_id,
                               existing_search_intersections_by_id)
                        if search_jursidiction_id else {},
                        search_jurisdiction_unsaved))
                # Once saved, add it to the search location
                search_location.jurisdictions.set(search_jurisdiction)

        return UpsertSearchLocation(search_location=search_location)
Exemple #5
0
    def mutate(self, info, jurisdiction_data=None):
        deleted_jurisdiction_response = delete_if_marked_for_delete(
            Jurisdiction, UpsertJurisdiction, 'jurisdiction',
            jurisdiction_data)
        if deleted_jurisdiction_response:
            return deleted_jurisdiction_response

        # Make sure that all props are unique that must be, either by modifying values or erring.
        modified_jurisdiction_data = enforce_unique_props(
            jurisdiction_fields, jurisdiction_data)
        update_or_create_values = input_type_parameters_for_update_or_create(
            jurisdiction_fields, modified_jurisdiction_data)
        jurisdiction, created = update_or_create_with_revision(
            Jurisdiction, update_or_create_values)

        return UpsertJurisdiction(jurisdiction=jurisdiction)
Exemple #6
0
    def mutate(self, info, settings_data=None):
        # We must merge in existing settings.data if we are updating data
        if R.has('id', settings_data) and R.has('data', settings_data):
            # New data gets priority, but this is a deep merge.
            settings_data['data'] = R.merge_deep(
                Settings.objects.get(id=settings_data['id']).data,
                settings_data['data'])

        # Make sure that all props are unique that must be, either by modifying values or erring.
        modified_settings_data = enforce_unique_props(settings_fields,
                                                      settings_data)
        update_or_create_values = input_type_parameters_for_update_or_create(
            settings_fields, modified_settings_data)

        settings, created = update_or_create_with_revision(
            Settings, update_or_create_values)
        return UpsertSettings(settings=settings)
 def mutate(self, info, foo_data=None):
     modified_foo_data = R.merge(
         # Make sure unique fields are enforced, here by incrementing foo.key
         enforce_unique_props(foo_fields, foo_data),
         dict(
             # Force the FeatureCollection geojson into the GEOSGeometryCollection. This is just Geometry
             geo_collection=ewkt_from_feature_collection(
                 foo_data['geojson'])
             if R.prop('geojson', foo_data) else {},
             # Put the full FeatureCollection geojson into the geojson field.
             geojson=foo_data['geojson']
             if R.prop('geojson', foo_data) else {}))
     update_or_create_values = input_type_parameters_for_update_or_create(
         foo_fields, modified_foo_data)
     foo, created = update_or_create_with_revision(Foo,
                                                   update_or_create_values)
     return UpsertFoo(foo=foo)
Exemple #8
0
    def mutate(self, info, location_data=None):
        with transaction.atomic():
            deleted_location_response = delete_if_marked_for_delete(Location, UpsertLocation, 'location', location_data)
            if deleted_location_response:
                return deleted_location_response

            # We must merge in existing location.data if we are updating data
            if R.has('id', location_data) and R.has('data', location_data):
                # New data gets priority, but this is a deep merge.
                location_data['data'] = R.merge_deep(
                    Location.objects.get(id=location_data['id']).data,
                    location_data['data']
                )

            # Make sure that all props are unique that must be, either by modifying values or erring.
            modified_location_data = enforce_unique_props(location_fields, location_data)
            update_or_create_values = input_type_parameters_for_update_or_create(location_fields, modified_location_data)

            location, created = update_or_create_with_revision(Location, update_or_create_values)
            return UpsertLocation(location=location)
Exemple #9
0
        def mutate(self, info, user_state_data=None):
            """
                Update or create the user state
            :param info:
            :param user_state_data:
            :return:
            """

            # Check that all the scope instances in user_state.data exist. We permit deleted instances for now.
            new_data = R.prop_or({}, 'data', user_state_data)
            # Copy since Graphene reuses this data
            copied_new_data = copy.deepcopy(new_data)
            old_user_state_data = UserState.objects.get(
                id=user_state_data['id']
            ).data if R.prop_or(None, 'id', user_state_data) else None

            # Inspect the data and find all scope instances within UserState.data
            # This includes userRegions[*].region, userProject[*].project and within userRegions and userProjects
            # userSearch.userSearchLocations[*].search_location and whatever the implementing libraries define
            # in addition
            updated_new_data = validate_and_mutate_scope_instances(
                user_state_scope_instances_config,
                copied_new_data
            )

            # If either userProjects or userRegions are null, it means those scope instances aren't part
            # of the update, so merge in the old values
            if R.prop_or(None, 'id', user_state_data) and R.any_satisfy(
                    lambda user_scope_key: not R.prop_or(None, user_scope_key, updated_new_data),
                    ['userProjects', 'userRegions']
            ):
                # The special update case where one userScope collection is null,
                # indicates that we are only updating one userScope object. The rest
                # should remain the same and not be removed
                for user_scope_key in ['userProjects', 'userRegions']:
                    # Database values
                    old_user_scopes_by_id = user_scope_instances_by_id(
                        user_scope_key,
                        old_user_state_data
                    )
                    # New values with updates applied
                    new_user_scopes_by_id = user_scope_instances_by_id(
                        user_scope_key,
                        updated_new_data
                    )
                    # Prefer the old over the new, merging all objects but overriding lists
                    # We override lists because a non-null list always replaces the old list in the database
                    updated_new_data[user_scope_key] = R.values(R.merge_deep(
                        old_user_scopes_by_id,
                        new_user_scopes_by_id,
                        MyMerger(
                            # pass in a list of tuples,with the
                            # strategies you are looking to apply
                            # to each type.
                            [
                                (list, ["override_non_null"]),
                                (dict, ["merge"])
                            ],
                            # next, choose the fallback strategies,
                            # applied to all other types:
                            ["override"],
                            # finally, choose the strategies in
                            # the case where the types conflict:
                            ["override"]
                        )
                    ))

            # Update user_state_data the updated data
            modified_user_state_data = R.merge(user_state_data, dict(data=updated_new_data))

            # id or user.id can be used to identify the existing instance
            id_props = R.compact_dict(
                dict(
                    id=R.prop_or(None, 'id', modified_user_state_data),
                    user_id=R.item_str_path_or(None, 'user.id', modified_user_state_data)
                )
            )

            def fetch_and_merge(modified_user_state_data, props):
                existing = UserState.objects.filter(**props)
                # If the user doesn't have a user state yet
                if not R.length(existing):
                    return modified_user_state_data

                return merge_data_fields_on_update(
                    ['data'],
                    R.head(existing),
                    # Merge existing's id in case it wasn't in user_state_data
                    R.merge(modified_user_state_data, R.pick(['id'], existing))
                )

            modified_data = R.if_else(
                R.compose(R.length, R.keys),
                lambda props: fetch_and_merge(modified_user_state_data, props),
                lambda _: modified_user_state_data
            )(id_props)

            update_or_create_values = input_type_parameters_for_update_or_create(
                user_state_fields,
                # Make sure that all props are unique that must be, either by modifying values or erring.
                enforce_unique_props(
                    user_state_fields,
                    modified_data)
            )

            user_state, created = update_or_create_with_revision(UserState, update_or_create_values)
            return UpsertUserState(user_state=user_state)