Opened 10 years ago
Closed 10 years ago
#24476 closed Cleanup/optimization (fixed)
Allow using set_script_prefix as a contextmanager
Reported by: | Tim Graham | Owned by: | Bas Peschier |
---|---|---|---|
Component: | Core (URLs) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It would be useful if set_script_prefix()
could be used as a contextmanager in addition to as a regular function. That would allow replacing this redundant pattern in tests:
set_script_prefix('/beverages/') try: self.assertEqual(pf.get_absolute_url(), '/beverages/tea/') finally: clear_script_prefix()
with:
with set_script_prefix('/beverages/'): self.assertEqual(pf.get_absolute_url(), '/beverages/tea/')
Change History (9)
comment:1 by , 10 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:2 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 10 years ago
comment:4 by , 10 years ago
Something like this should work:
class set_script_prefix(object): """ Sets the script prefix for the current thread. Can be called directly or used as a context manager. """ def __init__(self, prefix): if not prefix.endswith('/'): prefix += '/' self._old_prefix = get_script_prefix() self._prefix = prefix self._set_prefix(prefix) def __enter__(self): return self._prefix def __exit__(self, exc_type, exc_val, exc_tb): self._set_prefix(self._old_prefix) def _set_prefix(self, prefix): _prefixes.value = prefix
comment:5 by , 10 years ago
Ah, yes. Combining context manager + call is doable, but not also with a decorator.
I like the current implementation because it leaves the original code simple. It only defines a helper for the test use case.
comment:6 by , 10 years ago
You can probably use contextlib.ContextDecorator
(backported in django.utils.decorators
) to make it into a decorator as well.
I don't have a particular opinion as to which approach is better though, I just liked the challenge of trying to make it work :)
comment:7 by , 10 years ago
It is! :-)
The PR uses ContextDecorator, but since a decorator gets called before you do anything, it would set the script prefix while importing the module if you put the meat in __init__
which is required to make a direct call work.
comment:8 by , 10 years ago
Has patch: | set |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Don't forget to check "Has patch" so the ticket appears in the review queue.
Combining a contextmanager while allowing a normal function call turned out to be less trivial than thought. Changed it into a test util.