- `PROJECT_OWNER`, `PROJECT_USERAME`, `RAW_CONTENT_URL` and `_version_re` are unused.
- `:changelog:` hyperlink target is unnecessary.
- `test_suite` and `tests_require` are deprecated since setuptools v41.5.0
Also:
- Remove redundant `galaxy.schema` module from the `app` package (it's
already in `data`)
- Fix requirements of the `app` and `webapps` packages
- Add missing `PyJWT` and `python-dateutil` to `tool.poetry.dependencies`
(which were already included in the pinned requirements as deps of deps)
Also:
- Remove redundant `galaxy.schema` module from the `app` package (it's
already in `data`)
- Fix requirements of the `app` and `webapps` packages
- Add missing `PyJWT` and `python-dateutil` to `tool.poetry.dependencies`
(which were already included in the pinned requirements as deps of deps)
instead of the deprecated starlette WSGIMiddleware that was vendored by
fastAPI. I'm also hoping this fixes the weird exceptions a la:
```
uvicorn.error ERROR 2022-02-14 11:59:42,141 [pN:main,p:4823,tN:Thread-216] Exception in ASGI application
Traceback (most recent call last):
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 364, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/fastapi/applications.py", line 212, in __call__
await super().__call__(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/routing.py", line 408, in handle
await self.app(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/fastapi/applications.py", line 212, in __call__
await super().__call__(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/applications.py", line 112, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette_context/middleware/raw_middleware.py", line 96, in __call__
await self.app(scope, receive, send_wrapper)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 65, in __call__
task_group.cancel_scope.cancel()
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 574, in __aexit__
raise exceptions[0]
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 611, in _run_wrapped_task
await coro
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/base.py", line 34, in coro
await self.app(scope, request.receive, send_stream.send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/routing.py", line 656, in __call__
await route.handle(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/routing.py", line 408, in handle
await self.app(scope, receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/wsgi.py", line 64, in __call__
await responder(receive, send)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/wsgi.py", line 91, in __call__
await anyio.to_thread.run_sync(self.wsgi, environ, self.start_response)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 572, in __aexit__
raise ExceptionGroup(exceptions)
anyio._backends._asyncio.ExceptionGroup: 2 exceptions were raised in the task group:
----------------------------
Traceback (most recent call last):
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 611, in _run_wrapped_task
await coro
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/wsgi.py", line 98, in sender
await send(message)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/exceptions.py", line 68, in sender
await send(message)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/streams/memory.py", line 193, in send
self.send_nowait(item)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/streams/memory.py", line 177, in send_nowait
raise BrokenResourceError
anyio.BrokenResourceError
----------------------------
Traceback (most recent call last):
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/wsgi.py", line 91, in __call__
await anyio.to_thread.run_sync(self.wsgi, environ, self.start_response)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/to_thread.py", line 29, in run_sync
limiter=limiter)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 818, in run_sync_in_worker_thread
return await future
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 754, in run
result = context.run(func, *args)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/starlette/middleware/wsgi.py", line 132, in wsgi
self.stream_send.send, {"type": "http.response.body", "body": b""}
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/from_thread.py", line 35, in run
return asynclib.run_async_from_thread(func, *args)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/_backends/_asyncio.py", line 847, in run_async_from_thread
return f.result()
File "/opt/hostedtoolcache/Python/3.7.12/x64/lib/python3.7/concurrent/futures/_base.py", line 435, in result
return self.__get_result()
File "/opt/hostedtoolcache/Python/3.7.12/x64/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/streams/memory.py", line 193, in send
self.send_nowait(item)
File "/home/runner/work/galaxy/galaxy/galaxy root/.venv/lib/python3.7/site-packages/anyio/streams/memory.py", line 177, in send_nowait
raise BrokenResourceError
anyio.BrokenResourceError
```
with:
```
find packages/ -name '*.py' | xargs black
```
The `packages/` directory is currently excluded in the `[tool.black]`
section of `pyproject.toml` because black follows symlinks.
to `pyproject.toml` and packages' `requirements.txt` .
We have been importing it explicitly since commit
fc2ce45767 (December 2020).
Also:
- Remove now unnecessary minimum version for pygithub
Dependency injection is cool - it should however not be confined to the top-layer of the application. Inversion of control can help every layer and is a great way to de-couple various parts of the app.
This code brings in a framework (Lagom) to build a dependency injection framework and then adds a small function (``depends``) that adapts it to FastAPI's dependency injection mechanism ("Depends").
The advantages to this approach are numerous.
We don't need to write these little adapters for each component of the backend to adapt it FastAPI. For example look at the change to the roles API controller:
```diff
-def get_role_manager(app: UniverseApplication = Depends(get_app)) -> RoleManager:
- return app.role_manager
-
-
@cbv(router)
class FastAPIRoles:
- role_manager: RoleManager = Depends(get_role_manager)
+ role_manager: RoleManager = depends(RoleManager)
```
This is much less boilerplate. We don't need to implement & type that function get_role_manager and we don't need to bring in the import on UniverseApplication.
Additionally, we've got a clean abstraction that shields us from ``fastapi`` imports in all of our controllers. It should make it more possible to switch to new frameworks and such as the Python ecosystem matures.
Also, the same DI that is used to inject ``RoleManager`` into this contoller is used to inject app into RoleManager when it is constructed during application initialization. Any component being managed by UniverseApplication can now rely on its constructor arguments to be injected if it wants. It is easy to see the cool examples on FastAPI and think it is just a technology for controllers, but it totally is not.
I don't think there is really a way to use FastAPI's dependency injection outside the context of that framework, but even if one could Lagom is superior. All the auto-wiring is by type and requires zero framework and zero configuration (https://github.com/meadsteve/lagom#auto-wiring-with-zero-configuraton).
Having a web framework provide these framework-bound extension points for injecting stuff into controllers was the state of the art of Java like 15 years ago. Skipping that whole learning process and using the type system and auto-wiring that isn't dependent on framework annotation really jumps out to Java circa 8 years ago!
Why Lagom is an interesting question. When researching DI frameworks, I couldn't find a clear winner but Lagom focus on type annotations versus annotating by name makes it clearly more modern than a lot frameworks by much bigger names (https://github.com/meadsteve/lagom/blob/master/docs/comparison.md). The other type-centric framework that had even a nice interface that I found was punq (https://punq.readthedocs.io/en/latest/). The development just doesn't seem as active on punq. While I didn't land up using the integration Lagom seems to have async frameworks in mind (https://github.com/meadsteve/lagom/blob/master/lagom/integrations/fast_api.py), so that is another plus. Ultimately though I think I can swap between these two with like 10 lines of code switch, they do cool things with very simple interfaces and neither requires a bunch of investment in annotation on your components.
Upgrade syntax using `pyupgrade --py36-plus` .
Manually drop several `six` imports.
Also:
- Remove broken pr_cache in scripts/bootstrap_history.py
- Fix broken prefix removal in lib/galaxy/tool_util/deps/mulled/mulled_build.py