mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2024-11-26 03:24:01 +03:00
Merged parent repo and configured refurbished tests
This commit is contained in:
commit
9cf72849e6
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
|
@ -1,7 +1,7 @@
|
||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: pydanny
|
||||||
patreon: danielroygreenfeld
|
patreon: roygreenfeld
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
|
|
@ -15,10 +15,6 @@ matrix:
|
||||||
include:
|
include:
|
||||||
- name: Test results
|
- name: Test results
|
||||||
script: tox -e py37
|
script: tox -e py37
|
||||||
- name: Run flake8 on result
|
|
||||||
script: tox -e flake8
|
|
||||||
- name: Run black on result
|
|
||||||
script: tox -e black
|
|
||||||
- name: Black template
|
- name: Black template
|
||||||
script: tox -e black-template
|
script: tox -e black-template
|
||||||
- name: Basic Docker
|
- name: Basic Docker
|
||||||
|
|
|
@ -88,6 +88,7 @@ Listed in alphabetical order.
|
||||||
Chris Pappalardo `@ChrisPappalardo`_
|
Chris Pappalardo `@ChrisPappalardo`_
|
||||||
Christopher Clarke `@chrisdev`_
|
Christopher Clarke `@chrisdev`_
|
||||||
Cole Mackenzie `@cmackenzie1`_
|
Cole Mackenzie `@cmackenzie1`_
|
||||||
|
Cole Maclean `@cole`_ @cole
|
||||||
Collederas `@Collederas`_
|
Collederas `@Collederas`_
|
||||||
Craig Margieson `@cmargieson`_
|
Craig Margieson `@cmargieson`_
|
||||||
Cristian Vargas `@cdvv7788`_
|
Cristian Vargas `@cdvv7788`_
|
||||||
|
@ -176,6 +177,7 @@ Listed in alphabetical order.
|
||||||
Oleg Russkin `@rolep`_
|
Oleg Russkin `@rolep`_
|
||||||
Pablo `@oubiga`_
|
Pablo `@oubiga`_
|
||||||
Parbhat Puri `@parbhat`_
|
Parbhat Puri `@parbhat`_
|
||||||
|
Pawan Chaurasia `@rjsnh1522`_
|
||||||
Peter Bittner `@bittner`_
|
Peter Bittner `@bittner`_
|
||||||
Peter Coles `@mrcoles`_
|
Peter Coles `@mrcoles`_
|
||||||
Philipp Matthies `@canonnervio`_
|
Philipp Matthies `@canonnervio`_
|
||||||
|
@ -206,6 +208,7 @@ Listed in alphabetical order.
|
||||||
Tubo Shi `@Tubo`_
|
Tubo Shi `@Tubo`_
|
||||||
Umair Ashraf `@umrashrf`_ @fabumair
|
Umair Ashraf `@umrashrf`_ @fabumair
|
||||||
Vadim Iskuchekov `@Egregors`_ @egregors
|
Vadim Iskuchekov `@Egregors`_ @egregors
|
||||||
|
Vicente G. Reyes `@reyesvicente`_ @highcenburg
|
||||||
Vitaly Babiy
|
Vitaly Babiy
|
||||||
Vivian Guillen `@viviangb`_
|
Vivian Guillen `@viviangb`_
|
||||||
Vlad Doster `@vladdoster`_
|
Vlad Doster `@vladdoster`_
|
||||||
|
@ -260,6 +263,7 @@ Listed in alphabetical order.
|
||||||
.. _@chuckus: https://github.com/chuckus
|
.. _@chuckus: https://github.com/chuckus
|
||||||
.. _@cmackenzie1: https://github.com/cmackenzie1
|
.. _@cmackenzie1: https://github.com/cmackenzie1
|
||||||
.. _@cmargieson: https://github.com/cmargieson
|
.. _@cmargieson: https://github.com/cmargieson
|
||||||
|
.. _@cole: https://github.com/cole
|
||||||
.. _@Collederas: https://github.com/Collederas
|
.. _@Collederas: https://github.com/Collederas
|
||||||
.. _@curtisstpierre: https://github.com/curtisstpierre
|
.. _@curtisstpierre: https://github.com/curtisstpierre
|
||||||
.. _@dadokkio: https://github.com/dadokkio
|
.. _@dadokkio: https://github.com/dadokkio
|
||||||
|
@ -337,11 +341,13 @@ Listed in alphabetical order.
|
||||||
.. _@originell: https://github.com/originell
|
.. _@originell: https://github.com/originell
|
||||||
.. _@oubiga: https://github.com/oubiga
|
.. _@oubiga: https://github.com/oubiga
|
||||||
.. _@parbhat: https://github.com/parbhat
|
.. _@parbhat: https://github.com/parbhat
|
||||||
|
.. _@rjsnh1522: https://github.com/rjsnh1522
|
||||||
.. _@pchiquet: https://github.com/pchiquet
|
.. _@pchiquet: https://github.com/pchiquet
|
||||||
.. _@phiberjenz: https://github.com/phiberjenz
|
.. _@phiberjenz: https://github.com/phiberjenz
|
||||||
.. _@purplediane: https://github.com/purplediane
|
.. _@purplediane: https://github.com/purplediane
|
||||||
.. _@raonyguimaraes: https://github.com/raonyguimaraes
|
.. _@raonyguimaraes: https://github.com/raonyguimaraes
|
||||||
.. _@reggieriser: https://github.com/reggieriser
|
.. _@reggieriser: https://github.com/reggieriser
|
||||||
|
.. _@reyesvicente: https://github.com/reyesvicente
|
||||||
.. _@rm--: https://github.com/rm--
|
.. _@rm--: https://github.com/rm--
|
||||||
.. _@rolep: https://github.com/rolep
|
.. _@rolep: https://github.com/rolep
|
||||||
.. _@romanosipenko: https://github.com/romanosipenko
|
.. _@romanosipenko: https://github.com/romanosipenko
|
||||||
|
|
14
README.rst
14
README.rst
|
@ -105,16 +105,16 @@ This project is run by volunteers. Please support them in their efforts to maint
|
||||||
|
|
||||||
Projects that provide financial support to the maintainers:
|
Projects that provide financial support to the maintainers:
|
||||||
|
|
||||||
Two Scoops of Django 1.11
|
Django Crash Course
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. image:: https://cdn.shopify.com/s/files/1/0304/6901/products/2017-06-29-tsd11-sticker-02.png
|
.. image:: https://cdn.shopify.com/s/files/1/0304/6901/files/Django-Crash-Course-300x436.jpg
|
||||||
:name: Two Scoops of Django 1.11 Cover
|
:name: Django Crash Course: Covers Django 3.0 and Python 3.8
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Two Scoops of Django
|
:alt: Django Crash Course
|
||||||
:target: http://twoscoopspress.com/products/two-scoops-of-django-1-11
|
:target: https://www.roygreenfeld.com/products/django-crash-course
|
||||||
|
|
||||||
Two Scoops of Django is the best dessert-themed Django reference in the universe
|
Django Crash Course for Django 3.0 and Python 3.8 is the best cheese-themed Django reference in the universe!
|
||||||
|
|
||||||
pyup
|
pyup
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -135,7 +135,7 @@ and then editing the results to include your name, email, and various configurat
|
||||||
|
|
||||||
First, get Cookiecutter. Trust me, it's awesome::
|
First, get Cookiecutter. Trust me, it's awesome::
|
||||||
|
|
||||||
$ pip install "cookiecutter>=1.4.0"
|
$ pip install "cookiecutter>=1.7.0"
|
||||||
|
|
||||||
Now run it against this repo::
|
Now run it against this repo::
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ Provided you have opted for Celery (via setting ``use_celery`` to ``y``) there a
|
||||||
|
|
||||||
* ``celeryworker`` running a Celery worker process;
|
* ``celeryworker`` running a Celery worker process;
|
||||||
* ``celerybeat`` running a Celery beat process;
|
* ``celerybeat`` running a Celery beat process;
|
||||||
* ``flower`` running Flower_ (for more info, check out :ref:`CeleryFlower` instructions for local environment).
|
* ``flower`` running Flower_.
|
||||||
|
|
||||||
|
The ``flower`` service is served by Traefik over HTTPS, through the port ``5555``. For more information about Flower and its login credentials, check out :ref:`CeleryFlower` instructions for local environment.
|
||||||
|
|
||||||
.. _`Flower`: https://github.com/mher/flower
|
.. _`Flower`: https://github.com/mher/flower
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = -x --tb=short
|
addopts = -v --tb=short
|
||||||
python_paths = .
|
python_paths = .
|
||||||
norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/*
|
norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/*
|
||||||
markers =
|
|
||||||
flake8: Run flake8 on all possible template combinations
|
|
||||||
black: Run black on all possible template combinations
|
|
||||||
|
|
|
@ -6,12 +6,12 @@ binaryornot==0.4.4
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
black==19.10b0
|
black==19.10b0
|
||||||
flake8==3.7.9
|
flake8==3.7.9
|
||||||
|
flake8-isort==2.8.0
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
tox==3.14.3
|
tox==3.14.5
|
||||||
pytest==5.3.5
|
pytest==5.4.1
|
||||||
pytest_cases==1.12.1
|
pytest-cookies==0.5.1
|
||||||
pytest-cookies==0.5.0
|
pytest-instafail==0.4.1.post0
|
||||||
pytest-xdist==1.31.0
|
|
||||||
pyyaml==5.3
|
pyyaml==5.3
|
||||||
|
|
|
@ -3,7 +3,6 @@ import re
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from cookiecutter.exceptions import FailedHookException
|
from cookiecutter.exceptions import FailedHookException
|
||||||
from pytest_cases import fixture_plus
|
|
||||||
import sh
|
import sh
|
||||||
import yaml
|
import yaml
|
||||||
from binaryornot.check import is_binary
|
from binaryornot.check import is_binary
|
||||||
|
@ -26,67 +25,75 @@ def context():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@fixture_plus
|
SUPPORTED_COMBINATIONS = [
|
||||||
@pytest.mark.parametrize("windows", ["y", "n"], ids=lambda yn: f"win:{yn}")
|
{"open_source_license": "MIT"},
|
||||||
@pytest.mark.parametrize("use_docker", ["y", "n"], ids=lambda yn: f"docker:{yn}")
|
{"open_source_license": "BSD"},
|
||||||
@pytest.mark.parametrize("use_celery", ["y", "n"], ids=lambda yn: f"celery:{yn}")
|
{"open_source_license": "GPLv3"},
|
||||||
@pytest.mark.parametrize("use_mailhog", ["y", "n"], ids=lambda yn: f"mailhog:{yn}")
|
{"open_source_license": "Apache Software License 2.0"},
|
||||||
@pytest.mark.parametrize("use_sentry", ["y", "n"], ids=lambda yn: f"sentry:{yn}")
|
{"open_source_license": "Not open source"},
|
||||||
@pytest.mark.parametrize("use_compressor", ["y", "n"], ids=lambda yn: f"cmpr:{yn}")
|
{"windows": "y"},
|
||||||
@pytest.mark.parametrize("use_drf", ["y", "n"], ids=lambda yn: f"drf:{yn}")
|
{"windows": "n"},
|
||||||
@pytest.mark.parametrize(
|
{"use_pycharm": "y"},
|
||||||
"use_whitenoise,cloud_provider",
|
{"use_pycharm": "n"},
|
||||||
[
|
{"use_docker": "y"},
|
||||||
("y", "AWS"),
|
{"use_docker": "n"},
|
||||||
("y", "GCP"),
|
{"postgresql_version": "11.3"},
|
||||||
("y", "None"),
|
{"postgresql_version": "10.8"},
|
||||||
("n", "AWS"),
|
{"postgresql_version": "9.6"},
|
||||||
("n", "GCP"),
|
{"postgresql_version": "9.5"},
|
||||||
# no whitenoise + no cloud provider is not supported
|
{"postgresql_version": "9.4"},
|
||||||
],
|
{"cloud_provider": "AWS", "use_whitenoise": "y"},
|
||||||
ids=lambda id: f"wnoise:{id[0]}-cloud:{id[1]}",
|
{"cloud_provider": "AWS", "use_whitenoise": "n"},
|
||||||
)
|
{"cloud_provider": "GCP", "use_whitenoise": "y"},
|
||||||
@pytest.mark.parametrize(
|
{"cloud_provider": "GCP", "use_whitenoise": "n"},
|
||||||
"mail_service",
|
{"cloud_provider": "None", "use_whitenoise": "y"},
|
||||||
[
|
# Note: cloud_provider=None AND use_whitenoise=n is not supported
|
||||||
"Amazon SES",
|
{"use_drf": "y"},
|
||||||
"Mailgun",
|
{"use_drf": "n"},
|
||||||
"MailJet",
|
{"js_task_runner": "None"},
|
||||||
"Mandrill",
|
{"js_task_runner": "Gulp"},
|
||||||
"Postmark",
|
{"custom_bootstrap_compilation": "y"},
|
||||||
"Sendgrid",
|
{"custom_bootstrap_compilation": "n"},
|
||||||
"SendinBlue",
|
{"use_compressor": "y"},
|
||||||
"SparkPost",
|
{"use_compressor": "n"},
|
||||||
"Plain/Vanilla Django-Anymail"
|
{"use_celery": "y"},
|
||||||
# GCP or None (i.e. no cloud provider) + Amazon SES is not supported
|
{"use_celery": "n"},
|
||||||
],
|
{"use_mailhog": "y"},
|
||||||
ids=lambda id: f"mail:{id[0]}",
|
{"use_mailhog": "n"},
|
||||||
)
|
{"use_sentry": "y"},
|
||||||
def context_combination(
|
{"use_sentry": "n"},
|
||||||
windows,
|
{"use_whitenoise": "y"},
|
||||||
use_docker,
|
{"use_whitenoise": "n"},
|
||||||
use_celery,
|
{"use_heroku": "y"},
|
||||||
use_mailhog,
|
{"use_heroku": "n"},
|
||||||
use_sentry,
|
{"ci_tool": "None"},
|
||||||
use_compressor,
|
{"ci_tool": "Travis"},
|
||||||
use_whitenoise,
|
{"ci_tool": "Gitlab"},
|
||||||
use_drf,
|
{"keep_local_envs_in_vcs": "y"},
|
||||||
cloud_provider,
|
{"keep_local_envs_in_vcs": "n"},
|
||||||
mail_service,
|
{"debug": "y"},
|
||||||
):
|
{"debug": "n"},
|
||||||
"""Fixture that parametrize the function where it's used."""
|
{"mail_service", "AWS SES"},
|
||||||
return {
|
{"mail_service", "Mailgun"},
|
||||||
"windows": windows,
|
{"mail_service", "Mailjet"},
|
||||||
"use_docker": use_docker,
|
{"mail_service", "Mandrill"},
|
||||||
"use_compressor": use_compressor,
|
{"mail_service", "Postmark"},
|
||||||
"use_celery": use_celery,
|
{"mail_service", "Sendgrid"},
|
||||||
"use_mailhog": use_mailhog,
|
{"mail_service", "SendinBlue"},
|
||||||
"use_sentry": use_sentry,
|
{"mail_service", "SparkPost"},
|
||||||
"use_whitenoise": use_whitenoise,
|
{"mail_service", "Other SMTP"},
|
||||||
"use_drf": use_drf,
|
]
|
||||||
"cloud_provider": cloud_provider,
|
|
||||||
"mail_service": mail_service,
|
UNSUPPORTED_COMBINATIONS = [
|
||||||
}
|
{"cloud_provider": "None", "use_whitenoise": "n"},
|
||||||
|
{"cloud_provider": "GCP", "mail_service": "Amazon SES"},
|
||||||
|
{"cloud_provider": "None", "mail_service": "Amazon SES"}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _fixture_id(ctx):
|
||||||
|
"""Helper to get a user friendly test name from the parametrized context."""
|
||||||
|
return "-".join(f"{key}:{value}" for key, value in ctx.items())
|
||||||
|
|
||||||
|
|
||||||
def build_files_list(root_dir):
|
def build_files_list(root_dir):
|
||||||
|
@ -99,9 +106,7 @@ def build_files_list(root_dir):
|
||||||
|
|
||||||
|
|
||||||
def check_paths(paths):
|
def check_paths(paths):
|
||||||
"""Method to check all paths have correct substitutions,
|
"""Method to check all paths have correct substitutions."""
|
||||||
used by other tests cases
|
|
||||||
"""
|
|
||||||
# Assert that no match is found in any of the files
|
# Assert that no match is found in any of the files
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if is_binary(path):
|
if is_binary(path):
|
||||||
|
@ -113,13 +118,10 @@ def check_paths(paths):
|
||||||
assert match is None, msg.format(path)
|
assert match is None, msg.format(path)
|
||||||
|
|
||||||
|
|
||||||
def test_project_generation(cookies, context, context_combination):
|
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||||
"""
|
def test_project_generation(cookies, context, context_override):
|
||||||
Test that project is generated and fully rendered.
|
"""Test that project is generated and fully rendered."""
|
||||||
|
result = cookies.bake(extra_context={**context, **context_override})
|
||||||
This is parametrized for each combination from ``context_combination`` fixture
|
|
||||||
"""
|
|
||||||
result = cookies.bake(extra_context={**context, **context_combination})
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert result.exception is None
|
assert result.exception is None
|
||||||
assert result.project.basename == context["project_slug"]
|
assert result.project.basename == context["project_slug"]
|
||||||
|
@ -130,34 +132,26 @@ def test_project_generation(cookies, context, context_combination):
|
||||||
check_paths(paths)
|
check_paths(paths)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.flake8
|
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||||
def test_flake8_passes(cookies, context_combination):
|
def test_flake8_passes(cookies, context_override):
|
||||||
"""
|
"""Generated project should pass flake8."""
|
||||||
Generated project should pass flake8.
|
result = cookies.bake(extra_context=context_override)
|
||||||
|
|
||||||
This is parametrized for each combination from ``context_combination`` fixture
|
|
||||||
"""
|
|
||||||
result = cookies.bake(extra_context=context_combination)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sh.flake8(str(result.project))
|
sh.flake8(str(result.project))
|
||||||
except sh.ErrorReturnCode as e:
|
except sh.ErrorReturnCode as e:
|
||||||
pytest.fail(e)
|
pytest.fail(e.stdout.decode())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.black
|
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||||
def test_black_passes(cookies, context_combination):
|
def test_black_passes(cookies, context_override):
|
||||||
"""
|
"""Generated project should pass black."""
|
||||||
Generated project should pass black.
|
result = cookies.bake(extra_context=context_override)
|
||||||
|
|
||||||
This is parametrized for each combination from ``context_combination`` fixture
|
|
||||||
"""
|
|
||||||
result = cookies.bake(extra_context=context_combination)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sh.black("--check", "--diff", "--exclude", "migrations", f"{result.project}/")
|
sh.black("--check", "--diff", "--exclude", "migrations", f"{result.project}/")
|
||||||
except sh.ErrorReturnCode as e:
|
except sh.ErrorReturnCode as e:
|
||||||
pytest.fail(e)
|
pytest.fail(e.stdout.decode())
|
||||||
|
|
||||||
|
|
||||||
def test_travis_invokes_pytest(cookies, context):
|
def test_travis_invokes_pytest(cookies, context):
|
||||||
|
@ -205,27 +199,10 @@ def test_invalid_slug(cookies, context, slug):
|
||||||
assert isinstance(result.exception, FailedHookException)
|
assert isinstance(result.exception, FailedHookException)
|
||||||
|
|
||||||
|
|
||||||
def test_no_whitenoise_and_no_cloud_provider(cookies, context):
|
@pytest.mark.parametrize("invalid_context", UNSUPPORTED_COMBINATIONS)
|
||||||
"""It should not generate project if neither whitenoise or cloud provider are set"""
|
def test_error_if_incompatible(cookies, context, invalid_context):
|
||||||
context.update({"use_whitenoise": "n", "cloud_provider": "None"})
|
"""It should not generate project an incompatible combination is selected."""
|
||||||
result = cookies.bake(extra_context=context)
|
context.update(invalid_context)
|
||||||
|
|
||||||
assert result.exit_code != 0
|
|
||||||
assert isinstance(result.exception, FailedHookException)
|
|
||||||
|
|
||||||
|
|
||||||
def test_gcp_with_aws_ses_mail_service(cookies, context):
|
|
||||||
"""It should not generate project if SES is set with GCP cloud provider"""
|
|
||||||
context.update({"cloud_provider": "GCP", "mail_service": "Amazon SES"})
|
|
||||||
result = cookies.bake(extra_context=context)
|
|
||||||
|
|
||||||
assert result.exit_code != 0
|
|
||||||
assert isinstance(result.exception, FailedHookException)
|
|
||||||
|
|
||||||
|
|
||||||
def test_no_cloud_provider_with_aws_ses_mail_service(cookies, context):
|
|
||||||
"""It should not generate project if SES is set with no cloud provider"""
|
|
||||||
context.update({"cloud_provider": "None", "mail_service": "Amazon SES"})
|
|
||||||
result = cookies.bake(extra_context=context)
|
result = cookies.bake(extra_context=context)
|
||||||
|
|
||||||
assert result.exit_code != 0
|
assert result.exit_code != 0
|
||||||
|
|
12
tox.ini
12
tox.ini
|
@ -1,18 +1,10 @@
|
||||||
[tox]
|
[tox]
|
||||||
skipsdist = true
|
skipsdist = true
|
||||||
envlist = py37,flake8,black,black-template
|
envlist = py37,black-template
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
deps = -rrequirements.txt
|
deps = -rrequirements.txt
|
||||||
commands = pytest -m "not flake8" -m "not black" {posargs:./tests}
|
commands = pytest {posargs:./tests}
|
||||||
|
|
||||||
[testenv:flake8]
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = pytest -m flake8 {posargs:./tests}
|
|
||||||
|
|
||||||
[testenv:black]
|
|
||||||
deps = -rrequirements.txt
|
|
||||||
commands = pytest -m black {posargs:./tests}
|
|
||||||
|
|
||||||
[testenv:black-template]
|
[testenv:black-template]
|
||||||
deps = black
|
deps = black
|
||||||
|
|
|
@ -13,8 +13,8 @@ indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
[*.py]
|
[*.py]
|
||||||
line_length = 120
|
line_length = 88
|
||||||
known_first_party = {{ cookiecutter.project_slug }}
|
known_first_party = {{cookiecutter.project_slug}},config
|
||||||
multi_line_output = 3
|
multi_line_output = 3
|
||||||
default_section = THIRDPARTY
|
default_section = THIRDPARTY
|
||||||
recursive = true
|
recursive = true
|
||||||
|
|
|
@ -16,4 +16,5 @@ repos:
|
||||||
entry: flake8
|
entry: flake8
|
||||||
language: python
|
language: python
|
||||||
types: [python]
|
types: [python]
|
||||||
|
args: ['--config=setup.cfg']
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,5 @@ release: python manage.py migrate
|
||||||
web: gunicorn config.wsgi:application
|
web: gunicorn config.wsgi:application
|
||||||
{% if cookiecutter.use_celery == "y" -%}
|
{% if cookiecutter.use_celery == "y" -%}
|
||||||
worker: celery worker --app=config.celery_app --loglevel=info
|
worker: celery worker --app=config.celery_app --loglevel=info
|
||||||
|
beat: celery beat --app=config.celery_app --loglevel=info
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
|
@ -9,6 +9,11 @@ entryPoints:
|
||||||
web-secure:
|
web-secure:
|
||||||
# https
|
# https
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
|
||||||
|
flower:
|
||||||
|
address: ":5555"
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
letsencrypt:
|
letsencrypt:
|
||||||
|
@ -41,6 +46,17 @@ http:
|
||||||
tls:
|
tls:
|
||||||
# https://docs.traefik.io/master/routing/routers/#certresolver
|
# https://docs.traefik.io/master/routing/routers/#certresolver
|
||||||
certResolver: letsencrypt
|
certResolver: letsencrypt
|
||||||
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
|
||||||
|
flower-secure-router:
|
||||||
|
rule: "Host(`{{ cookiecutter.domain_name }}`)"
|
||||||
|
entryPoints:
|
||||||
|
- flower
|
||||||
|
service: flower
|
||||||
|
tls:
|
||||||
|
# https://docs.traefik.io/master/routing/routers/#certresolver
|
||||||
|
certResolver: letsencrypt
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
middlewares:
|
middlewares:
|
||||||
redirect:
|
redirect:
|
||||||
|
@ -52,13 +68,20 @@ http:
|
||||||
# https://docs.traefik.io/master/middlewares/headers/#hostsproxyheaders
|
# https://docs.traefik.io/master/middlewares/headers/#hostsproxyheaders
|
||||||
# https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
|
# https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
|
||||||
headers:
|
headers:
|
||||||
hostsProxyHeaders: ['X-CSRFToken']
|
hostsProxyHeaders: ["X-CSRFToken"]
|
||||||
|
|
||||||
services:
|
services:
|
||||||
django:
|
django:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
servers:
|
servers:
|
||||||
- url: http://django:5000
|
- url: http://django:5000
|
||||||
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
|
||||||
|
flower:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: http://flower:5555
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
# https://docs.traefik.io/master/providers/file/
|
# https://docs.traefik.io/master/providers/file/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from rest_framework.routers import DefaultRouter, SimpleRouter
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from rest_framework.routers import DefaultRouter, SimpleRouter
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.api.views import UserViewSet
|
from {{ cookiecutter.project_slug }}.users.api.views import UserViewSet
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
|
|
||||||
# set the default Django settings module for the 'celery' program.
|
# set the default Django settings module for the 'celery' program.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
"""isort:skip_file"""
|
||||||
{% if cookiecutter.use_sentry == 'y' -%}
|
{% if cookiecutter.use_sentry == 'y' -%}
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import include, path
|
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.views.generic import TemplateView
|
from django.urls import include, path
|
||||||
from django.views import defaults as default_views
|
from django.views import defaults as default_views
|
||||||
{% if cookiecutter.use_drf == 'y' -%}
|
from django.views.generic import TemplateView
|
||||||
|
{%- if cookiecutter.use_drf == 'y' %}
|
||||||
from rest_framework.authtoken.views import obtain_auth_token
|
from rest_framework.authtoken.views import obtain_auth_token
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "0.0.0.0:80:80"
|
- "0.0.0.0:80:80"
|
||||||
- "0.0.0.0:443:443"
|
- "0.0.0.0:443:443"
|
||||||
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
- "0.0.0.0:5555:5555"
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:5.0
|
image: redis:5.0
|
||||||
|
@ -60,8 +63,6 @@ services:
|
||||||
flower:
|
flower:
|
||||||
<<: *django
|
<<: *django
|
||||||
image: {{ cookiecutter.project_slug }}_production_flower
|
image: {{ cookiecutter.project_slug }}_production_flower
|
||||||
ports:
|
|
||||||
- "5555:5555"
|
|
||||||
command: /start-flower
|
command: /start-flower
|
||||||
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
|
@ -10,8 +10,8 @@ whitenoise==5.0.1 # https://github.com/evansd/whitenoise
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
redis==3.4.1 # https://github.com/andymccurdy/redis-py
|
redis==3.4.1 # https://github.com/andymccurdy/redis-py
|
||||||
{%- if cookiecutter.use_celery == "y" %}
|
{%- if cookiecutter.use_celery == "y" %}
|
||||||
celery==4.4.0 # pyup: < 5.0 # https://github.com/celery/celery
|
celery==4.4.1 # pyup: < 5.0 # https://github.com/celery/celery
|
||||||
django-celery-beat==1.6.0 # https://github.com/celery/django-celery-beat
|
django-celery-beat==2.0.0 # https://github.com/celery/django-celery-beat
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
flower==0.9.3 # https://github.com/mher/flower
|
flower==0.9.3 # https://github.com/mher/flower
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
@ -19,11 +19,11 @@ flower==0.9.3 # https://github.com/mher/flower
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
django==2.2.10 # pyup: < 3.0 # https://www.djangoproject.com/
|
django==2.2.11 # pyup: < 3.0 # https://www.djangoproject.com/
|
||||||
django-environ==0.4.5 # https://github.com/joke2k/django-environ
|
django-environ==0.4.5 # https://github.com/joke2k/django-environ
|
||||||
django-model-utils==4.0.0 # https://github.com/jazzband/django-model-utils
|
django-model-utils==4.0.0 # https://github.com/jazzband/django-model-utils
|
||||||
django-allauth==0.41.0 # https://github.com/pennersr/django-allauth
|
django-allauth==0.41.0 # https://github.com/pennersr/django-allauth
|
||||||
django-crispy-forms==1.8.1 # https://github.com/django-crispy-forms/django-crispy-forms
|
django-crispy-forms==1.9.0 # https://github.com/django-crispy-forms/django-crispy-forms
|
||||||
{%- if cookiecutter.use_compressor == "y" %}
|
{%- if cookiecutter.use_compressor == "y" %}
|
||||||
django-compressor==2.4 # https://github.com/django-compressor/django-compressor
|
django-compressor==2.4 # https://github.com/django-compressor/django-compressor
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
@ -31,4 +31,3 @@ django-redis==4.11.0 # https://github.com/niwinz/django-redis
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
djangorestframework==3.11.0 # https://github.com/encode/django-rest-framework
|
djangorestframework==3.11.0 # https://github.com/encode/django-rest-framework
|
||||||
coreapi==2.3.3 # https://github.com/core-api/python-client
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
-r ./base.txt
|
-r ./base.txt
|
||||||
|
|
||||||
Werkzeug==0.16.1 # https://github.com/pallets/werkzeug
|
Werkzeug==1.0.0 # https://github.com/pallets/werkzeug
|
||||||
ipdb==0.12.3 # https://github.com/gotcha/ipdb
|
ipdb==0.13.2 # https://github.com/gotcha/ipdb
|
||||||
Sphinx==2.3.1 # https://github.com/sphinx-doc/sphinx
|
Sphinx==2.4.4 # https://github.com/sphinx-doc/sphinx
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
||||||
{%- else %}
|
{%- else %}
|
||||||
|
@ -11,7 +11,7 @@ psycopg2-binary==2.8.4 # https://github.com/psycopg/psycopg2
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
mypy==0.761 # https://github.com/python/mypy
|
mypy==0.770 # https://github.com/python/mypy
|
||||||
django-stubs==1.4.0 # https://github.com/typeddjango/django-stubs
|
django-stubs==1.4.0 # https://github.com/typeddjango/django-stubs
|
||||||
pytest==5.3.5 # https://github.com/pytest-dev/pytest
|
pytest==5.3.5 # https://github.com/pytest-dev/pytest
|
||||||
pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
|
pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
|
||||||
|
@ -19,19 +19,20 @@ pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
|
||||||
# Code quality
|
# Code quality
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
flake8==3.7.9 # https://github.com/PyCQA/flake8
|
flake8==3.7.9 # https://github.com/PyCQA/flake8
|
||||||
|
flake8-isort==2.8.0 # https://github.com/gforcada/flake8-isort
|
||||||
coverage==5.0.3 # https://github.com/nedbat/coveragepy
|
coverage==5.0.3 # https://github.com/nedbat/coveragepy
|
||||||
black==19.10b0 # https://github.com/ambv/black
|
black==19.10b0 # https://github.com/ambv/black
|
||||||
pylint-django==2.0.13 # https://github.com/PyCQA/pylint-django
|
pylint-django==2.0.14 # https://github.com/PyCQA/pylint-django
|
||||||
{%- if cookiecutter.use_celery == 'y' %}
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
pre-commit==2.0.1 # https://github.com/pre-commit/pre-commit
|
pre-commit==2.2.0 # https://github.com/pre-commit/pre-commit
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy
|
factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy
|
||||||
|
|
||||||
django-debug-toolbar==2.2 # https://github.com/jazzband/django-debug-toolbar
|
django-debug-toolbar==2.2 # https://github.com/jazzband/django-debug-toolbar
|
||||||
django-extensions==2.2.6 # https://github.com/django-extensions/django-extensions
|
django-extensions==2.2.8 # https://github.com/django-extensions/django-extensions
|
||||||
django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin
|
django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin
|
||||||
pytest-django==3.8.0 # https://github.com/pytest-dev/pytest-django
|
pytest-django==3.8.0 # https://github.com/pytest-dev/pytest-django
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
gunicorn==20.0.4 # https://github.com/benoitc/gunicorn
|
gunicorn==20.0.4 # https://github.com/benoitc/gunicorn
|
||||||
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
|
||||||
{%- if cookiecutter.use_whitenoise == 'n' %}
|
{%- if cookiecutter.use_whitenoise == 'n' %}
|
||||||
Collectfast==1.3.1 # https://github.com/antonagestam/collectfast
|
Collectfast==2.1.0 # https://github.com/antonagestam/collectfast
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_sentry == "y" %}
|
{%- if cookiecutter.use_sentry == "y" %}
|
||||||
sentry-sdk==0.14.1 # https://github.com/getsentry/sentry-python
|
sentry-sdk==0.14.2 # https://github.com/getsentry/sentry-python
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.models import User
|
from {{ cookiecutter.project_slug }}.users.models import User
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.mixins import RetrieveModelMixin, ListModelMixin, UpdateModelMixin
|
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import GenericViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from django.contrib.auth import get_user_model, forms
|
from django.contrib.auth import forms, get_user_model
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
from celery.result import EagerResult
|
from celery.result import EagerResult
|
||||||
|
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.tasks import get_users_count
|
from {{ cookiecutter.project_slug }}.users.tasks import get_users_count
|
||||||
from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory
|
from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from django.urls import reverse, resolve
|
from django.urls import resolve, reverse
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.models import User
|
from {{ cookiecutter.project_slug }}.users.models import User
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.views import (
|
from {{ cookiecutter.project_slug }}.users.views import (
|
||||||
|
user_detail_view,
|
||||||
user_redirect_view,
|
user_redirect_view,
|
||||||
user_update_view,
|
user_update_view,
|
||||||
user_detail_view,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = "users"
|
app_name = "users"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import DetailView, RedirectView, UpdateView
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.views.generic import DetailView, RedirectView, UpdateView
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user