-
Notifications
You must be signed in to change notification settings - Fork 0
/
fabfile.py
executable file
·202 lines (168 loc) · 6.82 KB
/
fabfile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
from fabric.api import hide, lcd, local, settings, task
import fabric.colors as colors
import os
import os.path
import random
import sys
SAFECHARS = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
def slugify(value):
"""
Converts to lowercase, removes non-word characters (alphanumerics and
underscores) and converts spaces to hyphens. Also strips leading and
trailing whitespace.
"""
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
value = re.sub('[^\w\s-]', '', value).strip().lower()
return mark_safe(re.sub('[-\s]+', '-', value))
@task
def book_project(name, root="~/Documents",
template="~/templates/sphinx_project", slug=None):
"""Create a Sphinx documentation project directory."""
if not slug:
slug = slugify(name)
project_dir = _path(root, slug)
try:
os.makedirs(project_dir)
except OSError: # already exists
pass
template_dir = _path(template)
_copy_template(template_dir, project_dir, name)
@task
def django_env(name, *packages):
"""Bootstrap a python virtualenv and a new Django project"""
project_name = name
envdir = _path(os.environ['WORKON_HOME'], project_name)
with settings(hide('warnings', 'running'), warn_only=True):
print(colors.blue("Creating virtualenv %s..." % project_name,
bold=True))
local('source /usr/local/bin/virtualenvwrapper.sh;' +
'mkvirtualenv --no-site-packages %s' % project_name)
# Bootstrap the django code
django_project(project_name, envdir)
project_dir = _path(envdir, project_name)
local('echo "export DJANGO_SETTINGS_MODULE=' +
'%s.settingsdev" >>%s/bin/postactivate' % (project_name, envdir))
local('echo "unset DJANGO_SETTINGS_MODULE" >>' +
'%s/bin/postdeactivate' % envdir)
print(colors.blue("Installing pip requirements (may take a while)...",
bold=True))
with lcd(project_dir):
local('source ../bin/activate; ' +
'pip install -r requirements-dev.txt')
@task
def django_project(name, root='.', template='~/templates/django_project'):
"""Create a new Django project (replaces startproject)"""
project_template = _path(template)
root_dir = _path(root, name)
try:
os.makedirs(root_dir)
except OSError: # already exists
pass
print colors.blue("Creating Django project %s..." % name, bold=True)
_copy_template(project_template, root_dir, name)
# Start new Django project
@task
def django_app(name, root='.', template='~/templates/django_app'):
"""Create a new standalone Django app (replaces startapp)"""
root_dir = _path(root, name)
template_dir = _path(template)
try:
os.makedirs(root_dir)
except OSError: # already exists
pass
print(colors.blue("Creating Django app %s..." % name, bold=True))
_copy_template(template_dir, root_dir, name)
# Start new Python project
@task
def pyproject(name, root='.', template='~/templates/pyproject'):
"""Create a new Python project (module or application)"""
root_dir = _path(root, name)
template_dir = _path(template)
try:
os.makedirs(root_dir)
except OSError: # already exists
pass
print colors.blue("Creating Python project %s..." % name, bold=True)
_copy_template(template_dir, root_dir, name)
@task
def test_colors():
"""Prints some strings with color output"""
print(colors.red("red text"))
print(colors.red("Bold red text", bold=True))
print(colors.green("green text"))
print(colors.green("Bold green text", bold=True))
print(colors.blue("blue text"))
print(colors.blue("Bold blue text", bold=True))
print(colors.cyan("cyan text"))
print(colors.cyan("Bold cyan text", bold=True))
print(colors.yellow("yellow text"))
print(colors.yellow("Bold yellow text", bold=True))
print(colors.magenta("magenta text"))
print(colors.magenta("Bold magenta text", bold=True))
print(colors.white("white text"))
print(colors.white("Bold white text", bold=True))
################################################
# Utility Functions
################################################
def _path(*args):
return os.path.realpath(os.path.expanduser(os.path.expandvars(
os.path.join(*args))))
def _make_writeable(filename):
"""
Make sure that the file is writeable. Useful if our source is
read-only.
"""
import stat
if sys.platform.startswith('java'):
# On Jython there is no os.access()
return
if not os.access(filename, os.W_OK):
st = os.stat(filename)
new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
os.chmod(filename, new_permissions)
# Lifted from django-extensions and modified slightly -VV
def _copy_template(template_dir, copy_to, project_name, target=None,
secret_key=None):
"""copies the specified template directory to the copy_to location"""
import shutil
if secret_key is None:
secret_key = ''.join([random.choice(SAFECHARS) for i in range(52)])
if target is None:
target = project_name
template_dir = os.path.normpath(template_dir)
# walks the template structure and copies it
for d, subdirs, files in os.walk(template_dir):
relative_dir = d[len(template_dir)+1:]
d_new = os.path.join(copy_to, relative_dir).replace('+NAME+', target)
if relative_dir and not os.path.exists(d_new):
os.mkdir(d_new)
for i, subdir in enumerate(subdirs):
if subdir.startswith('.'):
del subdirs[i]
for f in files:
if f.endswith('.pyc') or f.startswith('.DS_Store'):
continue
path_old = os.path.join(d, f)
path_new = os.path.join(d_new, f.replace('+NAME+', target))
if os.path.exists(path_new):
path_new = os.path.join(d_new, f)
if os.path.exists(path_new):
continue
if path_new.endswith('.tmpl'):
path_new = path_new[:-5]
fp_old = open(path_old, 'r')
fp_new = open(path_new, 'w')
fp_new.write(fp_old.read()
.replace('{{ project_name }}', project_name)
.replace('{{ secret_key }}', secret_key)
)
fp_old.close()
fp_new.close()
try:
shutil.copymode(path_old, path_new)
_make_writeable(path_new)
except OSError:
sys.stderr.write("Notice: Couldn't set permission bits on %s."
% path_new)
sys.stderr.write("You're probably using an uncommon " +
"filesystem setup. No problem.\n")