async def the_resolver(obj: Any, args: Dict[str, Any], *_: Any): if args: if 'id' in args: args['obj_id'] = args['id'] del args['id'] args = pythonify_dict(args) prop = getattr(obj, python_name) check.invariant(callable(prop), 'must be async function') return await prop(**args)
async def mutation_resolver(obj: Any, args: Dict[str, Any], context: PentContext, *_: Any) -> Any: args = process_args(args) pent_data_cls = context.cls_from_name(pent_data_cls_name) pent_data = pent_data_cls(**args['data']) args['data'] = pent_data prop = getattr(obj, python_name) check.invariant(callable(prop), 'must be async function') return await prop(**args)
def create_grapple_type_definition(type_ast: TypeDefinition) -> GrappleTypeDef: check.isinst(type_ast, TypeDefinition) if isinstance(type_ast, ObjectTypeDefinition): return create_grapple_object_type(type_ast) elif isinstance(type_ast, InputObjectTypeDefinition): return create_grapple_input_type(type_ast) elif isinstance(type_ast, EnumTypeDefinition): return create_grapple_enum_type(type_ast) check.invariant(False, 'node not supported: ' + str(type_ast)) return None
def print_generated_pent_payload(writer: CodeWriter, payload_type: GrappleTypeDef) -> None: check.invariant(payload_type.type_varietal == TypeVarietal.OBJECT, 'must be object') check.invariant( len(payload_type.fields) == 1, 'Payload type should only have one field') out_field = payload_type.fields[0] payload_class_text = PENT_PAYLOAD_DATA_TEMPLATE.format( name=payload_type.name, field_name=out_field.python_name) writer.line(payload_class_text)
def print_generated_enum(writer: CodeWriter, enum_type: GrappleTypeDef) -> None: check.invariant(enum_type.type_varietal == TypeVarietal.ENUM, 'must be enum') writer.line('class {name}(Enum):'.format(name=enum_type.name)) writer.increase_indent() for value in enum_type.values: writer.line("{value} = '{value}'".format(value=value)) writer.decrease_indent() writer.blank_line()
def get_mutation_classes(document_ast: GrappleDocument, field: GrappleField) -> Tuple[str, str, str]: data_cls = get_data_arg_in_pent(field) payload_cls = field.type_ref.python_typename payload_type = document_ast.type_named(payload_cls) check.invariant( len(payload_type.fields) == 1, 'payload class for vanilla crud should only have one field') data_field = payload_type.fields[0] pent_cls = data_field.type_ref.python_typename return (pent_cls, data_cls, payload_cls)
def print_create_pent_field(writer: CodeWriter, document_ast: GrappleDocument, field: GrappleField) -> None: check.invariant(len(field.args) == 1, 'createPent should only have 1 arg') pent_cls, data_cls, payload_cls = get_mutation_classes(document_ast, field) writer.line('async def %s(self, data):' % field.python_name) writer.increase_indent() # begin implemenation writer.line( "return await gen_create_pent_dynamic" "(self.context, '{pent_cls}', '{data_cls}', '{payload_cls}', data)". format(pent_cls=pent_cls, data_cls=data_cls, payload_cls=payload_cls)) writer.decrease_indent() # end implemenation writer.blank_line()
def print_create_pent_field(writer: CodeWriter, document_ast: GrappleDocument, field: GrappleField) -> None: check.invariant(len(field.args) == 1, 'createPent should only have 1 arg') pent_cls, data_cls, payload_cls = get_mutation_classes(document_ast, field) writer.line( "async def {name}(self, data: '{data_cls}') -> Pent: # mypy circ {typing}" .format(name=field.python_name, data_cls=data_cls, typing=python_typing_string(field.type_ref))) writer.increase_indent() # begin implemenation writer.line( "return await gen_create_pent_dynamic" "(self.context, '{pent_cls}', '{data_cls}', '{payload_cls}', data) # type: ignore" .format(pent_cls=pent_cls, data_cls=data_cls, payload_cls=payload_cls)) writer.decrease_indent() # end implemenation writer.blank_line()
def print_update_pent_field(writer: CodeWriter, document_ast: GrappleDocument, field: GrappleField) -> None: check.invariant(len(field.args) == 2, 'updatePent should have 2 args') check_required_id_arg(field) pent_cls, data_cls, payload_cls = get_mutation_classes(document_ast, field) writer.line(("async def {name}(self, obj_id: UUID, data: '{data_cls}')" " -> PentMutationPayload: # mypy circ {typing}").format( name=field.python_name, data_cls=data_cls, typing=python_typing_string(field.type_ref))) writer.increase_indent() # begin implemenation writer.line( "return await gen_update_pent_dynamic" "(self.context, obj_id, '{pent_cls}', '{data_cls}', '{payload_cls}', data) # type: ignore" .format(pent_cls=pent_cls, data_cls=data_cls, payload_cls=payload_cls)) writer.decrease_indent() # end implementation writer.blank_line()
def get_stored_on_type(field: GrappleField) -> str: check.invariant(field.type_ref.varietal == TypeRefVarietal.NONNULL, 'outer non null') check.invariant(field.type_ref.inner_type.varietal == TypeRefVarietal.LIST, 'then list') check.invariant( field.type_ref.inner_type.inner_type.varietal == TypeRefVarietal.NONNULL, 'then nonnull' ) check.invariant( field.type_ref.inner_type.inner_type.inner_type.varietal == TypeRefVarietal.NAMED, 'then named' ) return field.type_ref.inner_type.inner_type.inner_type.python_typename
def print_gen_from_stored_id_field(writer: CodeWriter, field: GrappleField) -> None: check.invariant( len(field.args) == 0, 'genFromStoredId should have no args') check.invariant(field.type_ref.varietal == TypeRefVarietal.NAMED, 'only supports bare types for now') cls_name = field.type_ref.python_typename # very hard coded for now. should be configurable via argument to directive optionally prop = to_snake_case(field.name) + '_id' writer.line("async def %s(self) -> Pent: # mypy circ %s" % (field.python_name, python_typing_string(field.type_ref))) writer.increase_indent() # begin implemenation writer.line("return await self.gen_from_stored_id_dynamic" "('{cls_name}', '{prop}') # type: ignore".format( cls_name=cls_name, prop=prop)) writer.decrease_indent() # end implementation writer.blank_line()
def print_delete_pent_field(writer: CodeWriter, field: GrappleField) -> None: check.invariant(len(field.args) == 1, 'deletePent should only have 1 arg') check_required_id_arg(field) if not isinstance(field.field_varietal_data, DeletePentData): check.failed('must be DeletePentData') payload_cls = field.type_ref.python_typename pent_cls = field.field_varietal_data.type writer.line( "async def %s(self, obj_id: UUID) -> PentMutationPayload: # mypy circ %s" % (field.python_name, python_typing_string(field.type_ref))) writer.increase_indent() # begin implemenation writer.line( ("return await gen_delete_pent_dynamic(self.context" ", '{pent_cls}', '{payload_cls}', obj_id) # type: ignore").format( pent_cls=pent_cls, payload_cls=payload_cls)) writer.decrease_indent() # end implementation writer.blank_line()
def print_graphql_field(writer: CodeWriter, _document_ast: GrappleDocument, grapple_field: GrappleField) -> None: type_ref_str = type_ref_string(grapple_field.type_ref) writer.line("'%s': GraphQLField(" % grapple_field.name) writer.increase_indent() # begin args to GraphQLField .ctor writer.line('type=%s, # type: ignore' % type_ref_str) if grapple_field.args: writer.line('args={') writer.increase_indent() # begin entries in args dictionary for grapple_arg in grapple_field.args: arg_type_ref_str = type_ref_string(grapple_arg.type_ref) if grapple_arg.default_value is None: writer.line("'%s': GraphQLArgument(type=%s), # type: ignore" % (grapple_arg.name, arg_type_ref_str)) else: writer.line( "'%s': GraphQLArgument(type=%s, default_value=%s), # type: ignore" % (grapple_arg.name, arg_type_ref_str, grapple_arg.default_value)) writer.decrease_indent() # end entries in args dictionary writer.line('},') # close args dictionary python_name = grapple_field.python_name if grapple_field.field_varietal.is_mutation: data_arg = None for arg in grapple_field.args: if arg.name == 'data': data_arg = arg break check.invariant(data_arg, 'mutations must have an arg named data') check.invariant(data_arg.name == 'data', 'mutation argument name must be data') check.invariant(data_arg.type_ref.varietal == TypeRefVarietal.NONNULL, 'data argument must be required') data_cls = data_arg.type_ref.inner_type.python_typename writer.line("resolver=define_pent_mutation_resolver('%s', '%s')," % (python_name, data_cls)) elif grapple_field.field_varietal.is_gen_varietal: writer.line("resolver=define_default_gen_resolver('%s')," % python_name) else: writer.line("resolver=define_default_resolver('%s')," % python_name) writer.decrease_indent() # end args to GraphQLField .ctor writer.line('),') # close GraphQLField .ctor
def check_required_id_arg(field: GrappleField) -> None: id_arg = get_required_arg(field.args, 'id') check.invariant(id_arg.type_ref.varietal == TypeRefVarietal.NONNULL, 'arg must be non null') check.invariant(id_arg.type_ref.inner_type.graphql_typename == 'UUID', 'arg must be UUID')
def get_data_arg_in_pent(field: GrappleField) -> str: data_arg = get_required_arg(field.args, 'data') check.invariant(data_arg.type_ref.varietal == TypeRefVarietal.NONNULL, 'input argument must be non null') return data_arg.type_ref.inner_type.python_typename
def get_first_after_args( field: GrappleField ) -> Tuple[GrappleFieldArgument, GrappleFieldArgument, str]: check.invariant(len(field.args) == 2, 'browse/conn should have 2 args') first_arg = get_required_arg(field.args, 'first') check.invariant(first_arg.default_value, 'must have default value') after_arg = get_required_arg(field.args, 'after') check.invariant(after_arg.type_ref.graphql_typename == 'UUID', 'arg must be UUID') check.invariant(field.type_ref.varietal == TypeRefVarietal.NONNULL, 'outer non null') check.invariant(field.type_ref.inner_type.varietal == TypeRefVarietal.LIST, 'then list') check.invariant( field.type_ref.inner_type.inner_type.varietal == TypeRefVarietal.NONNULL, 'then nonnull') check.invariant( field.type_ref.inner_type.inner_type.inner_type.varietal == TypeRefVarietal.NAMED, 'then named') target_type = field.type_ref.inner_type.inner_type.inner_type.python_typename return (first_arg, after_arg, target_type)