From 60881c5942417fed0549e8a48f0695991e6a4d0a Mon Sep 17 00:00:00 2001 From: Paul Hallett Date: Thu, 5 Oct 2023 08:54:33 +1300 Subject: [PATCH] Deployed 0b6fae4 with MkDocs version: 1.5.3 --- 404.html | 2 +- CHANGELOG/index.html | 2 +- compatibility/index.html | 2 +- examples/index.html | 2 +- index.html | 2 +- install/index.html | 2 +- search/search_index.json | 2 +- sitemap.xml | 14 ++-- sitemap.xml.gz | Bin 272 -> 272 bytes testing/index.html | 2 +- usage/index.html | 158 ++++++++++++++++++++++++++++----------- 11 files changed, 129 insertions(+), 59 deletions(-) diff --git a/404.html b/404.html index 81d18f0..b190d30 100644 --- a/404.html +++ b/404.html @@ -255,7 +255,7 @@ - Commands + Use diff --git a/CHANGELOG/index.html b/CHANGELOG/index.html index 504b661..c427275 100644 --- a/CHANGELOG/index.html +++ b/CHANGELOG/index.html @@ -264,7 +264,7 @@ - Commands + Use diff --git a/compatibility/index.html b/compatibility/index.html index 441b12c..4aaeb92 100644 --- a/compatibility/index.html +++ b/compatibility/index.html @@ -266,7 +266,7 @@ - Commands + Use diff --git a/examples/index.html b/examples/index.html index 87721fd..360e77c 100644 --- a/examples/index.html +++ b/examples/index.html @@ -266,7 +266,7 @@ - Commands + Use diff --git a/index.html b/index.html index af986c6..3fc40c8 100644 --- a/index.html +++ b/index.html @@ -332,7 +332,7 @@ - Commands + Use diff --git a/install/index.html b/install/index.html index ffb67b5..7f2e2b6 100644 --- a/install/index.html +++ b/install/index.html @@ -276,7 +276,7 @@ - Commands + Use diff --git a/search/search_index.json b/search/search_index.json index df68dd4..1d50e52 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\u269c\ufe0f Clientele","text":""},{"location":"#generate-loveable-python-http-api-clients","title":"Generate loveable Python HTTP API Clients","text":"

Clientele lets you generate fully-typed, pythonic HTTP API Clients using an OpenAPI schema.

It's easy to use:

# Install as a global tool - it's not a dependency!\npipx install clientele\n# Generate a client\nclientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o api_client/\n
"},{"location":"#generated-code","title":"Generated code","text":"

The generated code is designed by python developers, for python developers.

It uses modern tooling and has a great developer experience.

from my_api import client, schemas\n# Pydantic models for inputs and outputs\ndata = schemas.RequestDataRequest(my_input=\"test\")\n# Easy to read client functions\nresponse = client.request_data_request_data_post(data=data)\n# Handle responses elegantly\nmatch response:\ncase schemas.RequestDataResponse():\n# Handle valid response\n...\ncase schemas.ValidationError():\n# Handle validation error\n...\n

The generated code is tiny - the example schema we use for documentation and testing only requires 250 lines of code and 5 files.

"},{"location":"#async-support","title":"Async support","text":"

You can choose to generate either a sync or an async client - we support both:

from my_async_api import client\n# Async client functions\nresponse = await client.simple_request_simple_request_get()\n
"},{"location":"#other-features","title":"Other features","text":""},{"location":"CHANGELOG/","title":"Change log","text":""},{"location":"CHANGELOG/#063","title":"0.6.3","text":""},{"location":"CHANGELOG/#062","title":"0.6.2","text":""},{"location":"CHANGELOG/#061","title":"0.6.1","text":""},{"location":"CHANGELOG/#060","title":"0.6.0","text":""},{"location":"CHANGELOG/#052","title":"0.5.2","text":""},{"location":"CHANGELOG/#051","title":"0.5.1","text":"

Additionally, an async test client is now included in the test suite. It has identical tests to the standard one but uses the async client instead.

"},{"location":"CHANGELOG/#050","title":"0.5.0","text":""},{"location":"CHANGELOG/#please-delete-the-constantspy-file-when-updating-to-this-version-to-have-new-features-take-affect","title":"Please delete the constants.py file when updating to this version to have new features take affect","text":""},{"location":"CHANGELOG/#044","title":"0.4.4","text":"

Examples and documentation now includes a very complex example schema built using FastAPI that offers the following variations:

A huge test suite has been added to the CI pipeline for this project using a copy of the generated client from the schema above.

"},{"location":"CHANGELOG/#043","title":"0.4.3","text":""},{"location":"CHANGELOG/#042","title":"0.4.2","text":""},{"location":"CHANGELOG/#041","title":"0.4.1","text":""},{"location":"CHANGELOG/#040","title":"0.4.0","text":""},{"location":"CHANGELOG/#032","title":"0.3.2","text":""},{"location":"CHANGELOG/#031","title":"0.3.1","text":""},{"location":"CHANGELOG/#030","title":"0.3.0","text":""},{"location":"CHANGELOG/#020","title":"0.2.0","text":""},{"location":"CHANGELOG/#010","title":"0.1.0","text":""},{"location":"compatibility/","title":"\ud83d\udcb1 Compatibility","text":""},{"location":"compatibility/#great-compatibility","title":"Great compatibility","text":"

Any standard 3.0.x implementation works very well.

We have tested Clientele with:

"},{"location":"compatibility/#no-compatibility","title":"No compatibility","text":"

We do not support 2.x aka \"Swagger\" - this format is quite different and deprecated.

"},{"location":"compatibility/#a-note-on-compatbility","title":"A note on compatbility","text":"

When we were building Clientele, we discovered that, despite a fantastic specification, OpenAPI has a lot of poor implementations.

As pythonistas, we started with the auto-generated OpenAPI schemas provided by FastAPI, and then we branched out to large APIs like Twilio to test what we built.

Despite the effort, we still keep finding subtly different OpenAPI implementations.

Because of this we cannot guarentee 100% compatibility with an API, but we can give you a good indication of what we've tested.

"},{"location":"examples/","title":"\ud83e\ude84 Client example","text":"

Let's build an API Client using clientele and an example OpenAPI schema.

Our GitHub has a bunch of schemas that are proven to work with clientele, so let's use one of those!

"},{"location":"examples/#generate-the-client","title":"Generate the client","text":"

Simply:

clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/\n

The -u parameter expects a URL, you can provide a path to a file with -f instead if you download the file.

The -o parameter is the output directory of the generated client.

Run it now and you will see this output:

my_client/\n    __init__.py\n    client.py\n    constants.py\n    http.py\n    MANIFEST\n    schemas.py\n
"},{"location":"examples/#client","title":"Client","text":"

Let's go over each file and talk about what it does

"},{"location":"examples/#get-functions","title":"GET functions","text":"

The client.py file provides all the API functions from the OpenAPI schema.

my_client/client.py
import typing  # noqa\nfrom . import schemas  # noqa\nfrom . import http  # noqa\ndef simple_request_simple_request_get() -> schemas.SimpleResponse:\n\"\"\"Simple Request\"\"\"\nresponse = http.get(url=\"/simple-request\")\nreturn http.handle_response(simple_request_simple_request_get, response)\n...\n

We can see one of the functions here, simple_request_simple_request_get, is for a straight-forward HTTP GET request without any input arguments, and it returns a schema object.

Here is how you might use it:

from my_client import client\nclient.simple_request_simple_request_get()\n>>> SimpleResponse(name='Paul')\n
"},{"location":"examples/#post-and-put-functions","title":"POST and PUT functions","text":"

A more complex example is shown just below. This is for an HTTP POST method, and it requires an input property called data that is an instance of a schema, and returns a union of responses. If the endpoint has url parameters or query parameters, they will appear as input arguments to the function alongside the data argument.

def request_data_request_data_post(\ndata: schemas.RequestDataRequest,\n) -> typing.Union[schemas.RequestDataResponse, schemas.HTTPValidationError]:\n\"\"\"Request Data\"\"\"\nresponse = http.post(url=\"/request-data\", data=data.model_dump())\nreturn http.handle_response(request_data_request_data_post, response)\n

Here is how you might use it:

from my_client import client, schemas\ndata = schemas.RequestDataRequest(my_input=\"Hello, world\")\nresponse = client.request_data_request_data_post(data=data)\n>>> RequestDataResponse(your_input='Hello, world')\n

Clientele also supports HTTP PUT functionality in the exact same way as HTTP POST:

from my_client import client, schemas\ndata = schemas.RequestDataRequest(my_input=\"Hello, world\")\nresponse = client.request_data_request_data_put(data=data)\n>>> RequestDataResponse(your_input='Hello, world')\n
"},{"location":"examples/#url-and-query-parameters","title":"URL and Query parameters","text":"

If your endpoint takes path parameters (aka URL parameters) then clientele will turn them into parameters in the function:

from my_client import client\nclient.parameter_request_simple_request(your_input=\"gibberish\")\n>>> ParameterResponse(your_input='gibberish')\n

Query parameters will also be generated the same way. See this example for a function that takes a required query parameter.

"},{"location":"examples/#handling-responses","title":"Handling responses","text":"

Because we're using Pydantic to manage the input data, we get a strongly-typed response object. This works beautifully with the new structural pattern matching feature in Python 3.10:

response = client.request_data_request_data_post(data=data)\n# Handle responses elegantly\nmatch response:\ncase schemas.RequestDataResponse():\n# Handle valid response\n...\ncase schemas.ValidationError():\n# Handle validation error\n...\n
"},{"location":"examples/#api-exceptions","title":"API Exceptions","text":"

Clientele works by matching the shape of the response object with the Pydantic return types of a function. When it matches one, it generates the pydantic object and returns it.

If the response object is an unintended one, it will not match a return type.

In this case, the function will raise an http.APIException.

from my_client import client, http\ntry:\ngood_response = my_client.get_my_thing()\nexcept http.APIException as e:\n# The API got a response we didn't expect\nprint(e.response.status_code)\n

The response object will be attached to this exception class for later inspection.

"},{"location":"examples/#schemas","title":"Schemas","text":"

The schemas.py file has all the possible schemas, request and response, and even Enums, for the API.

They are all subclassed from pydantic's BaseModel. Here are a few examples:

my_client/schemas.py
import typing  # noqa\nimport pydantic  # noqa\nfrom enum import Enum  # noqa\nclass ParameterResponse(pydantic.BaseModel):\nyour_input: str\nclass RequestDataRequest(pydantic.BaseModel):\nmy_input: str\nclass RequestDataResponse(pydantic.BaseModel):\nmy_input: str\n# Enums subclass str so they serialize to JSON nicely\nclass ExampleEnum(str, Enum):\nONE = \"ONE\"\nTWO = \"TWO\"\n
"},{"location":"examples/#configuration","title":"Configuration","text":"

One of the problems with auto-generated clients is that you often need to configure them, and if you try and regenerate the client at some point then your configuration gets wiped clean and you have to do it all over again.

Clientele solves this problem by providing an entry point for configuration that will never be overwritten - constants.py.

When you first generate the project, you will see a file called constants.py and it will offer configuration functions a bit like this:

\"\"\"\nThis file will never be updated on subsequent clientele runs.\nUse it as a space to store configuration and constants.\nDO NOT CHANGE THE FUNCTION NAMES\n\"\"\"\ndef api_base_url() -> str:\n\"\"\"\n    Modify this function to provide the current api_base_url.\n    \"\"\"\nreturn \"http://localhost\"\n

Subsequent runs of the generate command will not change this file the first time is made, so you are free to modify the defaults to suit your needs, for example, if you need to source the base url of your API for different configurations, you can modify the api_base_url function like this:

from my_project import my_config\ndef api_base_url() -> str:\n\"\"\"\n    Modify this function to provide the current api_base_url.\n    \"\"\"\nif my_config.debug:\nreturn \"http://localhost:8000\"\nelif my_config.production:\nreturn \"http://my-production-url.com\"\n

Just keep the function names the same and you're good to go.

"},{"location":"examples/#authentication","title":"Authentication","text":"

If your OpenAPI spec provides security information for the following authentication methods:

Then clientele will provide you information on the environment variables you need to set to make this work during the generation. For example:

Please see my_client/constants.py to set authentication variables\n

The constants.py file will have entry points for you to configure, for example, HTTP Bearer authentication will need the get_bearer_token function to be updated, something like this:

def get_bearer_token() -> str:\n\"\"\"\n    HTTP Bearer authentication.\n    Used by many authentication methods - token, jwt, etc.\n    Does not require the \"Bearer\" content, just the key as a string.\n    \"\"\"\nfrom os import environ\nreturn environ.get(\"MY_AUTHENTICATION_TOKEN\")\n
"},{"location":"examples/#additional-headers","title":"Additional headers","text":"

If you want to pass specific headers with all requests made by the client, you can configure the additional_headers function in constants.py to do this.

def additional_headers() -> dict:\n\"\"\"\n    Modify this function ot provide additional headers to all\n    HTTP requests made by this client.\n    \"\"\"\nreturn {}\n

Please note that if you are using this with authentication headers, then authentication headers will overwrite these defaults if they keys match.

"},{"location":"install/","title":"\ud83c\udfd7\ufe0f Install","text":"

We recommend installing with pipx as a global CLI command:

pipx install clientele\n

Once installed you can run clientele version to make sure you have the latest version:

> clientele version\nclientele 0.6.3\n
"},{"location":"testing/","title":"Testing","text":"

Clientele is designed for easy testing, and our own test suite is a great example of how easily you can write mock tests for your API Client.

import pytest\nfrom httpx import Response\nfrom respx import MockRouter\nfrom .test_client import client, constants, schemas\nBASE_URL = constants.api_base_url()\n@pytest.mark.respx(base_url=BASE_URL)\ndef test_simple_request_simple_request_get(respx_mock: MockRouter):\n# Given\nmocked_response = {\"status\": \"hello world\"}\nmock_path = \"/simple-request\"\nrespx_mock.get(mock_path).mock(\nreturn_value=Response(json=mocked_response, status_code=200)\n)\n# When\nresponse = client.simple_request_simple_request_get()\n# Then\nassert isinstance(response, schemas.SimpleResponse)\nassert len(respx_mock.calls) == 1\ncall = respx_mock.calls[0]\nassert call.request.url == BASE_URL + mock_path\n

We recommend you install respx for writing your tests.

"},{"location":"usage/","title":"\ud83d\udcdd Commands","text":""},{"location":"usage/#validate","title":"Validate","text":"

Validate lets you check if an OpenAPI schema will work with clientele. Some OpenAPI schema generators do not comply properly with the specification and it is a good way to check if your schema is correct.

clientele validate -u http://path.com/to/openapi.json\n

Alternatively you can provide a local file:

clientele validate -f /path/to/openapi.json\n
"},{"location":"usage/#generate","title":"Generate","text":""},{"location":"usage/#from-a-url","title":"From a URL","text":"

Assuming the OpenAPI schema is available on the internet somewhere, you can query it to generate your client.

clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/\n

Note

The example above uses a test OpenAPI format, and will work if you copy/paste it!

"},{"location":"usage/#from-a-file","title":"From a file","text":"

Alternatively, if you have a local file you can use it to generate your client.

clientele generate -f path/to/file.json -o my_client/\n
"},{"location":"usage/#async-client","title":"Async Client","text":"

If you prefer an asyncio client, just pass --asyncio t to your command.

clientele generate -f path/to/file.json -o my_client/ --asyncio t\n

Note

You can use this command later to swap between a sync and async client so long as the OpenAPI schema remains the same, so don't worry about making a hard decision now.

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\u269c\ufe0f Clientele","text":""},{"location":"#generate-loveable-python-http-api-clients","title":"Generate loveable Python HTTP API Clients","text":"

Clientele lets you generate fully-typed, pythonic HTTP API Clients using an OpenAPI schema.

It's easy to use:

# Install as a global tool - it's not a dependency!\npipx install clientele\n# Generate a client\nclientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o api_client/\n
"},{"location":"#generated-code","title":"Generated code","text":"

The generated code is designed by python developers, for python developers.

It uses modern tooling and has a great developer experience.

from my_api import client, schemas\n# Pydantic models for inputs and outputs\ndata = schemas.RequestDataRequest(my_input=\"test\")\n# Easy to read client functions\nresponse = client.request_data_request_data_post(data=data)\n# Handle responses elegantly\nmatch response:\ncase schemas.RequestDataResponse():\n# Handle valid response\n...\ncase schemas.ValidationError():\n# Handle validation error\n...\n

The generated code is tiny - the example schema we use for documentation and testing only requires 250 lines of code and 5 files.

"},{"location":"#async-support","title":"Async support","text":"

You can choose to generate either a sync or an async client - we support both:

from my_async_api import client\n# Async client functions\nresponse = await client.simple_request_simple_request_get()\n
"},{"location":"#other-features","title":"Other features","text":""},{"location":"CHANGELOG/","title":"Change log","text":""},{"location":"CHANGELOG/#063","title":"0.6.3","text":""},{"location":"CHANGELOG/#062","title":"0.6.2","text":""},{"location":"CHANGELOG/#061","title":"0.6.1","text":""},{"location":"CHANGELOG/#060","title":"0.6.0","text":""},{"location":"CHANGELOG/#052","title":"0.5.2","text":""},{"location":"CHANGELOG/#051","title":"0.5.1","text":"

Additionally, an async test client is now included in the test suite. It has identical tests to the standard one but uses the async client instead.

"},{"location":"CHANGELOG/#050","title":"0.5.0","text":""},{"location":"CHANGELOG/#please-delete-the-constantspy-file-when-updating-to-this-version-to-have-new-features-take-affect","title":"Please delete the constants.py file when updating to this version to have new features take affect","text":""},{"location":"CHANGELOG/#044","title":"0.4.4","text":"

Examples and documentation now includes a very complex example schema built using FastAPI that offers the following variations:

A huge test suite has been added to the CI pipeline for this project using a copy of the generated client from the schema above.

"},{"location":"CHANGELOG/#043","title":"0.4.3","text":""},{"location":"CHANGELOG/#042","title":"0.4.2","text":""},{"location":"CHANGELOG/#041","title":"0.4.1","text":""},{"location":"CHANGELOG/#040","title":"0.4.0","text":""},{"location":"CHANGELOG/#032","title":"0.3.2","text":""},{"location":"CHANGELOG/#031","title":"0.3.1","text":""},{"location":"CHANGELOG/#030","title":"0.3.0","text":""},{"location":"CHANGELOG/#020","title":"0.2.0","text":""},{"location":"CHANGELOG/#010","title":"0.1.0","text":""},{"location":"compatibility/","title":"\ud83d\udcb1 Compatibility","text":""},{"location":"compatibility/#great-compatibility","title":"Great compatibility","text":"

Any standard 3.0.x implementation works very well.

We have tested Clientele with:

"},{"location":"compatibility/#no-compatibility","title":"No compatibility","text":"

We do not support 2.x aka \"Swagger\" - this format is quite different and deprecated.

"},{"location":"compatibility/#a-note-on-compatbility","title":"A note on compatbility","text":"

When we were building Clientele, we discovered that, despite a fantastic specification, OpenAPI has a lot of poor implementations.

As pythonistas, we started with the auto-generated OpenAPI schemas provided by FastAPI, and then we branched out to large APIs like Twilio to test what we built.

Despite the effort, we still keep finding subtly different OpenAPI implementations.

Because of this we cannot guarentee 100% compatibility with an API, but we can give you a good indication of what we've tested.

"},{"location":"examples/","title":"\ud83e\ude84 Client example","text":"

Let's build an API Client using clientele and an example OpenAPI schema.

Our GitHub has a bunch of schemas that are proven to work with clientele, so let's use one of those!

"},{"location":"examples/#generate-the-client","title":"Generate the client","text":"

Simply:

clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/\n

The -u parameter expects a URL, you can provide a path to a file with -f instead if you download the file.

The -o parameter is the output directory of the generated client.

Run it now and you will see this output:

my_client/\n    __init__.py\n    client.py\n    constants.py\n    http.py\n    MANIFEST\n    schemas.py\n
"},{"location":"examples/#client","title":"Client","text":"

Let's go over each file and talk about what it does

"},{"location":"examples/#get-functions","title":"GET functions","text":"

The client.py file provides all the API functions from the OpenAPI schema.

my_client/client.py
import typing  # noqa\nfrom . import schemas  # noqa\nfrom . import http  # noqa\ndef simple_request_simple_request_get() -> schemas.SimpleResponse:\n\"\"\"Simple Request\"\"\"\nresponse = http.get(url=\"/simple-request\")\nreturn http.handle_response(simple_request_simple_request_get, response)\n...\n

We can see one of the functions here, simple_request_simple_request_get, is for a straight-forward HTTP GET request without any input arguments, and it returns a schema object.

Here is how you might use it:

from my_client import client\nclient.simple_request_simple_request_get()\n>>> SimpleResponse(name='Paul')\n
"},{"location":"examples/#post-and-put-functions","title":"POST and PUT functions","text":"

A more complex example is shown just below. This is for an HTTP POST method, and it requires an input property called data that is an instance of a schema, and returns a union of responses. If the endpoint has url parameters or query parameters, they will appear as input arguments to the function alongside the data argument.

def request_data_request_data_post(\ndata: schemas.RequestDataRequest,\n) -> typing.Union[schemas.RequestDataResponse, schemas.HTTPValidationError]:\n\"\"\"Request Data\"\"\"\nresponse = http.post(url=\"/request-data\", data=data.model_dump())\nreturn http.handle_response(request_data_request_data_post, response)\n

Here is how you might use it:

from my_client import client, schemas\ndata = schemas.RequestDataRequest(my_input=\"Hello, world\")\nresponse = client.request_data_request_data_post(data=data)\n>>> RequestDataResponse(your_input='Hello, world')\n

Clientele also supports HTTP PUT functionality in the exact same way as HTTP POST:

from my_client import client, schemas\ndata = schemas.RequestDataRequest(my_input=\"Hello, world\")\nresponse = client.request_data_request_data_put(data=data)\n>>> RequestDataResponse(your_input='Hello, world')\n
"},{"location":"examples/#url-and-query-parameters","title":"URL and Query parameters","text":"

If your endpoint takes path parameters (aka URL parameters) then clientele will turn them into parameters in the function:

from my_client import client\nclient.parameter_request_simple_request(your_input=\"gibberish\")\n>>> ParameterResponse(your_input='gibberish')\n

Query parameters will also be generated the same way. See this example for a function that takes a required query parameter.

"},{"location":"examples/#handling-responses","title":"Handling responses","text":"

Because we're using Pydantic to manage the input data, we get a strongly-typed response object. This works beautifully with the new structural pattern matching feature in Python 3.10:

response = client.request_data_request_data_post(data=data)\n# Handle responses elegantly\nmatch response:\ncase schemas.RequestDataResponse():\n# Handle valid response\n...\ncase schemas.ValidationError():\n# Handle validation error\n...\n
"},{"location":"examples/#api-exceptions","title":"API Exceptions","text":"

Clientele works by matching the shape of the response object with the Pydantic return types of a function. When it matches one, it generates the pydantic object and returns it.

If the response object is an unintended one, it will not match a return type.

In this case, the function will raise an http.APIException.

from my_client import client, http\ntry:\ngood_response = my_client.get_my_thing()\nexcept http.APIException as e:\n# The API got a response we didn't expect\nprint(e.response.status_code)\n

The response object will be attached to this exception class for later inspection.

"},{"location":"examples/#schemas","title":"Schemas","text":"

The schemas.py file has all the possible schemas, request and response, and even Enums, for the API.

They are all subclassed from pydantic's BaseModel. Here are a few examples:

my_client/schemas.py
import typing  # noqa\nimport pydantic  # noqa\nfrom enum import Enum  # noqa\nclass ParameterResponse(pydantic.BaseModel):\nyour_input: str\nclass RequestDataRequest(pydantic.BaseModel):\nmy_input: str\nclass RequestDataResponse(pydantic.BaseModel):\nmy_input: str\n# Enums subclass str so they serialize to JSON nicely\nclass ExampleEnum(str, Enum):\nONE = \"ONE\"\nTWO = \"TWO\"\n
"},{"location":"examples/#configuration","title":"Configuration","text":"

One of the problems with auto-generated clients is that you often need to configure them, and if you try and regenerate the client at some point then your configuration gets wiped clean and you have to do it all over again.

Clientele solves this problem by providing an entry point for configuration that will never be overwritten - constants.py.

When you first generate the project, you will see a file called constants.py and it will offer configuration functions a bit like this:

\"\"\"\nThis file will never be updated on subsequent clientele runs.\nUse it as a space to store configuration and constants.\nDO NOT CHANGE THE FUNCTION NAMES\n\"\"\"\ndef api_base_url() -> str:\n\"\"\"\n    Modify this function to provide the current api_base_url.\n    \"\"\"\nreturn \"http://localhost\"\n

Subsequent runs of the generate command will not change this file the first time is made, so you are free to modify the defaults to suit your needs, for example, if you need to source the base url of your API for different configurations, you can modify the api_base_url function like this:

from my_project import my_config\ndef api_base_url() -> str:\n\"\"\"\n    Modify this function to provide the current api_base_url.\n    \"\"\"\nif my_config.debug:\nreturn \"http://localhost:8000\"\nelif my_config.production:\nreturn \"http://my-production-url.com\"\n

Just keep the function names the same and you're good to go.

"},{"location":"examples/#authentication","title":"Authentication","text":"

If your OpenAPI spec provides security information for the following authentication methods:

Then clientele will provide you information on the environment variables you need to set to make this work during the generation. For example:

Please see my_client/constants.py to set authentication variables\n

The constants.py file will have entry points for you to configure, for example, HTTP Bearer authentication will need the get_bearer_token function to be updated, something like this:

def get_bearer_token() -> str:\n\"\"\"\n    HTTP Bearer authentication.\n    Used by many authentication methods - token, jwt, etc.\n    Does not require the \"Bearer\" content, just the key as a string.\n    \"\"\"\nfrom os import environ\nreturn environ.get(\"MY_AUTHENTICATION_TOKEN\")\n
"},{"location":"examples/#additional-headers","title":"Additional headers","text":"

If you want to pass specific headers with all requests made by the client, you can configure the additional_headers function in constants.py to do this.

def additional_headers() -> dict:\n\"\"\"\n    Modify this function ot provide additional headers to all\n    HTTP requests made by this client.\n    \"\"\"\nreturn {}\n

Please note that if you are using this with authentication headers, then authentication headers will overwrite these defaults if they keys match.

"},{"location":"install/","title":"\ud83c\udfd7\ufe0f Install","text":"

We recommend installing with pipx as a global CLI command:

pipx install clientele\n

Once installed you can run clientele version to make sure you have the latest version:

> clientele version\nclientele 0.6.3\n
"},{"location":"testing/","title":"Testing","text":"

Clientele is designed for easy testing, and our own test suite is a great example of how easily you can write mock tests for your API Client.

import pytest\nfrom httpx import Response\nfrom respx import MockRouter\nfrom .test_client import client, constants, schemas\nBASE_URL = constants.api_base_url()\n@pytest.mark.respx(base_url=BASE_URL)\ndef test_simple_request_simple_request_get(respx_mock: MockRouter):\n# Given\nmocked_response = {\"status\": \"hello world\"}\nmock_path = \"/simple-request\"\nrespx_mock.get(mock_path).mock(\nreturn_value=Response(json=mocked_response, status_code=200)\n)\n# When\nresponse = client.simple_request_simple_request_get()\n# Then\nassert isinstance(response, schemas.SimpleResponse)\nassert len(respx_mock.calls) == 1\ncall = respx_mock.calls[0]\nassert call.request.url == BASE_URL + mock_path\n

We recommend you install respx for writing your tests.

"},{"location":"usage/","title":"\ud83d\udcdd Use Clientele","text":"

Note

You can type clientele COMMAND --help at anytime to see explicit information about the available arguments.

"},{"location":"usage/#generate","title":"generate","text":"

Generate a Python HTTP Client from an OpenAPI Schema.

"},{"location":"usage/#from-a-url","title":"From a URL","text":"

Use the -u or --url argument.

-o or --output is the target directory for the generate client.

clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/\n

Note

The example above uses one of our test schemas, and will work if you copy/paste it!

"},{"location":"usage/#from-a-file","title":"From a file","text":"

Alternatively you can provide a local file using the -f or --file argument.

clientele generate -f path/to/file.json -o my_client/\n
"},{"location":"usage/#asyncio","title":"Async.io","text":"

If you prefer an asyncio client, just pass --asyncio t to your command.

clientele generate -f path/to/file.json -o my_client/ --asyncio t\n
"},{"location":"usage/#validate","title":"validate","text":"

Validate lets you check if an OpenAPI schema will work with clientele.

Note

Some OpenAPI schema generators do not conform to the specification.

Clientele uses openapi-core to validate the schema.

"},{"location":"usage/#from-a-url_1","title":"From a URL","text":"

Use the -u or --url argument.

-o or --output is the target directory for the generate client.

clientele validate -u http://path.com/to/openapi.json\n
"},{"location":"usage/#from-a-file-path","title":"From a file path","text":"

Alternatively you can provide a local file using the -f or --file argument.

clientele validate -f /path/to/openapi.json\n
"},{"location":"usage/#version","title":"version","text":"

Print the current version of Clientele:

> clientele version\nClientele 0.7.0\n
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index f1cf4fb..7169ee5 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,37 +2,37 @@ https://phalt.github.io/clientele/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/CHANGELOG/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/compatibility/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/examples/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/install/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/testing/ - 2023-10-02 + 2023-10-04 daily https://phalt.github.io/clientele/usage/ - 2023-10-02 + 2023-10-04 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 0772362d792fc4bd717ad0b5ad54a7471330f54b..bc8e2475e813cddc04e8af432574481e6ef5cc16 100644 GIT binary patch delta 253 zcmVe`oN{|;efAAKVGNa6%R*!jY^*UfmH2pn%5TJ0uganK1e_&vph`IA?oO$3 z93>$`YdVs#ZxmUV22vMM74lZ-RhDWBICrNieYAQ?p%l|O<5@PyZrDqV%6e^tz~DiZ zYVyt33~?K4y(utwlTGn;iLH1OHOm#z)^W2t7!nMeHs{SEEm`TlkH`0}<} zGNg@dXBhYBk&jCTg@b83542=P48+F!B_lErr^8(`;y|YPhr>QS>BrJPu^D0Y;RFBx Djq!Wc delta 253 zcmV5OT9Ldn{>5Hx3?$VCe$+r zR9|BM`u*#>IK}4FV)6|=x!_B&mYGPv+fX@Qm*VU5CA}9Ly()$t2{?&nPo-#>yGNzQ zag^j3TGNpXeXYngaUgXQRVE*VUL~=nfNOWD0)y343dNYNG03uZ+zfl^g0gMsz%wAI zLQTH;njvmOrSmMmOV?SN< - Commands + Use diff --git a/usage/index.html b/usage/index.html index 2d53422..349b229 100644 --- a/usage/index.html +++ b/usage/index.html @@ -22,7 +22,7 @@ - Commands - ⚜️ Clientele + Use - ⚜️ Clientele @@ -73,7 +73,7 @@
- + Skip to content @@ -109,7 +109,7 @@
- Commands + Use
@@ -275,7 +275,7 @@ - Commands + Use @@ -286,7 +286,7 @@ - Commands + Use @@ -307,19 +307,12 @@ @@ -458,19 +485,12 @@ @@ -517,35 +571,51 @@ -

📝 Commands

-

Validate

-

Validate lets you check if an OpenAPI schema will work with clientele. Some OpenAPI schema generators do not comply properly with the specification and it is a good way to check if your schema is correct.

-
clientele validate -u http://path.com/to/openapi.json
-
-

Alternatively you can provide a local file:

-
clientele validate -f /path/to/openapi.json
-
-

Generate

+

📝 Use Clientele

+
+

Note

+

You can type clientele COMMAND --help at anytime to see explicit information about the available arguments.

+
+

generate

+

Generate a Python HTTP Client from an OpenAPI Schema.

From a URL

-

Assuming the OpenAPI schema is available on the internet somewhere, you can query it to generate your client.

-
clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/
+

Use the -u or --url argument.

+

-o or --output is the target directory for the generate client.

+
clientele generate -u https://raw.githubusercontent.com/phalt/clientele/main/example_openapi_specs/best.json -o my_client/
 

Note

-

The example above uses a test OpenAPI format, and will work if you copy/paste it!

+

The example above uses one of our test schemas, and will work if you copy/paste it!

From a file

-

Alternatively, if you have a local file you can use it to generate your client.

-
clientele generate -f path/to/file.json -o my_client/
+

Alternatively you can provide a local file using the -f or --file argument.

+
clientele generate -f path/to/file.json -o my_client/
 
-

Async Client

+

Async.io

If you prefer an asyncio client, just pass --asyncio t to your command.

-
clientele generate -f path/to/file.json -o my_client/ --asyncio t
+
clientele generate -f path/to/file.json -o my_client/ --asyncio t
 
+

validate

+

Validate lets you check if an OpenAPI schema will work with clientele.

Note

-

You can use this command later to swap between a sync and async client so long as the OpenAPI schema remains the same, so don't worry about making a hard decision now.

+

Some OpenAPI schema generators do not conform to the specification.

+

Clientele uses openapi-core to validate the schema.

+

From a URL

+

Use the -u or --url argument.

+

-o or --output is the target directory for the generate client.

+
clientele validate -u http://path.com/to/openapi.json
+
+

From a file path

+

Alternatively you can provide a local file using the -f or --file argument.

+
clientele validate -f /path/to/openapi.json
+
+

version

+

Print the current version of Clientele:

+
> clientele version
+Clientele 0.7.0
+