{"id":16495653,"url":"https://github.com/bitranox/lib_shopware6_api_base","last_synced_at":"2026-02-03T21:05:42.354Z","repository":{"id":41935463,"uuid":"441849494","full_name":"bitranox/lib_shopware6_api_base","owner":"bitranox","description":"python3 base API client for shopware6","archived":false,"fork":false,"pushed_at":"2026-01-10T11:42:31.000Z","size":218,"stargazers_count":23,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-11T03:16:33.878Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitranox.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGES.rst","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-26T09:03:01.000Z","updated_at":"2026-01-02T23:10:08.000Z","dependencies_parsed_at":"2024-05-21T18:32:09.446Z","dependency_job_id":"56f64d26-bece-44a6-9bb5-6d72e09eeed2","html_url":"https://github.com/bitranox/lib_shopware6_api_base","commit_stats":{"total_commits":54,"total_committers":2,"mean_commits":27.0,"dds":0.01851851851851849,"last_synced_commit":"7dc3edaa8efcca843fdcbbc5d61e2760b6a0fb5e"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/bitranox/lib_shopware6_api_base","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitranox%2Flib_shopware6_api_base","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitranox%2Flib_shopware6_api_base/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitranox%2Flib_shopware6_api_base/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitranox%2Flib_shopware6_api_base/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitranox","download_url":"https://codeload.github.com/bitranox/lib_shopware6_api_base/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitranox%2Flib_shopware6_api_base/sbom","scorecard":{"id":240664,"data":{"date":"2025-08-11","repo":{"name":"github.com/bitranox/lib_shopware6_api_base","commit":"91cbc907e71f891bef1b12712dc51e4005fd7981"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:29","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Warn: no topLevel permission defined: .github/workflows/python-package.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":0,"reason":"dangerous workflow patterns detected","details":["Warn: script injection with untrusted input ' github.head_ref ': .github/workflows/python-package.yml:198"],"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":10,"reason":"SAST tool detected: CodeQL","details":["Info: SAST configuration detected: CodeQL","Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-package.yml:177: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/python-package.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-package.yml:181: update your workflow using https://app.stepsecurity.io/secureworkflow/bitranox/lib_shopware6_api_base/python-package.yml/master?enable=pin","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:79","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:80","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:81","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:83","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:84","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:88","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:190","Warn: pipCommand not pinned by hash: tests/local_testscripts/lib_bash_functions.sh:205","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   8 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":3,"reason":"7 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2014-14 / GHSA-652x-xj99-gmcc","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2014-13 / GHSA-cfj3-7x9c-4p3h","Warn: Project is vulnerable to: PYSEC-2018-28 / GHSA-x84v-xcm2-53pg","Warn: Project is vulnerable to: PYSEC-2024-48 / GHSA-fj7x-q9j7-g6q6","Warn: Project is vulnerable to: PYSEC-2022-238 / GHSA-h3qr-fjhm-jphw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T06:38:08.867Z","repository_id":41935463,"created_at":"2025-08-17T06:38:08.868Z","updated_at":"2025-08-17T06:38:08.868Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29057119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T20:13:53.544Z","status":"ssl_error","status_checked_at":"2026-02-03T20:13:40.507Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T14:31:56.656Z","updated_at":"2026-02-03T21:05:42.335Z","avatar_url":"https://github.com/bitranox.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"lib_shopware6_api_base\n======================\n\n\nVersion v2.1.9 as of 2024-09-30 see `Changelog`_\n\n|build_badge| |codeql| |license| |pypi|\n|pypi-downloads| |black| |codecov| |cc_maintain| |cc_issues| |cc_coverage| |snyk|\n\n\n\n.. |build_badge| image:: https://github.com/bitranox/lib_shopware6_api_base/actions/workflows/python-package.yml/badge.svg\n   :target: https://github.com/bitranox/lib_shopware6_api_base/actions/workflows/python-package.yml\n\n\n.. |codeql| image:: https://github.com/bitranox/lib_shopware6_api_base/actions/workflows/codeql-analysis.yml/badge.svg?event=push\n   :target: https://github.com//bitranox/lib_shopware6_api_base/actions/workflows/codeql-analysis.yml\n\n.. |license| image:: https://img.shields.io/github/license/webcomics/pywine.svg\n   :target: http://en.wikipedia.org/wiki/MIT_License\n\n.. |jupyter| image:: https://mybinder.org/badge_logo.svg\n   :target: https://mybinder.org/v2/gh/bitranox/lib_shopware6_api_base/master?filepath=lib_shopware6_api_base.ipynb\n\n.. for the pypi status link note the dashes, not the underscore !\n.. |pypi| image:: https://img.shields.io/pypi/status/lib-shopware6-api-base?label=PyPI%20Package\n   :target: https://badge.fury.io/py/lib_shopware6_api_base\n\n.. badge until 2023-10-08:\n.. https://img.shields.io/codecov/c/github/bitranox/lib_shopware6_api_base\n.. badge from 2023-10-08:\n.. |codecov| image:: https://codecov.io/gh/bitranox/lib_shopware6_api_base/graph/badge.svg\n   :target: https://codecov.io/gh/bitranox/lib_shopware6_api_base\n\n.. |cc_maintain| image:: https://img.shields.io/codeclimate/maintainability-percentage/bitranox/lib_shopware6_api_base?label=CC%20maintainability\n   :target: https://codeclimate.com/github/bitranox/lib_shopware6_api_base/maintainability\n   :alt: Maintainability\n\n.. |cc_issues| image:: https://img.shields.io/codeclimate/issues/bitranox/lib_shopware6_api_base?label=CC%20issues\n   :target: https://codeclimate.com/github/bitranox/lib_shopware6_api_base/maintainability\n   :alt: Maintainability\n\n.. |cc_coverage| image:: https://img.shields.io/codeclimate/coverage/bitranox/lib_shopware6_api_base?label=CC%20coverage\n   :target: https://codeclimate.com/github/bitranox/lib_shopware6_api_base/test_coverage\n   :alt: Code Coverage\n\n.. |snyk| image:: https://snyk.io/test/github/bitranox/lib_shopware6_api_base/badge.svg\n   :target: https://snyk.io/test/github/bitranox/lib_shopware6_api_base\n\n.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n   :target: https://github.com/psf/black\n\n.. |pypi-downloads| image:: https://img.shields.io/pypi/dm/lib-shopware6-api-base\n   :target: https://pypi.org/project/lib-shopware6-api-base/\n   :alt: PyPI - Downloads\n\nthis is a basic API client for shopware6 which can be used on windows, Linux, MacOs.\nIt supports all available authorisation types to the Admin and Storefront API.\nPaginated requests are supported.\n\nThis is only the basic abstraction layer, to enjoy higher level functions, check out \"lib_shopware6_api\"\n\n\nOn github it can be only tested on linux, because we can not run a docker shopware container service on MacOS or Windows.\n\n----\n\nautomated tests, Github Actions, Documentation, Badges, etc. are managed with `PizzaCutter \u003chttps://github\n.com/bitranox/PizzaCutter\u003e`_ (cookiecutter on steroids)\n\nPython version required: 3.8.0 or newer\n\ntested on recent linux with python 3.8, 3.9, 3.10, 3.11, 3.12, pypy-3.9, pypy-3.10, graalpy-24.1 - architectures: amd64\n\n`100% code coverage \u003chttps://codeclimate.com/github/bitranox/lib_shopware6_api_base/test_coverage\u003e`_, flake8 style checking ,mypy static type checking ,tested under `Linux \u003chttps://github.com/bitranox/lib_shopware6_api_base/actions/workflows/python-package.yml\u003e`_, automatic daily builds and monitoring\n\n----\n\n- `Usage`_\n- `Usage from Commandline`_\n- `Installation and Upgrade`_\n- `Requirements`_\n- `Acknowledgements`_\n- `Contribute`_\n- `Report Issues \u003chttps://github.com/bitranox/lib_shopware6_api_base/blob/master/ISSUE_TEMPLATE.md\u003e`_\n- `Pull Request \u003chttps://github.com/bitranox/lib_shopware6_api_base/blob/master/PULL_REQUEST_TEMPLATE.md\u003e`_\n- `Code of Conduct \u003chttps://github.com/bitranox/lib_shopware6_api_base/blob/master/CODE_OF_CONDUCT.md\u003e`_\n- `License`_\n- `Changelog`_\n\n----\n\n\n\nUsage\n-----------\n\n- `configuration`_\n- `methods`_\n- `headers`_\n- `Store API`_\n- `Admin API`_\n- `Query Syntax`_\n    - `Aggregations`_\n        - `AvgAggregation`_\n        - `CountAggregation`_\n        - `MaxAggregation`_\n        - `MinAggregation`_\n        - `SumAggregation`_\n        - `StatsAggregation`_\n        - `TermsAggregation`_\n        - `FilterAggregation`_\n        - `EntityAggregation`_\n        - `DateHistogramAggregation`_\n        - `NestingAggregations`_\n    - `Associations`_\n    - `Filters`_\n        - `EqualsFilter`_\n        - `EqualsAnyFilter`_\n        - `ContainsFilter`_\n        - `RangeFilter`_\n        - `NotFilter`_\n        - `MultiFilter`_\n        - `PrefixFilter`_\n        - `SuffixFilter`_\n    - `Grouping`_\n    - `ids`_\n    - `includes`_\n    - `page \u0026 limit`_\n    - `Query`_\n    - `Sort`_\n        - `FieldSorting`_\n        - `AscFieldSorting`_\n        - `DescFieldSorting`_\n\nconfiguration\n-------------\n\n    the configuration is passed to the client as a configuration object of the type \"ConfShopware6ApiBase\"\n    simply copy the Class definition of \"ConfShopware6ApiBase\" and create Your own configuration file, for instance \"my_shop_config.py\"\n\n.. code-block:: python\n\n    import attrs\n\n\n    @attrs.define\n    class ConfShopware6ApiBase(object):\n        # the api url, like : 'https://shop.yourdomain.com/api'\n        shopware_admin_api_url: str = \"\"\n        # the storefront api url, like : 'https://shop.yourdomain.com/store-api'\n        shopware_storefront_api_url: str = \"\"\n\n        \"\"\"\n        Admin API:\n        for User Credentials Grant Type:\n        ==================================\n        - with refresh token\n        - we recommend to only use this grant flow for client applications that should\n          perform administrative actions and require a user-based authentication\n\n        \"\"\"\n        username: str = \"\"\n        password: str = \"\"\n\n        \"\"\"\n        Admin API:\n        for Resource Owner Password Grant Type:\n        =======================================\n        - no refresh token\n        - should be used for machine-to-machine communications, such as CLI jobs or automated services\n        see https://shopware.stoplight.io/docs/admin-api/ZG9jOjEwODA3NjQx-authentication-and-authorisation\n        setup via Web Administration Interface \u003e settings \u003e system \u003e integration: \"access_id\" and \"access_secret\"\n        or directly via URL : https://shop.yourdomain.com/admin#/sw/integration/index\n        \"\"\"\n        # the client ID, setup at Web Administration Interface \u003e settings \u003e system \u003e integration \u003e access_id\n        client_id: str = \"\"\n        # the client secret, setup at Web Administration Interface \u003e settings \u003e system \u003e integration \u003e access_secret\n        client_secret: str = \"\"\n\n        \"\"\"\n        Admin API:\n        Grant Type to use:\n        ==================\n        which grant type to use - can be either 'user_credentials'- or 'resource_owner'\n        \"\"\"\n        grant_type: str = \"\"\n\n        \"\"\"\n        Store API:\n        sw-access-key set in Administration/Sales Channels/API\n        \"\"\"\n        store_api_sw_access_key: str = \"\"\n\nnow You can use this configuration:\n\n.. code-block::\n\n    from lib_shopware6_api_base import Shopware6AdminAPIClientBase\n    from my_shop_config import ConfShopware6ApiBase\n\n    my_conf = ConfShopware6ApiBase()\n    my_api_client = Shopware6AdminAPIClientBase(config=my_conf)\n    ...\n\n- test configuration\n\nfor testing we use the dockware docker container,\nsee : `dockware \u003chttps://developer.shopware.com/docs/guides/installation/dockware\u003e`_\n\n\non gitHub actions the dockware docker test container is installed as a service and is available\nfor communication on localhost\n\nYou can start the dockware container locally with the command : sudo docker run -d --rm -p 80:80 --name dockware dockware/dev:latest\n\nnow You can test against that container with :\n\n.. code-block::\n\n    my_api_client = Shopware6AdminAPIClientBase(use_docker_test_container=True)\n    ...\n\n\nmethods\n-------\n\nplease note, that on github actions the test configuration is used automatically,\ntherefore on all examples no configuration is passed on purpose.\n\nmethods which take the parameter 'payload', the payload is of following type :\n\nPayLoad = Union[None, Dict[str, Any], Criteria]\n\nfor the definition of \"Criteria\" see `Query Syntax`_\n\n\nheaders\n-------\n\n\nEndpoints like ``/api/_action/sync`` require request specific custom headers to manipulate the api behavior\n\nsee : `Bulk Payloads Performance`_  and `Bulk edit entities`_ in the Admin API Documentation\n\n.. _`Bulk Payloads Performance`: https://shopware.stoplight.io/docs/admin-api/faf8f8e4e13a0-bulk-payloads#performance\n.. _`Bulk edit entities`: https://shopware.stoplight.io/docs/admin-api/0612cb5d960ef-bulk-edit-entities\n\nYou may pass such custom header fields like that :\n\n.. code-block::\n\n    # only for python version \u003e= 3.8:\n    update_header_fields = HEADER_write_in_single_transactions | HEADER_index_asynchronously\n\n    #   or the same for python 3.7:\n    update_header_fields: dict = dict()\n    update_header_fields.update(HEADER_index_asynchronously)\n    update_header_fields.update(HEADER_write_in_single_transactions)\n\n    #   or the same written explicitly for python 3.7:\n    update_heater_fields = {'single-operation' : 'true', 'indexing-behavior' : 'use-queue-indexing'}\n\n    # and pass those \"update_heater_fields\" to the request method parameter\n    # (mostly \"request_post\", with endpoint \"/api/_action/sync\")\n\n\nfollowing header fields are pre-defined :\n\n.. code-block:: python\n\n    HEADER_write_in_separate_transactions: Dict[str, str] = {\"single-operation\": \"false\"}  # default\n    HEADER_write_in_single_transactions: Dict[str, str] = {\"single-operation\": \"true\"}\n    HEADER_index_synchronously: Dict[str, str] = {\"indexing-behavior\": \"null\"}  # default\n    HEADER_index_asynchronously: Dict[str, str] = {\"indexing-behavior\": \"use-queue-indexing\"}\n    HEADER_index_disabled: Dict[str, str] = {\"indexing-behavior\": \"disable-indexing\"}\n    HEADER_fail_on_error: Dict[str, str] = {\"fail-on-error\": \"true\"}  # default\n    HEADER_do_not_fail_on_error: Dict[str, str] = {\"fail-on-error\": \"false\"}\n\nStore API\n---------\n\n.. code-block:: python\n\n    class Shopware6StoreFrontClientBase(object):\n        def __init__(self, config: Optional[ConfShopware6ApiBase] = None, use_docker_test_container: bool = False) -\u003e None:\n            \"\"\"\n            the Shopware6 Storefront Base API\n\n            :param config:  You can pass a configuration object here.\n                            If not given and gitHub actions is detected, or use_docker_test_container == True:\n                                conf_shopware6_api_docker_testcontainer.py will be loaded automatically\n                            If not given and no gitHub actions is detected:\n                                conf_shopware6_api_base_rotek.py will be loaded automatically\n\n            :param use_docker_test_container:   if True, and no config is given, the dockware config will be loaded\n\n            \u003e\u003e\u003e # Test to load automatic configuration\n            \u003e\u003e\u003e my_storefront_client = Shopware6StoreFrontClientBase()\n\n            \u003e\u003e\u003e # Test pass configuration\n            \u003e\u003e\u003e if _is_github_actions():\n            ...     my_config = _load_config_for_docker_test_container()\n            ...     my_storefront_client = Shopware6StoreFrontClientBase(config=my_config)\n\n            \"\"\"\n\n- Store API Get\n\n.. code-block:: python\n\n        def request_get(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            make a get request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_storefront_client = Shopware6StoreFrontClientBase()\n\n            \u003e\u003e\u003e # test GET a dictionary\n            \u003e\u003e\u003e my_response = my_storefront_client.request_get(request_url='context')\n\n            \u003e\u003e\u003e # test GET a List\n            \u003e\u003e\u003e my_response = my_storefront_client.request_get(request_url='sitemap')\n            Traceback (most recent call last):\n                ...\n            conf_shopware6_api_base_classes.ShopwareAPIError: received a list instead of a dict - You need to use the method request_get_list\n\n            \"\"\"\n\n- Store API Get List\n\n.. code-block:: python\n\n        def request_get_list(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e List[Dict[str, Any]]:\n            \"\"\"\n            make a get request, expecting a list of dictionaries as result\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                List[response_dict]: a list of dictionaries\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_storefront_client = Shopware6StoreFrontClientBase()\n\n            \u003e\u003e\u003e # test GET a List\n            \u003e\u003e\u003e my_response = my_storefront_client.request_get_list(request_url='sitemap')\n\n            \u003e\u003e\u003e # test GET a dictionary\n            \u003e\u003e\u003e my_response = my_storefront_client.request_get_list(request_url='context')\n            Traceback (most recent call last):\n                ...\n            conf_shopware6_api_base_classes.ShopwareAPIError: received a dict instead of a list - You need to use the method request_get\n\n\n            \"\"\"\n\n- Store API Patch\n\n.. code-block:: python\n\n        def request_patch(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a patch request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\n- Store API Post\n\n.. code-block:: python\n\n        def request_post(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            make a post request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_storefront_client = Shopware6StoreFrontClientBase()\n\n            \u003e\u003e\u003e # test POST without payload\n            \u003e\u003e\u003e my_response = my_storefront_client.request_post(request_url='product')\n            \u003e\u003e\u003e assert 'elements' in my_response\n\n            \u003e\u003e\u003e # test POST with payload\n            \u003e\u003e\u003e # see : https://shopware.stoplight.io/docs/store-api/b3A6ODI2NTY4MQ-fetch-a-list-of-products\n            \u003e\u003e\u003e my_payload = Criteria()\n            \u003e\u003e\u003e my_payload.filter.append(EqualsFilter(field='active', value='true'))\n            \u003e\u003e\u003e my_response = my_storefront_client.request_post(request_url='product', payload=my_payload)\n            \u003e\u003e\u003e assert 'elements' in my_response\n\n            \"\"\"\n\n- Store API Put\n\n.. code-block:: python\n\n        def request_put(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            make a put request\n\n            parameters:\n                http_method: get, post, put, delete\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\n- Store API Delete\n\n.. code-block:: python\n\n        def request_delete(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            make a delete request\n\n            parameters:\n                http_method: get, post, put, delete\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\nAdmin API\n---------\n\n.. code-block:: python\n\n    class Shopware6AdminAPIClientBase(object):\n        def __init__(self, config: Optional[ConfShopware6ApiBase] = None, use_docker_test_container: bool = False) -\u003e None:\n            \"\"\"\n            the Shopware6 Admin Base API\n\n            :param config:  You can pass a configuration object here.\n                    If not given and gitHub actions is detected, or use_docker_test_container == True:\n                        conf_shopware6_api_docker_testcontainer.py will be loaded automatically\n                    If not given and no gitHub actions is detected:\n                        conf_shopware6_api_base_rotek.py will be loaded automatically\n\n            :param use_docker_test_container:   if True, and no config is given, the dockware config will be loaded\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_api_client = Shopware6AdminAPIClientBase()\n\n            \"\"\"\n\n- Admin API GET\n\n.. code-block:: python\n\n        def request_get(self, request_url: str, payload: PayLoad = None, update_header_fields: Optional[Dict[str, str]] = None) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a get request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_api_client = Shopware6AdminAPIClientBase()\n\n            \u003e\u003e\u003e # test resource owner token\n            \u003e\u003e\u003e ignore = my_api_client._get_access_token_by_user_credentials()\n            \u003e\u003e\u003e my_api_client._get_session()\n            \u003e\u003e\u003e ignore = my_api_client.request_get('customer-group')  # noqa\n\n            \u003e\u003e\u003e # test resource owner token refresh\n            \u003e\u003e\u003e my_access_token = my_api_client.token['access_token']\n            \u003e\u003e\u003e my_api_client.token['expires_in']=-1\n            \u003e\u003e\u003e my_api_client.token['expires_at']=time.time()-1\n            \u003e\u003e\u003e ignore = my_api_client.request_get('customer-group')\n            \u003e\u003e\u003e assert my_api_client.token['access_token'] != my_access_token\n\n            \u003e\u003e\u003e # Test client credentials token\n            \u003e\u003e\u003e ignore = my_api_client._get_access_token_by_resource_owner()\n            \u003e\u003e\u003e my_api_client._get_session()\n            \u003e\u003e\u003e ignore = my_api_client.request_get('customer-group')  # noqa\n\n            \u003e\u003e\u003e # test client credentials token refresh\n            \u003e\u003e\u003e my_access_token = my_api_client.token['access_token']\n            \u003e\u003e\u003e my_api_client.token['expires_in']=-1\n            \u003e\u003e\u003e my_api_client.token['expires_at']=time.time()-1\n            \u003e\u003e\u003e ignore = my_api_client.request_get('customer-group')\n            \u003e\u003e\u003e assert my_api_client.token['access_token'] != my_access_token\n\n            \"\"\"\n\n- Admin API GET Paginated\n\n.. code-block:: python\n\n        def request_get_paginated(\n            self, request_url: str, payload: PayLoad = None, junk_size: int = 100, update_header_fields: Optional[Dict[str, str]] = None\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            get the data paginated - metadata 'total' and 'totalCountMode' will be updated\n            the paginated request reads those records in junks of junk_size=100 for performance reasons.\n\n            payload \"limit\" will be respected (meaning we deliver only 'limit' results back)\n            payload \"page\" will be ignored\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                limit : the junk size\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_api_client = Shopware6AdminAPIClientBase()\n\n            \u003e\u003e\u003e # test read product junk_size=3, limit = 4\n            \u003e\u003e\u003e my_payload={'limit': 4}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_get_paginated(request_url='product', payload=my_payload, junk_size=3)\n            \u003e\u003e\u003e assert 4 == len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=3, no limit\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_get_paginated(request_url='product', junk_size=3)\n            \u003e\u003e\u003e assert 3 \u003c len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=3, limit = 2\n            \u003e\u003e\u003e my_payload={'limit': 2}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_get_paginated(request_url='product', payload=my_payload, junk_size=3)\n            \u003e\u003e\u003e assert 2 == len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=3, limit = 4\n            \u003e\u003e\u003e my_payload={'limit': 4}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_get_paginated(request_url='product', payload=my_payload, junk_size=3)\n            \u003e\u003e\u003e assert 4 == len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=10, limit = None\n            \u003e\u003e\u003e my_payload=Criteria()\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_get_paginated(request_url='product', payload=my_payload, junk_size=10)\n            \u003e\u003e\u003e assert 5 \u003c len(my_response_dict['data'])\n            \"\"\"\n\n- Admin API PATCH\n\n.. code-block:: python\n\n        def request_patch(\n            self,\n            request_url: str,\n            payload: PayLoad = None,\n            content_type: str = \"json\",\n            additional_query_params: Optional[Dict[str, Any]] = None,\n            update_header_fields: Optional[Dict[str, str]] = None,\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a patch request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary or bytes\n                content_type: any valid content type like json, octet-stream, ...\n                additional_query_params: additional query parameters for patch, post, put, delete\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\n- Admin API POST\n\n.. code-block:: python\n\n        def request_post(\n            self,\n            request_url: str,\n            payload: PayLoad = None,\n            content_type: str = \"json\",\n            additional_query_params: Optional[Dict[str, Any]] = None,\n            update_header_fields: Optional[Dict[str, str]] = None,\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a post request\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary or bytes\n                content_type: any valid content type like json, octet-stream, ...\n                additional_query_params: additional query parameters for patch, post, put, delete\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\n- Admin API POST PAGINATED\n\n.. code-block:: python\n\n        def request_post_paginated(\n            self, request_url: str, payload: PayLoad = None, junk_size: int = 100, update_header_fields: Optional[Dict[str, str]] = None\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            post the data paginated - metadata 'total' and 'totalCountMode' will be updated\n            if You expect a big number of records, the paginated request reads those records in junks of junk_size=100 for performance reasons.\n\n            payload \"limit\" will be respected (meaning we deliver only 'limit' results back)\n            payload \"page\" will be ignored\n\n            parameters:\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                junk_size : the junk size\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \u003e\u003e\u003e # Setup\n            \u003e\u003e\u003e my_api_client = Shopware6AdminAPIClientBase()\n            \u003e\u003e\u003e my_url = 'search/product'\n\n            \u003e\u003e\u003e # test read product junk_size=10, limit = None\n            \u003e\u003e\u003e my_payload=Criteria()\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_post_paginated(request_url=my_url, payload=my_payload, junk_size=10)\n            \u003e\u003e\u003e assert 5 \u003c len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=10, no limit\n            \u003e\u003e\u003e my_payload=None\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_post_paginated(request_url=my_url, payload=my_payload, junk_size=10)\n            \u003e\u003e\u003e assert 10 \u003c len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=3, limit = 2\n            \u003e\u003e\u003e my_payload={'limit': 2}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_post_paginated(request_url=my_url, payload=my_payload, junk_size=3)\n            \u003e\u003e\u003e assert 2 == len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # test read product junk_size=3, limit = 4\n            \u003e\u003e\u003e my_payload={'limit': 4}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_post_paginated(request_url=my_url, payload=my_payload, junk_size=3)\n            \u003e\u003e\u003e assert 4 == len(my_response_dict['data'])\n\n            \u003e\u003e\u003e # search for orders\n            \u003e\u003e\u003e # test https://github.com/bitranox/lib_shopware6_api_base/issues/11\n            \u003e\u003e\u003e import pprint\n            \u003e\u003e\u003e date_from = '2024-09-29T00:00:00.000Z'\n            \u003e\u003e\u003e date_to = '2024-09-29T23:59:59.999Z'\n            \u003e\u003e\u003e my_criteria = Criteria()\n            \u003e\u003e\u003e my_criteria.filter.append(RangeFilter(field=\"orderDate\", parameters = {'gte': date_from, 'lte': date_to}))\n            \u003e\u003e\u003e my_criteria.filter.append(MultiFilter('or', [\n            ...     EqualsFilter(field='documents.documentType.technicalName', value='invoice'),\n            ...     EqualsFilter(field='documents.documentType.technicalName', value='storno')]))\n            \u003e\u003e\u003e pprint_attrs(my_criteria)\n            {'limit': None,\n             'page': None,\n             'filter': [{'type': 'range',\n                         'field': 'orderDate',\n                         'parameters': {'gte': '2024-09-29T00:00:00.000Z',\n                                        'lte': '2024-09-29T23:59:59.999Z'}},\n                        {'type': 'multi',\n                         'operator': 'or',\n                         'queries': [{'type': 'equals',\n                                      'field': 'documents.documentType.technicalName',\n                                      'value': 'invoice'},\n                                     {'type': 'equals',\n                                      'field': 'documents.documentType.technicalName',\n                                      'value': 'storno'}]}],\n             'term': None,\n             'total_count_mode': None}\n            \u003e\u003e\u003e my_response_dict = my_api_client.request_post_paginated(request_url='search/order', payload=my_criteria)\n            \u003e\u003e\u003e pprint.pprint(my_response_dict)\n            {'data': []}\n            \"\"\"\n\n- Admin API PUT\n\n.. code-block:: python\n\n        def request_put(\n            self,\n            request_url: str,\n            payload: PayLoad = None,\n            content_type: str = \"json\",\n            additional_query_params: Optional[Dict[str, Any]] = None,\n            update_header_fields: Optional[Dict[str, str]] = None,\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a put request\n\n            parameters:\n                http_method: get, post, put, delete\n                request_url: API Url, without the common api prefix\n                payload : a dictionary or bytes\n                content_type: any valid content type like json, octet-stream, ...\n                additional_query_params: additional query parameters for patch, post, put, delete\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\n- Admin API DELETE\n\n.. code-block:: python\n\n        def request_delete(\n            self,\n            request_url: str,\n            payload: PayLoad = None,\n            additional_query_params: Optional[Dict[str, Any]] = None,\n            update_header_fields: Optional[Dict[str, str]] = None,\n        ) -\u003e Dict[str, Any]:\n            \"\"\"\n            makes a delete request\n\n            parameters:\n                http_method: get, post, put, delete\n                request_url: API Url, without the common api prefix\n                payload : a dictionary\n                additional_query_params: additional query parameters for patch, post, put, delete\n                update_header_fields: allows to modify or add header fields\n\n            returns\n                response_dict: dictionary with the response as dict\n\n            \"\"\"\n\nQuery Syntax\n------------\n\nThe querying syntax closely resembling the one from the internal DAL.\nIf you're familiar with Shopware 6 DAL syntax and how to retrieve it,\nyou might see the examples are predictable and straightforward\n\na search criteria follows the following schema:\n\n.. code-block:: python\n\n    @attrs.define\n    class Criteria:\n        \"\"\"\n        see: https://shopware.stoplight.io/docs/store-api/ZG9jOjEwODExNzU2-search-queries\n\n        structure of Criteria:\n\n        parameter:\n\n        aggregations  List[Aggregation]                    Specify aggregations to be computed on-the-fly\n        associations  Dict['\u003cname\u003e', 'Criteria']           Allows to load additional data to the standard data of an entity\n        filter        List[Filter]                         Allows you to filter the result and aggregations\n        grouping      List['\u003cfieldname\u003e']                  allows you to group the result over fields\n        ids           List['\u003cid\u003e']                         Limits the search to a list of Ids\n        includes      Dict['apiAlias', List[\u003cfieldname\u003e]]  Restricts the output to the defined fields\n        limit         Optional[int]                        Defines the number of entries to be determined\n        page          Optional[int]                        Defines at which page the search result should start\n        post-filter                           not implemented at the moment\n        query         List[Query]                          Enables you to determine a ranking for the search result\n        sort          List[Sort]                           Defines the sorting of the search result\n        term          Optional[str]                        text search on all records based on their data model and weighting\n                                                           Don't use term parameters together with query parameters.\n        total-count-mode    Optional[int]                  Defines whether a total must be determined\n\n\n        \u003e\u003e\u003e # Test empty\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None, 'page': None, 'term': None, 'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test Average aggregation\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.limit=1\n        \u003e\u003e\u003e my_criteria.includes['product'] = ['id', 'name']\n        \u003e\u003e\u003e my_criteria.aggregations = [AvgAggregation('average-price', 'price')]\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 1,\n         'page': None,\n         'aggregations': [{'name': 'average-price', 'type': 'avg', 'field': 'price'}],\n         'includes': {'product': ['id', 'name']},\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test Filter aggregation\n        \u003e\u003e\u003e my_criteria = Criteria(limit=1, includes={'product':['id', 'name']},\n        ...     aggregations=[FilterAggregation(name='active-price-avg',\n        ...                                    filter=[EqualsFilter(field='active', value=True)],\n        ...                                    aggregation=AvgAggregation(name='avg-price',field='price'))])\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 1,\n         'page': None,\n         'aggregations': [{'name': 'active-price-avg',\n                           'type': 'filter',\n                           'filter': [{'type': 'equals',\n                                       'field': 'active',\n                                       'value': True}],\n                           'aggregation': {'name': 'avg-price',\n                                           'type': 'avg',\n                                           'field': 'price'}}],\n         'includes': {'product': ['id', 'name']},\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Association{{{\n        \u003e\u003e\u003e # Test Association\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.associations['products'] = Criteria(limit=5, filter=[EqualsFilter('active', 'true')])\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'associations': {'products': {'limit': 5,\n                                       'page': None,\n                                       'filter': [{'type': 'equals',\n                                                   'field': 'active',\n                                                   'value': 'true'}],\n                                       'term': None,\n                                       'total_count_mode': None}},\n         'term': None,\n         'total_count_mode': None}\n        \u003e\u003e\u003e # Association}}}\n\n        \u003e\u003e\u003e # Test append filters\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.page = 0\n        \u003e\u003e\u003e my_criteria.limit=1\n        \u003e\u003e\u003e my_criteria.filter.append(EqualsFilter('a', 'a'))\n        \u003e\u003e\u003e my_criteria.filter.append(EqualsFilter('b', 'b'))\n        \u003e\u003e\u003e my_criteria.filter.append(EqualsFilter('d', 'd'))\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 1,\n         'page': 0,\n         'filter': [{'type': 'equals', 'field': 'a', 'value': 'a'},\n                    {'type': 'equals', 'field': 'b', 'value': 'b'},\n                    {'type': 'equals', 'field': 'd', 'value': 'd'}],\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test set filters\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.filter = [EqualsFilter('a', 'a'), EqualsFilter('b', 'b'), EqualsFilter('d', 'd')]\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'filter': [{'type': 'equals', 'field': 'a', 'value': 'a'},\n                    {'type': 'equals', 'field': 'b', 'value': 'b'},\n                    {'type': 'equals', 'field': 'd', 'value': 'd'}],\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Grouping{{{\n        \u003e\u003e\u003e # Test Grouping\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.limit=5\n        \u003e\u003e\u003e my_criteria.grouping=['active']\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 5,\n         'page': None,\n         'grouping': ['active'],\n         'term': None,\n         'total_count_mode': None}\n        \u003e\u003e\u003e # Grouping}}}\n\n        \u003e\u003e\u003e # ids{{{\n        \u003e\u003e\u003e # Test ids\n        \u003e\u003e\u003e # note that the limit is automatically set to 3, and page to 1, which is for our paginated request\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'ids': ['012cd563cf8e4f0384eed93b5201cc98',\n                 '075fb241b769444bb72431f797fd5776',\n                 '090fcc2099794771935acf814e3fdb24'],\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test ids with a limit already set, which should fail\n        \u003e\u003e\u003e # You can use either \"limit\" or \"ids\", but not both, see : https://github.com/bitranox/lib_shopware6_api_base#ids\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.limit = 5\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        Traceback (most recent call last):\n            ...\n        ValueError: You can use either \"limit\" or \"ids\", but not both, ...\n\n        \u003e\u003e\u003e # Test to set limit after ids are passed, which should fail\n        \u003e\u003e\u003e # You can use either \"limit\" or \"ids\", but not both, see : https://github.com/bitranox/lib_shopware6_api_base#ids\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        \u003e\u003e\u003e my_criteria.limit = 2\n        Traceback (most recent call last):\n            ...\n        ValueError: You can use either \"limit\" or \"ids\", but not both, ...\n\n        \u003e\u003e\u003e # ids}}}\n\n        \u003e\u003e\u003e # includes{{{\n        \u003e\u003e\u003e # Test includes\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.includes['product'] = ['id', 'name']\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'includes': {'product': ['id', 'name']},\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # includes}}}\n\n        \u003e\u003e\u003e # page\u0026limit{{{\n        \u003e\u003e\u003e my_criteria = Criteria(page=1, limit=5)\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 5, 'page': 1, 'term': None, 'total_count_mode': None}\n\n        \u003e\u003e\u003e # page\u0026limit}}}\n\n        \u003e\u003e\u003e # Test Query\n        \u003e\u003e\u003e my_criteria = Criteria(\n        ...    query=[Query(score=500, query=ContainsFilter(field='name', value='Bronze')),\n        ...           Query(score=500, query=EqualsFilter(field='active', value='true')),\n        ...           Query(score=100, query=EqualsFilter(field='manufacturerId', value='db3c17b1e572432eb4a4c881b6f9d68f'))])\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'query': [{'score': 500,\n                    'query': {'type': 'contains', 'field': 'name', 'value': 'Bronze'}},\n                   {'score': 500,\n                    'query': {'type': 'equals', 'field': 'active', 'value': 'true'}},\n                   {'score': 100,\n                    'query': {'type': 'equals',\n                              'field': 'manufacturerId',\n                              'value': 'db3c17b1e572432eb4a4c881b6f9d68f'}}],\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test Sorting\n        \u003e\u003e\u003e my_criteria = Criteria(limit=5,\n        ...                        sort=[FieldSorting('name', 'ASC', True),\n        ...                              DescFieldSorting('active')])\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 5,\n         'page': None,\n         'sort': [{'field': 'name', 'order': 'ASC', 'naturalSorting': True},\n                  {'field': 'active', 'order': 'DESC', 'naturalSorting': None}],\n         'term': None,\n         'total_count_mode': None}\n\n        \"\"\"\n\nAggregations\n------------\nback to `Query Syntax`_\n\n- `AvgAggregation`_\n- `CountAggregation`_\n- `MaxAggregation`_\n- `MinAggregation`_\n- `SumAggregation`_\n- `StatsAggregation`_\n- `TermsAggregation`_\n- `FilterAggregation`_\n- `EntityAggregation`_\n- `DateHistogramAggregation`_\n- `NestingAggregations`_\n\n\nAvgAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class AvgAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The Avg aggregation makes it possible to calculate the average value for a field.\n        The following SQL statement is executed in the background: AVG(price).\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = AvgAggregation('avg-price', 'price')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'avg-price', 'type': 'avg', 'field': 'price'}\n\n        \"\"\"\n\nCountAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class CountAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The count aggregation makes it possible to determine the number of entries for a field that are filled with a value.\n        The following SQL statement is executed in the background: COUNT(DISTINCT(manufacturerId)).\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = CountAggregation('count-manufacturers', 'manufacturerId')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'count-manufacturers', 'type': 'count', 'field': 'manufacturerId'}\n\n        \"\"\"\n\nMaxAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class MaxAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The max aggregation allows you to determine the maximum value of a field.\n        The following SQL statement is executed in the background: MAX(price).\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = MaxAggregation('max-price', 'price')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'max-price', 'type': 'max', 'field': 'price'}\n\n        \"\"\"\n\nMinAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class MinAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The min aggregation makes it possible to determine the minimum value of a field.\n        The following SQL statement is executed in the background: MIN(price)\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = MinAggregation('min-price', 'price')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'min-price', 'type': 'min', 'field': 'price'}\n\n        \"\"\"\n\nSumAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class SumAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The sum aggregation makes it possible to determine the total of a field.\n        The following SQL statement is executed in the background: SUM(price)\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = SumAggregation('sum-price', 'price')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'sum-price', 'type': 'sum', 'field': 'price'}\n\n        \"\"\"\n\nStatsAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class StatsAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n        The stats aggregation makes it possible to calculate several values at once for a field.\n        This includes the previous max, min, avg and sum aggregation.\n        The following SQL statement is executed in the background: SELECT MAX(price), MIN(price), AVG(price), SUM(price)\n\n        :parameter:\n            name: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = StatsAggregation('stats-price', 'price')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'stats-price', 'type': 'stats', 'field': 'price'}\n\n        \"\"\"\n\nTermsAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class TermsAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n\n        The terms aggregation belongs to the bucket aggregations.\n        This allows you to determine the values of a field.\n        The result contains each value once and how often this value occurs in the result.\n        The terms aggregation also supports the following parameters:\n            limit - Defines a maximum number of entries to be returned (default: zero)\n            sort - Defines the order of the entries. By default the following is not sorted\n            aggregation - Enables you to calculate further aggregations for each key\n        The following SQL statement is executed in the background: SELECT DISTINCT(manufacturerId) as key, COUNT(manufacturerId) as count\n\n\n        :parameter:\n            name: str\n            field: str\n            sort: Optional[SortType]\n            limit: Optional[int]\n            aggregation: Optional[]\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = TermsAggregation(name='manufacturer-ids', limit=3, sort=DescFieldSorting('manufacturer.name'), field='manufacturerId')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'manufacturer-ids',\n         'type': 'terms',\n         'field': 'manufacturerId',\n         'sort': {'field': 'manufacturer.name',\n                  'order': 'DESC',\n                  'naturalSorting': None},\n         'limit': 3,\n         'aggregation': None}\n\n        \"\"\"\n\nFilterAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class FilterAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n\n        The filter aggregation belongs to the bucket aggregations.\n        Unlike all other aggregations, this aggregation does not determine any result, it cannot be used alone.\n        It is only used to further restrict the result of an aggregation in a criterion.\n        Filters which defined inside the filter property of this aggregation type,\n        are only used when calculating this aggregation.\n        The filters have no effect on other aggregations or on the result of the search.\n\n        parameter:\n            name: str\n            sort: SortType\n            filter: List of FilterType\n            aggregation : AggregationType\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = FilterAggregation(\n        ...     name='active-price-avg',\n        ...     filter=[EqualsFilter(field='active', value=True)],\n        ...     aggregation=AvgAggregation(name='avg-price',field='price'))\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'active-price-avg',\n         'type': 'filter',\n         'filter': [{'type': 'equals', 'field': 'active', 'value': True}],\n         'aggregation': {'name': 'avg-price', 'type': 'avg', 'field': 'price'}}\n\n        \"\"\"\n\nEntityAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class EntityAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n\n        The entity aggregation is similar to the terms aggregation, it belongs to the bucket aggregations.\n        As with terms aggregation, all unique values are determined for a field.\n        The aggregation then uses the determined keys to load the defined entity. The keys are used here as ids.\n\n        :parameter:\n            name: str\n            definition: str\n            field: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = EntityAggregation(name='manufacturers', definition='product_manufacturer', field='manufacturerId')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'manufacturers',\n         'type': 'entity',\n         'definition': 'product_manufacturer',\n         'field': 'manufacturerId'}\n        \"\"\"\n\nDateHistogramAggregation\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    @attrs.define\n    class DateHistogramAggregation:\n        \"\"\"\n        see aggregations reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference\n\n        The histogram aggregation is used as soon as the data to be determined refers to a date field.\n        With the histogram aggregation,\n        one of the following date intervals can be given: minute, hour, day, week, month, quarter, year, day.\n        This interval groups the result and calculates the corresponding count of hits.\n\n        :parameter:\n            name: str\n            field: str\n            interval: str ,  possible values: 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year', 'day'\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_aggregation = DateHistogramAggregation(name='release-dates', field='releaseDate', interval='month')\n        \u003e\u003e\u003e pprint_attrs(my_aggregation)\n        {'name': 'release-dates',\n         'type': 'histogram',\n         'field': 'releaseDate',\n         'interval': 'month'}\n\n        \"\"\"\n\nNestingAggregations\n========================\nback to `Aggregations`_\n\n.. code-block:: python\n\n    \"\"\"\n    see: https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/aggregations-reference#nesting-aggregations\n    \"\"\"\n\nAssociations\n------------------------\nback to `Query Syntax`_\n\nThe associations parameter allows you to load additional data to the minimal data set\nof an entity without sending an extra request - similar to a SQL Join.\nThe key of the parameter is the property name of the association in the entity.\nYou can pass a nested criteria just for that association - e.g. to perform a sort\nto or apply filters within the association.\n\n.. code-block:: python\n\n        \u003e\u003e\u003e # Test Association\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.associations['products'] = Criteria(limit=5, filter=[EqualsFilter('active', 'true')])\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'associations': {'products': {'limit': 5,\n                                       'page': None,\n                                       'filter': [{'type': 'equals',\n                                                   'field': 'active',\n                                                   'value': 'true'}],\n                                       'term': None,\n                                       'total_count_mode': None}},\n         'term': None,\n         'total_count_mode': None}\n        \u003e\u003e\u003e\n\nFilters\n------------------------\nback to `Query Syntax`_\n\n- `EqualsFilter`_\n- `EqualsAnyFilter`_\n- `ContainsFilter`_\n- `RangeFilter`_\n- `NotFilter`_\n- `MultiFilter`_\n- `PrefixFilter`_\n- `SuffixFilter`_\n\nEqualsFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class EqualsFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Equals filter allows you to check fields for an exact value.\n        The following SQL statement is executed in the background: WHERE stock = 10.\n\n        :parameter:\n            field: str\n            value: Union[str, int]      # probably also bool\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_filter = EqualsFilter('stock', 10)\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'equals', 'field': 'stock', 'value': 10}\n\n        \u003e\u003e\u003e my_filter = EqualsFilter('stock', None)\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'equals', 'field': 'stock', 'value': None}\n\n        \"\"\"\n\nEqualsAnyFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class EqualsAnyFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The EqualsAny filter allows you to filter a field where at least one of the defined values matches exactly.\n        The following SQL statement is executed in the background:\n        WHERE productNumber IN ('3fed029475fa4d4585f3a119886e0eb1', '77d26d011d914c3aa2c197c81241a45b').\n\n        :parameter:\n            field: str\n            value: List[str]\n\n        \u003e\u003e\u003e # Test Keyword param\n        \u003e\u003e\u003e my_filter = EqualsAnyFilter(field = 'productNumber', value = [\"3fed029475fa4d4585f3a119886e0eb1\", \"77d26d011d914c3aa2c197c81241a45b\"])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'equalsAny',\n         'field': 'productNumber',\n         'value': ['3fed029475fa4d4585f3a119886e0eb1',\n                   '77d26d011d914c3aa2c197c81241a45b']}\n\n        \u003e\u003e\u003e # Test positional param\n        \u003e\u003e\u003e my_filter = EqualsAnyFilter('productNumber', [\"3fed029475fa4d4585f3a119886e0eb1\", \"77d26d011d914c3aa2c197c81241a45b\"])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'equalsAny',\n         'field': 'productNumber',\n         'value': ['3fed029475fa4d4585f3a119886e0eb1',\n                   '77d26d011d914c3aa2c197c81241a45b']}\n\n        \"\"\"\n\nContainsFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class ContainsFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Contains Filter allows you to filter a field to an approximate value, where the passed value must be contained as a full value.\n        The following SQL statement is executed in the background: WHERE name LIKE '%Lightweight%'.\n\n        :parameter:\n            field: str\n            value: List[str]\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_filter = ContainsFilter(field = 'productNumber', value = 'Lightweight')\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'contains', 'field': 'productNumber', 'value': 'Lightweight'}\n\n        \"\"\"\n\nRangeFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class RangeFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Range filter allows you to filter a field to a value space. This can work with date or numerical values.\n        Within the parameter property the following values are possible:\n            gte =\u003e Greater than equals  (You might pass 'gte' or range_filter.gte)\n            lte =\u003e Less than equals     (You might pass 'lte' or range_filter.lte)\n            gt =\u003e Greater than          (You might pass 'gt' or range_filter.gt)\n            lt =\u003e Less than             (You might pass 'lt' or range_filter.lt)\n\n        :parameter:\n            field: str\n            parameters: Dict[str, Union[int, datetime]]\n\n        \u003e\u003e\u003e # Test (pass range type as string)\n        \u003e\u003e\u003e my_filter = RangeFilter(field = 'stock', parameters = {'gte': 20, 'lte': 30})\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'range', 'field': 'stock', 'parameters': {'gte': 20, 'lte': 30}}\n\n        \u003e\u003e\u003e # Test (pass range type from 'range_filter' object)\n        \u003e\u003e\u003e my_filter = RangeFilter(field = 'stock', parameters = {range_filter.gte: 20, range_filter.lte: 30})\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'range', 'field': 'stock', 'parameters': {'gte': 20, 'lte': 30}}\n\n        \u003e\u003e\u003e # Test (wrong range)\n        \u003e\u003e\u003e my_filter = RangeFilter(field = 'stock', parameters = {'gte': 20, 'less': 30})\n        Traceback (most recent call last):\n            ...\n        ValueError: \"less\" is not a valid range\n\n        \"\"\"\n\nNotFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class NotFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Not Filter is a container which allows to negate any kind of filter.\n        The operator allows you to define the combination of queries within the NOT filter (\"OR\" and \"AND\").\n        The following SQL statement is executed in the background: WHERE !(stock = 1 OR availableStock = 1):\n\n        :parameter:\n            operator: 'or' | 'and'\n            queries: List[Filter]\n\n        \u003e\u003e\u003e # Test (pass operator as string)\n        \u003e\u003e\u003e my_filter = NotFilter('or', [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'not',\n         'operator': 'or',\n         'queries': [{'type': 'equals', 'field': 'stock', 'value': 1},\n                     {'type': 'equals', 'field': 'availableStock', 'value': 10}]}\n\n        \u003e\u003e\u003e # Test (pass operator from 'not_filter_operator' object)\n        \u003e\u003e\u003e my_filter = NotFilter(not_filter_operator.or_, [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'not',\n         'operator': 'or',\n         'queries': [{'type': 'equals', 'field': 'stock', 'value': 1},\n                     {'type': 'equals', 'field': 'availableStock', 'value': 10}]}\n\n        \u003e\u003e\u003e # Test unknown operator\n        \u003e\u003e\u003e my_filter = NotFilter('duck', [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        Traceback (most recent call last):\n            ...\n        ValueError: (\"'operator' must be in ['and', 'or'] (got 'duck')\", ...)\n\n        \"\"\"\n\nMultiFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class MultiFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Multi Filter is a container, which allows to set logical links between filters.\n        The operator allows you to define the links between the queries within the Multi filter (\"OR\" and \"AND\").\n        The following SQL statement is executed in the background: WHERE (stock = 1 OR availableStock = 1)\n\n        :parameter:\n            operator: 'or' | 'and'\n            queries: List[Filter]\n\n        \u003e\u003e\u003e # Test (pass operator as string)\n        \u003e\u003e\u003e my_filter = MultiFilter('or', [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'multi',\n         'operator': 'or',\n         'queries': [{'type': 'equals', 'field': 'stock', 'value': 1},\n                     {'type': 'equals', 'field': 'availableStock', 'value': 10}]}\n\n        \u003e\u003e\u003e # Test (pass operator from 'not_filter_operator' object)\n        \u003e\u003e\u003e my_filter = MultiFilter(multi_filter_operator.or_, [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'multi',\n         'operator': 'or',\n         'queries': [{'type': 'equals', 'field': 'stock', 'value': 1},\n                     {'type': 'equals', 'field': 'availableStock', 'value': 10}]}\n\n        \u003e\u003e\u003e # Test unknown operator\n        \u003e\u003e\u003e my_filter = MultiFilter('duck', [EqualsFilter('stock', 1), EqualsFilter('availableStock', 10)])\n        Traceback (most recent call last):\n            ...\n        ValueError: (\"'operator' must be in ['and', 'or'] (got 'duck')\", ...)\n\n        \"\"\"\n\nPrefixFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class PrefixFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Prefix Filter allows you to filter a field to an approximate value, where the passed value must be the start of a full value.\n        The following SQL statement is executed in the background: WHERE name LIKE 'Lightweight%'.\n\n        :parameter:\n            field: str\n            value: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_filter = PrefixFilter('name', 'Lightweight')\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'prefix', 'field': 'name', 'value': 'Lightweight'}\n\n        \"\"\"\n\nSuffixFilter\n========================\nback to `Filters`_\n\n.. code-block:: python\n\n    @attrs.define\n    class SuffixFilter:\n        \"\"\"\n        see filter reference : https://developer.shopware.com/docs/resources/references/core-reference/dal-reference/filters-reference\n        The Suffix Filter allows you to filter a field to an approximate value, where the passed value must be the end of a full value.\n        The following SQL statement is executed in the background: WHERE name LIKE '%Lightweight'.\n\n        :parameter:\n            field: str\n            value: str\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_filter = SuffixFilter('name', 'Lightweight')\n        \u003e\u003e\u003e pprint_attrs(my_filter)\n        {'type': 'suffix', 'field': 'name', 'value': 'Lightweight'}\n\n        \"\"\"\n\nGrouping\n------------------------\nback to `Query Syntax`_\n\nThe grouping parameter allows you to group the result over fields.\nIt can be used to realise queries such as:\n\n- Fetch one product for each manufacturer\n- Fetch one order per day and customer\n\n.. code-block:: python\n\n        \u003e\u003e\u003e # Test Grouping\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.limit=5\n        \u003e\u003e\u003e my_criteria.grouping=['active']\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 5,\n         'page': None,\n         'grouping': ['active'],\n         'term': None,\n         'total_count_mode': None}\n        \u003e\u003e\u003e\n\nids\n------------------------\nback to `Query Syntax`_\n\nIf you want to perform a simple lookup using just the ids of records,\nyou can pass a list of those using the ids field.\nPlease note that as soon as You use ids, limit and page does not apply anymore !\n\n.. code-block:: python\n\n        \u003e\u003e\u003e # Test ids\n        \u003e\u003e\u003e # note that the limit is automatically set to 3, and page to 1, which is for our paginated request\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'ids': ['012cd563cf8e4f0384eed93b5201cc98',\n                 '075fb241b769444bb72431f797fd5776',\n                 '090fcc2099794771935acf814e3fdb24'],\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e # Test ids with a limit already set, which should fail\n        \u003e\u003e\u003e # You can use either \"limit\" or \"ids\", but not both, see : https://github.com/bitranox/lib_shopware6_api_base#ids\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.limit = 5\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        Traceback (most recent call last):\n            ...\n        ValueError: You can use either \"limit\" or \"ids\", but not both, ...\n\n        \u003e\u003e\u003e # Test to set limit after ids are passed, which should fail\n        \u003e\u003e\u003e # You can use either \"limit\" or \"ids\", but not both, see : https://github.com/bitranox/lib_shopware6_api_base#ids\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.ids=[\"012cd563cf8e4f0384eed93b5201cc98\", \"075fb241b769444bb72431f797fd5776\", \"090fcc2099794771935acf814e3fdb24\"]\n        \u003e\u003e\u003e my_criteria.limit = 2\n        Traceback (most recent call last):\n            ...\n        ValueError: You can use either \"limit\" or \"ids\", but not both, ...\n\n        \u003e\u003e\u003e\n\nincludes\n------------------------\nback to `Query Syntax`_\n\nThe includes parameter allows you to restrict the returned fields.\n\nTransfer only what you need - reduces response payload\nEasier to consume for client applications\nWhen debugging, the response is smaller and you can concentrate on the essential fields\n\n.. code-block:: python\n\n        \u003e\u003e\u003e # Test includes\n        \u003e\u003e\u003e my_criteria = Criteria()\n        \u003e\u003e\u003e my_criteria.includes['product'] = ['id', 'name']\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'includes': {'product': ['id', 'name']},\n         'term': None,\n         'total_count_mode': None}\n\n        \u003e\u003e\u003e\n\nAll response types come with a apiAlias field which you can use to identify the\ntype in your includes field.\n\nIf you only want a categories id, add: \"category\": [\"id\"].\n\nFor entities, this is the entity name: product, product_manufacturer, order_line_item, ...\n\nFor other non-entity-types like a listing result or a line item, check the full response.\nThis pattern applies not only to simple fields but also to associations.\n\npage \u0026 limit\n------------------------\nback to `Query Syntax`_\n\nThe page and limit parameters can be used to control pagination. The page parameter is 1-indexed.\nPlease note that as soon as You use ids, limit and page does not apply anymore !\n\n.. code-block:: python\n\n        \u003e\u003e\u003e my_criteria = Criteria(page=1, limit=5)\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': 5, 'page': 1, 'term': None, 'total_count_mode': None}\n\n        \u003e\u003e\u003e\n\nQuery\n------------------------\nback to `Query Syntax`_\n\nUse this parameter to create a weighted search query that returns a _score for each found entity.\nAny filter type can be used for the query. A score has to be defined for each query.\nThe sum of the matching queries then results in the total _score value.\n\n.. code-block:: python\n\n    @attrs.define\n    class Query:\n        \"\"\"\n        see: https://shopware.stoplight.io/docs/store-api/ZG9jOjEwODExNzU2-search-queries#query\n        Enables you to determine a ranking for the search result\n        Use this parameter to create a weighted search query that returns a _score for each found entity.\n        Any filter type can be used for the query. A score has to be defined for each query.\n        The sum of the matching queries then results in the total _score value.\n\n        parameter\n            score   int\n            query   FilterType\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_criteria = Criteria(\n        ...    query=[Query(score=500, query=ContainsFilter(field='name', value='Bronze')),\n        ...           Query(score=500, query=EqualsFilter(field='active', value='true')),\n        ...           Query(score=100, query=EqualsFilter(field='manufacturerId', value='db3c17b1e572432eb4a4c881b6f9d68f'))])\n\n        \u003e\u003e\u003e pprint_attrs(my_criteria)\n        {'limit': None,\n         'page': None,\n         'query': [{'score': 500,\n                    'query': {'type': 'contains', 'field': 'name', 'value': 'Bronze'}},\n                   {'score': 500,\n                    'query': {'type': 'equals', 'field': 'active', 'value': 'true'}},\n                   {'score': 100,\n                    'query': {'type': 'equals',\n                              'field': 'manufacturerId',\n                              'value': 'db3c17b1e572432eb4a4c881b6f9d68f'}}],\n         'term': None,\n         'total_count_mode': None}\n\n        \"\"\"\n\nSort\n------------------------\nback to `Query Syntax`_\n\nThe sort parameter allows to control the sorting of the result.\nSeveral sorts can be transferred at the same time.\n\nThe field parameter defines which field is to be used for sorting.\nThe order parameter defines the sort direction.\nThe parameter naturalSorting allows to use a Natural Sorting Algorithm\n\nFieldSorting\n===============\n\n.. code-block:: python\n\n    @attrs.define\n    class FieldSorting:\n        \"\"\"\n        see: https://shopware.stoplight.io/docs/store-api/ZG9jOjEwODExNzU2-search-queries#sort\n        The sort parameter allows to control the sorting of the result. Several sorts can be transferred at the same time.\n        The field parameter defines which field is to be used for sorting.\n        The order parameter defines the sort direction.\n        The parameter naturalSorting allows to use a Natural Sorting Algorithm\n\n        parameter:\n            field : str\n            order : str \"ASC\" or \"DESC\"\n            naturalSorting : Optional[bool]\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_sorting = FieldSorting('name', 'ASC', True)\n        \u003e\u003e\u003e pprint_attrs(my_sorting)\n        {'field': 'name', 'order': 'ASC', 'naturalSorting': True}\n\n        \"\"\"\n\nAscFieldSorting\n===============\n\n.. code-block:: python\n\n    @attrs.define\n    class AscFieldSorting:\n        \"\"\"\n        see: https://shopware.stoplight.io/docs/store-api/ZG9jOjEwODExNzU2-search-queries#sort\n        The sort parameter allows to control the sorting of the result. Several sorts can be transferred at the same time.\n        The field parameter defines which field is to be used for sorting.\n        The order parameter defines the sort direction.\n        The parameter naturalSorting allows to use a Natural Sorting Algorithm\n\n        parameter:\n            field : str\n            naturalSorting : Optional[bool]\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_sorting = AscFieldSorting('name', True)\n        \u003e\u003e\u003e pprint_attrs(my_sorting)\n        {'field': 'name', 'order': 'ASC', 'naturalSorting': True}\n\n        \"\"\"\n\nDescFieldSorting\n=================\n\n.. code-block:: python\n\n    @attrs.define\n    class DescFieldSorting:\n        \"\"\"\n        see: https://shopware.stoplight.io/docs/store-api/ZG9jOjEwODExNzU2-search-queries#sort\n        The sort parameter allows to control the sorting of the result. Several sorts can be transferred at the same time.\n        The field parameter defines which field is to be used for sorting.\n        The order parameter defines the sort direction.\n        The parameter naturalSorting allows to use a Natural Sorting Algorithm\n\n        parameter:\n            field : str\n            naturalSorting : Optional[bool]\n\n        \u003e\u003e\u003e # Test\n        \u003e\u003e\u003e my_sorting = DescFieldSorting('name', True)\n        \u003e\u003e\u003e pprint_attrs(my_sorting)\n        {'field': 'name', 'order': 'DESC', 'naturalSorting': True}\n\n        \"\"\"\n\nUsage from Commandline\n------------------------\n\n.. code-block::\n\n   Usage: lib_shopware6_api_base [OPTIONS] COMMAND [ARGS]...\n\n     python3 base API client for shopware6\n\n   Options:\n     --version                     Show the version and exit.\n     --traceback / --no-traceback  return traceback information on cli\n     -h, --help                    Show this message and exit.\n\n   Commands:\n     info  get program information\n\nInstallation and Upgrade\n------------------------\n\n- Before You start, its highly recommended to update pip:\n\n\n.. code-block::\n\n    python -m pip --upgrade pip\n\n- to install the latest release from PyPi via pip (recommended):\n\n.. code-block::\n\n    python -m pip install --upgrade lib_shopware6_api_base\n\n\n- to install the latest release from PyPi via pip, including test dependencies:\n\n.. code-block::\n\n    python -m pip install --upgrade lib_shopware6_api_base[test]\n\n- to install the latest version from github via pip:\n\n\n.. code-block::\n\n    python -m pip install --upgrade git+https://github.com/bitranox/lib_shopware6_api_base.git\n\n\n- include it into Your requirements.txt:\n\n.. code-block::\n\n    # Insert following line in Your requirements.txt:\n    # for the latest Release on pypi:\n    lib_shopware6_api_base\n\n    # for the latest development version :\n    lib_shopware6_api_base @ git+https://github.com/bitranox/lib_shopware6_api_base.git\n\n    # to install and upgrade all modules mentioned in requirements.txt:\n    python -m pip install --upgrade -r /\u003cpath\u003e/requirements.txt\n\n\n- to install the latest development version, including test dependencies from source code:\n\n.. code-block::\n\n    # cd ~\n    $ git clone https://github.com/bitranox/lib_shopware6_api_base.git\n    $ cd lib_shopware6_api_base\n    python -m pip install -e .[test]\n\n- via makefile:\n  makefiles are a very convenient way to install. Here we can do much more,\n  like installing virtual environments, clean caches and so on.\n\n.. code-block:: shell\n\n    # from Your shell's homedirectory:\n    $ git clone https://github.com/bitranox/lib_shopware6_api_base.git\n    $ cd lib_shopware6_api_base\n\n    # to run the tests:\n    $ make test\n\n    # to install the package\n    $ make install\n\n    # to clean the package\n    $ make clean\n\n    # uninstall the package\n    $ make uninstall\n\nRequirements\n------------\nfollowing modules will be automatically installed :\n\n.. code-block:: bash\n\n    ## Project Requirements\n    attrs\u003e=21.3.0\n    click\n    cli_exit_tools\n    lib_detect_testenv\n    oauthlib\n    requests\n    requests-oauthlib\n\nAcknowledgements\n----------------\n\n- special thanks to \"uncle bob\" Robert C. Martin, especially for his books on \"clean code\" and \"clean architecture\"\n\nContribute\n----------\n\nI would love for you to fork and send me pull request for this project.\n- `please Contribute \u003chttps://github.com/bitranox/lib_shopware6_api_base/blob/master/CONTRIBUTING.md\u003e`_\n\nLicense\n-------\n\nThis software is licensed under the `MIT license \u003chttp://en.wikipedia.org/wiki/MIT_License\u003e`_\n\n---\n\nChangelog\n=========\n\n- new MAJOR version for incompatible API changes,\n- new MINOR version for added functionality in a backwards compatible manner\n- new PATCH version for backwards compatible bug fixes\n\nv2.1.9\n---------\n2024-09-29:\n    - add graalpy tests\n\nv2.1.8\n---------\n2024-09-29:\n    - add example for /search/order via post request\n\nv2.1.7\n---------\n2023-10-18:\n    - validator for \"Criteria.ids\" and \"Criteria.limit\"\n    - if \"Criteria.ids\" are passed, set \"limits\" to the number of ids\n    - prevent that \"Criteria.limits\" and \"Criteria.ids\" are set simultaneous\n    - bump up coverage\n\nv2.1.6\n---------\n2023-10-18:\n    - correcting \"Filter Aggregation\", some typos correction\n\nv2.1.5\n---------\n2023-10-18:\n    - get rid of special pretty printer version \"pprint3x\" for python 3.7 and below\n    - correcting type hint for filter \"ContainsFilter\"\n\nv2.1.4\n---------\n2023-10-18:\n    - correct EqualsAnyFilter, thanks to Patrik Hofmann for finding that bug.\n\nv2.1.3\n---------\n2023-07-14:\n    - add codeql badge\n    - move 3rd_party_stubs outside the src directory to ``./.3rd_party_stubs``\n    - add pypy 3.10 tests\n    - add python 3.12-dev tests\n\nv2.1.2\n---------\n2023-07-13:\n    - require minimum python 3.8\n    - remove python 3.7 tests\n\nv2.1.1\n---------\n2023-07-13:\n    - introduce PEP517 packaging standard\n    - introduce pyproject.toml build-system\n    - remove setup.cfg\n    - remove setup.py\n    - update black config\n    - clean ./tests/test_cli.py\n\nv2.1.0\n---------\n2023-06-28:\n    - introduce additional header fields\n    - update black config\n    - remove travis config\n    - remove bettercodehub config\n    - do not upload .egg files to pypi.org\n    - update github actions : checkout@v3 and setup-python@v4\n    - remove \"better code\" badges\n    - remove python 3.6 tests\n    - adding python 3.11 tests\n    - update pypy tests to 3.9\n\nv2.0.9\n---------\n2022-07-04: support additional query parameters for patch, post ,put and delete requests\n\nv2.0.8\n---------\n2022-07-04: allow different content-types in order to be able to upload documents as octet-stream\n\nv2.0.7.3\n---------\n2022-06-30: specify correct \"attr\" version in requirements\n\nv2.0.7.2\n---------\n2022-06-02: update to github actions checkout@v3 and setup-python@v3\n\nv2.0.7.1\n--------\n2022-06-01: update github actions test matrix\n\nv2.0.7\n--------\n2022-04-12: retry the request (experimental, but not harmful at all) if failed.\n  - issue https://github.com/bitranox/lib_shopware6_api/issues/1\n  - sometimes (seldom, after about 10 minutes connected) we got: \"error code: 9, status: 401\n    The resource owner or authorization server denied the request, detail: Access token could not be verified.\"\n  - it seems to work when retry the request\n\nv2.0.6\n--------\n2022-03-29: remedy mypy Untyped decorator makes function \"cli_info\" untyped\n\nv2.0.5\n------\n2022-02-15: documentation update\n\nv2.0.4\n------\n2022-02-15: documentation update\n\nv2.0.3\n------\n2022-01-18: mypy type adjustments\n\nv2.0.2\n------\n2022-01-09:\n    - handle dal.Criteria 'ids' correctly\n    - remove empty lists and dicts from dal.Criteria\n\nv2.0.1\n------\n2022-01-06: correct import for dal.Criteria\n\nv2.0.0\n------\n2022-01-04:\n    - make it possible to pass None Values to Filters (Bug)\n    - paginated request now respect limits\n\nv1.3.2\n------\n2022-01-04: improve detection of the dal.Criteria Class\n\nv1.3.1\n------\n2021-12-31: implement testing for python 3.6, 3.7\n\nv1.3.0\n--------\n2021-12-29: add Sort, Group, Aggregations, Associations, etc ..\n\nv1.2.0\n--------\n2021-12-28: add Criteria, Filters\n\nv1.1.0\n--------\n2021-12-27: add Store Api DELETE/GET/GET LIST/PATCH/PUT methods\n\nv1.0.0\n--------\n2021-12-26: initial release\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitranox%2Flib_shopware6_api_base","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitranox%2Flib_shopware6_api_base","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitranox%2Flib_shopware6_api_base/lists"}