Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/samples-python-flask-connexion3-server.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
name: Python Flask (Connexion 3) Server
name: Python Flask Server

on:
push:
paths:
- samples/server/petstore/python-flask/**
- samples/server/petstore/python-flask-connexion3/**
- modules/openapi-generator/src/main/resources/python-flask/**
- modules/openapi-generator/src/test/resources/3_0/python-flask/**
- .github/workflows/samples-python-flask-connexion3-server.yaml
pull_request:
paths:
- samples/server/petstore/python-flask/**
- samples/server/petstore/python-flask-connexion3/**
- modules/openapi-generator/src/main/resources/python-flask/**
- modules/openapi-generator/src/test/resources/3_0/python-flask/**
- .github/workflows/samples-python-flask-connexion3-server.yaml
jobs:
build:
name: Test Python Flask (Connexion 3) server
name: Test Python Flask server (${{ matrix.sample }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sample:
# servers
- samples/server/petstore/python-flask/
- samples/server/petstore/python-flask-connexion3/
steps:
- uses: actions/checkout@v7
Expand All @@ -30,6 +36,12 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r test-requirements.txt
- name: Test
- name: Test JSON serialization
working-directory: ${{ matrix.sample }}
run: >-
python -m pytest --import-mode=importlib
"$GITHUB_WORKSPACE/modules/openapi-generator/src/test/resources/3_0/python-flask/test_json_serialization.py"
- name: Test existing Connexion 3 sample
if: matrix.sample == 'samples/server/petstore/python-flask-connexion3/'
working-directory: ${{ matrix.sample }}
run: pytest
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ is an example of building a OpenAPI-enabled Flask server.
This example uses the [Connexion](https://github.com/zalando/connexion) library on top of Flask.

## Requirements
Python 3.5.2+
Python 3.11+
Comment thread
Bernardoow marked this conversation as resolved.

## Usage
To run the server, please execute the following from the root directory:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import connexion
{{^useConnexion3}}
from flask_testing import TestCase

from {{packageName}}.encoder import JSONEncoder
from {{packageName}}.encoder import JSONProvider


class BaseTestCase(TestCase):

def create_app(self):
logging.getLogger('connexion.operation').setLevel('ERROR')
app = connexion.App(__name__, specification_dir='../openapi/')
app.app.json_encoder = JSONEncoder
app.app.json = JSONProvider(app.app)
app.add_api('openapi.yaml', pythonic_params=True)
return app.app
{{/useConnexion3}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ from {{packageName}} import encoder
def main():
{{^useConnexion3}}
app = connexion.App(__name__, specification_dir='./openapi/')
app.app.json_encoder = encoder.JSONEncoder
app.app.json = encoder.JSONProvider(app.app)
app.add_api('openapi.yaml',
arguments={'title': '{{appName}}'},
pythonic_params=True)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
{{^useConnexion3}}
from connexion.apps.flask_app import FlaskJSONEncoder

from {{modelPackage}}.base_model import Model


class JSONEncoder(FlaskJSONEncoder):
include_nulls = False

def default(self, o):
if isinstance(o, Model):
dikt = {}
for attr in o.openapi_types:
value = getattr(o, attr)
if value is None and not self.include_nulls:
continue
attr = o.attribute_map[attr]
dikt[attr] = value
return dikt
return FlaskJSONEncoder.default(self, o)
from connexion.apps.flask_app import FlaskJSONProvider
{{/useConnexion3}}
{{#useConnexion3}}
import datetime
Expand All @@ -26,29 +8,39 @@ import json
import uuid

from werkzeug.http import http_date
{{/useConnexion3}}

from {{modelPackage}}.base_model import Model


def _model_to_dict(model, include_nulls):
dikt = {}
for attr in model.openapi_types:
value = getattr(model, attr)
if value is None and not include_nulls:
continue
dikt[model.attribute_map[attr]] = value
return dikt


{{^useConnexion3}}
class JSONProvider(FlaskJSONProvider):
include_nulls = False

def default(self, o):
if isinstance(o, Model):
return _model_to_dict(o, self.include_nulls)
return super().default(o)
{{/useConnexion3}}
{{#useConnexion3}}
class JSONEncoder(json.JSONEncoder):
include_nulls = False

def default(self, o):
if isinstance(o, Model):
dikt = {}
for attr in o.openapi_types:
value = getattr(o, attr)
if value is None and not self.include_nulls:
continue
attr = o.attribute_map[attr]
dikt[attr] = value
return dikt
# Connexion 3 removed FlaskJSONEncoder, which is what used to
# give us this handling for free -- replicate it here so
# date/datetime/Decimal/UUID-typed model attributes (e.g. an
# OpenAPI `date-time` field) still serialize instead of raising
# TypeError. http_date() matches Flask's own default encoder
# behavior for date/datetime (RFC 2822, not ISO 8601).
return _model_to_dict(o, self.include_nulls)
# Preserve this adapter's HTTP-date and string representations.
# Connexion 2 delegates special types to its JSON provider instead.
if isinstance(o, datetime.date):
return http_date(o)
if isinstance(o, (decimal.Decimal, uuid.UUID)):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,18 @@
{{^useConnexion3}}
connexion[swagger-ui] >= 2.6.0; python_version>="3.6"
# 2.3 is the last version that supports python 3.4-3.5
connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4"
# prevent breaking dependencies from advent of connexion>=3.0
connexion[swagger-ui] <= 2.14.2; python_version>"3.4"
# connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug
# we must peg werkzeug versions below to fix connexion
# https://github.com/zalando/connexion/pull/1044
werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4"
# Connexion 2.x
connexion[swagger-ui]>=2.15.1,<3.0.0
{{/useConnexion3}}
{{#useConnexion3}}
# pinned to 3.3.0+ (not just the first 3.0.0 release) since that's the
# earliest version verified to work with the Jsonifier/test_client setup
# below, and the first to officially support Python 3.13/3.14
connexion[flask,swagger-ui,uvicorn] >= 3.3.0,<4.0.0
# Connexion 3.x
connexion[flask,swagger-ui,uvicorn]>=3.3.0,<4.0.0
{{/useConnexion3}}
{{^useConnexion3}}
swagger-ui-bundle >= 0.0.2
{{/useConnexion3}}
{{#useConnexion3}}
# connexion's own swagger-ui extra already requires this floor; pinned
# explicitly here too so requirements.txt is self-documenting.
swagger-ui-bundle >= 1.1.0
{{/useConnexion3}}
python_dateutil >= 2.6.0

Flask>=2.3.3,<4.0.0
python-dateutil>=2.8.2
setuptools>=21.0.0

{{^useConnexion3}}
{{#featureCORS}}
# should support both Python 2 and Python 3
flask-cors >= 3.0.10
flask-cors>=4.0.0
{{/featureCORS}}
{{/useConnexion3}}
setuptools >= 21.0.0
{{^useConnexion3}}
Flask == 2.1.1
{{/useConnexion3}}
{{#useConnexion3}}
Flask >= 2.2.0,<4.0.0
{{/useConnexion3}}
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import sys

from setuptools import setup, find_packages

NAME = "{{packageName}}"
VERSION = "{{packageVersion}}"
{{#apiInfo}}{{#apis}}{{#-last}}
# To install the library, run the following
#
# python setup.py install
#
# prerequisite: setuptools
# http://pypi.python.org/pypi/setuptools

{{#apiInfo}}{{#apis}}{{#-last}}
REQUIRES = [
{{^useConnexion3}}
"connexion>=2.0.2,<=2.14.2",
"swagger-ui-bundle>=0.0.2",
"connexion[swagger-ui]>=2.15.1,<3.0.0",
{{#featureCORS}}
"flask-cors>=4.0.0",
{{/featureCORS}}
{{/useConnexion3}}
{{#useConnexion3}}
"connexion[flask,swagger-ui,uvicorn]>=3.3.0,<4.0.0",
"swagger-ui-bundle>=1.1.0",
"Flask>=2.2.0,<4.0.0",
{{/useConnexion3}}
"python_dateutil>=2.6.0"
"Flask>=2.3.3,<4.0.0",
"python-dateutil>=2.8.2",
]

setup(
Expand All @@ -31,13 +26,23 @@ setup(
author_email="{{infoEmail}}",
url="{{packageUrl}}",
keywords=["OpenAPI", "{{appName}}"],
python_requires=">=3.11",
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
install_requires=REQUIRES,
packages=find_packages({{#pythonSrcRoot}}"{{{.}}}"{{/pythonSrcRoot}}),{{#pythonSrcRoot}}
package_dir={"": "{{{.}}}"},{{/pythonSrcRoot}}
package_data={'': ['{{#pythonSrcRoot}}{{{.}}}/{{/pythonSrcRoot}}openapi/openapi.yaml']},
packages=find_packages({{#pythonSrcRoot}}"{{{.}}}"{{/pythonSrcRoot}}),
{{#pythonSrcRoot}}
package_dir={"": "{{{.}}}"},
{{/pythonSrcRoot}}
package_data={
"": [
"{{#pythonSrcRoot}}{{{.}}}/{{/pythonSrcRoot}}openapi/openapi.yaml"
]
},
include_package_data=True,
entry_points={
'console_scripts': ['{{packageName}}={{packageName}}.__main__:main']},
"console_scripts": [
"{{packageName}}={{packageName}}.__main__:main"
]
},
long_description="""\
{{appDescription}}
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ py>=1.4.31
randomize>=0.13
{{/useNose}}
{{^useNose}}
pytest~=7.1.0
pytest>=7.1.0,<10.0.0
pytest-cov>=2.8.1
pytest-randomly>=1.2.3
{{/useNose}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
# ref: https://docs.travis-ci.com/user/languages/python
language: python
python:
{{^useConnexion3}}
- "3.2"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
{{/useConnexion3}}
{{#useConnexion3}}
- "3.9"
- "3.10"
- "3.11"
- "3.12"
{{/useConnexion3}}
- "3.13"
- "3.14"
- "3.15"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This matrix adds Python 3.15 even though generated setup.py explicitly rejects Python 3.15 (python_requires=">=3.11,<3.15"). Remove this entry or raise the package support constraint and dependency support together before testing 3.15.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/python-flask/travis.mustache, line 8:

<comment>This matrix adds Python 3.15 even though generated `setup.py` explicitly rejects Python 3.15 (`python_requires=">=3.11,<3.15"`). Remove this entry or raise the package support constraint and dependency support together before testing 3.15.</comment>

<file context>
@@ -1,21 +1,12 @@
-{{/useConnexion3}}
+  - "3.13"
+  - "3.14"
+  - "3.15"
+
 # command to install dependencies
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connexion3 was update to be compatible with 3.15 but not yet release.. I can wait for this !!

spec-first/connexion@3216244


# command to install dependencies
install: "pip install -r requirements.txt"
# command to run tests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import sys

if sys.version_info < (3, 7):
import typing
def is_generic(klass):
"""Determine whether klass is a generic class."""
return hasattr(klass, '__origin__')

def is_generic(klass):
""" Determine whether klass is a generic class """
return type(klass) == typing.GenericMeta

def is_dict(klass):
""" Determine whether klass is a Dict """
return klass.__extra__ == dict
def is_dict(klass):
"""Determine whether klass is a Dict."""
return getattr(klass, '__origin__', None) is dict

def is_list(klass):
""" Determine whether klass is a List """
return klass.__extra__ == list

else:

def is_generic(klass):
""" Determine whether klass is a generic class """
return hasattr(klass, '__origin__')

def is_dict(klass):
""" Determine whether klass is a Dict """
return klass.__origin__ == dict

def is_list(klass):
""" Determine whether klass is a List """
return klass.__origin__ == list
def is_list(klass):
"""Determine whether klass is a List."""
return getattr(klass, '__origin__', None) is list
Loading
Loading