Exemple #1
0
class Query(graphene.ObjectType):
    """Allow querying objects."""

    allReleases = graphene.List(Release)
    getReleases = graphene.Field(lambda: graphene.List(Release),
                                 name=graphene.String(),
                                 id_prefix=graphene.String(),
                                 composed_by_bodhi=graphene.Boolean(),
                                 state=graphene.String())

    getUpdates = graphene.Field(lambda: graphene.List(Update),
                                stable_karma=graphene.Int(),
                                stable_days=graphene.Int(),
                                unstable_karma=graphene.Int(),
                                status=graphene.String(),
                                request=graphene.String(),
                                pushed=graphene.Boolean(),
                                critpath=graphene.Boolean(),
                                date_approved=graphene.String(),
                                alias=graphene.String(),
                                user_id=graphene.Int(),
                                release_name=graphene.String())

    getBuildrootOverrides = graphene.Field(
        lambda: graphene.List(BuildrootOverride),
        submission_date=graphene.DateTime(),
        expiration_date=graphene.DateTime(),
        build_nvr=graphene.String(),
        submitter_username=graphene.String())

    def resolve_allReleases(self, info):
        """Answer Queries by fetching data from the Schema."""
        query = Release.get_query(info)  # SQLAlchemy query
        return query.all()

    def resolve_getReleases(self, info, **args):
        """Answer Release queries with a given argument."""
        query = Release.get_query(info)

        id_prefix = args.get("id_prefix")
        if id_prefix is not None:
            query = query.filter(ReleaseModel.id_prefix == id_prefix)

        name = args.get("name")
        if name is not None:
            query = query.filter(ReleaseModel.name == name)

        composed_by_bodhi = args.get("composed_by_bodhi")
        if composed_by_bodhi is not None:
            query = query.filter(
                ReleaseModel.composed_by_bodhi == composed_by_bodhi)

        state = args.get("state")
        if state is not None:
            query = query.filter(ReleaseModel.state == state)

        return query.all()

    def resolve_getUpdates(self, info, **args):
        """Answer Release queries with a given argument."""
        query = Update.get_query(info)

        stable_karma = args.get("stable_karma")
        if stable_karma is not None:
            query = query.filter(UpdateModel.stable_karma == stable_karma)

        stable_days = args.get("stable_days")
        if stable_days is not None:
            query = query.filter(UpdateModel.stable_days == stable_days)

        unstable_karma = args.get("unstable_karma")
        if unstable_karma is not None:
            query = query.filter(UpdateModel.unstable_karma == unstable_karma)

        status = args.get("status")
        if status is not None:
            query = query.filter(UpdateModel.status == status)

        request = args.get("request")
        if request is not None:
            query = query.filter(UpdateModel.request == request)

        pushed = args.get("pushed")
        if pushed is not None:
            query = query.filter(UpdateModel.pushed == pushed)

        critpath = args.get("critpath")
        if critpath is not None:
            query = query.filter(UpdateModel.critpath == critpath)

        date_approved = args.get("date_approved")
        if date_approved is not None:
            query = query.filter(UpdateModel.date_approved == date_approved)

        alias = args.get("alias")
        if alias is not None:
            query = query.filter(UpdateModel.alias == alias)

        user_id = args.get("user_id")
        if user_id is not None:
            query = query.filter(UpdateModel.user_id == user_id)

        release_name = args.get("release_name")
        if release_name is not None:
            query = query.join(
                UpdateModel.release).filter(ReleaseModel.name == release_name)

        return query.all()

    def resolve_getBuildrootOverrides(self, info, **args):
        """Answer Release queries with a given argument."""
        query = BuildrootOverride.get_query(info)

        submission_date = args.get("submission_date")
        if submission_date is not None:
            query = query.filter(
                BuildrootOverrideModel.submission_date == submission_date)

        expiration_date = args.get("expiration_date")
        if expiration_date is not None:
            query = query.filter(
                BuildrootOverrideModel.expiration_date == expiration_date)

        build_nvr = args.get("build_nvr")
        if build_nvr is not None:
            query = query.join(BuildrootOverrideModel.build).filter(
                BuildModel.nvr == build_nvr)

        submitter_username = args.get("submitter_username")
        if submitter_username is not None:
            query = query.join(BuildrootOverrideModel.submitter).filter(
                UserModel.name == submitter_username)

        return query.all()
