diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 755bc27..8a8e8d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,10 @@ name: Test -on: [push, pull_request] +on: + pull_request: + push: + branches: + - master jobs: build: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4e6a92c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1 @@ +repos: [] diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..e0d5efa --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Code of Conduct + +As contributors and maintainers of the Jazzband projects, and in the interest of +fostering an open and welcoming community, we pledge to respect all people who +contribute through reporting issues, posting feature requests, updating documentation, +submitting pull requests or patches, and other activities. + +We are committed to making participation in the Jazzband a harassment-free experience +for everyone, regardless of the level of experience, gender, gender identity and +expression, sexual orientation, disability, personal appearance, body size, race, +ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery +- Personal attacks +- Trolling or insulting/derogatory comments +- Public or private harassment +- Publishing other's private information, such as physical or electronic addresses, + without explicit permission +- Other unethical or unprofessional conduct + +The Jazzband roadies have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are not +aligned to this Code of Conduct, or to ban temporarily or permanently any contributor +for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +By adopting this Code of Conduct, the roadies commit themselves to fairly and +consistently applying these principles to every aspect of managing the jazzband +projects. Roadies who do not follow or enforce the Code of Conduct may be permanently +removed from the Jazzband roadies. + +This code of conduct applies both within project spaces and in public spaces when an +individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by +contacting the roadies at `roadies@jazzband.co`. All complaints will be reviewed and +investigated and will result in a response that is deemed necessary and appropriate to +the circumstances. Roadies are obligated to maintain confidentiality with regard to the +reporter of an incident. + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version +1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/3/0/ diff --git a/MANIFEST.in b/MANIFEST.in index 4f06150..3757d2b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,10 @@ -include README.rst -include CONTRIBUTING.md +include .pre-commit-config.yaml include AUTHORS +include CODE_OF_CONDUCT.md +include CONTRIBUTING.md +include LICENSE +include README.rst include tox.ini -recursive-include tests * recursive-include docs * recursive-include test_project * -include LICENSE +recursive-include tests * diff --git a/README.rst b/README.rst index 536b154..0716754 100644 --- a/README.rst +++ b/README.rst @@ -81,7 +81,7 @@ command line option, e.g. python manage.py runserver --settings=mysite.settings --configuration=Dev To enable Django to use your configuration you now have to modify your -**manage.py** or **wsgi.py** script to use django-configurations's versions +**manage.py**, **wsgi.py** or **asgi.py** script to use django-configurations's versions of the appropriate starter functions, e.g. a typical **manage.py** using django-configurations would look like this: @@ -120,5 +120,18 @@ The same applies to your **wsgi.py** file, e.g.: Here we don't use the default ``django.core.wsgi.get_wsgi_application`` function but instead ``configurations.wsgi.get_wsgi_application``. +Or if you are not serving your app via WSGI but ASGI instead, you need to modify your **asgi.py** file too.: + +.. code-block:: python + + import os + + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') + os.environ.setdefault('DJANGO_CONFIGURATION', 'DEV') + + from configurations.asgi import get_asgi_application + + application = get_asgi_application() + That's it! You can now use your project with ``manage.py`` and your favorite -WSGI enabled server. +WSGI/ASGI enabled server. diff --git a/configurations/asgi.py b/configurations/asgi.py new file mode 100644 index 0000000..da9401b --- /dev/null +++ b/configurations/asgi.py @@ -0,0 +1,8 @@ +from . import importer + +importer.install() + +from django.core.asgi import get_asgi_application # noqa: E402 + +# this is just for the crazy ones +application = get_asgi_application() diff --git a/configurations/base.py b/configurations/base.py index b1bc1e9..a09af41 100644 --- a/configurations/base.py +++ b/configurations/base.py @@ -32,10 +32,31 @@ class ConfigurationBase(type): for base in bases[::-1]: settings_vars.update(uppercase_attributes(base)) attrs = dict(settings_vars, **attrs) - # Fix ImproperlyConfigured issue introduced in Django + + deprecated_settings = { + # DEFAULT_HASHING_ALGORITHM is always deprecated, as it's a + # transitional setting + # https://docs.djangoproject.com/en/3.1/releases/3.1/#default-hashing-algorithm-settings + "DEFAULT_HASHING_ALGORITHM", + # DEFAULT_CONTENT_TYPE and FILE_CHARSET are deprecated in + # Django 2.2 and are removed in Django 3.0 + "DEFAULT_CONTENT_TYPE", + "FILE_CHARSET", + # When DEFAULT_AUTO_FIELD is not explicitly set, Django's emits a + # system check warning models.W042. This warning should not be + # suppressed, as downstream users are expected to make a decision. + # https://docs.djangoproject.com/en/3.2/releases/3.2/#customizing-type-of-auto-created-primary-keys + "DEFAULT_AUTO_FIELD", + } + # PASSWORD_RESET_TIMEOUT_DAYS is deprecated in favor of + # PASSWORD_RESET_TIMEOUT in Django 3.1 # https://github.com/django/django/commit/226ebb17290b604ef29e82fb5c1fbac3594ac163#diff-ec2bed07bb264cb95a80f08d71a47c06R163-R170 - if "PASSWORD_RESET_TIMEOUT_DAYS" in attrs and "PASSWORD_RESET_TIMEOUT" in attrs: - attrs.pop("PASSWORD_RESET_TIMEOUT_DAYS") + if "PASSWORD_RESET_TIMEOUT" in attrs: + deprecated_settings.add("PASSWORD_RESET_TIMEOUT_DAYS") + for deprecated_setting in deprecated_settings: + if deprecated_setting in attrs: + del attrs[deprecated_setting] + return super().__new__(cls, name, bases, attrs) def __repr__(self): diff --git a/configurations/values.py b/configurations/values.py index 38918ea..db4c38e 100644 --- a/configurations/values.py +++ b/configurations/values.py @@ -400,7 +400,7 @@ class PathValue(Value): value = super().setup(name) value = Path(value).expanduser() if self.check_exists and not value.exists(): - raise ValueError('Path {0!r} does not exist.'.format(value)) + raise ValueError('Path {0!r} does not exist.'.format(value)) value = value.absolute() return value if self.use_pathlib else str(value) diff --git a/configurations/wsgi.py b/configurations/wsgi.py index 54ab753..ea157a3 100644 --- a/configurations/wsgi.py +++ b/configurations/wsgi.py @@ -2,13 +2,7 @@ from . import importer importer.install() -try: - from django.core.wsgi import get_wsgi_application -except ImportError: # pragma: no cover - from django.core.handlers.wsgi import WSGIHandler - - def get_wsgi_application(): # noqa - return WSGIHandler() +from django.core.wsgi import get_wsgi_application # noqa: E402 # this is just for the crazy ones application = get_wsgi_application() diff --git a/docs/cookbook.rst b/docs/cookbook.rst index bb5f048..21624e5 100644 --- a/docs/cookbook.rst +++ b/docs/cookbook.rst @@ -182,7 +182,7 @@ probably just add the following to the **beginning** of your settings module: import configurations configurations.setup() -That has the same effect as using the ``manage.py`` or ``wsgi.py`` utilities. +That has the same effect as using the ``manage.py``, ``wsgi.py`` or ``asgi.py`` utilities. This will also call ``django.setup()``. >= 3.1 @@ -332,8 +332,8 @@ Channels -------- If you want to deploy a project that uses the Django channels with -`Daphne ` as the -`interface server ` +`Daphne `_ as the +`interface server `_ you have to use a asgi.py script similar to the following: .. code-block:: python diff --git a/docs/patterns.rst b/docs/patterns.rst index d2070b8..eff644a 100644 --- a/docs/patterns.rst +++ b/docs/patterns.rst @@ -21,7 +21,6 @@ file: class Dev(Base): DEBUG = True - TEMPLATE_DEBUG = DEBUG class Prod(Base): TIME_ZONE = 'America/New_York' diff --git a/docs/values.rst b/docs/values.rst index 5f5dcea..ebd21d1 100644 --- a/docs/values.rst +++ b/docs/values.rst @@ -46,7 +46,6 @@ value: class Dev(Configuration): DEBUG = values.BooleanValue(True) - TEMPLATE_DEBUG = values.BooleanValue(DEBUG) See the list of :ref:`built-in value classes` for more information. @@ -162,7 +161,7 @@ the prefix. :param environ: toggle for environment use :param environ_name: name of environment variable to look for :param environ_prefix: prefix to use when looking for environment variable - :param environ_required: wheter or not the value is required to be set as an environment variable + :param environ_required: whether or not the value is required to be set as an environment variable :type environ: bool :type environ_name: capitalized string or None :type environ_prefix: capitalized string @@ -353,6 +352,10 @@ Type values DEPARTMENTS = values.DictValue({ 'it': ['Mike', 'Joe'], }) + + Override using environment variables like this:: + + DJANGO_DEPARTMENTS={'it':['Mike','Joe'],'hr':['Emma','Olivia']} Validator values ^^^^^^^^^^^^^^^^ @@ -547,7 +550,7 @@ Other values :: - MIDDLEWARE_CLASSES = values.BackendsValue([ + MIDDLEWARE = values.BackendsValue([ 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', diff --git a/setup.py b/setup.py index 7a578e2..a77b6d8 100644 --- a/setup.py +++ b/setup.py @@ -26,15 +26,16 @@ setup( 'django-cadmin = configurations.management:execute_from_command_line', ], }, - install_requires=[], + install_requires=[ + 'django>=2.2', + 'setuptools', + ], extras_require={ 'cache': ['django-cache-url'], 'database': ['dj-database-url'], 'email': ['dj-email-url'], 'search': ['dj-search-url'], 'testing': [ - 'django-discover-runner', - 'mock', 'django-cache-url>=1.0.0', 'dj-database-url', 'dj-email-url', diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 295981c..879a3b8 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -5,7 +5,6 @@ class Base(Configuration): # Django settings for test_project project. DEBUG = values.BooleanValue(True, environ=True) - TEMPLATE_DEBUG = DEBUG ADMINS = ( # ('Your Name', 'your_email@example.com'), @@ -95,7 +94,7 @@ class Base(Configuration): 'django.template.loaders.app_directories.Loader', ) - MIDDLEWARE_CLASSES = ( + MIDDLEWARE = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', diff --git a/tests/management/__init__.py b/tests/management/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/management/commands/__init__.py b/tests/management/commands/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/management/commands/old_optparse_command.py b/tests/management/commands/old_optparse_command.py deleted file mode 100644 index d7844e5..0000000 --- a/tests/management/commands/old_optparse_command.py +++ /dev/null @@ -1,16 +0,0 @@ -from optparse import make_option -from django.core.management.base import BaseCommand - - -class Command(BaseCommand): - - # Used by a specific test to see how unupgraded - # management commands play with configurations. - # See the test code for more details. - - option_list = BaseCommand.option_list + ( - make_option('--arg1', action='store_true'), - ) - - def handle(self, *args, **options): - pass