PK!vLXclass_settings/__init__.py__version__ = "0.1.0" from .env import Env, env from .settings import Settings def setup(): import importlib import os import sys from django.conf import settings from django.core.exceptions import ImproperlyConfigured from .importers import SettingsImporter from .utils import patch_settings_setup global _setup if _setup: return # Prevent DJANGO_SETTINGS_MODULE getting mutated twice via the autoreloader if os.environ.get("RUN_MAIN") != "true": try: settings_module = os.environ["DJANGO_SETTINGS_MODULE"] settings_class = os.environ["DJANGO_SETTINGS_CLASS"] except KeyError as error: raise ImproperlyConfigured( "Settings could not be setup. The environment variable {!r} " "is not defined.".format(error.args[0]) ) os.environ["DJANGO_SETTINGS_MODULE"] = "{}:{}".format( settings_module, settings_class ) sys.meta_path.append(SettingsImporter()) @patch_settings_setup # Needed for manage.py --settings support def settings_setup(): module_path = os.environ["DJANGO_SETTINGS_MODULE"] module = importlib.import_module(module_path) # Prevent manage.py from swallowing exceptions arising from # settings._setup and make sure to call settings.configure first to # allow it to error on multiple calls. old = settings._wrapped settings.configure(module, SETTINGS_MODULE=module_path) new = settings._wrapped settings._wrapped = old settings._setup() settings._wrapped = new _setup = True _setup = False PK!k$8hhclass_settings/env.pyimport contextlib import functools import os import sys from django.core.exceptions import ImproperlyConfigured from . import parsers from .options import Options class Missing: def __bool__(self): return False missing = Missing() class Env: def __init__(self): self._prefix = None self._parsers = {} # Populate with default parsers for name, parser in vars(parsers).items(): if name.startswith("_"): continue if callable(parser): self.parser(parser) def __call__(self, name=None, *, prefix=None, default=missing): frame = sys._getframe(1) while frame is not None: options = frame.f_locals.get("__meta__") if isinstance(options, Options): break frame = frame.f_back else: options = None if name is None: if options is None: raise TypeError("'name' is required outside of Settings classes") return DeferredEnv(self, prefix=prefix, default=default) prefix = ( prefix if prefix is not None else self._prefix if self._prefix is not None else options.env_prefix ) if prefix.islower() and not prefix.endswith("_"): prefix += "_" name = prefix + name if prefix is not None else name if default is not missing: return os.environ.get(name, default) try: return os.environ[name] except KeyError: raise ImproperlyConfigured( "Environment variable {!r} not set".format(name.upper()) ) def __getattr__(self, name): try: return self._parsers[name] except KeyError: cls_name = type(self).__name__ raise AttributeError( "{!r} object has no attribute {!r}".format(cls_name, name) ) @contextlib.contextmanager def prefixed(self, prefix): old_prefix = self._prefix if old_prefix is None: self._prefix = prefix else: self._prefix += prefix yield self._prefix = old_prefix def parser(self, _func=None, *, name=None, parse_default=False): def decorator(func): @functools.wraps(func) def parser(name=None, *, prefix=None, default=missing, **kwargs): try: value = self(name, prefix=prefix) except ImproperlyConfigured: if default is not missing: if parse_default: default = func(default, **kwargs) return default raise if isinstance(value, DeferredEnv): value._parser = functools.partial(parser, **kwargs) else: value = func(value, **kwargs) return value parser_name = name if name is not None else func.__name__ self._parsers[parser_name] = parser return func return decorator if _func is None else decorator(_func) class DeferredEnv: def __init__(self, env, *, prefix=None, default=missing): self._env = env self._prefix = prefix self._default = default self._parser = None def _parse(self, name): if self._parser is not None: return self._parser(name, prefix=self._prefix, default=self._default) else: return self._env(name, prefix=self._prefix, default=self._default) env = Env() PK!uclass_settings/importers.pyimport importlib.machinery import types from django.core.exceptions import ImproperlyConfigured class SettingsModule(types.ModuleType): def __init__(self, name, cls): super().__init__(name, cls.__doc__) self.SETTINGS_CLASS = cls def __dir__(self): return set(super().__dir__() + dir(self.SETTINGS_CLASS)) def __getattr__(self, name): return getattr(self.SETTINGS_CLASS, name) class SettingsImporter: def find_spec(self, fullname, path=None, target=None): if ":" not in fullname.rpartition(".")[2]: return None settings_module = fullname.rsplit(":", maxsplit=1)[0] return importlib.machinery.ModuleSpec(fullname, self, origin=settings_module) def create_module(self, spec): settings_module, settings_class = spec.name.rsplit(":", maxsplit=1) module = importlib.import_module(settings_module) # manage.py only catches ImproperlyConfigured and ImportError try: cls = getattr(module, settings_class) except AttributeError as error: raise ImproperlyConfigured(error) return SettingsModule(spec.name, cls()) def exec_module(self, module): pass PK!}class_settings/options.pyfrom django.conf import global_settings class Options: def __init__(self, meta): self.default_settings = getattr(meta, "default_settings", global_settings) self.env_prefix = getattr(meta, "env_prefix", "DJANGO_") PK!6FFclass_settings/parsers.pyimport builtins import functools def _get_parser(parser): is_builtin = parser in vars(builtins).values() is_class = isinstance(parser, type) if is_builtin and is_class and parser.__name__ in globals(): parser = globals()[parser.__name__] return parser def _sequence_parser(type): @functools.wraps(type) def parser(value, separator=",", subparser=None): items = map(builtins.str.strip, value.split(separator)) if subparser is not None: subparser = _get_parser(subparser) items = map(subparser, items) return type(items) return parser # Numeric types int = int float = float complex = complex # Sequence types list = _sequence_parser(list) tuple = _sequence_parser(tuple) # Text sequence types str = str # Binary sequence types bytes = bytes bytearray = bytearray # Set types set = _sequence_parser(set) frozenset = _sequence_parser(frozenset) # Mapping types def dict(value, separator=",", itemseparator="=", keyparser=None, valueparser=None): items = map(builtins.str.strip, value.split(separator)) keys, values = zip( *(map(builtins.str.strip, item.split(itemseparator)) for item in items) ) if keyparser is not None: keyparser = _get_parser(keyparser) keys = map(keyparser, keys) if valueparser is not None: valueparser = _get_parser(valueparser) values = map(valueparser, values) return builtins.dict(zip(keys, values)) # Other types def bool(value): if value.lower() in ["true", "t", "yes", "y", "on", "1"]: return True elif value.lower() in ["false", "f", "no", "n", "off", "0"]: return False else: raise ValueError("Could not convert {!r} to bool".format(value)) # Custom def json(value): import json return json.loads(value) PK!8? class_settings/settings.pyimport __future__ import ast import inspect import sys import tokenize from .env import DeferredEnv from .options import Options class SettingsDict(dict): def __setitem__(self, key, value): if isinstance(value, DeferredEnv): value = value._parse(key) super().__setitem__(key, value) class SettingsMeta(type): def __prepare__(name, bases): frame = sys._getframe(1) filename = inspect.getsourcefile(frame) with tokenize.open(filename) as file: lines = file.readlines()[frame.f_lineno - 1 :] source = "".join(inspect.getblock(lines)) cls_node = ast.parse(source).body[0] for node in reversed(list(ast.iter_child_nodes(cls_node))): if isinstance(node, ast.ClassDef) and node.name == "Meta": cf_mask = sum( getattr(__future__, feature).compiler_flag for feature in __future__.all_feature_names ) code = compile( ast.Module(body=[node]), filename="", mode="exec", flags=frame.f_code.co_flags & cf_mask, dont_inherit=True, ) globals = frame.f_globals locals = {} exec(code, globals, locals) meta = locals["Meta"] break else: for base in bases: if hasattr(base, "Meta"): meta = base.Meta break else: meta = None return SettingsDict(__meta__=Options(meta)) def __new__(meta, name, bases, namespace): options = namespace.pop("__meta__", None) if not isinstance(options, Options): raise RuntimeError("__meta__ is not an Options object") namespace["_meta"] = options return super().__new__(meta, name, bases, namespace) class Settings(metaclass=type("Meta", (type,), {})): # Hack for __class__ assignment def __dir__(self): default_settings = self._meta.default_settings return set(super().__dir__() + dir(default_settings)) def __getattr__(self, name): default_settings = self._meta.default_settings return getattr(default_settings, name) def is_overridden(self, setting): return setting in vars(self) Settings.__class__ = SettingsMeta PK!Z>>class_settings/utils.pyimport functools from django.conf import settings def patch_settings_setup(func): @functools.wraps(settings._setup) def setup(*args, **kwargs): object.__delattr__(settings, "_setup") func() # Circumvent any custom logic object.__setattr__(settings, "_setup", setup) return func PK!ӡn**-django_class_settings-0.1.0.dist-info/LICENSEMIT License Copyright (c) 2018 orlnub123 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!HlUT+django_class_settings-0.1.0.dist-info/WHEEL HM K-*ϳR03rOK-J,/R(O-)T0343 /, (-JLR()*M IL*4KM̫PK!H|tƉ) .django_class_settings-0.1.0.dist-info/METADATAVmS6_6xJi IB;Ld[vtȖ* ]q^hCb]˳$/4E%9 qbN45FkиsT(éָֈ n0⮳?EN=I2x Ș<e:{0`1-4' B%qƢHYV*b].\$ [3+djoXB¿<XX(B0xl)5C|=rNv r ?YHoۻjwµWaEj EL 꽃]"}ܖR P ɡ.x>Pz^nޭ5~јb{0YEw\F(FF ƙ 9L|Jcݏ!Q)43BUg]cŤm#,C7$4&JIJ@Q?Le%rHlV?JgQϓRrk­< %r(LXX\rV711ۃJF¥ rVІuM} BN)hAS4F3eBCA 9UhLMt ^Ą?4Î3X0% GPD )BuPD^{6!10񸙹,BuM?47C:K|eU>|tnϵď  MI5֘x z݇p8ԉu\W]"$Ъǧ8pה7x}<j A+6X2Fnܹ`Jq=ܷ;Ivy ےz?nJOհjx O%3d,9#5מ%ONdW'z „Q-J[bv+: t;'V܋?a6oay9<>ADYq?yg"C/^I-W]8Wh?ڑz"WF RyyvC/Greu7\=L9 yɛkE9P|C4&$6dZڙ +ew8[CZIaEVoPK!H ,django_class_settings-0.1.0.dist-info/RECORD9@6fLPn(,  b_?x홠=0ɭ2&_iA$`OC$xB;7-82/VUtNN؋.!?[9i1RFDj'ҊSmtgOkjGuva0e*,i" JRK6:T;(Y]ZbLk7j˹΃1SFۀ:X D AK~N7N/lMyhsQU ~rmuw~Z!'|QvI]{~%uK-Xֵ3h}mD~GEzR"p݃2*G)T^qKղ<kD<2POeKcAA)b 0ˊ)p ,gX!m$5I6е}(pP,i-Y+ֆl\%ź Q+9?S=2# ˌȺ_PK!vLXclass_settings/__init__.pyPK!k$8hhclass_settings/env.pyPK!ukclass_settings/importers.pyPK!}gclass_settings/options.pyPK!6FFclass_settings/parsers.pyPK!8? #class_settings/settings.pyPK!Z>>,class_settings/utils.pyPK!ӡn**-C.django_class_settings-0.1.0.dist-info/LICENSEPK!HlUT+2django_class_settings-0.1.0.dist-info/WHEELPK!H|tƉ) .V3django_class_settings-0.1.0.dist-info/METADATAPK!H ,&8django_class_settings-0.1.0.dist-info/RECORDPK Y: