Skip to content

Commit

Permalink
ci: added python generation (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
emajo authored Feb 24, 2022
1 parent ce76030 commit f45fbd4
Show file tree
Hide file tree
Showing 7 changed files with 431 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/check-custom-templates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
sdk: ['php', 'javascript', 'csharp-netcore', 'ruby', 'java']
sdk: ['php', 'javascript', 'csharp-netcore', 'ruby', 'java', 'python']

steps:

- id: checkout
Expand Down
121 changes: 121 additions & 0 deletions .github/workflows/generate-python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Generate Python SDK
on:
repository_dispatch:
types: [generate-python]

jobs:
generate-python-sdk:
runs-on: ubuntu-latest
env:
GIT_REPO_ID: fattureincloud-python-sdk
GIT_USER_ID: fattureincloud
steps:

- id: checkout
name: Checkout repo
uses: actions/checkout@v2
with:
token: ${{ secrets.FATTUREINCLOUD_BOT_TOKEN }}

- id: checkout-python
name: Checkout Python repo
env:
GIT_REPO_PATH: '${{ env.GIT_USER_ID }}/${{ env.GIT_REPO_ID }}'
uses: actions/checkout@v2
with:
path: ./generated/python
ref: master
repository: ${{ env.GIT_REPO_PATH }}
token: ${{ secrets.FATTUREINCLOUD_BOT_TOKEN }}

- id: init-git
name: Init GIT
run: |
git config --global user.email "[email protected]"
git config --global user.name "fattureincloud-bot"
- id: setup-node
name: Setup Node.js
uses: actions/setup-node@v2

- id: setup-java
name: Setup Java
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '8'

- id: setup-libraries
name: Install libraries
run: |
npm install -g yarn
yarn global add @apidevtools/swagger-cli @openapitools/openapi-generator-cli standard-version
sudo add-apt-repository ppa:rmescandon/yq -y
sudo apt update
sudo apt install yq -y
cd ./scripts/
yarn
cd ../generated/python/scripts
yarn
- id: bump-python-sdk-version
name: Bump Python SDK
env:
OPENAPI_VERSION: ${{ github.event.client_payload.version }}
run: |
echo "openapi_version=$OPENAPI_VERSION"
BUMP_TYPE=$(node ./scripts/sdk-version-checker.js ./generated/python/sdk-version.yaml $OPENAPI_VERSION)
cd ./generated/python
if [ "$BUMP_TYPE" == "patch" ];then
echo 'Bumping the SDK patch version...'
standard-version --skip.tag --skip.changelog --skip.commit --release-as patch
elif [ "$BUMP_TYPE" == "openapi" ];then
echo 'Using the openapi version...'
standard-version --skip.tag --skip.changelog --skip.commit --release-as $OPENAPI_VERSION
else
echo "Something bad happened - impossible to bump Python SDK version. value=$BUMP_TYPE"
fi
SDK_VERSION=$(yq e '.info.version' ./sdk-version.yaml)
echo "sdk_version=$SDK_VERSION" >> $GITHUB_ENV
echo "openapi_version=$OPENAPI_VERSION" >> $GITHUB_ENV
- id: generate-python-sdk
name: Generate Python SDK
env:
PACKAGE_NAME: "fattureincloud_python_sdk"
PACKAGE_URL: "https://github.com/fattureincloud/fattureincloud-python-sdk"
PROJECT_NAME: "fattureincloud-python-sdk"
INFO_NAME: "\"Fatture in Cloud API Team\""
APP_NAME: "FattureInCloud"

run: |
SDK_VERSION=${{ env.sdk_version }}
echo "${{ env.sdk_version }}"
RELEASE_NOTE="\"bumping version to $SDK_VERSION\""
USER_AGENT="$APP_NAME/${{ env.sdk_version }}/Python-SDK"
node ./scripts/preprocess-spec.js
openapi-generator-cli generate -i ./openapi.yaml -g python -o ./generated/python/ -t ./templates/python --git-repo-id=${GIT_REPO_ID} --git-user-id=${GIT_USER_ID} --release-note=${RELEASE_NOTE} --http-user-agent=${USER_AGENT} --additional-properties=packageVersion=${SDK_VERSION},packageName=${PACKAGE_NAME},packageUrl=${PACKAGE_URL},projectName=${PROJECT_NAME},infoName=${INFO_NAME}
- id: create-pr
name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
path: ./generated/python
branch: "devel-${{ env.sdk_version }}"
token: "${{ secrets.FATTUREINCLOUD_BOT_TOKEN }}"
delete-branch: true
base: master
commit-message: "chore: bumping version to ${{ env.sdk_version }}"
title: "Updating SDK to ${{ env.sdk_version }}"
body: "New SDK verson ${{ env.sdk_version }} generated by Github Action from OpenAPI Spec ${{ env.openapi_version }}"
2 changes: 1 addition & 1 deletion .github/workflows/openapi-bump-and-publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
event: ['generate-php', 'generate-javascript', 'generate-csharp-netcore', 'generate-java', 'generate-ruby', 'generate-postman']
event: ['generate-php', 'generate-javascript', 'generate-csharp-netcore', 'generate-java', 'generate-ruby', 'generate-postman', 'generate-python']

needs: bump-and-publish
steps:
Expand Down
42 changes: 42 additions & 0 deletions templates/python/README.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# FattureInCloud Python SDK

{{#appDescriptionWithNewLines}}
{{{.}}}
{{/appDescriptionWithNewLines}}

This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:

- API version: {{appVersion}}
- Package version: {{packageVersion}}
{{^hideGenerationTimestamp}}
- Build date: {{generatedDate}}
{{/hideGenerationTimestamp}}
- Build package: {{generatorClass}}
{{#infoUrl}}
For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}})
{{/infoUrl}}

## Requirements.

Python >= 3.6

## Installation & Usage
### pip install

You can install our python package directly using:

```sh
pip install fattureincloud-python-sdk
```
(you may need to run `pip` with root permission: `sudo pip install fattureincloud-python-sdk`)

Then import the package:
```python
import {{{packageName}}}
```

## Getting Started

Please follow the [installation procedure](#installation--usage) and then run the following:

{{> README_common }}
112 changes: 112 additions & 0 deletions templates/python/README_common.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
```python
{{#apiInfo}}{{#apis}}{{#-last}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/-last}}{{/apis}}{{/apiInfo}}
import time
import {{{packageName}}}
from pprint import pprint
{{#apiInfo}}
{{#apis}}
{{#-first}}
from {{apiPackage}} import {{classFilename}}
{{#imports}}
{{{import}}}
{{/imports}}
{{#operations}}
{{#operation}}
{{#-first}}
{{> python_doc_auth_partial}}

# Enter a context with an instance of the API client
with {{{packageName}}}.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = {{classFilename}}.{{{classname}}}(api_client)
{{#allParams}}
{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
{{/allParams}}

try:
{{#summary}} # {{{.}}}
{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}
pprint(api_response){{/returnType}}
except {{{packageName}}}.ApiException as e:
print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e)
{{/-first}}
{{/operation}}
{{/operations}}
{{/-first}}
{{/apis}}
{{/apiInfo}}
```

## Documentation for API Endpoints

All URIs are relative to *{{basePath}}*

Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

## Documentation For Models

{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
{{/model}}{{/models}}

## Documentation For Authorization

{{^authMethods}}
All endpoints do not require authorization.
{{/authMethods}}
{{#authMethods}}
{{#last}} Authentication schemes defined for the API:{{/last}}
## {{{name}}}

{{#isApiKey}}
- **Type**: API key
- **API key parameter name**: {{{keyParamName}}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasic}}
{{#isBasicBasic}}
- **Type**: HTTP basic authentication
{{/isBasicBasic}}
{{#isBasicBearer}}
- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
{{/isBasicBearer}}
{{#isHttpSignature}}
- **Type**: HTTP signature authentication
{{/isHttpSignature}}
{{/isBasic}}
{{#isOAuth}}
- **Type**: OAuth
- **Flow**: {{{flow}}}
- **Authorization URL**: {{{authorizationUrl}}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}
{{#scopes}} - **{{{scope}}}**: {{{description}}}
{{/scopes}}
{{/isOAuth}}

{{/authMethods}}

## Author

{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}}
{{/-last}}{{/apis}}{{/apiInfo}}

## Notes for Large OpenAPI documents
If the OpenAPI document is large, imports in {{{packageName}}}.apis and {{{packageName}}}.models may fail with a
RecursionError indicating the maximum recursion limit has been exceeded. In that case, there are a couple of solutions:

Solution 1:
Use specific imports for apis and models like:
- `from {{{packageName}}}.api.default_api import DefaultApi`
- `from {{{packageName}}}.model.pet import Pet`

Solution 2:
Before importing the package, adjust the maximum recursion limit as shown below:
```
import sys
sys.setrecursionlimit(1500)
import {{{packageName}}}
from {{{packageName}}}.apis import *
from {{{packageName}}}.models import *
```
98 changes: 98 additions & 0 deletions templates/python/python_doc_auth_partial.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasic}}
{{#isBasicBasic}}

# Configure HTTP basic authorization: {{{name}}}
configuration = {{{packageName}}}.Configuration(
username = 'YOUR_USERNAME',
password = 'YOUR_PASSWORD'
)
{{/isBasicBasic}}
{{#isBasicBearer}}

# Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}}
configuration = {{{packageName}}}.Configuration(
access_token = 'YOUR_BEARER_TOKEN'
)
{{/isBasicBearer}}
{{#isHttpSignature}}

# Configure HTTP message signature: {{{name}}}
# The HTTP Signature Header mechanism that can be used by a client to
# authenticate the sender of a message and ensure that particular headers
# have not been modified in transit.
#
# You can specify the signing key-id, private key path, signing scheme,
# signing algorithm, list of signed headers and signature max validity.
# The 'key_id' parameter is an opaque string that the API server can use
# to lookup the client and validate the signature.
# The 'private_key_path' parameter should be the path to a file that
# contains a DER or base-64 encoded private key.
# The 'private_key_passphrase' parameter is optional. Set the passphrase
# if the private key is encrypted.
# The 'signed_headers' parameter is used to specify the list of
# HTTP headers included when generating the signature for the message.
# You can specify HTTP headers that you want to protect with a cryptographic
# signature. Note that proxies may add, modify or remove HTTP headers
# for legitimate reasons, so you should only add headers that you know
# will not be modified. For example, if you want to protect the HTTP request
# body, you can specify the Digest header. In that case, the client calculates
# the digest of the HTTP request body and includes the digest in the message
# signature.
# The 'signature_max_validity' parameter is optional. It is configured as a
# duration to express when the signature ceases to be valid. The client calculates
# the expiration date every time it generates the cryptographic signature
# of an HTTP request. The API server may have its own security policy
# that controls the maximum validity of the signature. The client max validity
# must be lower than the server max validity.
# The time on the client and server must be synchronized, otherwise the
# server may reject the client signature.
#
# The client must use a combination of private key, signing scheme,
# signing algorithm and hash algorithm that matches the security policy of
# the API server.
#
# See {{{packageName}}}.signing for a list of all supported parameters.
configuration = {{{packageName}}}.Configuration(
host = "{{{basePath}}}",
signing_info = {{{packageName}}}.signing.HttpSigningConfiguration(
key_id = 'my-key-id',
private_key_path = 'private_key.pem',
private_key_passphrase = 'YOUR_PASSPHRASE',
signing_scheme = {{{packageName}}}.signing.SCHEME_HS2019,
signing_algorithm = {{{packageName}}}.signing.ALGORITHM_ECDSA_MODE_FIPS_186_3,
hash_algorithm = {{{packageName}}}.signing.SCHEME_RSA_SHA256,
signed_headers = [
{{{packageName}}}.signing.HEADER_REQUEST_TARGET,
{{{packageName}}}.signing.HEADER_CREATED,
{{{packageName}}}.signing.HEADER_EXPIRES,
{{{packageName}}}.signing.HEADER_HOST,
{{{packageName}}}.signing.HEADER_DATE,
{{{packageName}}}.signing.HEADER_DIGEST,
'Content-Type',
'Content-Length',
'User-Agent'
],
signature_max_validity = datetime.timedelta(minutes=5)
)
)
{{/isHttpSignature}}
{{/isBasic}}
{{#isApiKey}}

# Configure API key authorization: {{{name}}}
configuration.api_key['{{{name}}}'] = 'YOUR_API_KEY'

# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['{{name}}'] = 'Bearer'
{{/isApiKey}}
{{#isOAuth}}

# Configure OAuth2 access token for authorization: {{{name}}}
configuration = {{{packageName}}}.Configuration(
access_token = "YOUR_ACCESS_TOKEN"
)
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}
Loading

0 comments on commit f45fbd4

Please sign in to comment.