Skip to content

Instantly share code, notes, and snippets.

@palevell
Created December 28, 2019 21:31
Show Gist options
  • Save palevell/3264ab36209c149d15e63fc8816fcdd6 to your computer and use it in GitHub Desktop.
Save palevell/3264ab36209c149d15e63fc8816fcdd6 to your computer and use it in GitHub Desktop.
This is a utily script to update the settings.py file in Django projects, based on the contents of the .env file. It also adds code for dotenv support.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# update_settings - Monday, December 23, 2019
__version__ = '1.1.10'
import os, re
from glob import glob
from os.path import basename, dirname, exists, getmtime, join
def main():
""" Update settings.py with my preferences """
# Read settings.py
contents_modified = False
with open(SETTINGS, 'rt') as infile:
contents = [x.rstrip() for x in infile.readlines()]
# Search & Insert
search_inserts = [
( "import os", "from dotenv import load_dotenv" ),
( "BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))",
"load_dotenv(os.path.join(BASE_DIR, '.env'))" ),
( "", "" ),
]
for search, insert in search_inserts:
if not search:
continue
s = contents.index(search)
if s and contents[s + 1] != insert:
# print(insert)
contents.insert(s + 1, insert)
contents_modified = True
# Search & Replace
search_replaces = [
("SECRET_KEY = ", "SECRET_KEY = os.getenv('SECRET_KEY') or "),
("TIME_ZONE = 'UTC'", "TIME_ZONE = os.getenv('TZ') or 'UTC'"),
("DEBUG = True", "DEBUG = os.getenv('DEBUG') or False"),
("", ""),
]
for search, replace in search_replaces:
if not search:
continue
for i in range(len(contents)):
# ToDo: SECRET_KEY, DEBUG = os.getenv()
if contents[i].startswith(search) and replace not in contents[i]:
contents[i] = contents[i].replace(search, replace)
contents_modified = True
# ToDo: TEMPLATES.DIRS = [ os.path.join(BASE_DIR, 'templates'), ]
# ToDo: TIME_ZONE = 'UTC' ==> TIME_ZONE = os.getenv('TZ') or 'America/Toronto'
# ToDo: LOGIN URLs, etc.
# Section Processing - TEMPLATES
section = 'TEMPLATES = '
inside_templates = False
for i in range(len(contents)):
if contents[i].startswith(section):
# print('Found TEMPLATES')
inside_templates = True
if inside_templates:
search = "'DIRS': [],"
replace = "'DIRS': [ os.path.join(BASE_DIR, 'templates'), ],"
if contents[i].strip() == search and replace not in contents[i]:
contents[i] = contents[i].replace(search, replace)
contents_modified = True
if contents[i] == ']':
inside_templates = False
# Process .env file
with open('.env', 'rt') as envfile:
# Only load non-blank lines that aren't comments and strip newline characters
envlines = [x.rstrip() for x in envfile.readlines() if x != '\n' and not x.startswith('#')]
# print(envlines)
varnames = []
for line in envlines:
varnames.append(line.split('=')[0])
# print(varnames)
vars_regex = re.compile(r'(%s)\s*=' % '|'.join(varnames))
# print("RegEx:", vars_regex)
found = []
for i in range(len(contents)):
line = contents[i]
match = vars_regex.search(line)
if match:
word = match[0].split('=')[0].strip()
found.append(word)
not_found = []
for v in varnames:
if v not in found:
not_found.append(v)
if not_found:
addlines = [x + " = os.getenv('%s')" % x for x in not_found]
addlines.insert(0, "\n\n# Additional environment variables in .env added by 'update_settings'")
contents += addlines + ['\n\n\n',]
contents_modified = True
# Process any changes
if contents_modified:
# Remove duplicate lines from file
newlines = []
lastline = ''
for c in contents:
if c != lastline:
newlines.append(c)
if c.strip() != '':
lastline = c
contents = newlines
# Write updated file to disk
with open(WORKFILE, 'wt') as outfile:
outfile.writelines([ x + os.linesep for x in contents ])
os.renames(SETTINGS, SETTINGS + '~')
os.renames(WORKFILE, SETTINGS)
else:
print("No modifications detected.")
return
def init():
""" Prepare for main() processing """
global SETTINGS, WORKFILE
settings_py = glob('**/%s' % SETTINGS, recursive=True)
if not settings_py:
raise FileNotFoundError(SETTINGS)
SETTINGS = settings_py[0]
parts = SETTINGS.split(os.sep)
parts[-1] = '.' + parts[-1]
if not exists(SETTINGS):
raise FileNotFoundError(SETTINGS)
WORKFILE = os.sep.join(parts)
return
def eoj():
if exists(BACKUP_FILE):
os.system('meld %s %s' % (BACKUP_FILE, SETTINGS))
return
def debug_breakpoint():
pass
return
if __name__ == '__main__':
SETTINGS = 'settings.py'
WORKFILE = '.' + SETTINGS
BACKUP_FILE = SETTINGS + '~'
init()
main()
eoj()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment