mirror of
				https://github.com/cookiecutter/cookiecutter-django.git
				synced 2025-11-04 09:57:30 +03:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									090c81731b
								
							
						
					
					
						commit
						86e33e8714
					
				| 
						 | 
					@ -22,7 +22,7 @@ DJANGO_ADMIN_URL                        n/a                         r'^admin/'
 | 
				
			||||||
DJANGO_CACHES                           CACHES (default)            locmem                                         redis
 | 
					DJANGO_CACHES                           CACHES (default)            locmem                                         redis
 | 
				
			||||||
DJANGO_DATABASES                        DATABASES (default)         See code                                       See code
 | 
					DJANGO_DATABASES                        DATABASES (default)         See code                                       See code
 | 
				
			||||||
DJANGO_DEBUG                            DEBUG                       True                                           False
 | 
					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_BROWSER_XSS_FILTER        SECURE_BROWSER_XSS_FILTER   n/a                                            True
 | 
				
			||||||
DJANGO_SECURE_SSL_REDIRECT              SECURE_SSL_REDIRECT         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
 | 
					DJANGO_SECURE_CONTENT_TYPE_NOSNIFF      SECURE_CONTENT_TYPE_NOSNIFF n/a                                            True
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only
 | 
				
			||||||
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
 | 
					 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
from __future__ import print_function
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import random
 | 
					import random
 | 
				
			||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
import string
 | 
					import string
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Get the root project directory
 | 
					 | 
				
			||||||
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Use the system PRNG if possible
 | 
					 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
 | 
					    # Inspired by
 | 
				
			||||||
 | 
					    # https://github.com/django/django/blob/master/django/utils/crypto.py
 | 
				
			||||||
    random = random.SystemRandom()
 | 
					    random = random.SystemRandom()
 | 
				
			||||||
    using_sysrandom = True
 | 
					    using_sysrandom = True
 | 
				
			||||||
