def convert_form_field_with_choices(field, name=None, form=None): """ Helper method to convert a field to graphene Field type. :param name: form field's name :param field: form field to convert to :param form: field's form :return: graphene Field """ choices = getattr(field, "choices", None) # If is a choice field, but not depends on models if (not isinstance( field, (forms.ModelMultipleChoiceField, forms.ModelChoiceField)) and choices): if form: name = to_camel_case("{}_{}".format(get_form_name(form), field.label or name)) else: name = field.label or name name = to_camel_case(name.replace(" ", "_")) choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): """Enum type definition""" @property def description(self): """Return field description""" return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) return enum(description=field.help_text, required=field.required) # pylint: disable=E1102 return convert_form_field(field)
def get_errors(form_errors): errors = [] for field, field_messages in form_errors.items(): messages = [] json_error = None for message in field_messages: try: json_error = json.loads(message) except json.decoder.JSONDecodeError: messages.append(message) child_errors = [] if json_error: child_errors = [] for f, m in json_error.items(): m = [i['message'] for i in m] f = to_camel_case(f) if f != '__all__' else f child_errors.append(ErrorType(field=f, messages=m)) child_errors = child_errors if child_errors else None messages = messages if messages else None field = to_camel_case(field) if field != '__all__' else field errors.append( ErrorType(field=field, messages=messages, errors=child_errors)) return errors
def _test_filter_prefix_starts_ends_with_contains_wildcard_lookups(self): """"Test filters `prefix`, `starts_with` and `ends_with` lookups (on field `category`). :return: """ with self.subTest('Test filter on field `category` "Elastic" ' 'using `contains` lookup'): self.__test_filter_text_lookups('"ytho"', self.num_python_posts, LOOKUP_QUERY_CONTAINS) with self.subTest('Test filter on field `category` "Elastic" ' 'using `wildcard` lookup'): self.__test_filter_text_lookups('"*ytho*"', self.num_python_posts, LOOKUP_FILTER_WILDCARD) with self.subTest('Test filter on field `category` "Elastic" ' 'using `prefix` lookup'): self.__test_filter_text_lookups( '"Pyth"', self.num_python_posts, to_camel_case(LOOKUP_FILTER_PREFIX)) with self.subTest('Test filter on field `category` "Elastic" ' 'using `starts_with` lookup'): self.__test_filter_text_lookups( '"Pyth"', self.num_python_posts, to_camel_case(LOOKUP_QUERY_STARTSWITH)) with self.subTest('Test filter on field `category` "Elastic" ' 'using `ends_with` lookup'): self.__test_filter_text_lookups( '"ython"', self.num_python_posts, to_camel_case(LOOKUP_QUERY_ENDSWITH))
def assert_called_correctly(**kwargs): for key, val in kwargs.items(): if val: assert variables[to_camel_case(key)] == val else: assert variables.get(to_camel_case(key)) is None return fake_domains
def get_type_field(gql_type, gql_name): fields = gql_type._meta.fields for name, field in fields.items(): if to_camel_case(gql_name) == to_camel_case(name): if isinstance(field, Dynamic): field = field.get_type() else: field = field if isinstance(field, List): field_type = field.of_type else: field_type = field.type return name, field_type
def optimize_queryset(qs, info, root, callback=None): """ Pulls in available database relations to avoid N+1 queries. For example the following query: { carts { id name ...cartInfo } } fragment cartInfo on CartType { store { id name } } It will automatically pull in the 'store' relation (assuming its a ForeignKey or ManyToMany) using the ORM. >>> qs = Cart.objects.all() >>> optimize_queryset(qs, info, 'carts') """ # right now we're only handling one level deep root_len = len(to_camel_case(root)) + 1 selected_fields = set([ x[root_len:] if x.startswith(root) else x for x in get_selected_names(info) ]) select = [] for field in qs.model._meta.fields: field_name = to_camel_case(field.name) if field_name in selected_fields: if isinstance(field, ForeignKey): select.append(field.name) if select: qs = qs.select_related(*select) prefetch = [] for field in qs.model._meta.many_to_many: field_name = to_camel_case(field.name) if field_name in selected_fields: prefetch.append(field.name) if prefetch: qs = qs.prefetch_related(*prefetch) if callback: qs = callback(queryset=qs, selected_fields=selected_fields, info=info) return qs
def convert_choice_field_to_enum(field): """ Add support to convert ordering choices to Graphql enum. Label is used as enum name. """ registry = get_global_registry() converted = registry.get_converted_field(field) if converted: return converted def get_choices(choices): for value, help_text in choices: if value: name = convert_choice_name(value) description = help_text yield name, value, description name = to_camel_case(field.label) choices = list(get_choices(field.choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) converted = enum(description=field.help_text, required=field.required) registry.register_converted_field(field, converted) return converted
def convert_django_field_with_choices(field, registry=None): if registry is not None: converted = registry.get_converted_field(field) if converted: return converted choices = getattr(field, "choices", None) if choices: field_class = field.owner name = to_camel_case("{}_{}".format(field_class.__name__, field.name)) choices = list(get_choices(dict(choices))) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) converted = enum(description=field.help_text, required=field.required) else: converted = convert_django_field(field, registry) if registry is not None: registry.register_converted_field(field, converted) return converted
def convert_django_field_with_choices(field, registry=None, input_flag=None, nested_fields=False): choices = getattr(field, 'choices', None) if choices: meta = field.model._meta name = '{}_{}_{}'.format(meta.object_name, field.name, 'Enum') if input_flag: name = '{}_{}'.format(name, input_flag) name = to_camel_case(name) enum = registry.get_type_for_enum(name) if not enum: choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) registry.register_enum(name, enum) return enum(description=field.help_text or field.verbose_name, required=is_required(field) and input_flag == 'create') return convert_django_field(field, registry, input_flag, nested_fields)
class Meta(DefaultMeta): name = kwargs.get("name") or to_camel_case( "{}_List_Type".format(kwargs.get("model").__name__)) results_field_name = kwargs.get("results_field_name") pagination = kwargs.get("pagination") description = "Auto generated list Type for {} model".format( kwargs.get("model").__name__)
class Meta(DefaultMeta): name = kwargs.get("name") or to_camel_case( "{}_{}_Generic_Type".format( kwargs.get("model").__name__, args[0])) input_for = args[0] description = "Auto generated InputType for {} model".format( kwargs.get("model").__name__)
class DjangoNodeFieldTest(BaseTest, TestCase): op_name = to_camel_case("get_basic_model_id") expected_return_payload = { "data": { op_name: { "text": "Some text", "id": to_global_id(BasicModelNodeType.__name__, 1) } } } def setUp(self): super(DjangoNodeFieldTest, self).setUp() @property def query(self): self.login() model = BasicFactory(text='Some text') return queries.generic_query % { "params": 'id: "%s"' % to_global_id(BasicModelNodeType.__name__, model.id), "name": self.op_name, "fields": "text id" }
def convert_django_field_with_choices(field, registry=None): if registry is not None: converted = registry.get_converted_field(field) if converted: return converted choices = getattr(field, "choices", None) # If we have choices and they contain keys as string... if choices and tuple_keys_contain_str(choices): meta = field.model._meta name = to_camel_case("{}_{}".format(meta.object_name, field.name)) choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) converted = enum(description=field.help_text, required=not field.null) # If we have no choices or they are integers else: converted = convert_django_field(field, registry) if registry is not None: registry.register_converted_field(field, converted) return converted
def dynamic_type(): key = '{}_{}'.format(field.name, field.model.__name__.lower()) if input_flag is not None: key = '{}_{}'.format(key, input_flag) key = to_camel_case(key) model = field.model ct_field = None fk_field = None required = False for f in get_model_fields(model): if f[0] == field.ct_field: ct_field = f[1] elif f[0] == field.fk_field: fk_field = f[1] if fk_field is not None and ct_field is not None: break if ct_field is not None and fk_field is not None: required = (is_required(ct_field) and is_required(fk_field)) or required if input_flag: return GenericForeignKeyInputType( description='Input Type for a GenericForeignKey field', required=required and input_flag == 'create') _type = registry.get_type_for_enum(key) if not _type: _type = GenericForeignKeyType # return Field(_type, description=field.help_text or field.verbose_name, required=field.null) return Field(_type, description='Type for a GenericForeignKey field', required=required and input_flag == 'create')
def test_retrieving_the_restricted_attributes_restricted( staff_api_client, color_attribute, permission_manage_products, attribute, expected_value, ): """Checks if the attributes are restricted and if their default value is the expected one.""" attribute = to_camel_case(attribute) query = (""" { attributes(first: 10) { edges { node { %s } } } } """ % attribute) found_attributes = get_graphql_content( staff_api_client.post_graphql(query, permissions=[ permission_manage_products ]))["data"]["attributes"]["edges"] assert len(found_attributes) == 1 assert found_attributes[0]["node"][attribute] == expected_value
def convert_django_field_with_choices( field, registry=None, required=None, field_many_to_many_extras=None, field_foreign_key_extras=None, ): choices = getattr(field, "choices", None) if choices: registry_name = to_camel_case("{}_{}_{}".format( field.model._meta.object_name, field.name, "Input")) # Fetch this from registry, if exists. We don't want to duplicate enum fields. enum = None if registry: from_registry = registry.get_converted_field(registry_name) if from_registry: return from_registry(description=field.help_text, required=is_required(field, required)) converted = convert_choices_field(field, choices, required) # Register enum fields if registry: registry.register_converted_field(registry_name, converted) return converted(description=field.help_text, required=is_required(field, required)) else: converted = convert_django_field_to_input(field, registry, required, field_many_to_many_extras, field_foreign_key_extras) return converted
def generate_enum_name(django_model_meta, field): if graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME: # Try and import custom function custom_func = import_string( graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME) name = custom_func(field) elif graphene_settings.DJANGO_CHOICE_FIELD_ENUM_V3_NAMING is True: name = "{app_label}{object_name}{field_name}Choices".format( app_label=to_camel_case(django_model_meta.app_label.title()), object_name=django_model_meta.object_name, field_name=to_camel_case(field.name.title()), ) else: name = to_camel_case("{}_{}".format(django_model_meta.object_name, field.name)) return name
def format_error(error): if hasattr(error, 'original_error'): err = error.original_error formatted_error = {} if isinstance(err, AppException): if isinstance(err, InternalErrorException): log_error(err.detail, exc_info=(err.__class__, err, err.stack)) formatted_error['message'] = err.detail formatted_error['code'] = err.code else: log_error('Exception during GraphQL method execution.', exc_info=(err.__class__, err, err.stack)) formatted_error['message'] = 'Internal error.' formatted_error['code'] = InternalErrorException.code if hasattr(err, 'errors') and err.errors is not None: formatted_error['errors'] = [{ 'key': to_camel_case(x.key), 'message': x.message } for x in err.errors] if error.locations is not None: formatted_error['locations'] = [{ 'line': loc.line, 'column': loc.column } for loc in error.locations] return formatted_error if isinstance(error, GraphQLError): return format_graphql_error(error) return {'message': str(error)}
def convert_django_input_field_with_choices(field, registry=None, convert_choices_to_enum=True): if registry is not None: converted = registry.get_converted_field(field) if converted: return converted choices = getattr(field, "choices", None) if choices and convert_choices_to_enum: meta = field.model._meta name = to_camel_case("{}_{}".format(meta.object_name, field.name)) choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) required = not (field.blank or field.null) converted = enum(description=field.help_text, required=required) else: converted = convert_django_input_field(field, registry) if registry is not None: registry.register_converted_field(field, converted) return converted
def formfield(self, **kwargs): # Postfixing newly created filter with Argument to avoid conflicts # with query nodes meta = self.model._meta name = to_camel_case(f"{meta.object_name}_{self.name}_argument") return super().formfield(label=name, **kwargs)
def dynamic_type(): key = '{}_{}'.format(field.name, field.model.__name__.lower()) if input_flag is not None: key = '{}_{}'.format(key, input_flag) key = to_camel_case(key) model = field.model ct_field = None fk_field = None required = False for f in get_model_fields(model): if f[0] == field.ct_field: ct_field = f[1] elif f[0] == field.fk_field: fk_field = f[1] if fk_field is not None and ct_field is not None: break if ct_field is not None and fk_field is not None: required = (is_required(ct_field) and is_required(fk_field)) or required if input_flag: return GenericForeignKeyInputType(description='Input Type for a GenericForeignKey field', required=required and input_flag == 'create') _type = registry.get_type_for_enum(key) if not _type: _type = GenericForeignKeyType # return Field(_type, description=field.help_text or field.verbose_name, required=field.null) return Field(_type, description='Type for a GenericForeignKey field', required=required and input_flag == 'create')
def create_mutation(schemas): base = (graphene.ObjectType,) mutations = {to_camel_case(mutation.__name__): mutation.Field() for schema in schemas for mutation in schema.mutations.values()} mutation_type = type('Mutation', base, mutations) return add_schemas(mutation_type, schemas)
def convert_post_data_to_formset_data( snake_formset_name: str, formset: forms.BaseFormSet, data: QueryDict ) -> QueryDict: ''' Convert CamelCased POST data for the given formsets into snake_cased POST data. ''' snake_cased_data = QueryDict(mutable=True) camel_formset_name = to_camel_case(snake_formset_name) total_forms_key = f'{camel_formset_name}-{formsets.TOTAL_FORM_COUNT}' total_forms = _get_safe_int( data.get(total_forms_key, ''), default=0, max_value=formsets.DEFAULT_MAX_NUM) for special_key in SPECIAL_FORMSET_FIELD_NAMES: snake_key = f'{snake_formset_name}-{special_key}' camel_key = f'{camel_formset_name}-{special_key}' value = data.getlist(camel_key) _set_list_if_nonempty(snake_cased_data, snake_key, value) form = get_formset_form(formset) for i in range(total_forms): for snake_field_name in form.fields: snake_key = f'{snake_formset_name}-{i}-{snake_field_name}' camel_key = f'{camel_formset_name}-{i}-{to_camel_case(snake_field_name)}' value = data.getlist(camel_key) _set_list_if_nonempty(snake_cased_data, snake_key, value) return snake_cased_data
def convert_django_field_with_choices( field, registry=None, input_flag=None, nested_field=False ): choices = getattr(field, "choices", None) if choices: meta = field.model._meta name = "{}_{}_{}".format(meta.object_name, field.name, "Enum") if input_flag: name = "{}_{}".format(name, input_flag) name = to_camel_case(name) enum = registry.get_type_for_enum(name) if not enum: enum = construct_enum_field_type(name, choices) registry.register_enum(name, enum) if type(field).__name__ == "MultiSelectField": return DjangoListField( enum, description=field.help_text or field.verbose_name, required=is_required(field) and input_flag == "create", ) return enum( description=field.help_text or field.verbose_name, required=is_required(field) and input_flag == "create", ) return convert_django_field(field, registry, input_flag, nested_field)
def validate_mutation(validate_dict, data): for key in validate_dict.keys(): if key in data.keys(): validator = validate_dict[key] camel_case_key = to_camel_case(key) if type(data[key]) == str: max_length = validator.get('max') max_length_invalid = max_length is not None and len( data[key]) > max_length min_length = validator.get('min') min_length_invalid = min_length is not None and len( data[key]) < min_length if max_length_invalid or min_length_invalid: raise GraphQLError( f'Value in field {camel_case_key} outside constraints') else: max_value = validator.get('max') max_value_invalid = max_value is not None and data[ key] > validator['max'] min_value = validator.get('min') min_value_invalid = min_value is not None and data[ key] < validator['min'] if max_value_invalid or min_value_invalid: raise GraphQLError( f'Value in field {camel_case_key} outside constraints')
def convert_with_choices(field, choices): meta = field.model._meta name = to_camel_case("{}_{}".format(meta.object_name, field.name)) choices = [(convert_choice_name(value), str(name)) for value, name in choices] enum = Enum(name, choices) return enum(required=not field.null)
def from_errors(cls, errors): data = { to_camel_case(key) if key != "__all__" and graphene_settings.CAMELCASE_ERRORS else key: value for key, value in errors.items() } return [cls(field=key, messages=value) for key, value in data.items()]
def schema_for_field(field, name, registry=None): registry = registry or get_global_registry() s = get_field_schema(field, registry) default_value = getattr(field, "default", None) if default_value is NOT_PROVIDED: default_value = None if default_value is not None and callable(default_value): default_value = default_value() if default_value is not None: if isinstance(default_value, decimal.Decimal): default_value = str(default_value) if isinstance(default_value, (datetime.datetime, datetime.date, datetime.time)): default_value = default_value.isoformat() if isinstance(field, (ManyToOneRel, ManyToManyRel)): required = not field.null else: required = not field.blank and field.default is NOT_PROVIDED items = getattr(field, "choices", None) if items: if isinstance(items, dict): # pragma:nocover items = items.items() choices = [] for (_original_v, label), (n, _value, _desc) in zip(items, get_choices(items)): choices.append( { "label": label, "value": n, } ) else: choices = None s = update_dict_nested( s, { "name": to_camel_case(name), # FIXME: Get verbose_name and help_text for m2m "label": getattr(field, "verbose_name", None), "help_text": getattr(field, "help_text", None), "hidden": name == "id", "choices": choices, "default_value": default_value, "validation": { "required": required, "min_length": getattr(field, "min_length", None), "max_length": getattr(field, "max_length", None), "min_value": None, "max_value": None, }, }, ) return s
def test_update_product_variant_unset_amounts( staff_api_client, product, permission_manage_products, field ): """Ensure setting nullable amounts to null is properly handled (setting the amount to none) and doesn't override the currency. """ query = """ mutation updateVariant ( $id: ID!, $sku: String!, $costPrice: Decimal, $priceOverride: Decimal) { productVariantUpdate( id: $id, input: { sku: $sku, costPrice: $costPrice, priceOverride: $priceOverride }) { productVariant { name sku quantity costPrice { currency amount localized } priceOverride { currency amount localized } } } } """ variant = product.variants.first() variant_id = graphene.Node.to_global_id("ProductVariant", variant.pk) sku = variant.sku camel_case_field_name = to_camel_case(field) variables = {"id": variant_id, "sku": sku, camel_case_field_name: None} response = staff_api_client.post_graphql( query, variables, permissions=[permission_manage_products] ) variant.refresh_from_db() assert variant.currency is not None assert getattr(variant, field) is None content = get_graphql_content(response) data = content["data"]["productVariantUpdate"]["productVariant"] assert data[camel_case_field_name] is None
class Meta: model = kwargs.get('model') name = kwargs.get('name') or to_camel_case('{}_Generic_Type'.format(kwargs.get('model') .__name__)) only_fields = kwargs.get('only_fields') exclude_fields = kwargs.get('exclude_fields') filter_fields = kwargs.get('filter_fields') registry = kwargs.get('registry') skip_registry = kwargs.get('skip_registry') description = 'Auto generated Type for {} model'.format(kwargs.get('model')._meta.verbose_name)
def filter_for_lookup(cls, field, lookup_type): filter_class, params = super().filter_for_lookup(field, lookup_type) if issubclass(filter_class, ChoiceFilter): meta = field.model._meta # Postfixing newly created filter with Argument to avoid conflicts # with query nodes name = to_camel_case(f"{meta.object_name}_{field.name}_argument") params["label"] = name return filter_class, params
def register(self, cls, for_input=None): from .types import DjangoInputObjectType, DjangoObjectType assert issubclass( cls, (DjangoInputObjectType, DjangoObjectType)), 'Only DjangoInputObjectType or DjangoObjectType can be' \ ' registered, received "{}"'.format(cls.__name__) assert cls._meta.registry == self, 'Registry for a Model have to match.' if not getattr(cls._meta, 'skip_registry', False): key = '{}_{}'.format(cls._meta.model.__name__.lower(), for_input) \ if for_input else cls._meta.model.__name__.lower() self._registry[to_camel_case(key)] = cls
def convert_django_field_with_choices(field, registry=None): choices = getattr(field, 'choices', None) if choices: meta = field.model._meta name = to_camel_case('{}_{}'.format(meta.object_name, field.name)) choices = list(get_choices(choices)) named_choices = [(c[0], c[1]) for c in choices] named_choices_descriptions = {c[0]: c[2] for c in choices} class EnumWithDescriptionsType(object): @property def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) return enum(description=field.help_text, required=not field.null) return convert_django_field(field, registry)
def resolve(value, directive, root, info, **kwargs): value = value if isinstance(value, six.string_types) else str(value) return to_camel_case(value)
def get_type_for_model(self, model, for_input=None): key = '{}_{}'.format(model.__name__.lower(), for_input) if for_input else model.__name__.lower() return self._registry.get(to_camel_case(key))