2015-09-10 03:56:27 +03:00
|
|
|
"""
|
2018-02-07 22:52:52 +03:00
|
|
|
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`).
|
2015-09-15 04:55:41 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only
|
2015-09-10 03:56:27 +03:00
|
|
|
"""
|
2018-02-07 22:52:52 +03:00
|
|
|
|
2015-09-10 03:56:27 +03:00
|
|
|
import os
|
|
|
|
import random
|
|
|
|
import shutil
|
2017-02-14 02:37:14 +03:00
|
|
|
import string
|
2018-02-07 22:52:52 +03:00
|
|
|
import sys
|
2015-09-10 03:56:27 +03:00
|
|
|
|
|
|
|
try:
|
2018-02-07 22:52:52 +03:00
|
|
|
# Inspired by
|
|
|
|
# https://github.com/django/django/blob/master/django/utils/crypto.py
|
2015-09-10 03:56:27 +03:00
|
|
|
random = random.SystemRandom()
|
|
|
|
using_sysrandom = True
|
|
|
|
except NotImplementedError:
|
|
|
|
using_sysrandom = False
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
PROJECT_DIR_PATH = os.path.realpath(os.path.curdir)
|
2016-04-08 10:45:09 +03:00
|
|
|
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_file(file_path):
|
|
|
|
if os.path.exists(file_path):
|
|
|
|
os.remove(file_path)
|
2015-09-10 03:56:27 +03:00
|
|
|
|
2015-10-15 19:29:43 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
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))
|
2015-10-15 19:29:43 +03:00
|
|
|
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_gplv3_files():
|
|
|
|
file_names = [
|
|
|
|
'COPYING',
|
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
2015-10-15 19:29:43 +03:00
|
|
|
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
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)
|
2015-09-15 04:55:41 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
docs_dir_path = os.path.join(PROJECT_DIR_PATH, 'docs', 'pycharm')
|
|
|
|
if os.path.exists(docs_dir_path):
|
|
|
|
shutil.rmtree(docs_dir_path)
|
2015-09-15 04:55:41 +03:00
|
|
|
|
2015-10-15 19:29:43 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_docker_files():
|
|
|
|
shutil.rmtree(os.path.join(PROJECT_DIR_PATH, 'compose'))
|
2015-09-10 03:56:27 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
file_names = [
|
|
|
|
'local.yml',
|
|
|
|
'production.yml',
|
|
|
|
'.dockerignore',
|
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
2015-09-10 03:56:27 +03:00
|
|
|
|
2016-06-06 00:16:02 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_heroku_files():
|
|
|
|
file_names = [
|
|
|
|
'Procfile',
|
|
|
|
'runtime.txt',
|
2018-03-04 14:43:54 +03:00
|
|
|
'requirements.txt',
|
2018-02-07 22:52:52 +03:00
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
remove_file(os.path.join(PROJECT_DIR_PATH, file_name))
|
2016-06-06 00:16:02 +03:00
|
|
|
|
2015-09-10 03:56:27 +03:00
|
|
|
|
2018-03-04 14:44:37 +03:00
|
|
|
def remove_dotenv_file():
|
|
|
|
remove_file(os.path.join(PROJECT_DIR_PATH, '.env'))
|
2016-03-23 20:51:25 +03:00
|
|
|
|
2016-04-08 10:45:09 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_grunt_files():
|
|
|
|
file_names = [
|
|
|
|
'Gruntfile.js',
|
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
2016-04-08 10:45:09 +03:00
|
|
|
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_gulp_files():
|
|
|
|
file_names = [
|
|
|
|
'gulpfile.js',
|
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
2016-04-08 10:45:09 +03:00
|
|
|
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def remove_packagejson_file():
|
|
|
|
file_names = [
|
|
|
|
'package.json',
|
|
|
|
]
|
|
|
|
for file_name in file_names:
|
|
|
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
2016-04-08 10:45:09 +03:00
|
|
|
|
2016-06-04 03:31:36 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
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)
|
2016-06-04 03:31:36 +03:00
|
|
|
|
2016-04-08 10:45:09 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
def generate_random_string(length,
|
|
|
|
using_digits=False,
|
|
|
|
using_ascii_letters=False,
|
|
|
|
using_punctuation=False):
|
2016-06-24 17:59:55 +03:00
|
|
|
"""
|
2018-02-07 22:52:52 +03:00
|
|
|
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.
|
2016-06-24 17:59:55 +03:00
|
|
|
"""
|
2018-02-07 22:52:52 +03:00
|
|
|
if not using_sysrandom:
|
|
|
|
return None
|
|
|
|
|
|
|
|
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)])
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
with open(file_path, 'r+') as f:
|
|
|
|
file_contents = f.read().replace(flag, value)
|
|
|
|
f.seek(0)
|
|
|
|
f.write(file_contents)
|
|
|
|
f.truncate()
|
|
|
|
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2016-04-08 10:45:09 +03:00
|
|
|
)
|
2018-02-07 22:52:52 +03:00
|
|
|
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()
|
2018-03-01 22:43:00 +03:00
|
|
|
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
2018-02-07 22:52:52 +03:00
|
|
|
remove_gplv3_files()
|
|
|
|
|
|
|
|
if '{{ cookiecutter.use_pycharm }}'.lower() == 'n':
|
|
|
|
remove_pycharm_files()
|
|
|
|
|
|
|
|
if '{{ cookiecutter.use_docker }}'.lower() == 'n':
|
|
|
|
remove_docker_files()
|
|
|
|
|
2018-03-04 14:43:54 +03:00
|
|
|
if '{{ cookiecutter.use_heroku }}'.lower() == 'n':
|
|
|
|
remove_heroku_files()
|
2018-02-07 22:52:52 +03:00
|
|
|
|
2018-03-04 14:44:37 +03:00
|
|
|
if '{{ cookiecutter.use_docker }}'.lower() == 'n' and '{{ cookiecutter.use_heroku }}'.lower() == 'n':
|
|
|
|
remove_dotenv_file()
|
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
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()
|
|
|
|
|
2016-04-08 10:45:09 +03:00
|
|
|
|
2018-02-07 22:52:52 +03:00
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|