Exemple #2
0
class Query(graphene.AbstractType):
    all_services = graphene.List(ServiceType, kind=graphene.String())
    all_locations = graphene.List(LocationType, id=graphene.Int())
    all_items = graphene.List(MissingItemType, id=graphene.Int())
    all_offices = graphene.List(OfficeType, id=graphene.Int())
    all_querys = graphene.List(SQLQueryType, id=graphene.Int())
    service = graphene.Field(ServiceType, id=graphene.Int())
    location = graphene.Field(LocationType, id=graphene.Int())
    item = graphene.Field(MissingItemType, id=graphene.Int())
    office = graphene.Field(OfficeType, id=graphene.Int())
    query = graphene.Field(SQLQueryType, id=graphene.Int())

    def resolve_all_services(self, info, **kwargs):
        kind = kwargs.get('kind')
        if kind is not None:
            return Service.objects.all().filter(kind=kind)

        return Service.objects.all()

    def resolve_all_locations(self, info, **kwargs):
        id = kwargs.get('id')
        source = None

        if id is not None:
            source = Service.objects.get(pk=id)

        if source is not None:
            return Location.objects.all().filter(Service=source)

        return Location.objects.all()

    def resolve_all_items(self, info, **kwargs):
        id = kwargs.get('id')
        source = None

        if id is not None:
            source = Service.objects.get(pk=id)

        if source is not None:
            return MissingItem.objects.all().filter(Service=source)

        return MissingItem.objects.all()

    def resolve_all_offices(self, info, **kwargs):
        id = kwargs.get('id')
        source = None

        if id is not None:
            source = Service.objects.get(pk=id)

        if source is not None:
            return Office.objects.all().filter(Service=source)

        return Office.objects.all()

    def resolve_all_querys(self, info, **kwargs):
        id = kwargs.get('id')
        source = None

        if id is not None:
            source = Service.objects.get(pk=id)

        if source is not None:
            return SQLQuery.objects.all().filter(Service=source)

        return SQLQuery.objects.all()

    def resolve_service(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return Service.objects.get(pk=id)

        return None

    def resolve_location(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return Location.objects.get(pk=id)

        return None

    def resolve_item(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return MissingItem.objects.get(pk=id)

        return None

    def resolve_office(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return Office.objects.get(pk=id)

        return None

    def resolve_query(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return SQLQuery.objects.get(pk=id)

        return None
Exemple #3
0
class ProductStockFilterInput(graphene.InputObjectType):
    warehouse_ids = graphene.List(graphene.NonNull(graphene.ID),
                                  required=False)
    quantity = graphene.Field(IntRangeInput, required=False)
Exemple #4
0
class ProductVariant(CountableDjangoObjectType, MetadataObjectType):
    quantity = graphene.Int(
        required=True,
        description="Quantity of a product in the store's possession, "
        "including the allocated stock that is waiting for shipment.",
    )
    stock_quantity = graphene.Int(
        required=True, description="Quantity of a product available for sale."
    )
    price_override = graphene.Field(
        Money,
        description=(
            "Override the base price of a product if necessary. A value of `null` "
            "indicates that the default product price is used."
        ),
    )
    price = graphene.Field(
        Money,
        description="Price of the product variant.",
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, "
            "has been replaced by 'pricing.priceUndiscounted'"
        ),
    )
    availability = graphene.Field(
        VariantPricingInfo,
        description=(
            "Informs about variant's availability in the storefront, current price and "
            "discounted price."
        ),
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, has been renamed to `pricing`."
        ),
    )
    pricing = graphene.Field(
        VariantPricingInfo,
        description=(
            "Lists the storefront variant's pricing, the current price and discounts, "
            "only meant for displaying."
        ),
    )
    is_available = graphene.Boolean(
        description="Whether the variant is in stock and visible or not."
    )
    attributes = gql_optimizer.field(
        graphene.List(
            graphene.NonNull(SelectedAttribute),
            required=True,
            description="List of attributes assigned to this variant.",
        )
    )
    cost_price = graphene.Field(Money, description="Cost price of the variant.")
    margin = graphene.Int(description="Gross margin percentage value.")
    quantity_ordered = graphene.Int(description="Total quantity ordered.")
    revenue = graphene.Field(
        TaxedMoney,
        period=graphene.Argument(ReportingPeriod),
        description=(
            "Total revenue generated by a variant in given period of time. Note: this "
            "field should be queried using `reportProductSales` query as it uses "
            "optimizations suitable for such calculations."
        ),
    )
    images = gql_optimizer.field(
        graphene.List(
            lambda: ProductImage, description="List of images for the product variant."
        ),
        model_field="images",
    )
    translation = graphene.Field(
        ProductVariantTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=(
            "Returns translated Product Variant fields " "for the given language code."
        ),
        resolver=resolve_translation,
    )
    digital_content = gql_optimizer.field(
        graphene.Field(
            DigitalContent, description="Digital content for the product variant."
        ),
        model_field="digital_content",
    )

    class Meta:
        description = (
            "Represents a version of a product such as different size or color."
        )
        only_fields = [
            "id",
            "name",
            "product",
            "quantity_allocated",
            "sku",
            "track_inventory",
            "weight",
        ]
        interfaces = [relay.Node]
        model = models.ProductVariant

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_digital_content(root: models.ProductVariant, *_args):
        return getattr(root, "digital_content", None)

    @staticmethod
    def resolve_stock_quantity(root: models.ProductVariant, _info):
        exact_quantity_available = root.quantity_available
        return min(exact_quantity_available, settings.MAX_CHECKOUT_LINE_QUANTITY)

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=["attributes__values", "attributes__assignment__attribute"]
    )
    def resolve_attributes(root: models.ProductVariant, info):
        return resolve_attribute_list(root, user=info.context.user)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_margin(root: models.ProductVariant, *_args):
        return get_margin_for_variant(root)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_cost_price(root: models.ProductVariant, *_args):
        return root.cost_price

    @staticmethod
    def resolve_price(root: models.ProductVariant, *_args):
        return (
            root.price_override
            if root.price_override is not None
            else root.product.price
        )

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("product",), only=["price_override_amount", "currency"]
    )
    def resolve_pricing(root: models.ProductVariant, info):
        context = info.context
        availability = get_variant_availability(
            root,
            context.discounts,
            context.country,
            context.currency,
            extensions=context.extensions,
        )
        return VariantPricingInfo(**availability._asdict())

    resolve_availability = resolve_pricing

    @staticmethod
    def resolve_is_available(root: models.ProductVariant, _info):
        return root.is_available

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_price_override(root: models.ProductVariant, *_args):
        return root.price_override

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_quantity(root: models.ProductVariant, *_args):
        return root.quantity

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_quantity_ordered(root: models.ProductVariant, *_args):
        # This field is added through annotation when using the
        # `resolve_report_product_sales` resolver.
        return getattr(root, "quantity_ordered", None)

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_quantity_allocated(root: models.ProductVariant, *_args):
        return root.quantity_allocated

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_revenue(root: models.ProductVariant, *_args, period):
        start_date = reporting_period_to_date(period)
        return calculate_revenue_for_variant(root, start_date)

    @staticmethod
    def resolve_images(root: models.ProductVariant, *_args):
        return root.images.all()

    @classmethod
    def get_node(cls, info, id):
        user = info.context.user
        visible_products = models.Product.objects.visible_to_user(user).values_list(
            "pk", flat=True
        )
        qs = cls._meta.model.objects.filter(product__id__in=visible_products)
        return cls.maybe_optimize(info, qs, id)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_private_meta(root, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
Exemple #5
0
class ProductType(CountableDjangoObjectType, MetadataObjectType):
    products = gql_optimizer.field(
        PrefetchingConnectionField(
            Product, description="List of products of this type."
        ),
        prefetch_related=prefetch_products,
    )
    tax_rate = TaxRateType(description="A type of tax rate.")
    tax_type = graphene.Field(
        TaxType, description="A type of tax. Assigned by enabled tax gateway"
    )
    variant_attributes = graphene.List(
        Attribute, description="Variant attributes of that product type."
    )
    product_attributes = graphene.List(
        Attribute, description="Product attributes of that product type."
    )
    available_attributes = gql_optimizer.field(
        FilterInputConnectionField(Attribute, filter=AttributeFilterInput())
    )

    class Meta:
        description = (
            "Represents a type of product. It defines what attributes are available to "
            "products of this type."
        )
        interfaces = [relay.Node]
        model = models.ProductType
        only_fields = [
            "has_variants",
            "id",
            "is_digital",
            "is_shipping_required",
            "name",
            "weight",
            "tax_type",
        ]

    @staticmethod
    def resolve_tax_type(root: models.ProductType, info):
        tax_data = info.context.extensions.get_tax_code_from_object_meta(root)
        return TaxType(tax_code=tax_data.code, description=tax_data.description)

    @staticmethod
    def resolve_tax_rate(root: models.ProductType, info, **_kwargs):
        # FIXME this resolver should be dropped after we drop tax_rate from API
        if not hasattr(root, "meta"):
            return None
        tax = root.meta.get("taxes", {}).get("vatlayer", {})
        return tax.get("code")

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related="product_attributes__attributeproduct"
    )
    def resolve_product_attributes(root: models.ProductType, *_args, **_kwargs):
        return root.product_attributes.product_attributes_sorted().all()

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related="variant_attributes__attributevariant"
    )
    def resolve_variant_attributes(root: models.ProductType, *_args, **_kwargs):
        return root.variant_attributes.variant_attributes_sorted().all()

    @staticmethod
    def resolve_products(root: models.ProductType, info, **_kwargs):
        if hasattr(root, "prefetched_products"):
            return root.prefetched_products
        qs = root.products.visible_to_user(info.context.user)
        return gql_optimizer.query(qs, info)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_available_attributes(root: models.ProductType, info, **kwargs):
        qs = models.Attribute.objects.get_unassigned_attributes(root.pk)
        return resolve_attributes(info, qs=qs, **kwargs)

    @staticmethod
    @permission_required("account.manage_products")
    def resolve_private_meta(root, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
class BillNode(OCDBaseNode):
    legislative_session = graphene.Field(LegislativeSessionNode)
    identifier = graphene.String()
    title = graphene.String()
    from_organization = graphene.Field(OrganizationNode)
    classification = graphene.List(graphene.String)
    subject = graphene.List(graphene.String)

    # related fields
    abstracts = graphene.List(BillAbstractNode)
    other_titles = graphene.List(BillTitleNode)
    other_identifiers = graphene.List(BillIdentifierNode)
    actions = graphene.List(BillActionNode)
    sponsorships = graphene.List(BillSponsorshipNode)
    related_bills = graphene.List(RelatedBillNode)
    documents = graphene.List(BillDocumentNode)
    versions = graphene.List(BillDocumentNode)
    sources = graphene.List(LinkNode)
    votes = DjangoConnectionField("graphapi.legislative.VoteConnection")

    # extra fields
    openstates_url = graphene.String()

    def resolve_abstracts(self, info):
        return self.abstracts.all()

    def resolve_other_titles(self, info):
        return self.other_titles.all()

    def resolve_other_identifiers(self, info):
        return self.other_identifiers.all()

    def resolve_actions(self, info):
        if "actions" not in getattr(self, "_prefetched_objects_cache", []):
            return optimize(
                self.actions.all(),
                info,
                [
                    (
                        ".relatedEntities",
                        Prefetch(
                            "related_entities",
                            BillActionRelatedEntity.objects.all().select_related(
                                "organization", "person"
                            ),
                        ),
                    )
                ],
                [".organization"],
            )
        else:
            return self.actions.all()

    def resolve_sponsorships(self, info):
        return self.sponsorships.all()

    def resolve_documents(self, info):
        if "documents" not in getattr(self, "_prefetched_objects_cache", []):
            return optimize(self.documents.all(), info, [".links"])
        else:
            return self.documents.all()

    def resolve_versions(self, info):
        if "versions" not in getattr(self, "_prefetched_objects_cache", []):
            return optimize(self.versions.all(), info, [".links"])
        else:
            return self.versions.all()

    def resolve_sources(self, info):
        return self.sources.all()

    def resolve_votes(self, info, first=None, last=None, before=None, after=None):
        if "votes" not in getattr(self, "_prefetched_objects_cache", []):
            return optimize(
                self.votes.all(),
                info,
                [
                    ".counts",
                    (
                        ".votes",
                        Prefetch(
                            "votes", PersonVote.objects.all().select_related("voter")
                        ),
                    ),
                ],
            )
        else:
            return self.votes.all()

    def resolve_related_bills(self, info):
        if "related_bills" not in getattr(self, "_prefetched_objects_cache", []):
            return optimize(self.related_bills.all(), info, None, [".relatedBill"])
        else:
            return self.related_bills.all()

    def resolve_openstates_url(self, info):
        session = self.legislative_session
        abbr = session.jurisdiction_id.split("/")[-2].split(":")[1]
        identifier = self.identifier.replace(" ", "")
        return f"https://openstates.org/{abbr}/bills/{session.identifier}/{identifier}"
Exemple #7
0
class GraphenePartition(graphene.ObjectType):
    name = graphene.NonNull(graphene.String)
    partition_set_name = graphene.NonNull(graphene.String)
    solid_selection = graphene.List(graphene.NonNull(graphene.String))
    mode = graphene.NonNull(graphene.String)
    runConfigOrError = graphene.NonNull(GraphenePartitionRunConfigOrError)
    tagsOrError = graphene.NonNull(GraphenePartitionTagsOrError)
    runs = graphene.Field(
        non_null_list(GraphenePipelineRun),
        filter=graphene.Argument(GraphenePipelineRunsFilter),
        cursor=graphene.String(),
        limit=graphene.Int(),
    )
    status = graphene.Field(GraphenePipelineRunStatus)

    class Meta:
        name = "Partition"

    def __init__(self, external_repository_handle, external_partition_set,
                 partition_name):
        self._external_repository_handle = check.inst_param(
            external_repository_handle, "external_respository_handle",
            RepositoryHandle)
        self._external_partition_set = check.inst_param(
            external_partition_set, "external_partition_set",
            ExternalPartitionSet)
        self._partition_name = check.str_param(partition_name,
                                               "partition_name")

        super().__init__(
            name=partition_name,
            partition_set_name=external_partition_set.name,
            solid_selection=external_partition_set.solid_selection,
            mode=external_partition_set.mode,
        )

    def resolve_runConfigOrError(self, graphene_info):
        return get_partition_config(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set.name,
            self._partition_name,
        )

    def resolve_tagsOrError(self, graphene_info):
        return get_partition_tags(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set.name,
            self._partition_name,
        )

    def resolve_runs(self, graphene_info, **kwargs):
        filters = kwargs.get("filter")
        partition_tags = {
            PARTITION_SET_TAG: self._external_partition_set.name,
            PARTITION_NAME_TAG: self._partition_name,
        }
        if filters is not None:
            filters = filters.to_selector()
            runs_filter = PipelineRunsFilter(
                run_ids=filters.run_ids,
                pipeline_name=filters.pipeline_name,
                statuses=filters.statuses,
                tags=merge_dicts(filters.tags, partition_tags),
            )
        else:
            runs_filter = PipelineRunsFilter(tags=partition_tags)

        return get_runs(graphene_info,
                        runs_filter,
                        cursor=kwargs.get("cursor"),
                        limit=kwargs.get("limit"))
Exemple #8
0
class SetPassword(CreateToken):
    user = graphene.Field(User,
                          description="A user instance with new password.")
    account_errors = graphene.List(
        graphene.NonNull(AccountError),
        description="List of errors that occurred executing the mutation.",
    )

    class Arguments:
        token = graphene.String(
            description="A one-time token required to set the password.",
            required=True)

    class Meta:
        description = ("Sets the user's password from the token sent by email "
                       "using the RequestPasswordReset mutation.")

    @classmethod
    def mutate(cls, root, info, **data):
        email = data["email"]
        password = data["password"]
        token = data["token"]

        try:
            cls._set_password_for_user(email, password, token)
        except ValidationError as e:
            errors = validation_error_to_error_type(e)
            return cls.handle_typed_errors(errors)
        return super().mutate(root, info, **data)

    @classmethod
    def _set_password_for_user(cls, email, password, token):
        try:
            user = models.User.objects.get(email=email)
        except ObjectDoesNotExist:
            raise ValidationError({
                "email":
                ValidationError("User doesn't exist",
                                code=AccountErrorCode.NOT_FOUND)
            })
        if not default_token_generator.check_token(user, token):
            raise ValidationError({
                "token":
                ValidationError(INVALID_TOKEN, code=AccountErrorCode.INVALID)
            })
        try:
            password_validation.validate_password(password, user)
        except ValidationError as error:
            raise ValidationError({"password": error})
        user.set_password(password)
        user.save(update_fields=["password"])
        account_events.customer_password_reset_event(user=user)

    @classmethod
    def handle_typed_errors(cls, errors: list):
        account_errors = [
            AccountError(field=e.field, message=e.message, code=code)
            for e, code, _params in errors
        ]
        return cls(errors=[e[0] for e in errors],
                   account_errors=account_errors)
Exemple #9
0
 class Arguments:
     ids = graphene.List(graphene.ID,
                         required=True,
                         description='List of page IDs to delete.')
Exemple #10
0
def _get_fields(model, only_fields, exclude_fields, required_fields):
    fields = [
        (field.name, field)
        for field in sorted(list(model._meta.fields +
                                 model._meta.many_to_many))
    ]

    # Only add the field as input field if the foreign key (reverse side)
    # can be set to null, otherwise updates won't work.
    fields.extend([
        (field.related_name or field.name + "_set", field) for field in sorted(
            list(model._meta.related_objects),
            key=lambda field: field.name,
        ) if not isinstance(field, ManyToOneRel) or field.remote_field.null
    ], )

    ret = collections.OrderedDict()
    for name, field in fields:
        if ((only_fields and name not in only_fields) or name in exclude_fields
                or str(name).endswith("+")
                or name in ["created_at", "updated_at", "archived_at"]):
            continue

        if name == "id":
            f = graphene.ID(description="The ID of the object.", )
        elif isinstance(field, models.FileField):
            f = UploadType(description=field.help_text, )
        elif isinstance(field, models.BooleanField):
            f = graphene.Boolean(description=field.help_text, )
        elif isinstance(field, (models.ForeignKey, models.OneToOneField)):
            f = graphene.ID(description=field.help_text, )
        elif isinstance(field, models.ManyToManyField):
            f = graphene.List(
                graphene.ID,
                description=field.help_text,
            )
        elif isinstance(field, (ManyToOneRel, ManyToManyRel)):
            reverse_rel_include = graphene_django_plus_settings.MUTATIONS_INCLUDE_REVERSE_RELATIONS
            # Checking whether it was globally configured to not include reverse relations
            if isinstance(field, ManyToOneRel
                          ) and not reverse_rel_include and not only_fields:
                continue

            f = graphene.List(
                graphene.ID,
                description="Set list of {0}".format(
                    field.related_model._meta.verbose_name_plural, ),
            )
        else:
            f = convert_django_field_with_choices(field, _registry)

        if required_fields is not None:
            f.kwargs["required"] = name in required_fields
        else:
            if isinstance(field, (ManyToOneRel, ManyToManyRel)):
                f.kwargs["required"] = not field.null
            else:
                f.kwargs[
                    "required"] = not field.blank and field.default is NOT_PROVIDED

        if getattr(field, "choices", None):
            items = field.choices
            if isinstance(items, dict):
                items = items.items()

            choices = []
            for (original_v, label), (n, value,
                                      desc) in zip(items, get_choices(items)):
                choices.append({
                    "label": label,
                    "name": n,
                    "value": value,
                })
        else:
            choices = None

        s = get_field_schema(field)
        s.update({
            "name": name,
            # FIXME: Get verbose_name and help_text for m2m
            "label": getattr(field, "verbose_name", None),
            "help_text": getattr(field, "help_text", None),
            "max_length": getattr(field, "max_length", None),
            "choices": choices,
        })

        ret[name] = {
            "field": f,
            "schema": s,
        }

    return ret
Exemple #11
0
class BaseMutation(ClientIDMutation):
    """Base mutation enchanced with permission checking and relay id handling."""
    class Meta:
        abstract = True

    #: A list of errors that happened during the mutation
    errors = graphene.List(
        graphene.NonNull(MutationErrorType),
        description=_(
            "List of errors that occurred while executing the mutation."),
    )

    @classmethod
    def __init_subclass_with_meta__(
        cls,
        permissions=None,
        permissions_any=True,
        allow_unauthenticated=False,
        input_schema=None,
        _meta=None,
        **kwargs,
    ):
        if not _meta:
            _meta = BaseMutationOptions(cls)

        _meta.permissions = permissions or []
        _meta.permissions_any = permissions_any
        _meta.allow_unauthenticated = allow_unauthenticated
        _meta.input_schema = input_schema or {}

        super().__init_subclass_with_meta__(_meta=_meta, **kwargs)

        iname = cls.Input._meta.name
        input_schema_registry[iname] = {
            "input_object": iname,
            "fields": list(_meta.input_schema.values()),
        }

    @classmethod
    def get_node(cls, info, node_id, field="id", only_type=None):
        """Get the node object given a relay global id."""
        if not node_id:
            return None

        try:
            node = get_node(node_id, only_type)
        except (AssertionError, GraphQLError) as e:
            raise ValidationError({field: str(e)})
        else:
            if node is None:  # pragma: no cover
                raise ValidationError(
                    {field: "Couldn't resolve to a node: {}".format(node_id)})

        return node

    @classmethod
    def get_nodes(cls, ids, field, only_type=None):
        """Get a list of node objects given a list of relay global ids."""
        try:
            instances = get_nodes(ids, only_type)
        except GraphQLError as e:
            raise ValidationError({field: str(e)})

        return instances

    @classmethod
    def check_permissions(cls, user):
        """Check permissions for the given user.

        Subclasses can override this to avoid the permission checking or
        extending it. Remember to call `super()` in the later case.
        """
        if not cls._meta.allow_unauthenticated and not check_authenticated(
                user):
            return False

        if not cls._meta.permissions:
            return True

        return check_perms(user,
                           cls._meta.permissions,
                           any_perm=cls._meta.permissions_any)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **data):
        """Mutate checking permissions.

        We override the default graphene's method to call
        :meth:`.check_permissions` and populate :attr:`.errors` in case
        of errors automatically.

        The mutation itself should be defined in :meth:`.perform_mutation`.
        """
        if not cls.check_permissions(info.context.user):
            raise PermissionDenied()

        try:
            response = cls.perform_mutation(root, info, **data)
            if response.errors is None:
                response.errors = []
            return response
        except ValidationError as e:
            errors = _get_validation_errors(e)
            return cls(errors=errors)

    @classmethod
    def perform_mutation(cls, root, info, **data):
        """Perform the mutation.

        This should be implemented in subclasses to perform the mutation.
        """
        raise NotImplementedError
