Skip to content

Commit

Permalink
Fixture for modify_setting (didn't end up using it yet...)
Browse files Browse the repository at this point in the history
  • Loading branch information
davegaeddert committed Jul 31, 2024
1 parent bfd8010 commit 318c24b
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 319 deletions.
9 changes: 9 additions & 0 deletions plain-pytest/plain/pytest/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ def client() -> Client:
def request_factory() -> RequestFactory:
"""A Plain RequestFactory instance."""
return RequestFactory()


@pytest.fixture()
def modify_setting(name, value):
"""A fixture to temporarily modify a Plain setting."""
original_value = getattr(settings, name)
setattr(settings, name, value)
yield value
setattr(settings, name, original_value)
6 changes: 0 additions & 6 deletions plain/plain/packages/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,6 @@ def set_installed_packages(self, installed):
self.clear_cache()
self.populate(installed)

def unset_installed_packages(self):
"""Cancel a previous call to set_installed_packages()."""
self.package_configs = self.stored_package_configs.pop()
self.packages_ready = self.models_ready = self.ready = True
self.clear_cache()

def clear_cache(self):
"""
Clear all internal caches, for methods that alter the app registry.
Expand Down
49 changes: 0 additions & 49 deletions plain/plain/runtime/user_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,52 +302,3 @@ def is_overridden(self, setting):

def __repr__(self):
return f'<{self.__class__.__name__} "{self.SETTINGS_MODULE}">'


# Currently used for test settings override... nothing else
class UserSettingsHolder:
"""Holder for user configured settings."""

# SETTINGS_MODULE doesn't make much sense in the manually configured
# (standalone) case.
SETTINGS_MODULE = None

def __init__(self, default_settings):
"""
Requests for configuration variables not in this class are satisfied
from the module specified in default_settings (if possible).
"""
self.__dict__["_deleted"] = set()
self.default_settings = default_settings

def __getattr__(self, name):
if not name.isupper() or name in self._deleted:
raise AttributeError
return getattr(self.default_settings, name)

def __setattr__(self, name, value):
self._deleted.discard(name)
super().__setattr__(name, value)

def __delattr__(self, name):
self._deleted.add(name)
if hasattr(self, name):
super().__delattr__(name)

def __dir__(self):
return sorted(
s
for s in [*self.__dict__, *dir(self.default_settings)]
if s not in self._deleted
)

def is_overridden(self, setting):
deleted = setting in self._deleted
set_locally = setting in self.__dict__
set_on_default = getattr(
self.default_settings, "is_overridden", lambda s: False
)(setting)
return deleted or set_locally or set_on_default

def __repr__(self):
return f"<{self.__class__.__name__}>"
8 changes: 0 additions & 8 deletions plain/plain/test/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
"""Plain Unit Test framework."""

from plain.test.client import Client, RequestFactory
from plain.test.utils import (
ignore_warnings,
modify_settings,
override_settings,
)

__all__ = [
"Client",
"RequestFactory",
"ignore_warnings",
"modify_settings",
"override_settings",
]
37 changes: 36 additions & 1 deletion plain/plain/test/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from http.cookies import SimpleCookie
from importlib import import_module
from io import BytesIO, IOBase
from itertools import chain
from urllib.parse import unquote_to_bytes, urljoin, urlparse, urlsplit

from plain.http import HttpHeaders, HttpRequest, QueryDict
Expand All @@ -16,7 +17,6 @@
from plain.json import PlainJSONEncoder
from plain.runtime import settings
from plain.signals import got_request_exception, request_started
from plain.test.utils import ContextList
from plain.urls import resolve
from plain.utils.encoding import force_bytes
from plain.utils.functional import SimpleLazyObject
Expand All @@ -40,6 +40,41 @@
JSON_CONTENT_TYPE_RE = _lazy_re_compile(r"^application\/(.+\+)?json")


class ContextList(list):
"""
A wrapper that provides direct key access to context items contained
in a list of context objects.
"""

def __getitem__(self, key):
if isinstance(key, str):
for subcontext in self:
if key in subcontext:
return subcontext[key]
raise KeyError(key)
else:
return super().__getitem__(key)

def get(self, key, default=None):
try:
return self.__getitem__(key)
except KeyError:
return default

def __contains__(self, key):
try:
self[key]
except KeyError:
return False
return True

def keys(self):
"""
Flattened keys of subcontexts.
"""
return set(chain.from_iterable(d for subcontext in self for d in subcontext))


class RedirectCycleError(Exception):
"""The test client has been asked to follow a redirect loop."""

Expand Down
Loading

0 comments on commit 318c24b

Please sign in to comment.