-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve separation between FastAPI and Starlette #20
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #20 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 8 9 +1
Lines 219 221 +2
=========================================
+ Hits 219 221 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
As far as I can tell, it's not possible to install both FastAPI 0.62 and Starlette 0.14 in the same Poetry project. FastAPI 0.62.0 has Starlette pinned at 0.13.6, and attempts to add Starlette 0.14 raise a Poetry `SolverProblemError` (on Poetry 1.1.4): ```text ❯ poetry add starlette@'^0.14' Updating dependencies Resolving dependencies... (0.1s) SolverProblemError Because fastapi (0.62.0) depends on starlette (0.13.6) and no versions of fastapi match >0.62,<0.63, fastapi (>=0.62,<0.63) requires starlette (0.13.6). So, because inboard depends on both fastapi (^0.62) and starlette (^0.14), version solving failed. at ~/.poetry/lib/poetry/puzzle/solver.py:241 in _solve 237│ packages = result.packages 238│ except OverrideNeeded as e: 239│ return self.solve_in_compatibility_mode(e.overrides, use_latest=use_latest) 240│ except SolveFailure as e: → 241│ raise SolverProblemError(e) 242│ 243│ results = dict( 244│ depth_first_search( 245│ PackageNode(self._package, packages), aggregate_package_nodes ``` I would be open to having FastAPI 0.62 and Starlette 0.14 be separate sets of dependencies, but even if only one set of extras is installed (`poetry install -E starlette`), Poetry appears to resolve all the dependencies together, so the environment will still end up with Starlette 0.13.6. The easiest solution is to just install the Starlette version pinned by FastAPI (0.13.6), but add a Poetry union operator (`||`) so upgrading to Starlette 0.14 is at least possible in the future. The order of the union doesn't seem to matter. In Docker, FastAPI can be removed from the Poetry project prior to installing Starlette, so that Starlette 0.14 can be installed.
61960ca
to
bbd9e61
Compare
Sourcery Code Quality Report✅ Merging this PR will increase code quality in the affected files by 7.81%.
Here are some functions in these files that still need a tune-up:
Legend and ExplanationThe emojis denote the absolute quality of the code:
The 👍 and 👎 indicate whether the quality has improved or gotten worse with this pull request. Please see our documentation here for details on how these metrics are calculated. We are actively working on this report - lots more documentation and extra metrics to come! Let us know what you think of it by mentioning @sourcery-ai in a comment. |
This reverts commit bbd9e61. #20 https://python-poetry.org/docs/dependency-specification/ Poetry 1.1.4 installs and builds the project, and `poetry check` returns `All set!`, but `poetry publish` fails to upload to PyPI because of the union operator in the version constraint for Starlette. The docs on dependency specification show the union operator like this: ```toml [tool.poetry.dependencies] pathlib2 = { version = "^2.2", python = "~2.7 || ^3.2" } ``` and mine looks like this: ```toml [tool.poetry.dependencies] starlette = {version = "0.13.6 || ^0.14", optional = true} ``` It may be that the union operator can only be used in the `python` constraint. I'm just going to remove it. GitHub Actions: https://github.com/br3ndonland/inboard/runs/1583331395 ```text Building inboard (0.7.0) - Building sdist - Built inboard-0.7.0.tar.gz - Building wheel - Built inboard-0.7.0-py3-none-any.whl Publishing inboard (0.7.0) to PyPI - Uploading inboard-0.7.0-py3-none-any.whl 0% - Uploading inboard-0.7.0-py3-none-any.whl 100% UploadError HTTP Error 400: Invalid value for requires_dist. Error: Invalid requirement: 'starlette (0.13.6 || >=0.14,<0.15); extra == "starlette"'. at ~/.poetry/lib/poetry/publishing/uploader.py:216 in _upload 212│ self._register(session, url) 213│ except HTTPError as e: 214│ raise UploadError(e) 215│ → 216│ raise UploadError(e) 217│ 218│ def _do_upload( 219│ self, session, url, dry_run=False 220│ ): # type: (requests.Session, str, Optional[bool]) -> None ```
#20 https://github.com/tiangolo/fastapi/releases/tag/0.65.0 FastAPI 0.65 now supports Starlette 0.14, which unblocks the issue described in #20, bbd9e61, and 12eef2a.
Description
FastAPI depends on Starlette. For simplicity, inboard was set up to install FastAPI from the get-go, because installing FastAPI will also install Starlette. However, this means that the Starlette application is dependent on FastAPI, which is sort of backwards. Within the inboard source code, the utilities module contained the HTTP Basic Auth implementations for Starlette and FastAPI, but because FastAPI was imported into that module, it also meant that the Starlette application required FastAPI in order to import the module.
This PR will improve the separation of concerns between FastAPI and Starlette, so that the FastAPI and Starlette features are independent, and the Starlette application can run without installing FastAPI.
Changes
Enable Starlette 0.14 (61960ca)(later reverted in 12eef2a)FastAPI 0.62.0 and Starlette 0.14 have mutually incompatible version constraints
As far as I can tell, it's not possible to install both FastAPI 0.62 and Starlette 0.14 in the same Poetry project. FastAPI 0.62.0 has Starlette pinned at 0.13.6. An update to Starlette 0.14 is under consideration, but requires some refactoring (fastapi/fastapi#2335). Attempts to add Starlette 0.14 to inboard directly raise a Poetry
SolverProblemError
(on Poetry 1.1.4):I would be open to having FastAPI 0.62 and Starlette 0.14 be separate sets of dependencies, but even if only one set of extras is installed (
poetry install -E starlette
), Poetry appears to resolve all the dependencies together, so the environment will still end up with Starlette 0.13.6.Docker partial solution
In Docker, FastAPI can be removed from the Poetry project prior to installing Starlette, so that Starlette 0.14 can be installed.
This looks like it would work well, but for some reason, running
poetry remove fastapi
installs all the dev dependencies, thenpoetry install --no-dev
removes them. Totally counterintuitive and inefficient.Docker build logs
Possible Poetry solutions
There are some related Poetry features, but none fully address this use case.
The union operator
The docs on dependency specification show a union operator (
||
) like this:It's unclear how or where the union operator can be used, and it is error-prone. For example, I had a recent PyPI publication fail because of the union operator. I tried constraining the Starlette dependency like this:
Poetry 1.1.4 installs and builds the project, and
poetry check
returnsAll set!
, butpoetry publish
fails to upload to PyPI because of the union operator in the version constraint for Starlette.GitHub Actions logs show:
Additionally, union operators may not work properly with multiple-constraint dependencies (python-poetry/poetry#2340).
Specifying multiple version constraints with
python
ormarkers
"Markers" are constraints used when installing Python packages. They are mostly for system-level constraints, like operating system and Python version, and don't seem like they can be used to specify groups of dependencies. There's no marker for FastAPI, so markers don't satisfy the use case here.
Markers are supported by Poetry, though they are only partially documented. If you would like to learn more about markers, and don't mind confusing yourself, you can read through the opaque "parsley grammar" in PEP 508.
Related:
pyproject.toml examples with multiple constraints
Based on tests/fixtures/project_with_multi_constraints_dependency/pyproject.toml.
Using a wildcard in the
tool.poetry.dependencies
section, and then usingtool.poetry.extras
to specify versionsI tried this out, but it doesn't work. Specifying version constraints for extras in pyproject.toml, then running
poetry update
, deletes the extras from poetry.lock.pyproject.toml example with version constraints in extras
Confusingly, running
poetry check
over the pyproject.toml returns an "All set!" success message, even though it's clearly not behaving as expected.This issue may be addressed in upcoming releases (python-poetry/poetry-core#103).