Exemple #12
0
class GrapheneSensorMetadata(graphene.ObjectType):
    assetKeys = graphene.List(graphene.NonNull(GrapheneAssetKey))

    class Meta:
        name = "SensorMetadata"
Exemple #13
0
class GiftCardBulkCreate(BaseMutation):
    count = graphene.Int(
        required=True,
        default_value=0,
        description="Returns how many objects were created.",
    )
    gift_cards = graphene.List(
        graphene.NonNull(GiftCard),
        required=True,
        default_value=[],
        description="List of created gift cards.",
    )

    class Arguments:
        input = GiftCardBulkCreateInput(
            required=True, description="Fields required to create gift cards."
        )

    class Meta:
        description = f"{ADDED_IN_31} Create gift cards. {PREVIEW_FEATURE}"
        model = models.GiftCard
        permissions = (GiftcardPermissions.MANAGE_GIFT_CARD,)
        error_type_class = GiftCardError

    @classmethod
    @traced_atomic_transaction()
    def perform_mutation(cls, _root, info, **data):
        input_data = data["input"]
        cls.clean_count_value(input_data)
        cls.clean_expiry_date(input_data)
        cls.clean_balance(input_data)
        GiftCardCreate.set_created_by_user(input_data, info)
        tags = input_data.pop("tags", None)
        instances = cls.create_instances(input_data, info)
        if tags:
            cls.assign_gift_card_tags(instances, tags)
        return cls(count=len(instances), gift_cards=instances)

    @staticmethod
    def clean_count_value(input_data):
        if not input_data["count"] > 0:
            raise ValidationError(
                {
                    "count": ValidationError(
                        "Count value must be greater than 0.",
                        code=GiftCardErrorCode.INVALID.value,
                    )
                }
            )

    @staticmethod
    def clean_expiry_date(input_data):
        expiry_date = input_data.get("expiry_date")
        if expiry_date and not is_date_in_future(expiry_date):
            raise ValidationError(
                {
                    "expiry_date": ValidationError(
                        "Expiry date cannot be in the past.",
                        code=GiftCardErrorCode.INVALID.value,
                    )
                }
            )

    @staticmethod
    def clean_balance(cleaned_input):
        balance = cleaned_input["balance"]
        amount = balance["amount"]
        currency = balance["currency"]
        try:
            validate_price_precision(amount, currency)
        except ValidationError as error:
            error.code = GiftCardErrorCode.INVALID.value
            raise ValidationError({"balance": error})
        if not amount > 0:
            raise ValidationError(
                {
                    "balance": ValidationError(
                        "Balance amount have to be greater than 0.",
                        code=GiftCardErrorCode.INVALID.value,
                    )
                }
            )
        cleaned_input["currency"] = currency
        cleaned_input["current_balance_amount"] = amount
        cleaned_input["initial_balance_amount"] = amount

    @staticmethod
    def create_instances(cleaned_input, info):
        count = cleaned_input.pop("count")
        balance = cleaned_input.pop("balance")
        gift_cards = models.GiftCard.objects.bulk_create(
            [
                models.GiftCard(code=generate_promo_code(), **cleaned_input)
                for _ in range(count)
            ]
        )
        events.gift_cards_issued_event(
            gift_cards, info.context.user, info.context.app, balance
        )
        return gift_cards

    @staticmethod
    def assign_gift_card_tags(
        instances: Iterable[models.GiftCard], tags_values: Iterable[str]
    ):
        tags = {tag.lower() for tag in tags_values}
        tags_instances = models.GiftCardTag.objects.filter(name__in=tags)
        tags_to_create = tags - set(tags_instances.values_list("name", flat=True))
        models.GiftCardTag.objects.bulk_create(
            [models.GiftCardTag(name=tag) for tag in tags_to_create]
        )
        for tag_instance in tags_instances.iterator():
            tag_instance.gift_cards.set(instances)
