-
Notifications
You must be signed in to change notification settings - Fork 43
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
[Code review question] How to do teardown? #37
Comments
Your ideal scenario (the one with |
I made a stab at something that could do the job. class ContextualProviderWrapper(CachedProviderWrapper):
def __del__(self):
for value in self._cache.values():
if inspect.isgenerator(value):
try:
next(value)
except StopIteration:
pass
def get(self, injector):
key = id(injector)
instance = self._old_provider.get(injector)
if key not in self._cache:
self._cache[key] = next(instance())
return self._cache[key]
class ContextualRequestScope(RequestScope):
def get(self, key, provider):
try:
return self._locals.scope[key]
except KeyError:
new_provider = ContextualProviderWrapper(provider)
self._locals.scope[key] = new_provider
return new_provider
contextual_request_scope = ScopeDecorator(ContextualRequestScope)
def setup_teardown():
# set up
yield
# tear down
def configure(binder)
binder.bind(
bind_key,
to=lambda: setup_teardown,
scope=contextual_request_scope
) Works for me. But I'd love your review :) |
Seems like a nice little hack :) Two notes to self:
As for your solution – my main concerns here would be:
While I believe a general-purpose scope-cleanup mechanism would be nice we're not there yet I'm afraid. I don't think cleaning things up manually here is too terrible all things considered. |
The cached CachedProviderWrapper is there to prevent multiple calls to I'll try and add type hints. About your concerns
So we could use
I think this is deterministically bound to the lifespan werkzurg locals, and is called when werkzurg releases them. However I could invoke a cleanup function manually. I agree it's a bit of a codesmell. If I submit a PR with these changes would you be happy to merge it? |
The note about type hints was for myself – I need to add them (the relevant ones) to I don't think class CleaningUpRequestScope(RequestScope):
def cleanup(self) -> None:
# run cleanup generators here
super().cleanup()
def get(self, key, provider):
# save cleanup generators somewhere here
# ...
# ...
FlaskInjector(request_scope_class=CleaningUpRequestScope) This will give you full determinism. I'm unlikely to accept a PR with this – among other things because passing a callable returning a generator to Also – cleaning things up seems so application-specific that I wouldn't necessarily want to involve a dependency injection library with it. |
Thanks for this project. I'm evaluating this as a way of managing dependencies in this large flask application I'm refactoring.
How would one manage cleanup of threadlocals, when you have to release things manually. In SQLAlchemy is this required, or anything that uses a threadpool.
I've made a working attempt (based off your example), but I'm not sure if it's the right direction.
Is there anything I could do to make this class more idiomatic with Injector?
What I think would be really lovely, instead of binding to a function, you could bind to something with a yield statement.
So
create_session
would becomeThe text was updated successfully, but these errors were encountered: