From 9661ecaf8feb7c9a615199f044f8d469df2c3340 Mon Sep 17 00:00:00 2001 From: Sander van Leeuwen Date: Wed, 25 Oct 2017 14:11:36 +0200 Subject: [PATCH 01/28] Remove boto related settings that aren't used Since upgrade to boto3 in commit 12db5176d6c4c we don't need AWS_HEADERS anymore --- .../config/settings/production.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py index cc518644a..b332c776f 100644 --- a/{{cookiecutter.project_slug}}/config/settings/production.py +++ b/{{cookiecutter.project_slug}}/config/settings/production.py @@ -100,17 +100,6 @@ AWS_STORAGE_BUCKET_NAME = env('DJANGO_AWS_STORAGE_BUCKET_NAME') AWS_AUTO_CREATE_BUCKET = True AWS_QUERYSTRING_AUTH = False -# AWS cache settings, don't change unless you know what you're doing: -AWS_EXPIRY = 60 * 60 * 24 * 7 - -# TODO See: https://github.com/jschneier/django-storages/issues/47 -# Revert the following and use str after the above-mentioned bug is fixed in -# either django-storage-redux or boto -control = 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY) -AWS_HEADERS = { - 'Cache-Control': bytes(control, encoding='latin-1') -} - # URL that handles the media served from MEDIA_ROOT, used for managing # stored files. {% if cookiecutter.use_whitenoise == 'y' -%} From 8bfe18b52ad1a48abe5ae0346b19a96a596aec64 Mon Sep 17 00:00:00 2001 From: Dayson Pais Date: Sat, 30 Dec 2017 12:16:19 +0530 Subject: [PATCH 02/28] Update django from 1.11.8 to 2.0 - Refactor django.core.urlresolvers module import to django.urls. Resolves: The django.core.urlresolvers module is removed in favor of its new location, django.urls. - Add an app namespace to urls in user app. Resolves: Support for setting a URL instance namespace without an application namespace is removed. --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- .../{{cookiecutter.project_slug}}/users/models.py | 2 +- .../{{cookiecutter.project_slug}}/users/tests/test_urls.py | 2 +- .../{{cookiecutter.project_slug}}/users/urls.py | 1 + .../{{cookiecutter.project_slug}}/users/views.py | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 369d8464f..3eb0ae550 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -6,7 +6,7 @@ wheel==0.30.0 # Conservative Django -django==1.11.8 # pyup: <2.0 +django==2.0 # pyup: <2.0 # Configuration django-environ==0.4.4 diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py index c06f15da4..915823658 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py @@ -1,5 +1,5 @@ from django.contrib.auth.models import AbstractUser -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py index 6e181cc8e..4935b0f3e 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_urls.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import reverse, resolve +from django.urls import reverse, resolve from test_plus.test import TestCase diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py index 600ccfbdf..7c83fab98 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py @@ -2,6 +2,7 @@ from django.conf.urls import url from . import views +app_name = 'users' urlpatterns = [ url( regex=r'^$', diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py index 777f42b74..7fa94c231 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py @@ -1,4 +1,4 @@ -from django.core.urlresolvers import reverse +from django.urls import reverse from django.views.generic import DetailView, ListView, RedirectView, UpdateView from django.contrib.auth.mixins import LoginRequiredMixin From 9ca98e02d48bbf81d5b67904702aef1c04ea7d48 Mon Sep 17 00:00:00 2001 From: Dayson Pais Date: Thu, 25 Jan 2018 10:36:06 +0100 Subject: [PATCH 03/28] Update base.txt --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 3eb0ae550..eff485865 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -6,7 +6,7 @@ wheel==0.30.0 # Conservative Django -django==2.0 # pyup: <2.0 +django==2.0 # Configuration django-environ==0.4.4 From d4420e3dd663fcaf2e0813008977aebfe7b6b0ae Mon Sep 17 00:00:00 2001 From: Dayson Pais Date: Mon, 5 Feb 2018 10:23:10 +0000 Subject: [PATCH 04/28] Update base.txt --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index eff485865..b7de59750 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -6,7 +6,7 @@ wheel==0.30.0 # Conservative Django -django==2.0 +django==2.0 # pyup: < 2.1 # Configuration django-environ==0.4.4 From d133026968aca97d39000295433642d8a30de91a Mon Sep 17 00:00:00 2001 From: Dayson Pais Date: Mon, 5 Feb 2018 23:29:36 +0000 Subject: [PATCH 05/28] Update 0001_initial.py Increase max length of User.last_name to 150 characters. --- .../users/migrations/0001_initial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py index b2cfca39f..7cc96f62c 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py @@ -22,7 +22,7 @@ class Migration(migrations.Migration): ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), From 86e33e8714c92a85a1c7dbba4b47ced4f36756a9 Mon Sep 17 00:00:00 2001 From: Nikita Shupeyko Date: Wed, 7 Feb 2018 22:52:52 +0300 Subject: [PATCH 06/28] Refactor *_gen_project hooks (#1490) * Fix ./hooks/pre_gen_project.py asking user to select an option once only + prettify output * Fix pre_gen hook not really exiting when it should * Refactor & prettify ./hooks/post_gen_project.py * Ensure same POSTGRES_USER is set across environments + get rid of env.example in favor of pre-generated .env. --- docs/settings.rst | 2 +- hooks/post_gen_project.py | 435 ++++++++++-------- hooks/pre_gen_project.py | 74 ++- .../config/settings/local.py | 2 +- .../config/settings/test.py | 2 +- {{cookiecutter.project_slug}}/env.example | 6 +- {{cookiecutter.project_slug}}/local.yml | 4 +- 7 files changed, 301 insertions(+), 224 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 8b4ad4053..20bf9e5e1 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -22,7 +22,7 @@ DJANGO_ADMIN_URL n/a r'^admin/' DJANGO_CACHES CACHES (default) locmem redis DJANGO_DATABASES DATABASES (default) See code See code DJANGO_DEBUG DEBUG True False -DJANGO_SECRET_KEY SECRET_KEY CHANGEME!!! raises error +DJANGO_SECRET_KEY SECRET_KEY !!!SET DJANGO_SECRET_KEY!!! raises error DJANGO_SECURE_BROWSER_XSS_FILTER SECURE_BROWSER_XSS_FILTER n/a True DJANGO_SECURE_SSL_REDIRECT SECURE_SSL_REDIRECT n/a True DJANGO_SECURE_CONTENT_TYPE_NOSNIFF SECURE_CONTENT_TYPE_NOSNIFF n/a True diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 9a6da7b67..0e16ffb70 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,238 +1,283 @@ """ -Does the following: +NOTE: + the below code is to be maintained Python 2.x-compatible + as the whole Cookiecutter Django project initialization + can potentially be run in Python 2.x environment + (at least so we presume in `pre_gen_project.py`). -1. Generates and saves random secret key -2. Removes the taskapp if celery isn't going to be used -3. Removes the .idea directory if PyCharm isn't going to be used -4. Copy files from /docs/ to {{ cookiecutter.project_slug }}/docs/ - - TODO: this might have to be moved to a pre_gen_hook - -A portion of this code was adopted from Django's standard crypto functions and -utilities, specifically: - https://github.com/django/django/blob/master/django/utils/crypto.py +TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only """ -from __future__ import print_function + import os import random import shutil import string +import sys -# Get the root project directory -PROJECT_DIRECTORY = os.path.realpath(os.path.curdir) - -# Use the system PRNG if possible try: + # Inspired by + # https://github.com/django/django/blob/master/django/utils/crypto.py random = random.SystemRandom() using_sysrandom = True except NotImplementedError: using_sysrandom = False - -def get_random_string(length=50): - """ - Returns a securely generated random string. - The default length of 12 with the a-z, A-Z, 0-9 character set returns - a 71-bit value. log_2((26+26+10)^12) =~ 71 bits - """ - punctuation = string.punctuation.replace('"', '').replace("'", '') - punctuation = punctuation.replace('\\', '') - if using_sysrandom: - return ''.join(random.choice( - string.digits + string.ascii_letters + punctuation - ) for i in range(length)) - - print( - "Cookiecutter Django couldn't find a secure pseudo-random number generator on your system." - " Please change change your SECRET_KEY variables in conf/settings/local.py and env.example" - " manually." - ) - return "CHANGEME!!" +PROJECT_DIR_PATH = os.path.realpath(os.path.curdir) -def set_secret_key(setting_file_location): - # Open locals.py - with open(setting_file_location) as f: - file_ = f.read() - - # Generate a SECRET_KEY that matches the Django standard - SECRET_KEY = get_random_string() - - # Replace "CHANGEME!!!" with SECRET_KEY - file_ = file_.replace('CHANGEME!!!', SECRET_KEY, 1) - - # Write the results to the locals.py module - with open(setting_file_location, 'w') as f: - f.write(file_) +def remove_file(file_path): + if os.path.exists(file_path): + os.remove(file_path) -def make_secret_key(project_directory): - """Generates and saves random secret key""" - # Determine the local_setting_file_location - local_setting = os.path.join( - project_directory, - 'config/settings/local.py' - ) - - # local.py settings file - set_secret_key(local_setting) - - env_file = os.path.join( - project_directory, - 'env.example' - ) - - # env.example file - set_secret_key(env_file) +def remove_open_source_project_only_files(): + file_names = [ + 'CONTRIBUTORS.txt', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) -def remove_file(file_name): - if os.path.exists(file_name): - os.remove(file_name) +def remove_gplv3_files(): + file_names = [ + 'COPYING', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) -def remove_task_app(project_directory): - """Removes the taskapp if celery isn't going to be used""" - # Determine the local_setting_file_location - task_app_location = os.path.join( - PROJECT_DIRECTORY, - '{{ cookiecutter.project_slug }}/taskapp' - ) - shutil.rmtree(task_app_location) +def remove_pycharm_files(): + idea_dir_path = os.path.join(PROJECT_DIR_PATH, '.idea') + if os.path.exists(idea_dir_path): + shutil.rmtree(idea_dir_path) - -def remove_pycharm_dir(project_directory): - """ - Removes directories related to PyCharm - if it isn't going to be used - """ - idea_dir_location = os.path.join(PROJECT_DIRECTORY, '.idea/') - if os.path.exists(idea_dir_location): - shutil.rmtree(idea_dir_location) - - docs_dir_location = os.path.join(PROJECT_DIRECTORY, 'docs/pycharm/') - if os.path.exists(docs_dir_location): - shutil.rmtree(docs_dir_location) - - -def remove_heroku_files(): - """ - Removes files needed for heroku if it isn't going to be used - """ - filenames = ["Procfile", "runtime.txt"] - for filename in ["Procfile", "runtime.txt"]: - file_name = os.path.join(PROJECT_DIRECTORY, filename) - remove_file(file_name) + docs_dir_path = os.path.join(PROJECT_DIR_PATH, 'docs', 'pycharm') + if os.path.exists(docs_dir_path): + shutil.rmtree(docs_dir_path) def remove_docker_files(): - """ - Removes files needed for docker if it isn't going to be used - """ - for filename in ["local.yml", "production.yml", ".dockerignore"]: - filename = os.path.join(PROJECT_DIRECTORY, filename) - if os.path.exists(filename): - os.remove(filename) + shutil.rmtree(os.path.join(PROJECT_DIR_PATH, 'compose')) - shutil.rmtree(os.path.join( - PROJECT_DIRECTORY, "compose" - )) + file_names = [ + 'local.yml', + 'production.yml', + '.dockerignore', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) + + +def remove_heroku_files(): + file_names = [ + 'Procfile', + 'runtime.txt', + ] + for file_name in file_names: + remove_file(os.path.join(PROJECT_DIR_PATH, file_name)) + + +def remove_paas_files(): + none_paas_files_left = True + + if '{{ cookiecutter.use_heroku }}'.lower() == 'n': + remove_heroku_files() + none_paas_files_left &= True + else: + none_paas_files_left &= False + + if none_paas_files_left: + remove_file(os.path.join(PROJECT_DIR_PATH, 'requirements.txt')) def remove_grunt_files(): - """ - Removes files needed for grunt if it isn't going to be used - """ - for filename in ["Gruntfile.js"]: - os.remove(os.path.join( - PROJECT_DIRECTORY, filename - )) + file_names = [ + 'Gruntfile.js', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) + def remove_gulp_files(): + file_names = [ + 'gulpfile.js', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) + + +def remove_packagejson_file(): + file_names = [ + 'package.json', + ] + for file_name in file_names: + os.remove(os.path.join(PROJECT_DIR_PATH, file_name)) + + +def remove_celery_app(): + shutil.rmtree(os.path.join(PROJECT_DIR_PATH, '{{ cookiecutter.project_slug }}', 'taskapp')) + + +def append_to_project_gitignore(path): + gitignore_file_path = os.path.join(PROJECT_DIR_PATH, '.gitignore') + with open(gitignore_file_path, 'a') as gitignore_file: + gitignore_file.write(path) + gitignore_file.write(os.linesep) + + +def generate_random_string(length, + using_digits=False, + using_ascii_letters=False, + using_punctuation=False): """ - Removes files needed for grunt if it isn't going to be used + Example: + opting out for 50 symbol-long, [a-z][A-Z][0-9] string + would yield log_2((26+26+50)^50) ~= 334 bit strength. """ - for filename in ["gulpfile.js"]: - os.remove(os.path.join( - PROJECT_DIRECTORY, filename - )) + if not using_sysrandom: + return None -def remove_packageJSON_file(): - """ - Removes files needed for grunt if it isn't going to be used - """ - for filename in ["package.json"]: - os.remove(os.path.join( - PROJECT_DIRECTORY, filename - )) - -def remove_copying_files(): - """ - Removes files needed for the GPLv3 licence if it isn't going to be used - """ - for filename in ["COPYING"]: - os.remove(os.path.join( - PROJECT_DIRECTORY, filename - )) + symbols = [] + if using_digits: + symbols += string.digits + if using_ascii_letters: + symbols += string.ascii_letters + if using_punctuation: + symbols += string.punctuation \ + .replace('"', '') \ + .replace("'", '') \ + .replace('\\', '') + return ''.join([random.choice(symbols) for _ in range(length)]) -# IN PROGRESS -# def copy_doc_files(project_directory): -# cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir'] -# cookiecutter_django_dir = os.path.join( -# cookiecutters_dir, -# 'cookiecutter-django', -# 'docs' -# ) -# target_dir = os.path.join( -# project_directory, -# 'docs' -# ) -# for name in os.listdir(cookiecutter_django_dir): -# if name.endswith('.rst') and not name.startswith('index'): -# src = os.path.join(cookiecutter_django_dir, name) -# dst = os.path.join(target_dir, name) -# shutil.copyfile(src, dst) +def set_flag(file_path, + flag, + value=None, + *args, + **kwargs): + if value is None: + random_string = generate_random_string(*args, **kwargs) + if random_string is None: + import sys + sys.stdout.write( + "We couldn't find a secure pseudo-random number generator on your system. " + "Please, make sure to manually {} later.".format(flag) + ) + random_string = flag + value = random_string -# 1. Generates and saves random secret key -make_secret_key(PROJECT_DIRECTORY) + with open(file_path, 'r+') as f: + file_contents = f.read().replace(flag, value) + f.seek(0) + f.write(file_contents) + f.truncate() -# 2. Removes the taskapp if celery isn't going to be used -if '{{ cookiecutter.use_celery }}'.lower() == 'n': - remove_task_app(PROJECT_DIRECTORY) - -# 3. Removes the .idea directory if PyCharm isn't going to be used -if '{{ cookiecutter.use_pycharm }}'.lower() != 'y': - remove_pycharm_dir(PROJECT_DIRECTORY) - -# 4. Removes all heroku files if it isn't going to be used -if '{{ cookiecutter.use_heroku }}'.lower() != 'y': - remove_heroku_files() - -# 5. Removes all docker files if it isn't going to be used -if '{{ cookiecutter.use_docker }}'.lower() != 'y': - remove_docker_files() - -# 6. Removes all JS task manager files if it isn't going to be used -if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp': - remove_grunt_files() -elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt': - remove_gulp_files() -else: - remove_gulp_files() - remove_grunt_files() - remove_packageJSON_file() + return value -# 9. Display a warning if use_docker and use_grunt are selected. Grunt isn't -# supported by our docker config atm. -if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y': - print( - "You selected to use docker and a JS task runner. This is NOT supported out of the box for now. You " - "can continue to use the project like you normally would, but you will need to add a " - "js task runner service to your docker configuration manually." +def set_django_secret_key(file_path): + django_secret_key = set_flag( + file_path, + '!!!SET DJANGO_SECRET_KEY!!!', + length=50, + using_digits=True, + using_ascii_letters=True ) + return django_secret_key -# 10. Removes files needed for the GPLv3 licence if it isn't going to be used. -if '{{ cookiecutter.open_source_license}}' != 'GPLv3': - remove_copying_files() + +def set_postgres_user(file_path, + value=None): + postgres_user = set_flag( + file_path, + '!!!SET POSTGRES_USER!!!', + value=value, + length=8, + using_ascii_letters=True + ) + return postgres_user + + +def set_postgres_password(file_path): + postgres_password = set_flag( + file_path, + '!!!SET POSTGRES_PASSWORD!!!', + length=42, + using_digits=True, + using_ascii_letters=True + ) + return postgres_password + + +def initialize_dotenv(postgres_user): + # Initializing `env.example` first. + envexample_file_path = os.path.join(PROJECT_DIR_PATH, 'env.example') + set_django_secret_key(envexample_file_path) + set_postgres_user(envexample_file_path, value=postgres_user) + set_postgres_password(envexample_file_path) + # Renaming `env.example` to `.env`. + dotenv_file_path = os.path.join(PROJECT_DIR_PATH, '.env') + shutil.move(envexample_file_path, dotenv_file_path) + + +def initialize_localyml(postgres_user): + set_postgres_user(os.path.join(PROJECT_DIR_PATH, 'local.yml'), value=postgres_user) + + +def initialize_local_settings(): + set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'local.py')) + + +def initialize_test_settings(): + set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'test.py')) + + +def main(): + postgres_user = generate_random_string(length=16, using_ascii_letters=True) + initialize_dotenv(postgres_user) + initialize_localyml(postgres_user) + initialize_local_settings() + initialize_test_settings() + + if '{{ cookiecutter.open_source_license }}' == 'Not open source': + remove_open_source_project_only_files() + elif '{{ cookiecutter.open_source_license}}' != 'GPLv3': + remove_gplv3_files() + + if '{{ cookiecutter.use_pycharm }}'.lower() == 'n': + remove_pycharm_files() + + if '{{ cookiecutter.use_docker }}'.lower() == 'n': + remove_docker_files() + + remove_paas_files() + + if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp': + remove_grunt_files() + elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt': + remove_gulp_files() + else: + remove_gulp_files() + remove_grunt_files() + remove_packagejson_file() + + if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] \ + and '{{ cookiecutter.use_docker }}'.lower() == 'y': + TERMINATOR = "\x1b[0m" + INFO = "\x1b[1;33m [INFO]: " + sys.stdout.write( + INFO + + "Docker and {} JS task runner ".format('{{ cookiecutter.js_task_runner }}'.lower().capitalize()) + + "working together not supported yet. " + "You can continue using the generated project like you normally would, " + "however you would need to add a JS task runner service " + "to your Docker Compose configuration manually." + + TERMINATOR + ) + + if '{{ cookiecutter.use_celery }}'.lower() == 'n': + remove_celery_app() + + +if __name__ == '__main__': + main() diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 91367d9ff..a65fedae8 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -1,27 +1,59 @@ +""" +NOTE: + the below code is to be maintained Python 2.x-compatible + as the whole Cookiecutter Django project initialization + can potentially be run in Python 2.x environment. + +TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only +""" + project_slug = '{{ cookiecutter.project_slug }}' - if hasattr(project_slug, 'isidentifier'): - assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!' + assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug) -heroku = '{{ cookiecutter.use_heroku }}'.lower() -docker = '{{ cookiecutter.use_docker }}'.lower() +using_docker = '{{ cookiecutter.use_docker }}'.lower() +if using_docker == 'n': + TERMINATOR = "\x1b[0m" + WARNING = "\x1b[1;33m [WARNING]: " + INFO = "\x1b[1;33m [INFO]: " + HINT = "\x1b[3;33m" + SUCCESS = "\x1b[1;32m [SUCCESS]: " -if docker == 'n': - import sys + import sys - python_major_version = sys.version_info[0] + python_major_version = sys.version_info[0] + if python_major_version == 2: + sys.stdout.write( + WARNING + + "Cookiecutter Django does not support Python 2. " + "Stability is guaranteed with Python 3.6+ only, " + "are you sure you want to proceed (y/n)? " + + TERMINATOR + ) + yes_options, no_options = frozenset(['y']), frozenset(['n']) + while True: + choice = raw_input().lower() + if choice in yes_options: + break + elif choice in no_options: + sys.stdout.write( + INFO + + "Generation process stopped as requested." + + TERMINATOR + ) + sys.exit(1) + else: + sys.stdout.write( + HINT + + "Please respond with {} or {}: ".format( + ', '.join(["'{}'".format(o) for o in yes_options if not o == '']), + ', '.join(["'{}'".format(o) for o in no_options if not o == '']) + ) + + TERMINATOR + ) - if python_major_version == 2: - sys.stdout.write("WARNING: Cookiecutter Django does not support Python 2! Stability is guaranteed with Python 3.6+ only. Are you sure you want to proceed? (y/n)") - - yes_options = set(['y']) - no_options = set(['n', '']) - choice = raw_input().lower() - if choice in no_options: - sys.exit(1) - elif choice in yes_options: - pass - else: - sys.stdout.write("Please respond with %s or %s" - % (', '.join([o for o in yes_options if not o == '']) - , ', '.join([o for o in no_options if not o == '']))) + sys.stdout.write( + SUCCESS + + "Project initialized, keep up the good work!" + + TERMINATOR + ) diff --git a/{{cookiecutter.project_slug}}/config/settings/local.py b/{{cookiecutter.project_slug}}/config/settings/local.py index 67a7074a5..c903795c7 100644 --- a/{{cookiecutter.project_slug}}/config/settings/local.py +++ b/{{cookiecutter.project_slug}}/config/settings/local.py @@ -24,7 +24,7 @@ TEMPLATES[0]['OPTIONS']['debug'] = DEBUG # ------------------------------------------------------------------------------ # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # Note: This key only used for development and testing. -SECRET_KEY = env('DJANGO_SECRET_KEY', default='CHANGEME!!!') +SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!') # Mail settings # ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/config/settings/test.py b/{{cookiecutter.project_slug}}/config/settings/test.py index d973428d7..01a412791 100644 --- a/{{cookiecutter.project_slug}}/config/settings/test.py +++ b/{{cookiecutter.project_slug}}/config/settings/test.py @@ -17,7 +17,7 @@ TEMPLATES[0]['OPTIONS']['debug'] = False # ------------------------------------------------------------------------------ # See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # Note: This key only used for development and testing. -SECRET_KEY = env('DJANGO_SECRET_KEY', default='CHANGEME!!!') +SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!') # Mail settings # ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/env.example b/{{cookiecutter.project_slug}}/env.example index 420ab4a5f..1d28cb599 100644 --- a/{{cookiecutter.project_slug}}/env.example +++ b/{{cookiecutter.project_slug}}/env.example @@ -1,7 +1,7 @@ # PostgreSQL -POSTGRES_PASSWORD=mysecretpass -POSTGRES_USER=postgresuser +POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!! +POSTGRES_USER=!!!SET POSTGRES_USER!!! CONN_MAX_AGE= # Domain name, used by caddy @@ -11,7 +11,7 @@ DOMAIN_NAME={{ cookiecutter.domain_name }} # DJANGO_READ_DOT_ENV_FILE=True DJANGO_ADMIN_URL= DJANGO_SETTINGS_MODULE=config.settings.production -DJANGO_SECRET_KEY=CHANGEME!!! +DJANGO_SECRET_KEY=!!!SET DJANGO_SECRET_KEY!!! DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }} # AWS Settings diff --git a/{{cookiecutter.project_slug}}/local.yml b/{{cookiecutter.project_slug}}/local.yml index aaf131fa2..b030e6174 100644 --- a/{{cookiecutter.project_slug}}/local.yml +++ b/{{cookiecutter.project_slug}}/local.yml @@ -15,7 +15,7 @@ services: volumes: - .:/app environment: - - POSTGRES_USER={{cookiecutter.project_slug}} + - POSTGRES_USER=!!!SET POSTGRES_USER!!! - USE_DOCKER=yes ports: - "8000:8000" @@ -29,7 +29,7 @@ services: - postgres_data_local:/var/lib/postgresql/data - postgres_backup_local:/backups environment: - - POSTGRES_USER={{cookiecutter.project_slug}} + - POSTGRES_USER=!!!SET POSTGRES_USER!!! {% if cookiecutter.use_mailhog == 'y' %} mailhog: image: mailhog/mailhog:v1.0.0 From fb83d8d8bd8a05553ec45687e14c3b89bd91f1ae Mon Sep 17 00:00:00 2001 From: David Date: Wed, 7 Feb 2018 20:54:56 +0100 Subject: [PATCH 07/28] Add Debian 9 (Stretch) os dependencies (#1496) --- .../utility/requirements-stretch.apt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 {{cookiecutter.project_slug}}/utility/requirements-stretch.apt diff --git a/{{cookiecutter.project_slug}}/utility/requirements-stretch.apt b/{{cookiecutter.project_slug}}/utility/requirements-stretch.apt new file mode 100644 index 000000000..a2b3a7e5e --- /dev/null +++ b/{{cookiecutter.project_slug}}/utility/requirements-stretch.apt @@ -0,0 +1,23 @@ +##basic build dependencies of various Django apps for Debian Jessie 9.x +#build-essential metapackage install: make, gcc, g++, +build-essential +#required to translate +gettext +python3-dev + +##shared dependencies of: +##Pillow, pylibmc +zlib1g-dev + +##Postgresql and psycopg2 dependencies +libpq-dev + +##Pillow dependencies +libtiff5-dev +libjpeg62-turbo-dev +libfreetype6-dev +liblcms2-dev +libwebp-dev + +##django-extensions +graphviz-dev From 4a81b8577d94ea11918d6c4e732d476fa544fc2e Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 8 Feb 2018 21:45:45 +0100 Subject: [PATCH 08/28] Update django-anymail from 1.3 to 1.4 (#1498) --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 001937eb4..82620365c 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -24,7 +24,7 @@ Collectfast==0.6.0 # Email backends for Mailgun, Postmark, SendGrid and more # ------------------------------------------------------- -django-anymail==1.3 +django-anymail==1.4 {% if cookiecutter.use_sentry_for_error_reporting == "y" -%} # Raven is the Sentry client From 7271934268f28ac7296e161c54cc134c12d8dc58 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 8 Feb 2018 21:46:03 +0100 Subject: [PATCH 09/28] Update psycopg2 to 2.7.4 (#1497) * Update psycopg2 from 2.7.3.2 to 2.7.4 * Update psycopg2 from 2.7.3.2 to 2.7.4 * Update psycopg2 from 2.7.3.2 to 2.7.4 --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- {{cookiecutter.project_slug}}/requirements/test.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index b25951562..3d29fe16a 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -36,7 +36,7 @@ django-allauth==0.35.0 # from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg {% else %} # Python-PostgreSQL Database Adapter -psycopg2==2.7.3.2 +psycopg2==2.7.4 {%- endif %} # Unicode slugification diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 82620365c..64997ba75 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -6,7 +6,7 @@ # Python-PostgreSQL Database Adapter # Assuming Windows is used locally, and *nix -- in production. # ------------------------------------------------------------ -psycopg2==2.7.3.2 +psycopg2==2.7.4 {%- endif %} # WSGI Handler diff --git a/{{cookiecutter.project_slug}}/requirements/test.txt b/{{cookiecutter.project_slug}}/requirements/test.txt index 5980a30ef..8e8969c73 100644 --- a/{{cookiecutter.project_slug}}/requirements/test.txt +++ b/{{cookiecutter.project_slug}}/requirements/test.txt @@ -4,7 +4,7 @@ {% if cookiecutter.windows == 'y' -%} # Python-PostgreSQL Database Adapter # If using Win for dev, this assumes Unix in test/prod -psycopg2==2.7.3.2 +psycopg2==2.7.4 {%- endif %} coverage==4.5 From dd756e432dc35fa5b0157466b9ead6a6f5240065 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Thu, 8 Feb 2018 15:26:11 -0800 Subject: [PATCH 10/28] Update boto3 from 1.5.24 to 1.5.25 --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 64997ba75..952ba4bd0 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -16,7 +16,7 @@ gunicorn==19.7.1 # Static and Media Storage # ------------------------------------------------ -boto3==1.5.24 +boto3==1.5.25 django-storages==1.6.5 {% if cookiecutter.use_whitenoise != 'y' -%} Collectfast==0.6.0 From 8941e4a81d3c8428477cdf1a2350df711cb098f4 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Fri, 9 Feb 2018 02:46:23 -0800 Subject: [PATCH 11/28] Update pytz from 2017.3 to 2018.3 --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 3d29fe16a..56a44833d 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -43,7 +43,7 @@ psycopg2==2.7.4 awesome-slugify==1.6.5 # Time zones support -pytz==2017.3 +pytz==2018.3 # Redis support django-redis==4.8.0 From e7a47c6f9b823081b24a16f4c0cd2fcaf393f255 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sun, 11 Feb 2018 02:06:17 -0500 Subject: [PATCH 12/28] Update coverage from 4.5 to 4.5.1 --- {{cookiecutter.project_slug}}/requirements/local.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt index 63ec8a534..cfd0b99cf 100644 --- a/{{cookiecutter.project_slug}}/requirements/local.txt +++ b/{{cookiecutter.project_slug}}/requirements/local.txt @@ -1,7 +1,7 @@ # Local development dependencies go here -r base.txt -coverage==4.5 +coverage==4.5.1 django-coverage-plugin==1.5.0 Sphinx==1.6.7 From 7d291e886305a3510f431aed015d4b0df595d943 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sun, 11 Feb 2018 02:06:18 -0500 Subject: [PATCH 13/28] Update coverage from 4.5 to 4.5.1 --- {{cookiecutter.project_slug}}/requirements/test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/test.txt b/{{cookiecutter.project_slug}}/requirements/test.txt index 8e8969c73..2a6ed87fa 100644 --- a/{{cookiecutter.project_slug}}/requirements/test.txt +++ b/{{cookiecutter.project_slug}}/requirements/test.txt @@ -7,7 +7,7 @@ psycopg2==2.7.4 {%- endif %} -coverage==4.5 +coverage==4.5.1 flake8==3.5.0 # pyup: != 2.6.0 django-test-plus==1.0.22 factory-boy==2.10.0 From c0bcf3d22ec3f086d5c1b902598ea5e6fadc6b36 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 12 Feb 2018 11:00:24 -0500 Subject: [PATCH 14/28] Update sphinx from 1.6.7 to 1.7.0 --- {{cookiecutter.project_slug}}/requirements/local.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt index 63ec8a534..113d01cf0 100644 --- a/{{cookiecutter.project_slug}}/requirements/local.txt +++ b/{{cookiecutter.project_slug}}/requirements/local.txt @@ -4,7 +4,7 @@ coverage==4.5 django-coverage-plugin==1.5.0 -Sphinx==1.6.7 +Sphinx==1.7.0 django-extensions==1.9.9 Werkzeug==0.14.1 django-test-plus==1.0.22 From 26e35a5c79ef7faf1cab468577c9d1cb34aa8eda Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Mon, 12 Feb 2018 21:26:27 -0500 Subject: [PATCH 15/28] Update boto3 from 1.5.25 to 1.5.27 --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 952ba4bd0..3bc011b6d 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -16,7 +16,7 @@ gunicorn==19.7.1 # Static and Media Storage # ------------------------------------------------ -boto3==1.5.25 +boto3==1.5.27 django-storages==1.6.5 {% if cookiecutter.use_whitenoise != 'y' -%} Collectfast==0.6.0 From d783367a8644cbdaa05af2d35470ef16666f4f03 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Tue, 13 Feb 2018 14:37:40 +0000 Subject: [PATCH 16/28] Prevent pyup to Update Celery automatically --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 56a44833d..a568ab566 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -50,7 +50,7 @@ django-redis==4.8.0 redis>=2.10.5 {% if cookiecutter.use_celery == "y" %} -celery==3.1.25 +celery==3.1.25 # pyup: <4.0 {% endif %} {% if cookiecutter.use_compressor == "y" %} From bef1bb856e8434984ef4201b9ba28ee0936ce5c0 Mon Sep 17 00:00:00 2001 From: Sander van Leeuwen Date: Tue, 13 Feb 2018 16:04:43 +0100 Subject: [PATCH 17/28] Add cache control via AWS_S3_OBJECT_PARAMETERS setting Previously covered by AWS_HEADERS --- .../config/settings/production.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py index b332c776f..327398374 100644 --- a/{{cookiecutter.project_slug}}/config/settings/production.py +++ b/{{cookiecutter.project_slug}}/config/settings/production.py @@ -100,6 +100,17 @@ AWS_STORAGE_BUCKET_NAME = env('DJANGO_AWS_STORAGE_BUCKET_NAME') AWS_AUTO_CREATE_BUCKET = True AWS_QUERYSTRING_AUTH = False +# AWS cache settings, don't change unless you know what you're doing: +AWS_EXPIRY = 60 * 60 * 24 * 7 + +# TODO See: https://github.com/jschneier/django-storages/issues/47 +# Revert the following and use str after the above-mentioned bug is fixed in +# either django-storage-redux or boto +control = 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY) +AWS_S3_OBJECT_PARAMETERS = { + 'CacheControl': bytes(control, encoding='latin-1'), +} + # URL that handles the media served from MEDIA_ROOT, used for managing # stored files. {% if cookiecutter.use_whitenoise == 'y' -%} From e8ca2dd8ea6396b8a9714ad270d0d56c4e847d01 Mon Sep 17 00:00:00 2001 From: Hashim Muqtadir Date: Fri, 16 Feb 2018 20:15:50 +0500 Subject: [PATCH 18/28] Add atomic requests setting to production.py (#1513) Since config/production.py sets a new value for `DATABASES['default']`, the `DATABASES['default']['ATOMIC_REQUESTS'] = True` setting from base gets overridden. So it's probably a good idea to add it back. --- {{cookiecutter.project_slug}}/config/settings/production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py index 33542fbf9..cb0b8021b 100644 --- a/{{cookiecutter.project_slug}}/config/settings/production.py +++ b/{{cookiecutter.project_slug}}/config/settings/production.py @@ -177,7 +177,7 @@ TEMPLATES[0]['OPTIONS']['loaders'] = [ # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ DATABASES['default'] = env.db('DATABASE_URL') DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default={{ _DEFAULT_CONN_MAX_AGE }}) - +DATABASES['default']['ATOMIC_REQUESTS'] = True # CACHING # ------------------------------------------------------------------------------ From 07d7482dbe5a247d317c4033d0e15b6747a91609 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 16 Feb 2018 16:16:09 +0100 Subject: [PATCH 19/28] Update boto3 from 1.5.27 to 1.5.30 (#1512) --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 3bc011b6d..5b5a7d844 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -16,7 +16,7 @@ gunicorn==19.7.1 # Static and Media Storage # ------------------------------------------------ -boto3==1.5.27 +boto3==1.5.30 django-storages==1.6.5 {% if cookiecutter.use_whitenoise != 'y' -%} Collectfast==0.6.0 From 68ae00e028b27d080ece89b64e75ded6e55446fe Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 16 Feb 2018 16:16:23 +0100 Subject: [PATCH 20/28] Update ipdb from 0.10.3 to 0.11 (#1511) --- {{cookiecutter.project_slug}}/requirements/local.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt index e5624830d..697a40288 100644 --- a/{{cookiecutter.project_slug}}/requirements/local.txt +++ b/{{cookiecutter.project_slug}}/requirements/local.txt @@ -13,7 +13,7 @@ factory-boy==2.10.0 django-debug-toolbar==1.9.1 # improved REPL -ipdb==0.10.3 +ipdb==0.11 pytest-django==3.1.2 pytest-sugar==0.9.1 From 97f0ca6fa782c8d886a9a62327e2601873e48b53 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 16 Feb 2018 22:42:20 +0100 Subject: [PATCH 21/28] Update django from 2.0 to 2.0.2 (#1514) --- {{cookiecutter.project_slug}}/requirements/base.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index 9d57acd63..5bbeb5ec1 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -6,7 +6,7 @@ wheel==0.30.0 # Conservative Django -django==2.0 # pyup: < 2.1 +django==2.0.2 # pyup: < 2.1 # Configuration django-environ==0.4.4 From cbd44dc4b94fe327bd2ad77eb1066b0eacbf9ec3 Mon Sep 17 00:00:00 2001 From: jose Gabriel Guzman Lopez Date: Sun, 18 Feb 2018 11:20:15 -0500 Subject: [PATCH 22/28] Update README.rst (#1518) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 6536ab7ec..b1dbe10d7 100644 --- a/README.rst +++ b/README.rst @@ -38,7 +38,7 @@ production-ready Django projects quickly. Features --------- -* For Django 1.11 +* For Django 2.0 * Works with Python 3.6 * Renders Django projects with 100% starting test coverage * Twitter Bootstrap_ v4.0.0 - beta 1 (`maintained Foundation fork`_ also available) From 1452fe6ecd707a0ec72775b8a0ab4bb93039e286 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 18 Feb 2018 17:20:27 +0100 Subject: [PATCH 23/28] Update boto3 from 1.5.30 to 1.5.31 (#1517) --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 5b5a7d844..09151486d 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -16,7 +16,7 @@ gunicorn==19.7.1 # Static and Media Storage # ------------------------------------------------ -boto3==1.5.30 +boto3==1.5.31 django-storages==1.6.5 {% if cookiecutter.use_whitenoise != 'y' -%} Collectfast==0.6.0 From 30dfbbd0aba298066a709bee78f14a448108b45d Mon Sep 17 00:00:00 2001 From: Wan Liuyang Date: Tue, 20 Feb 2018 16:04:16 +0800 Subject: [PATCH 24/28] Remove AWS S3 header bytes workaround --- {{cookiecutter.project_slug}}/config/settings/production.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/{{cookiecutter.project_slug}}/config/settings/production.py b/{{cookiecutter.project_slug}}/config/settings/production.py index f6f857876..3926f3db1 100644 --- a/{{cookiecutter.project_slug}}/config/settings/production.py +++ b/{{cookiecutter.project_slug}}/config/settings/production.py @@ -103,12 +103,8 @@ AWS_QUERYSTRING_AUTH = False # AWS cache settings, don't change unless you know what you're doing: AWS_EXPIRY = 60 * 60 * 24 * 7 -# TODO See: https://github.com/jschneier/django-storages/issues/47 -# Revert the following and use str after the above-mentioned bug is fixed in -# either django-storage-redux or boto -control = 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY) AWS_S3_OBJECT_PARAMETERS = { - 'CacheControl': bytes(control, encoding='latin-1'), + 'CacheControl': 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY), } # URL that handles the media served from MEDIA_ROOT, used for managing From c7238238f8804a0eeeb5b5ed6e7177c85c20a109 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Fri, 16 Feb 2018 22:00:34 +0000 Subject: [PATCH 25/28] Update README, Changelog and setup.py after Django 2.0 upgrade --- CHANGELOG.md | 4 ++++ README.rst | 2 +- setup.py | 5 ++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24f8d11cc..304732b9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All enhancements and patches to Cookiecutter Django will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [2018-02-16] +### Changed +- Upgraded to Django 2.0 (@epicwhale) + ## [2018-01-15] ### Changed - Removed Elastic Beanstalk support (@pydanny) diff --git a/README.rst b/README.rst index b1dbe10d7..b856810f1 100644 --- a/README.rst +++ b/README.rst @@ -41,7 +41,7 @@ Features * For Django 2.0 * Works with Python 3.6 * Renders Django projects with 100% starting test coverage -* Twitter Bootstrap_ v4.0.0 - beta 1 (`maintained Foundation fork`_ also available) +* Twitter Bootstrap_ v4.0.0 (`maintained Foundation fork`_ also available) * 12-Factor_ based settings via django-environ_ * Secure by default. We believe in SSL. * Optimized development and production settings diff --git a/setup.py b/setup.py index 56306f92d..a7efb0a64 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ except ImportError: # Our version ALWAYS matches the version of Django we support # If Django has a new release, we branch, tag, then update this setting after the tag. -version = '1.11.9' +version = '2.0.2' if sys.argv[-1] == 'tag': os.system('git tag -a %s -m "version %s"' % (version, version)) @@ -34,7 +34,7 @@ setup( classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Console', - 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.0', 'Intended Audience :: Developers', 'Natural Language :: English', 'License :: OSI Approved :: BSD License', @@ -42,7 +42,6 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development', ], keywords=( From 76334c086ec71a522e0aa4b5091fd0bd7b7d0cf4 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Tue, 20 Feb 2018 18:26:40 -0500 Subject: [PATCH 26/28] Update boto3 from 1.5.31 to 1.5.33 --- {{cookiecutter.project_slug}}/requirements/production.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 09151486d..75450eb92 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -16,7 +16,7 @@ gunicorn==19.7.1 # Static and Media Storage # ------------------------------------------------ -boto3==1.5.31 +boto3==1.5.33 django-storages==1.6.5 {% if cookiecutter.use_whitenoise != 'y' -%} Collectfast==0.6.0 From 3cfafcf347f035fb330ca1b6f3639d3ba2b50643 Mon Sep 17 00:00:00 2001 From: Daniel Roy Greenfeld Date: Wed, 21 Feb 2018 18:43:29 -0500 Subject: [PATCH 27/28] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index b856810f1..939ad4a9a 100644 --- a/README.rst +++ b/README.rst @@ -111,7 +111,7 @@ Two Scoops of Django 1.11 :name: Two Scoops of Django 1.11 Cover :align: center :alt: Two Scoops of Django - :target: http://twoscoopspress.org/products/two-scoops-of-django-1-11 + :target: http://twoscoopspress.com/products/two-scoops-of-django-1-11 Two Scoops of Django is the best dessert-themed Django reference in the universe From f4cadeec97ef9f00652c27b7f8caff53e31e1ce9 Mon Sep 17 00:00:00 2001 From: Daniel Roy Greenfeld Date: Wed, 21 Feb 2018 18:54:03 -0500 Subject: [PATCH 28/28] Disallow backslashes in author name --- hooks/pre_gen_project.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index a65fedae8..c48ce0ad8 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -11,6 +11,9 @@ project_slug = '{{ cookiecutter.project_slug }}' if hasattr(project_slug, 'isidentifier'): assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug) +assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name." + + using_docker = '{{ cookiecutter.use_docker }}'.lower() if using_docker == 'n': TERMINATOR = "\x1b[0m"