Exemple #14
0
 class Arguments:
     ids = graphene.List(
         graphene.ID,
         required=True,
         description="List of gift card IDs to deactivate.",
     )
Exemple #15
0
 class Arguments:
     ids = graphene.List(graphene.ID,
                         required=True,
                         description="List of orders IDs to cancel.")
class Query(graphene.ObjectType):
    users = graphene.List(Basic)

    def resolve_users(self, info):
        return BasicInformation.objects.all()
Exemple #17
0
class Query(graphene.ObjectType):
    messages = graphene.List(SupportMessageType)

    def resolve_messages(self, info):
        return SupportMessage.objects.all()
Exemple #18
0
class PersonNode(OCDBaseNode):
    name = graphene.String()
    sort_name = graphene.String()
    family_name = graphene.String()
    given_name = graphene.String()
    image = graphene.String()
    # not used: gender, summary, national_identity, biography
    birth_date = graphene.String()
    death_date = graphene.String()

    # related objects
    identifiers = graphene.List(IdentifierNode)
    other_names = graphene.List(NameNode)
    links = graphene.List(LinkNode)
    sources = graphene.List(LinkNode)
    contact_details = graphene.List(ContactDetailNode)

    # special attributes
    current_memberships = graphene.List(
        "graphapi.core.MembershipNode", classification=graphene.List(graphene.String)
    )
    old_memberships = graphene.List(
        "graphapi.core.MembershipNode", classification=graphene.List(graphene.String)
    )
    votes = graphene.List("graphapi.legislative.BillVoteNode")

    def resolve_identifiers(self, info):
        return self.identifiers.all()

    def resolve_other_names(self, info):
        return self.other_names.all()

    def resolve_links(self, info):
        return self.links.all()

    def resolve_sources(self, info):
        return self.sources.all()

    def resolve_contact_details(self, info):
        return self.contact_details.all()

    def resolve_current_memberships(self, info, classification=None):
        if hasattr(self, "current_memberships"):
            if classification:
                return [
                    m
                    for m in self.current_memberships
                    if m.organization.classification in classification
                ]
            return self.current_memberships
        else:
            return _membership_filter(
                self.memberships, info, classification, current=True
            )

    def resolve_old_memberships(self, info, classification=None):
        if hasattr(self, "old_memberships"):
            if classification:
                return [
                    m
                    for m in self.old_memberships
                    if m.organization.classification in classification
                ]
            return self.old_memberships
        else:
            return _membership_filter(
                self.memberships, info, classification, current=False
            )

    def resolve_votes(self, info):
        return self.votes.all()
Exemple #19
0
class GraphenePartitionSet(graphene.ObjectType):
    id = graphene.NonNull(graphene.ID)
    name = graphene.NonNull(graphene.String)
    pipeline_name = graphene.NonNull(graphene.String)
    solid_selection = graphene.List(graphene.NonNull(graphene.String))
    mode = graphene.NonNull(graphene.String)
    partitionsOrError = graphene.Field(
        graphene.NonNull(GraphenePartitionsOrError),
        cursor=graphene.String(),
        limit=graphene.Int(),
        reverse=graphene.Boolean(),
    )
    partition = graphene.Field(GraphenePartition,
                               partition_name=graphene.NonNull(
                                   graphene.String))
    partitionStatusesOrError = graphene.NonNull(
        GraphenePartitionStatusesOrError)
    repositoryOrigin = graphene.NonNull(GrapheneRepositoryOrigin)

    class Meta:
        name = "PartitionSet"

    def __init__(self, external_repository_handle, external_partition_set):
        self._external_repository_handle = check.inst_param(
            external_repository_handle, "external_respository_handle",
            RepositoryHandle)
        self._external_partition_set = check.inst_param(
            external_partition_set, "external_partition_set",
            ExternalPartitionSet)

        super().__init__(
            name=external_partition_set.name,
            pipeline_name=external_partition_set.pipeline_name,
            solid_selection=external_partition_set.solid_selection,
            mode=external_partition_set.mode,
        )

    def resolve_id(self, _graphene_info):
        return self._external_partition_set.get_external_origin_id()

    def resolve_partitionsOrError(self, graphene_info, **kwargs):
        return get_partitions(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set,
            cursor=kwargs.get("cursor"),
            limit=kwargs.get("limit"),
            reverse=kwargs.get("reverse"),
        )

    def resolve_partition(self, graphene_info, partition_name):
        return get_partition_by_name(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set,
            partition_name,
        )

    def resolve_partitionStatusesOrError(self, graphene_info):
        return get_partition_set_partition_statuses(
            graphene_info, self._external_repository_handle,
            self._external_partition_set.name)

    def resolve_repositoryOrigin(self, _):
        origin = self._external_partition_set.get_external_origin(
        ).external_repository_origin
        return GrapheneRepositoryOrigin(origin)
Exemple #20
0
 class Arguments:
     attributes = graphene.Argument(graphene.List(AttributeValueInput))
     category_id = graphene.ID()
Exemple #21
0
class AppQueries(graphene.ObjectType):
    apps_installations = graphene.List(
        graphene.NonNull(AppInstallation),
        description="List of all apps installations",
        required=True,
    )
    apps = FilterInputConnectionField(
        App,
        filter=AppFilterInput(description="Filtering options for apps."),
        sort_by=AppSortingInput(description="Sort apps."),
        description="List of the apps.",
    )
    app = graphene.Field(
        App,
        id=graphene.Argument(graphene.ID,
                             description="ID of the app.",
                             required=False),
        description=(
            "Look up an app by ID. "
            "If ID is not provided, return the currently authenticated app."),
    )

    app_extensions = FilterInputConnectionField(
        AppExtension,
        filter=AppExtensionFilterInput(
            description="Filtering options for apps extensions."),
        description=f"{ADDED_IN_31} List of all extensions",
    )
    app_extension = graphene.Field(
        AppExtension,
        id=graphene.Argument(graphene.ID,
                             description="ID of the app extension.",
                             required=True),
        description=f"{ADDED_IN_31} Look up an app extension by ID.",
    )

    @permission_required(AppPermission.MANAGE_APPS)
    def resolve_apps_installations(self, info, **kwargs):
        return resolve_apps_installations(info, **kwargs)

    @permission_required(AppPermission.MANAGE_APPS)
    def resolve_apps(self, info, **kwargs):
        return resolve_apps(info, **kwargs)

    def resolve_app(self, info, id=None):
        app = info.context.app
        if not id and app:
            return app
        return resolve_app(info, id)

    @staff_member_or_app_required
    def resolve_app_extensions(self, info, **kwargs):
        return resolve_app_extensions(info)

    @staff_member_or_app_required
    def resolve_app_extension(self, info, id):
        def app_is_active(app_extension):
            def is_active(app):
                if app.is_active:
                    return app_extension
                return None

            if not app_extension:
                return None

            return (AppByIdLoader(info.context).load(
                app_extension.app_id).then(is_active))

        _, id = from_global_id_or_error(id, "AppExtension")
        return AppExtensionByIdLoader(info.context).load(
            int(id)).then(app_is_active)
Exemple #22
0
 class Arguments:
     product_type_id = graphene.ID()
     category_id = graphene.ID()
     attributes = graphene.Argument(graphene.List(AttributeValueInput))