except NotImplementedError:
 | 
					except NotImplementedError:
 | 
				
			||||||
    using_sysrandom = False
 | 
					    using_sysrandom = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PROJECT_DIR_PATH = os.path.realpath(os.path.curdir)
 | 
				
			||||||
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!!"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def set_secret_key(setting_file_location):
 | 
					def remove_file(file_path):
 | 
				
			||||||
    # Open locals.py
 | 
					    if os.path.exists(file_path):
 | 
				
			||||||
    with open(setting_file_location) as f:
 | 
					        os.remove(file_path)
 | 
				
			||||||
        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 make_secret_key(project_directory):
 | 
					def remove_open_source_project_only_files():
 | 
				
			||||||
    """Generates and saves random secret key"""
 | 
					    file_names = [
 | 
				
			||||||
    # Determine the local_setting_file_location
 | 
					        'CONTRIBUTORS.txt',
 | 
				
			||||||
    local_setting = os.path.join(
 | 
					    ]
 | 
				
			||||||
        project_directory,
 | 
					    for file_name in file_names:
 | 
				
			||||||
        'config/settings/local.py'
 | 
					        os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # 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_file(file_name):
 | 
					def remove_gplv3_files():
 | 
				
			||||||
    if os.path.exists(file_name):
 | 
					    file_names = [
 | 
				
			||||||
        os.remove(file_name)
 | 
					        'COPYING',
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    for file_name in file_names:
 | 
				
			||||||
 | 
					        os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def remove_task_app(project_directory):
 | 
					def remove_pycharm_files():
 | 
				
			||||||
    """Removes the taskapp if celery isn't going to be used"""
 | 
					    idea_dir_path = os.path.join(PROJECT_DIR_PATH, '.idea')
 | 
				
			||||||
    # Determine the local_setting_file_location
 | 
					    if os.path.exists(idea_dir_path):
 | 
				
			||||||
    task_app_location = os.path.join(
 | 
					        shutil.rmtree(idea_dir_path)
 | 
				
			||||||
        PROJECT_DIRECTORY,
 | 
					 | 
				
			||||||
        '{{ cookiecutter.project_slug }}/taskapp'
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    shutil.rmtree(task_app_location)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    docs_dir_path = os.path.join(PROJECT_DIR_PATH, 'docs', 'pycharm')
 | 
				
			||||||
def remove_pycharm_dir(project_directory):
 | 
					    if os.path.exists(docs_dir_path):
 | 
				
			||||||
    """
 | 
					        shutil.rmtree(docs_dir_path)
 | 
				
			||||||
    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)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def remove_docker_files():
 | 
					def remove_docker_files():
 | 
				
			||||||
    """
 | 
					    shutil.rmtree(os.path.join(PROJECT_DIR_PATH, 'compose'))
 | 
				
			||||||
    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(
 | 
					    file_names = [
 | 
				
			||||||
        PROJECT_DIRECTORY, "compose"
 | 
					        '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():
 | 
					def remove_grunt_files():
 | 
				
			||||||
    """
 | 
					    file_names = [
 | 
				
			||||||
    Removes files needed for grunt if it isn't going to be used
 | 
					        'Gruntfile.js',
 | 
				
			||||||
    """
 | 
					    ]
 | 
				
			||||||
    for filename in ["Gruntfile.js"]:
 | 
					    for file_name in file_names:
 | 
				
			||||||
        os.remove(os.path.join(
 | 
					        os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
 | 
				
			||||||
            PROJECT_DIRECTORY, filename
 | 
					
 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def remove_gulp_files():
 | 
					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"]:
 | 
					    if not using_sysrandom:
 | 
				
			||||||
        os.remove(os.path.join(
 | 
					        return None
 | 
				
			||||||
            PROJECT_DIRECTORY, filename
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def remove_packageJSON_file():
 | 
					    symbols = []
 | 
				
			||||||
    """
 | 
					    if using_digits:
 | 
				
			||||||
    Removes files needed for grunt if it isn't going to be used
 | 
					        symbols += string.digits
 | 
				
			||||||
    """
 | 
					    if using_ascii_letters:
 | 
				
			||||||
    for filename in ["package.json"]:
 | 
					        symbols += string.ascii_letters
 | 
				
			||||||
        os.remove(os.path.join(
 | 
					    if using_punctuation:
 | 
				
			||||||
            PROJECT_DIRECTORY, filename
 | 
					        symbols += string.punctuation \
 | 
				
			||||||
        ))
 | 
					            .replace('"', '') \
 | 
				
			||||||
 | 
					            .replace("'", '') \
 | 
				
			||||||
def remove_copying_files():
 | 
					            .replace('\\', '')
 | 
				
			||||||
    """
 | 
					    return ''.join([random.choice(symbols) for _ in range(length)])
 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# IN PROGRESS
 | 
					def set_flag(file_path,
 | 
				
			||||||
# def copy_doc_files(project_directory):
 | 
					             flag,
 | 
				
			||||||
#     cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
 | 
					             value=None,
 | 
				
			||||||
#     cookiecutter_django_dir = os.path.join(
 | 
					             *args,
 | 
				
			||||||
#         cookiecutters_dir,
 | 
					             **kwargs):
 | 
				
			||||||
#         'cookiecutter-django',
 | 
					    if value is None:
 | 
				
			||||||
#         'docs'
 | 
					        random_string = generate_random_string(*args, **kwargs)
 | 
				
			||||||
#     )
 | 
					        if random_string is None:
 | 
				
			||||||
#     target_dir = os.path.join(
 | 
					            import sys
 | 
				
			||||||
#         project_directory,
 | 
					            sys.stdout.write(
 | 
				
			||||||
#         'docs'
 | 
					                "We couldn't find a secure pseudo-random number generator on your system. "
 | 
				
			||||||
#     )
 | 
					                "Please, make sure to manually {} later.".format(flag)
 | 
				
			||||||
#     for name in os.listdir(cookiecutter_django_dir):
 | 
					            )
 | 
				
			||||||
#         if name.endswith('.rst') and not name.startswith('index'):
 | 
					            random_string = flag
 | 
				
			||||||
#             src = os.path.join(cookiecutter_django_dir, name)
 | 
					        value = random_string
 | 
				
			||||||
#             dst = os.path.join(target_dir, name)
 | 
					 | 
				
			||||||
#             shutil.copyfile(src, dst)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 1. Generates and saves random secret key
 | 
					    with open(file_path, 'r+') as f:
 | 
				
			||||||
make_secret_key(PROJECT_DIRECTORY)
 | 
					        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
 | 
					    return value
 | 
				
			||||||
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()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 9. Display a warning if use_docker and use_grunt are selected. Grunt isn't
 | 
					def set_django_secret_key(file_path):
 | 
				
			||||||
#   supported by our docker config atm.
 | 
					    django_secret_key = set_flag(
 | 
				
			||||||
if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y':
 | 
					        file_path,
 | 
				
			||||||
    print(
 | 
					        '!!!SET DJANGO_SECRET_KEY!!!',
 | 
				
			||||||
        "You selected to use docker and a JS task runner. This is NOT supported out of the box for now. You "
 | 
					        length=50,
 | 
				
			||||||
        "can continue to use the project like you normally would, but you will need to add a "
 | 
					        using_digits=True,
 | 
				
			||||||
        "js task runner service to your docker configuration manually."
 | 
					        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':
 | 
					def set_postgres_user(file_path,
 | 
				
			||||||
    remove_copying_files()
 | 
					                      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()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 }}'
 | 
					project_slug = '{{ cookiecutter.project_slug }}'
 | 
				
			||||||
 | 
					 | 
				
			||||||
if hasattr(project_slug, 'isidentifier'):
 | 
					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()
 | 
					using_docker = '{{ cookiecutter.use_docker }}'.lower()
 | 
				
			||||||
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(
 | 
				
			||||||
		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)")
 | 
					        SUCCESS +
 | 
				
			||||||
 | 
					        "Project initialized, keep up the good work!" +
 | 
				
			||||||
		yes_options = set(['y'])
 | 
					        TERMINATOR
 | 
				
			||||||
		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 == ''])))
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
 | 
				
			||||||
# Note: This key only used for development and testing.
 | 
					# 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
 | 
					# Mail settings
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ TEMPLATES[0]['OPTIONS']['debug'] = False
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
 | 
					# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
 | 
				
			||||||
# Note: This key only used for development and testing.
 | 
					# 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
 | 
					# Mail settings
 | 
				
			||||||
# ------------------------------------------------------------------------------
 | 
					# ------------------------------------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# PostgreSQL
 | 
					# PostgreSQL
 | 
				
			||||||
POSTGRES_PASSWORD=mysecretpass
 | 
					POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!!
 | 
				
			||||||
POSTGRES_USER=postgresuser
 | 
					POSTGRES_USER=!!!SET POSTGRES_USER!!!
 | 
				
			||||||
CONN_MAX_AGE=
 | 
					CONN_MAX_AGE=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Domain name, used by caddy
 | 
					# Domain name, used by caddy
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ DOMAIN_NAME={{ cookiecutter.domain_name }}
 | 
				
			||||||
# DJANGO_READ_DOT_ENV_FILE=True
 | 
					# DJANGO_READ_DOT_ENV_FILE=True
 | 
				
			||||||
DJANGO_ADMIN_URL=
 | 
					DJANGO_ADMIN_URL=
 | 
				
			||||||
DJANGO_SETTINGS_MODULE=config.settings.production
 | 
					DJANGO_SETTINGS_MODULE=config.settings.production
 | 
				
			||||||
DJANGO_SECRET_KEY=CHANGEME!!!
 | 
					DJANGO_SECRET_KEY=!!!SET DJANGO_SECRET_KEY!!!
 | 
				
			||||||
DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}
 | 
					DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# AWS Settings
 | 
					# AWS Settings
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ services:
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - .:/app
 | 
					      - .:/app
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      - POSTGRES_USER={{cookiecutter.project_slug}}
 | 
					      - POSTGRES_USER=!!!SET POSTGRES_USER!!!
 | 
				
			||||||
      - USE_DOCKER=yes
 | 
					      - USE_DOCKER=yes
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "8000:8000"
 | 
					      - "8000:8000"
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ services:
 | 
				
			||||||
      - postgres_data_local:/var/lib/postgresql/data
 | 
					      - postgres_data_local:/var/lib/postgresql/data
 | 
				
			||||||
      - postgres_backup_local:/backups
 | 
					      - postgres_backup_local:/backups
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      - POSTGRES_USER={{cookiecutter.project_slug}}
 | 
					      - POSTGRES_USER=!!!SET POSTGRES_USER!!!
 | 
				
			||||||
{% if cookiecutter.use_mailhog == 'y' %}
 | 
					{% if cookiecutter.use_mailhog == 'y' %}
 | 
				
			||||||
  mailhog:
 | 
					  mailhog:
 | 
				
			||||||
    image: mailhog/mailhog:v1.0.0
 | 
					    image: mailhog/mailhog:v1.0.0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user