Skip to content

fix(api): propagate version kwarg in Api.init_app (#119)#651

Open
jbbqqf wants to merge 1 commit into
python-restx:masterfrom
jbbqqf:fix/119-init-app-version
Open

fix(api): propagate version kwarg in Api.init_app (#119)#651
jbbqqf wants to merge 1 commit into
python-restx:masterfrom
jbbqqf:fix/119-init-app-version

Conversation

@jbbqqf
Copy link
Copy Markdown

@jbbqqf jbbqqf commented May 22, 2026

Summary

Api.__init__ accepts a version argument (defaulting to "1.0"), but
Api.init_app() silently drops any version= supplied in kwargs. Other
swagger-info fields (title, description, terms_url, contact*,
license*, url_scheme) are already forwarded from kwargs onto self.*;
version was the missing one. Match the existing pattern.

Fixes #119.

Context

The bug has been around since init_app was introduced. Lazy
initialization is the recommended pattern when the Flask app isn't
available at construction time, so users who try

api = Api()                       # version="1.0" by default
api.init_app(app, version="2.0")  # silently dropped

end up with info.version: "1.0" in their generated Swagger document. There
is no warning, which makes it confusing — they can see title/description
take effect from the same call.

Changes

  • flask_restx/api.py: add self.version = kwargs.get("version", self.version)
    in init_app, mirroring the existing self.title = kwargs.get(...) lines.
    Also document version in the init_app docstring (it was already
    documented on __init__).
  • tests/test_api.py: regression test test_init_app_overrides_version
    that both checks api.version and the rendered /swagger.json
    info.version.
  • CHANGELOG.rst: 1.3.3 bug-fix entry.

Reproduce BEFORE/AFTER yourself (copy-paste)

# --- one-time setup ---
git clone https://github.com/python-restx/flask-restx.git /tmp/restx-119 && cd /tmp/restx-119
python3 -m venv .venv && . .venv/bin/activate
pip install -q -e ".[test]" tzdata

# --- BEFORE: origin/master, expect version="1.0" and the new test to fail ---
git checkout origin/master
python -c "
from flask import Flask
from flask_restx import Api
app = Flask(__name__)
api = Api(version='1.0')
api.init_app(app, version='2.5')
print('api.version =', api.version)
with app.test_client() as c:
    print('info.version =', c.get('/swagger.json').get_json()['info']['version'])
"
# Expected (BEFORE the fix):
#   api.version = 1.0
#   info.version = 1.0

# --- AFTER: this branch, expect version="2.5" ---
git fetch https://github.com/jbbqqf/flask-restx.git fix/119-init-app-version
git checkout FETCH_HEAD
python -c "
from flask import Flask
from flask_restx import Api
app = Flask(__name__)
api = Api(version='1.0')
api.init_app(app, version='2.5')
print('api.version =', api.version)
with app.test_client() as c:
    print('info.version =', c.get('/swagger.json').get_json()['info']['version'])
"
# Expected (AFTER the fix):
#   api.version = 2.5
#   info.version = 2.5

What I ran locally

$ pytest tests/test_api.py -v 2>&1 | tail -5
tests/test_api.py::APITest::test_specs_url PASSED
tests/test_api.py::APITest::test_url_scheme PASSED
============================== 29 passed in 0.06s ==============================

$ pytest tests/test_api.py -k "init_app_overrides_version" -v 2>&1 | tail -5
collected 29 items / 28 deselected / 1 selected
tests/test_api.py::APITest::test_init_app_overrides_version PASSED
======================= 1 passed, 28 deselected in 0.01s =======================

$ pytest -q --no-header 2>&1 | tail -2
FAILED tests/test_inputs.py::URLTest::test_check - Failed: DID NOT RAISE <class 'ValueError'>
1 failed, 1237 passed in 18.19s

The single failure (tests/test_inputs.py::URLTest::test_check) is
pre-existing on master and unrelated to this change — it depends on
http://this-domain-should-not-exist.com actually not resolving, which is
no longer true on the network where the suite ran.

Edge cases

# Scenario api init init_app call Expected api.version Verified by
1 constructor sets non-default, init_app supplies new value Api(version="1.0") init_app(app, version="2.5") "2.5" new regression test
2 constructor sets non-default, init_app omits version Api(version="3.0") init_app(app) (no version) "3.0" (unchanged) existing tests + kwargs.get(..., self.version)
3 constructor uses default, init_app omits version Api() (default "1.0") init_app(app) "1.0" (default preserved) existing test_root_endpoint_lazy flow

Risk / blast radius

Single-line change in init_app. The new behaviour only affects users who
already pass version= to init_app — today that value is silently
dropped, so any pre-existing caller is either already not relying on
init_app to set it (no observable change), or actively wishing it worked
(now does). No public API signature changes; no existing test required
edits.


PR drafted with assistance from Claude Code (Anthropic). The change was
reviewed manually against flask-restx's source. The reproducer block
above is the one I used during development; reviewers can paste it
verbatim.

The Api constructor accepts a version (default '1.0'), but Api.init_app()
silently dropped any version supplied in kwargs. As a result, calling

    api = Api()
    api.init_app(app, version='2.0')

left api.version (and the resulting Swagger info.version) on the default.
Match the existing pattern for title/description: pull version from kwargs
with the current value as fallback.

Add a regression test that fails on master and passes after the fix.

Fixes python-restx#119.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

'version' value is ignored when using 'init_app()'?

1 participant