Introduce wiring inspect filter

This commit is contained in:
Roman Mogylatov 2021-02-27 09:25:30 -05:00
parent 6763ad2934
commit 75e346cbdb
4 changed files with 103 additions and 4 deletions

View File

@ -9,6 +9,11 @@ follows `Semantic versioning`_
Development version
-------------------
- Introduce wiring inspect filter to filter out ``flask.request`` and other local proxy objects
from the inspection.
See issue: `#408 <https://github.com/ets-labs/python-dependency-injector/issues/408>`_.
Many thanks to `@bvanfleet <https://github.com/bvanfleet>`_ for reporting the issue and
help in finding the root cause.
- Add ``boto3`` example.
- Add tests for ``.as_float()`` modifier usage with wiring.
- Make refactoring of wiring module and tests.

View File

@ -37,10 +37,15 @@ else:
try:
from fastapi.params import Depends as FastAPIDepends
fastapi_installed = True
import fastapi.params
except ImportError:
fastapi_installed = False
fastapi = None
try:
import werkzeug.local
except ImportError:
werkzeug = None
from . import providers
@ -247,6 +252,26 @@ class ProvidersMap:
return providers_map
class InspectFilter:
def is_excluded(self, instance: object) -> bool:
if self._is_werkzeug_local_proxy(instance):
return True
elif self._is_fastapi_request(instance):
return True
else:
return False
def _is_werkzeug_local_proxy(self, instance: object) -> bool:
return werkzeug and isinstance(instance, werkzeug.local.LocalProxy)
def _is_fastapi_request(self, instance: object) -> bool:
return fastapi and isinstance(instance, fastapi.Request)
inspect_filter = InspectFilter()
def wire( # noqa: C901
container: Container,
*,
@ -268,6 +293,8 @@ def wire( # noqa: C901
for module in modules:
for name, member in inspect.getmembers(module):
if inspect_filter.is_excluded(member):
continue
if inspect.isfunction(member):
_patch_fn(module, name, member, providers_map)
elif inspect.isclass(member):
@ -530,7 +557,7 @@ def _is_fastapi_default_arg_injection(injection, kwargs):
def _is_fastapi_depends(param: Any) -> bool:
return fastapi_installed and isinstance(param, FastAPIDepends)
return fastapi and isinstance(param, fastapi.params.Depends)
def _is_patched(fn):

View File

@ -0,0 +1,34 @@
import sys
from flask import Flask, jsonify, request, current_app, session, g
from flask import _request_ctx_stack, _app_ctx_stack
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide
# This is here for testing wiring bypasses these objects without crashing
request, current_app, session, g # noqa
_request_ctx_stack, _app_ctx_stack # noqa
class Service:
def process(self) -> str:
return 'Ok'
class Container(containers.DeclarativeContainer):
service = providers.Factory(Service)
app = Flask(__name__)
@app.route('/')
@inject
def index(service: Service = Provide[Container.service]):
result = service.process()
return jsonify({'result': result})
container = Container()
container.wire(modules=[sys.modules[__name__]])

View File

@ -0,0 +1,33 @@
import unittest
# Runtime import to avoid syntax errors in samples on Python < 3.5 and reach top-dir
import os
_TOP_DIR = os.path.abspath(
os.path.sep.join((
os.path.dirname(__file__),
'../',
)),
)
_SAMPLES_DIR = os.path.abspath(
os.path.sep.join((
os.path.dirname(__file__),
'../samples/',
)),
)
import sys
sys.path.append(_TOP_DIR)
sys.path.append(_SAMPLES_DIR)
from wiringflask import web
class WiringFlaskTest(unittest.TestCase):
def test(self):
client = web.app.test_client()
with web.app.app_context():
response = client.get('/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, b'{"result":"Ok"}\n')