Exemple #23
0
class Product(CountableDjangoObjectType, MetadataObjectType):
    url = graphene.String(
        description="The storefront URL for the product.", required=True
    )
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for a product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    availability = graphene.Field(
        ProductPricingInfo,
        description=(
            "Informs about product's availability in the storefront, current price and "
            "discounts."
        ),
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, Has been renamed to `pricing`."
        ),
    )
    pricing = graphene.Field(
        ProductPricingInfo,
        description=(
            "Lists the storefront product's pricing, the current price and discounts, "
            "only meant for displaying."
        ),
    )
    is_available = graphene.Boolean(
        description="Whether the product is in stock and visible or not."
    )
    base_price = graphene.Field(Money, description="The product's default base price.")
    price = graphene.Field(
        Money,
        description="The product's default base price.",
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by "
            "`basePrice`"
        ),
    )
    minimal_variant_price = graphene.Field(
        Money, description="The price of the cheapest variant (including discounts)."
    )
    tax_type = graphene.Field(
        TaxType, description="A type of tax. Assigned by enabled tax gateway"
    )
    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this product.",
    )
    purchase_cost = graphene.Field(MoneyRange)
    margin = graphene.Field(Margin)
    image_by_id = graphene.Field(
        lambda: ProductImage,
        id=graphene.Argument(graphene.ID, description="ID of a product image."),
        description="Get a single product image by ID.",
    )
    variants = gql_optimizer.field(
        graphene.List(ProductVariant, description="List of variants for the product."),
        model_field="variants",
    )
    images = gql_optimizer.field(
        graphene.List(
            lambda: ProductImage, description="List of images for the product."
        ),
        model_field="images",
    )
    collections = gql_optimizer.field(
        graphene.List(
            lambda: Collection, description="List of collections for the product."
        ),
        model_field="collections",
    )
    translation = graphene.Field(
        ProductTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=("Returns translated Product fields for the given language code."),
        resolver=resolve_translation,
    )

    slug = graphene.String(required=True, description="The slug of a product.")

    class Meta:
        description = "Represents an individual item for sale in the storefront."
        interfaces = [relay.Node]
        model = models.Product
        only_fields = [
            "category",
            "charge_taxes",
            "description",
            "description_json",
            "id",
            "is_published",
            "name",
            "product_type",
            "publication_date",
            "seo_description",
            "seo_title",
            "updated_at",
            "weight",
        ]

    @staticmethod
    def resolve_tax_type(root: models.Product, info):
        tax_data = info.context.extensions.get_tax_code_from_object_meta(root)
        return TaxType(tax_code=tax_data.code, description=tax_data.description)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="images")
    def resolve_thumbnail(root: models.Product, info, *, size=255):
        image = root.get_first_image()
        if image:
            url = get_product_image_thumbnail(image, size, method="thumbnail")
            alt = image.alt
            return Image(alt=alt, url=info.context.build_absolute_uri(url))
        return None

    @staticmethod
    def resolve_url(root: models.Product, *_args):
        return root.get_absolute_url()

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=["publication_date", "charge_taxes", "price_amount", "currency", "meta"],
    )
    def resolve_pricing(root: models.Product, info):
        context = info.context
        availability = get_product_availability(
            root,
            context.discounts,
            context.country,
            context.currency,
            context.extensions,
        )
        return ProductPricingInfo(**availability._asdict())

    resolve_availability = resolve_pricing

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=("variants"))
    def resolve_is_available(root: models.Product, _info):
        return root.is_available

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_base_price(root: models.Product, _info):
        return root.price

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=["publication_date", "charge_taxes", "price_amount", "currency", "meta"],
    )
    def resolve_price(root: models.Product, info):
        price_range = root.get_price_range(info.context.discounts)
        price = info.context.extensions.apply_taxes_to_product(
            root, price_range.start, info.context.country
        )
        return price.net

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=[
            "product_type__attributeproduct__productassignments__values",
            "product_type__attributeproduct__attribute",
        ]
    )
    def resolve_attributes(root: models.Product, info):
        return resolve_attribute_list(root, user=info.context.user)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_purchase_cost(root: models.Product, *_args):
        purchase_cost, _ = get_product_costs_data(root)
        return purchase_cost

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_margin(root: models.Product, *_args):
        _, margin = get_product_costs_data(root)
        return Margin(margin[0], margin[1])

    @staticmethod
    def resolve_image_by_id(root: models.Product, info, id):
        pk = get_database_id(info, id, ProductImage)
        try:
            return root.images.get(pk=pk)
        except models.ProductImage.DoesNotExist:
            raise GraphQLError("Product image not found.")

    @staticmethod
    @gql_optimizer.resolver_hints(model_field="images")
    def resolve_images(root: models.Product, *_args, **_kwargs):
        return root.images.all()

    @staticmethod
    def resolve_variants(root: models.Product, *_args, **_kwargs):
        return root.variants.all()

    @staticmethod
    def resolve_collections(root: models.Product, *_args):
        return root.collections.all()

    @classmethod
    def get_node(cls, info, pk):
        if info.context:
            qs = cls._meta.model.objects.visible_to_user(info.context.user)
            return cls.maybe_optimize(info, qs, pk)
        return None

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_private_meta(root, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def resolve_slug(root: models.Product, *_args):
        return root.get_slug()

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
def make_schema():
    # Here we dynamically generate an interface similar to this example
    # https://github.com/graphql-python/graphene-sqlalchemy/blob/master/docs/examples.rst

    from sqlalchemy.orm.attributes import InstrumentedAttribute

    import graphene
    from graphene.relay import Connection, Node

    from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField

    # A map of all classes to list of sub-classes
    class_map = get_class_map(Base.__subclasses__())
    # Map of models to SQLAlchemyObjectType
    sql_map = dict()
    # Map of models to graphene.Interface
    ifa_map = dict()
    # Map of all things available on query, generates Schema
    queries = dict()

    IName = type(f'IName', (graphene.Interface, ), {
        'name': graphene.String(),
        'role': graphene.String()
    })

    for cls, subs in class_map.items():
        ifas = [Node]

        if cls in ifa_map:
            ifas.extend[ifa_map[cls]]
        else:
            ifa = make_graphene_interface(cls)
            ifas.insert(0, ifa)

        bases = list(cls.__bases__)
        while bases:
            base = bases.pop(0)
            if base in ifa_map:
                bases.extend(list(base.__bases__))
                ifas.extend(ifa_map[base])

        ifas = list(set(ifas))
        ifa_map[cls] = ifas[:]

        print(
            f'INTERFACES: {cls.__name__} => {", ".join([c.__name__ for c in ifas])}'
        )

        # Name for the Type of X
        name = cls.__name__.replace('Model', '')
        # Name for the Type of X and and relationship to Y
        conn_name = f'{name}Connection'
        # Name for a query of multiple X
        query_name = f'{name.lower()}s'

        SqlType = type(
            name, (SQLAlchemyObjectType, ), {
                'Meta': type('Meta', (), {
                    'model': cls,
                    'interfaces': tuple(ifas)
                })
            })

        SqlTypeConnection = type(conn_name, (Connection, ),
                                 {'Meta': type('Meta', (), {'node': SqlType})})

        sql_map[cls] = SqlType
        queries[f'relay_{query_name}'] = SQLAlchemyConnectionField(
            SqlTypeConnection)
        queries[query_name] = graphene.List(SqlType)
        queries[f'resolve_{query_name}'] = make_resolve_func(SqlType)
        print(f'{name} => {query_name} => {cls.__name__}')

    for cls, subs in class_map.items():
        if not subs: continue
        name = cls.__name__.replace('Model', '')

        sql_types = [sql_map[cls]] + [sql_map[s] for s in subs]

        # Name for the Type of X and that which is derived from X
        poly_name = f'Any{name}s'
        # Name for the query of multiple X and that which is derived from X
        poly_query_name = f'resolve_{poly_name}'

        SqlUnionType = type(
            poly_name, (graphene.Union, ), {
                'Meta':
                type('Meta', (), {
                    'types': tuple(sql_types),
                    'interfaces': (IName, )
                }),
                'resolve_type':
                make_resolve_type_func(sql_map)
            })

        queries[poly_name] = graphene.List(SqlUnionType)
        queries[poly_query_name] = make_resolve_func(SqlUnionType)
        print(
            f'{poly_name} => {poly_query_name} => {",".join([c.__name__ for c in subs])}'
        )

    # Always present
    queries['node'] = Node.Field()

    # Create actual query class
    Query = type('Query', (graphene.ObjectType, ), queries)
    schema = graphene.Schema(query=Query)
    return schema
Exemple #25
0
class PageTypeUpdateInput(PageTypeCreateInput):
    remove_attributes = graphene.List(
        graphene.NonNull(graphene.ID),
        description="List of attribute IDs to be assigned to the page type.",
    )
def get_input_fields_for_model(model,
                               only_fields,
                               exclude_fields,
                               optional_fields=(),
                               required_fields=(),
                               many_to_many_extras=None,
                               foreign_key_extras=None,
                               many_to_one_extras=None,
                               parent_type_name="",
                               field_types=None) -> OrderedDict:

    registry = get_global_registry()
    meta_registry = get_type_meta_registry()
    model_fields = get_model_fields(model)

    many_to_many_extras = many_to_many_extras or {}
    foreign_key_extras = foreign_key_extras or {}
    many_to_one_extras = many_to_one_extras or {}
    field_types = field_types or {}

    fields = OrderedDict()
    fields_lookup = {}
    for name, field in model_fields:
        # We ignore the primary key
        if getattr(field, "primary_key", False):
            continue

        # If the field has an override, use that
        if name in field_types:
            fields[name] = field_types[name]
            continue

        # Save for later
        fields_lookup[name] = field

        is_not_in_only = only_fields and name not in only_fields
        # is_already_created = name in options.fields
        is_excluded = name in exclude_fields  # or is_already_created
        # https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
        is_no_backref = str(name).endswith("+")
        if is_not_in_only or is_excluded or is_no_backref:
            # We skip this field if we specify only_fields and is not
            # in there. Or when we exclude this field in exclude_fields.
            # Or when there is no back reference.
            continue

        required = None
        if name in optional_fields:
            required = False
        elif name in required_fields:
            required = True

        converted = convert_django_field_with_choices(
            field, registry, required,
            many_to_many_extras.get(name, {}).get('exact'),
            foreign_key_extras.get(name, {}))
        fields[name] = converted

    # Create extra many_to_many_fields
    for name, extras in many_to_many_extras.items():
        field = fields_lookup.get(name)
        if field is None:
            raise GraphQLError(
                f"Error adding extras for {name} in model f{model}. Field {name} does not exist."
            )

        for extra_name, data in extras.items():

            # This is handled above
            if extra_name == "exact":
                continue

            if isinstance(data, bool):
                data = {}

            _type_name = data.get('type')
            _field = convert_many_to_many_field(field, registry, False, data,
                                                None)

            # Default to the same as the "exact" version
            if not _field:
                _field = fields[name]

            # operation = data.get('operation') or get_likely_operation_from_name(extra_name)
            fields[name + "_" + extra_name] = _field

    for name, extras in many_to_one_extras.items():
        field = fields_lookup.get(name)
        if field is None:
            raise GraphQLError(
                f"Error adding extras for {name} in model f{model}. Field {name} does not exist."
            )

        for extra_name, data in extras.items():

            argument_name = data.get('name', name + "_" + extra_name)

            # Override default
            if extra_name == "exact":
                argument_name = name

            if isinstance(data, bool):
                data = {"type": 'ID'}

            _type = data.get('type')
            if not _type or _type == "auto":
                # Create new type.
                _type_name = data.get(
                    'type_name',
                    f"{parent_type_name}Create{model.__name__}{name.capitalize()}"
                )
                converted_fields = get_input_fields_for_model(
                    field.related_model,
                    data.get('only_fields', ()),
                    data.get(
                        'exclude_fields', (field.field.name, )
                    ),  # Exclude the field referring back to the foreign key
                    data.get('optional_fields', ()),
                    data.get('required_fields', ()),
                    data.get('many_to_many_extras'),
                    data.get('foreign_key_extras'),
                    data.get('many_to_one_extras'),
                    parent_type_name=_type_name,
                    field_types=data.get('field_types'))
                InputType = type(_type_name, (InputObjectType, ),
                                 converted_fields)
                meta_registry.register(
                    _type_name, {
                        'auto_context_fields': data.get(
                            'auto_context_fields', {}),
                        'optional_fields': data.get('optional_fields', ()),
                        'required_fields': data.get('required_fields', ()),
                        'many_to_many_extras': data.get(
                            'many_to_many_extras', {}),
                        'many_to_one_extras': data.get('many_to_one_extras',
                                                       {}),
                        'foreign_key_extras': data.get('auto_context_fields',
                                                       {}),
                        'field_types': data.get('field_types', {}),
                    })
                _field = graphene.List(type(_type_name, (InputObjectType, ),
                                            converted_fields),
                                       required=False)
            else:
                _field = convert_many_to_many_field(field, registry, False,
                                                    data, None)

            fields[argument_name] = _field

    return fields
class GetNotificationsResponse(graphene.ObjectType, config_types.ResponseFields):
    notifications = graphene.List(NotificationType)
Exemple #28
0
class Query(object):
    all_comments_for_task = graphene.List(CommentType, taskId=graphene.String())

    def resolve_all_comments_for_task(self, info, taskId , **kwargs):
        taskInstance = Task.objects.get(id = taskId)
        return Comment.objects.filter(task = taskInstance)
Exemple #29
0
class StaffInput(UserInput):
    permissions = graphene.List(
        PermissionEnum,
        description='List of permission code names to assign to this user.')
class PostResults(graphene.ObjectType):
    posts = graphene.List(of_type=PostField)