dk-tasklib 3.0.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dk_tasklib-3.0.9.dist-info/METADATA +78 -0
- dk_tasklib-3.0.9.dist-info/RECORD +35 -0
- dk_tasklib-3.0.9.dist-info/WHEEL +5 -0
- dk_tasklib-3.0.9.dist-info/entry_points.txt +2 -0
- dk_tasklib-3.0.9.dist-info/top_level.txt +1 -0
- dktasklib/__init__.py +3 -0
- dktasklib/_version.py +1 -0
- dktasklib/clean.py +8 -0
- dktasklib/commands.py +95 -0
- dktasklib/concat.py +76 -0
- dktasklib/docs.py +225 -0
- dktasklib/entry_points/__init__.py +5 -0
- dktasklib/entry_points/confbase.py +172 -0
- dktasklib/entry_points/dktasklibcmd.py +102 -0
- dktasklib/entry_points/pytemplate.py +16 -0
- dktasklib/entry_points/taskbase.py +135 -0
- dktasklib/environment.py +11 -0
- dktasklib/executables.py +200 -0
- dktasklib/help.py +17 -0
- dktasklib/jstools.py +320 -0
- dktasklib/lessc.py +111 -0
- dktasklib/manage.py +71 -0
- dktasklib/npm.py +19 -0
- dktasklib/package/__init__.py +31 -0
- dktasklib/package/package_interface.py +103 -0
- dktasklib/pset.py +122 -0
- dktasklib/publish.py +50 -0
- dktasklib/rule.py +65 -0
- dktasklib/runners.py +40 -0
- dktasklib/upversion.py +165 -0
- dktasklib/urlinliner.py +90 -0
- dktasklib/utils.py +234 -0
- dktasklib/version.py +103 -0
- dktasklib/watch.py +90 -0
- dktasklib/wintask.py +4 -0
dktasklib/jstools.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import textwrap
|
|
3
|
+
|
|
4
|
+
from dktasklib.wintask import task
|
|
5
|
+
from invoke import Collection
|
|
6
|
+
from dktasklib import runners
|
|
7
|
+
from dktasklib.commands import Command
|
|
8
|
+
from dktasklib.executables import requires
|
|
9
|
+
from dktasklib.utils import cd, switch_extension
|
|
10
|
+
from dktasklib.version import copy_to_version
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def ensure_package_json(ctx):
|
|
14
|
+
"""Is this a node package?
|
|
15
|
+
"""
|
|
16
|
+
package_json = os.path.join(ctx.pkg.root, 'package.json')
|
|
17
|
+
if not os.path.exists(package_json):
|
|
18
|
+
print("Missing package.json file, creating default version..")
|
|
19
|
+
with cd(ctx.pkg.root):
|
|
20
|
+
ctx.run("npm init -f")
|
|
21
|
+
else:
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def ensure_babelrc(ctx):
|
|
26
|
+
"""babel needs a .babelrc file to do any work.
|
|
27
|
+
"""
|
|
28
|
+
babelrc = os.path.join(ctx.pkg.root, '.babelrc')
|
|
29
|
+
if not os.path.exists(babelrc):
|
|
30
|
+
print('Misssing %s (creating default version)' % babelrc)
|
|
31
|
+
with open(babelrc, 'w') as fp:
|
|
32
|
+
fp.write(textwrap.dedent("""
|
|
33
|
+
{
|
|
34
|
+
"presets": [
|
|
35
|
+
["env", {
|
|
36
|
+
"targets": {
|
|
37
|
+
"browsers": [
|
|
38
|
+
"last 2 versions",
|
|
39
|
+
"IE >= 11"
|
|
40
|
+
],
|
|
41
|
+
"useBuiltIns": true,
|
|
42
|
+
"node": "current"
|
|
43
|
+
}
|
|
44
|
+
}]
|
|
45
|
+
],
|
|
46
|
+
"ignore": [
|
|
47
|
+
"node_modules"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
"""))
|
|
51
|
+
else:
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def ensure_node_modules(ctx):
|
|
56
|
+
"""Has node init been called? (if not call it).
|
|
57
|
+
"""
|
|
58
|
+
node_modules = os.path.join(ctx.pkg.root, 'node_modules')
|
|
59
|
+
if not os.path.exists(node_modules):
|
|
60
|
+
with cd(ctx.pkg.root):
|
|
61
|
+
ctx.run("npm install --no-color")
|
|
62
|
+
else:
|
|
63
|
+
return True
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def ensure_es2015(ctx):
|
|
67
|
+
if 'babel-preset-es2015' not in runners.run("npm ls --depth=0 babel-preset-es2015 --no-color"):
|
|
68
|
+
print("didn't find babel-preset-es2015, installing it..")
|
|
69
|
+
with cd(ctx.pkg.root):
|
|
70
|
+
ctx.run("npm install babel-preset-es2015 --save-dev")
|
|
71
|
+
else:
|
|
72
|
+
return True
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def ensure_preset_es2016(ctx):
|
|
76
|
+
if 'babel-preset-es2015' not in runners.run("npm ls --depth=0 babel-preset-es2016 --no-color"):
|
|
77
|
+
print("didn't find babel-preset-es2016, installing it..")
|
|
78
|
+
with cd(ctx.pkg.root):
|
|
79
|
+
ctx.run("npm install babel-preset-es2016 --save-dev")
|
|
80
|
+
else:
|
|
81
|
+
return True
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def ensure_preset_es2017(ctx):
|
|
85
|
+
if 'babel-preset-es2017' not in runners.run("npm ls --depth=0 babel-preset-es2017 --no-color"):
|
|
86
|
+
print("didn't find babel-preset-es2017, installing it..")
|
|
87
|
+
with cd(ctx.pkg.root):
|
|
88
|
+
ctx.run("npm install babel-preset-es2017 --save-dev")
|
|
89
|
+
else:
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def ensure_preset_latest(ctx):
|
|
94
|
+
if 'babel-preset-env' not in runners.run("npm ls --depth=0 babel-preset-env --no-color"):
|
|
95
|
+
print("didn't find babel-preset-env, installing it..")
|
|
96
|
+
with cd(ctx.pkg.root):
|
|
97
|
+
ctx.run("npm install babel-preset-env --save-dev")
|
|
98
|
+
else:
|
|
99
|
+
return True
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def ensure_preset_babili(ctx):
|
|
103
|
+
if 'babel-preset-babili' not in runners.run("npm ls --depth=0 babel-preset-babili --no-color"):
|
|
104
|
+
print("didn't find babel-preset-babili, installing it..")
|
|
105
|
+
with cd(ctx.pkg.root):
|
|
106
|
+
ctx.run("npm install babel-preset-babili --save-dev")
|
|
107
|
+
else:
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def ensure_babelify(ctx):
|
|
112
|
+
if 'babelify' not in runners.run("npm ls --depth=0 babelify --no-color"):
|
|
113
|
+
print("didn't find babelify, installing it..")
|
|
114
|
+
with cd(ctx.pkg.root):
|
|
115
|
+
ctx.run("npm install --save-dev babelify --no-color", echo=False, encoding='utf-8')
|
|
116
|
+
else:
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def ensure_babel_minify(ctx):
|
|
121
|
+
nodepkgs = runners.run("npm ls --depth=0 babelify --no-color")
|
|
122
|
+
if 'babel-minify' not in nodepkgs and 'minify' not in nodepkgs:
|
|
123
|
+
print("didn't find babelify, installing it..")
|
|
124
|
+
with cd(ctx.pkg.root):
|
|
125
|
+
ctx.run("npm install --save-dev babelify --no-color", echo=False, encoding='utf-8')
|
|
126
|
+
else:
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def version_js(ctx, fname, kind='pkg', force=False):
|
|
131
|
+
"""Add version number to a .js file.
|
|
132
|
+
"""
|
|
133
|
+
dst = copy_to_version(
|
|
134
|
+
ctx,
|
|
135
|
+
fname,
|
|
136
|
+
kind=kind,
|
|
137
|
+
force=force
|
|
138
|
+
)
|
|
139
|
+
return dst
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@requires('nodejs', 'npm', 'browserify')
|
|
143
|
+
@task
|
|
144
|
+
def browserify(ctx,
|
|
145
|
+
source, dest,
|
|
146
|
+
babelify=False,
|
|
147
|
+
require=(),
|
|
148
|
+
external=(),
|
|
149
|
+
entry=None):
|
|
150
|
+
"""
|
|
151
|
+
Run ``browserify``
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
ctx (pyinvoke.Context): context
|
|
155
|
+
source (str): root source file
|
|
156
|
+
dest (str): path/name of assembled file
|
|
157
|
+
babelify (Bool): use babel transform
|
|
158
|
+
require (iterable): A module name or file to bundle.require()
|
|
159
|
+
Optionally use a colon separator to set the target.
|
|
160
|
+
external: Reference a file from another bundle. Files can be globs.
|
|
161
|
+
entry:
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
None
|
|
165
|
+
|
|
166
|
+
"""
|
|
167
|
+
print('ensure package.json:', ensure_package_json(ctx))
|
|
168
|
+
print('ensure node_modules:', ensure_node_modules(ctx))
|
|
169
|
+
|
|
170
|
+
options = "" # no source maps
|
|
171
|
+
if babelify:
|
|
172
|
+
print('ensure babelify:', ensure_babelify(ctx))
|
|
173
|
+
print('ensure preset latest:', ensure_preset_latest(ctx))
|
|
174
|
+
options += ' -t babelify'
|
|
175
|
+
options += ' --presets env'
|
|
176
|
+
for r in require:
|
|
177
|
+
options += ' -r "%s"' % r
|
|
178
|
+
for e in external:
|
|
179
|
+
options += ' -x "%s"' % e
|
|
180
|
+
if entry:
|
|
181
|
+
options += ' -e "%s"' % entry
|
|
182
|
+
cmd = "browserify {source} -o {dest} {options}".format(**locals())
|
|
183
|
+
ctx.run(cmd)
|
|
184
|
+
with open(dest, 'rb') as fp:
|
|
185
|
+
txt = fp.read()
|
|
186
|
+
if b'\r\n' in txt:
|
|
187
|
+
with open(dest, 'wb') as fp:
|
|
188
|
+
fp.write(txt.replace(b'\r\n', b'\n'))
|
|
189
|
+
return dest
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
babilicmd = Command('babili', '{src} {opts} -o {dst}',
|
|
193
|
+
requirements=('nodejs', 'npm', 'babili'))
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@requires('nodejs', 'npm', 'babili')
|
|
197
|
+
@task
|
|
198
|
+
def babili(ctx, src, dst):
|
|
199
|
+
babilicmd(
|
|
200
|
+
ctx,
|
|
201
|
+
src=src,
|
|
202
|
+
dst=dst,
|
|
203
|
+
)
|
|
204
|
+
return dst
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# babel-minify is linked to minify
|
|
208
|
+
babel_minifycmd = Command('babel-minify', '{src} {opts} -o {dst}',
|
|
209
|
+
requirements=('nodejs', 'npm', 'babel-minify'))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@requires('nodejs', 'npm', 'babel-minify')
|
|
213
|
+
@task
|
|
214
|
+
def babel_minify(ctx, src, dst):
|
|
215
|
+
"""
|
|
216
|
+
dkjs/node_modules/.bin> babel-minify --help
|
|
217
|
+
|
|
218
|
+
Usage: minify index.js [options]
|
|
219
|
+
|
|
220
|
+
IO Options:
|
|
221
|
+
--out-file, -o Output to a specific file
|
|
222
|
+
--out-dir, -d Output to a specific directory
|
|
223
|
+
|
|
224
|
+
Transform Options:
|
|
225
|
+
--mangle Context and scope aware variable renaming
|
|
226
|
+
--simplify Simplifies code for minification by reducing statements into
|
|
227
|
+
expressions
|
|
228
|
+
--booleans Transform boolean literals into !0 for true and !1 for false
|
|
229
|
+
--builtIns Minify standard built-in objects
|
|
230
|
+
--consecutiveAdds Inlines consecutive property assignments, array pushes, etc.
|
|
231
|
+
--deadcode Inlines bindings and tries to evaluate expressions.
|
|
232
|
+
--evaluate Tries to evaluate expressions and inline the result. Deals
|
|
233
|
+
with numbers and strings
|
|
234
|
+
--flipComparisons Optimize code for repetition-based compression algorithms
|
|
235
|
+
such as gzip.
|
|
236
|
+
--infinity Minify Infinity to 1/0
|
|
237
|
+
--memberExpressions Convert valid member expression property literals into plain
|
|
238
|
+
identifiers
|
|
239
|
+
--mergeVars Merge sibling variables into single variable declaration
|
|
240
|
+
--numericLiterals Shortening of numeric literals via scientific notation
|
|
241
|
+
--propertyLiterals Transform valid identifier property key literals into identifiers
|
|
242
|
+
--regexpConstructors Change RegExp constructors into literals
|
|
243
|
+
--removeConsole Removes all console.* calls
|
|
244
|
+
--removeDebugger Removes all debugger statements
|
|
245
|
+
--removeUndefined Removes rval's for variable assignments, return arguments from
|
|
246
|
+
functions that evaluate to undefined
|
|
247
|
+
--replace Replaces matching nodes in the tree with a given replacement node
|
|
248
|
+
--simplifyComparisons Convert === and !== to == and != if their types are inferred
|
|
249
|
+
to be the same
|
|
250
|
+
--typeConstructors Minify constructors to equivalent version
|
|
251
|
+
--undefinedToVoid Transforms undefined into void 0
|
|
252
|
+
|
|
253
|
+
Other Options:
|
|
254
|
+
--keepFnName Preserve Function Name (useful for code depending on fn.name)
|
|
255
|
+
--keepClassName Preserve Class Name (useful for code depending on c.name)
|
|
256
|
+
--keepFnArgs Don't remove unused fn arguments (useful for code depending on fn.length)
|
|
257
|
+
--tdz Detect usages of variables in the Temporal Dead Zone
|
|
258
|
+
|
|
259
|
+
Nested Options:
|
|
260
|
+
To use nested options (plugin specfic options) simply use the pattern
|
|
261
|
+
--pluginName.featureName.
|
|
262
|
+
|
|
263
|
+
For example,
|
|
264
|
+
minify index.js --mangle.keepClassName --deadcode.keepFnArgs --outFile index.min.js
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
babel_minifycmd(
|
|
268
|
+
ctx,
|
|
269
|
+
src=src,
|
|
270
|
+
dst=dst,
|
|
271
|
+
keepFnName=True,
|
|
272
|
+
keepClassName=True,
|
|
273
|
+
mangle=False,
|
|
274
|
+
simplify=False,
|
|
275
|
+
builtIns=True,
|
|
276
|
+
deadcode=False,
|
|
277
|
+
evaluate=False
|
|
278
|
+
)
|
|
279
|
+
return dst
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
uglifycmd = Command('uglifyjs', '{src} {opts} -o {dst}',
|
|
283
|
+
requirements=('nodejs', 'npm', 'uglify'))
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@requires('nodejs', 'npm', 'uglify')
|
|
287
|
+
@task
|
|
288
|
+
def uglifyjs(ctx,
|
|
289
|
+
src, dst,
|
|
290
|
+
compress=True, mangle=True):
|
|
291
|
+
uglifycmd(
|
|
292
|
+
ctx,
|
|
293
|
+
src=src,
|
|
294
|
+
dst=dst,
|
|
295
|
+
compress=compress,
|
|
296
|
+
mangle=mangle
|
|
297
|
+
)
|
|
298
|
+
return dst
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
@task(default=True)
|
|
302
|
+
def buildjs(ctx, src, dst, force=False, **kw):
|
|
303
|
+
uglify = kw.pop('uglify', False)
|
|
304
|
+
if kw.pop('browserify', False):
|
|
305
|
+
dst = browserify(ctx, src, dst,
|
|
306
|
+
babelify=kw.pop('babelify', src.endswith('.jsx')), **kw)
|
|
307
|
+
|
|
308
|
+
if uglify:
|
|
309
|
+
finaldst = switch_extension(dst, '.min.js')
|
|
310
|
+
dst = uglifyjs(ctx, dst, finaldst)
|
|
311
|
+
if force:
|
|
312
|
+
dst = copy_to_version(ctx, dst, force=force)
|
|
313
|
+
|
|
314
|
+
return dst
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
ns = Collection(browserify, uglifyjs)
|
|
318
|
+
ns.configure({
|
|
319
|
+
'static': 'static/{pkg.name}'
|
|
320
|
+
})
|
dktasklib/lessc.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dktasklib.wintask import task
|
|
3
|
+
from .rule import BuildRule
|
|
4
|
+
from .commands import Command
|
|
5
|
+
from dkfileutils.changed import Directory
|
|
6
|
+
from dkfileutils.path import Path
|
|
7
|
+
from invoke import Collection
|
|
8
|
+
from . import urlinliner
|
|
9
|
+
from .concat import copy
|
|
10
|
+
from .environment import env
|
|
11
|
+
from .utils import fmt, switch_extension, message
|
|
12
|
+
from .version import get_version
|
|
13
|
+
from .upversion import UpdateTemplateVersion
|
|
14
|
+
|
|
15
|
+
lessc = Command('lessc', '{opts} {src} {dst}',
|
|
16
|
+
requirements=('nodejs', 'npm', 'lessc'))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
BOOTSTRAP = Path(os.environ.get('SRV', '')) / 'ext' / 'bootstrap' / 'less'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@task(
|
|
23
|
+
default=True,
|
|
24
|
+
name='build_less',
|
|
25
|
+
help={
|
|
26
|
+
'version': "one of pkg|hash|svn",
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
class LessRule(BuildRule):
|
|
30
|
+
"""Build a ``.less`` file into a versioned and minified ``.css`` file.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
bootstrap_src = BOOTSTRAP
|
|
34
|
+
|
|
35
|
+
def __init__(self, *args, **kw):
|
|
36
|
+
self.after = [UpdateTemplateVersion(
|
|
37
|
+
kw.pop('import_fname',
|
|
38
|
+
'{pkg.source}/templates/{pkg.name}/{pkg.name}-css.html')
|
|
39
|
+
)]
|
|
40
|
+
super(LessRule.body, self).__init__(*args, **kw)
|
|
41
|
+
|
|
42
|
+
def __call__(self,
|
|
43
|
+
src='{pkg.source}/less/{pkg.name}.less',
|
|
44
|
+
dst='{pkg.source}/static/{pkg.name}/css/{pkg.name}-{version}.min.css',
|
|
45
|
+
version='pkg',
|
|
46
|
+
bootstrap=True,
|
|
47
|
+
force=False,
|
|
48
|
+
**kw):
|
|
49
|
+
c = env(self.ctx)
|
|
50
|
+
source = Path(fmt(src, c))
|
|
51
|
+
dest = Path(fmt(dst, c))
|
|
52
|
+
|
|
53
|
+
if not source.exists():
|
|
54
|
+
print("Missing source:", source, '(skipping)')
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
for fname in source.dirname().glob("*.inline"):
|
|
58
|
+
urlinliner.inline(self.ctx, fname)
|
|
59
|
+
|
|
60
|
+
if not force and not Directory(source.dirname()).changed(glob='**/*.less'):
|
|
61
|
+
print("No changes: {input_dir}/{glob}, add --force to build.".format(
|
|
62
|
+
input_dir=source.dirname(), glob='**/*.less'))
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
path = kw.pop('path', [])
|
|
66
|
+
if bootstrap:
|
|
67
|
+
path.append(self.bootstrap_src)
|
|
68
|
+
|
|
69
|
+
cssname = dest.relpath().format(version=get_version(self.ctx, source, version))
|
|
70
|
+
lessc(
|
|
71
|
+
self.ctx,
|
|
72
|
+
src=source.relpath(),
|
|
73
|
+
dst=cssname,
|
|
74
|
+
include_path=path,
|
|
75
|
+
strict_imports=True,
|
|
76
|
+
inline_urls=False,
|
|
77
|
+
autoprefix="last 4 versions",
|
|
78
|
+
clean_css="-b --s0",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
with message("Creating copy without version number.."):
|
|
82
|
+
copy( # create a copy without version number too..
|
|
83
|
+
self.ctx,
|
|
84
|
+
cssname,
|
|
85
|
+
Path(cssname).dirname() / switch_extension(source.basename(), '.css'),
|
|
86
|
+
force=True
|
|
87
|
+
)
|
|
88
|
+
return cssname
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
ns = Collection('lessc', LessRule)
|
|
92
|
+
ns.configure({
|
|
93
|
+
'force': False,
|
|
94
|
+
'pkg': {
|
|
95
|
+
'root': '<package-root-directory>',
|
|
96
|
+
'name': '<package-name>',
|
|
97
|
+
'source': '<source-dir>',
|
|
98
|
+
'version': '<version-string>',
|
|
99
|
+
},
|
|
100
|
+
'bootstrap': {
|
|
101
|
+
'src': os.path.join(os.environ.get('BOOTSTRAPSRC', ''), 'less'),
|
|
102
|
+
},
|
|
103
|
+
'lessc': {
|
|
104
|
+
'use_bootstrap': False,
|
|
105
|
+
'build_dir': 'build/css',
|
|
106
|
+
'input_dir': '{pkg.source}/less',
|
|
107
|
+
'input_fname': '{pkg.name}.less',
|
|
108
|
+
'output_dir': '{pkg.source}/static/{pkg.name}/css/',
|
|
109
|
+
'output_fname': '{pkg.name}.css',
|
|
110
|
+
}
|
|
111
|
+
})
|
dktasklib/manage.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from dkfileutils.path import Path
|
|
5
|
+
from dkfileutils.pfind import pfind
|
|
6
|
+
from dkfileutils.changed import changed, Directory
|
|
7
|
+
from dktasklib.wintask import task
|
|
8
|
+
from invoke import run
|
|
9
|
+
from .utils import cd, env, find_pymodule
|
|
10
|
+
from .package import Package
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
DEFAULT_SETTINGS_MODULE = 'settings'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@task
|
|
17
|
+
def manage(ctx, cmd, settings=None, manage_path=None, venv=None):
|
|
18
|
+
"""Run manage.py with `settings` in a separate process.
|
|
19
|
+
"""
|
|
20
|
+
settings = settings or DEFAULT_SETTINGS_MODULE
|
|
21
|
+
with env(DJANGO_SETTINGS_MODULE=settings, PYTHONWARNINGS='ignore'):
|
|
22
|
+
if manage_path is None:
|
|
23
|
+
settings_dir = find_pymodule(settings)
|
|
24
|
+
manage_path = Path(pfind(settings_dir, 'manage.py')).dirname()
|
|
25
|
+
|
|
26
|
+
with cd(manage_path):
|
|
27
|
+
call = "python manage.py {cmd}"
|
|
28
|
+
if venv:
|
|
29
|
+
call = "vex {venv} python manage.py {cmd} --traceback"
|
|
30
|
+
|
|
31
|
+
run(call.format(venv=venv, cmd=cmd))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@task
|
|
35
|
+
def collectstatic(ctx, settings=None, venv=None, clobber=False, force=False):
|
|
36
|
+
"Run collectstatic with settings from package.json ('django_settings_module')"
|
|
37
|
+
if not hasattr(ctx, 'pkg'):
|
|
38
|
+
ctx.pkg = Package()
|
|
39
|
+
|
|
40
|
+
if not (force or Directory(ctx.pkg.django_static).changed()):
|
|
41
|
+
print("Skipping collectstic: no changes to static dir.")
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
if not clobber:
|
|
45
|
+
# check that we don't overwrite versioned resources
|
|
46
|
+
changed_versioned_resources = False
|
|
47
|
+
static = Path(os.environ['SRV']) / 'data' / 'static'
|
|
48
|
+
for fname in ctx.pkg.django_static.glob(r'**/*\d+.min.*'):
|
|
49
|
+
pubname = static / fname.relpath(ctx.pkg.django_static)
|
|
50
|
+
if pubname.exists():
|
|
51
|
+
if pubname.open('rb').read() != fname.open('rb').read():
|
|
52
|
+
changed_versioned_resources = True
|
|
53
|
+
print()
|
|
54
|
+
print("ERROR: versioned file has changes:")
|
|
55
|
+
print(" contents of: ", fname)
|
|
56
|
+
print(" is different from:", pubname)
|
|
57
|
+
print()
|
|
58
|
+
if changed_versioned_resources:
|
|
59
|
+
print("Exiting due to changes in versioned resources. "
|
|
60
|
+
"You should probably revert the changes and create "
|
|
61
|
+
"a new version.")
|
|
62
|
+
sys.exit(1)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
settings = settings or ctx.pkg.django_settings_module
|
|
66
|
+
except AttributeError:
|
|
67
|
+
settings = DEFAULT_SETTINGS_MODULE
|
|
68
|
+
print("using settings:", settings, 'venv:', venv)
|
|
69
|
+
manage(ctx, "collectstatic --noinput", settings=settings, venv=venv)
|
|
70
|
+
# record changes made by collectstatic
|
|
71
|
+
changed(ctx.pkg.django_static)
|
dktasklib/npm.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
from dktasklib.executables import exe
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def npm(cmdline):
|
|
7
|
+
npm_exe = exe.find('npm', requires=['nodejs']) # noqa
|
|
8
|
+
return subprocess.check_output("npm " + cmdline, shell=True).decode('u8')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def global_package(pkgname):
|
|
12
|
+
"""Check if an npm package is installed globally.
|
|
13
|
+
"""
|
|
14
|
+
try:
|
|
15
|
+
# this is the 'correct' way, but it's increadably slow (4+ secs)
|
|
16
|
+
npm('ls -g --depth 0 ' + pkgname)
|
|
17
|
+
return True
|
|
18
|
+
except subprocess.CalledProcessError:
|
|
19
|
+
return False
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from dktasklib.wintask import task
|
|
2
|
+
from .package_interface import Package
|
|
3
|
+
from ..utils import format_table, Column
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@task
|
|
7
|
+
def package(ctx):
|
|
8
|
+
"""Print detected package directories.
|
|
9
|
+
"""
|
|
10
|
+
pkg = ctx.pkg if hasattr(ctx, 'pkg') else Package()
|
|
11
|
+
|
|
12
|
+
def row(attribute, value, description=''):
|
|
13
|
+
return dict(attribute=attribute, value=value, description=description)
|
|
14
|
+
|
|
15
|
+
print("The dk-tasklib Package object thinks your code has the following layout:")
|
|
16
|
+
|
|
17
|
+
print(format_table(
|
|
18
|
+
[
|
|
19
|
+
row('package_name', pkg.package_name, '(repo/pip-installable name)'),
|
|
20
|
+
row('name', pkg.name, '(importable name)'),
|
|
21
|
+
row('root', pkg.root, '(wc)'),
|
|
22
|
+
row('source', pkg.source, '(source directory)'),
|
|
23
|
+
row('source_js', pkg.source_js, '(js source directory)'),
|
|
24
|
+
row('source_less', pkg.source_less, '(less source directory)'),
|
|
25
|
+
row('docs', pkg.docs, '(docs directory)'),
|
|
26
|
+
row('django?', 'yes' if pkg.is_django() else 'no', '(django?)'),
|
|
27
|
+
],
|
|
28
|
+
Column(field='attribute'),
|
|
29
|
+
Column(field='value'),
|
|
30
|
+
Column(field='description'),
|
|
31
|
+
))
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from configparser import RawConfigParser
|
|
3
|
+
|
|
4
|
+
import invoke
|
|
5
|
+
from dkfileutils.pfind import pfind as _pfind
|
|
6
|
+
from dkfileutils.path import Path
|
|
7
|
+
# from dkfileutils.changed import Directory
|
|
8
|
+
from invoke.config import Config
|
|
9
|
+
from dkpkg import Package as DKPKGPackage
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def pfind(path, *fnames):
|
|
13
|
+
res = _pfind(path, *fnames)
|
|
14
|
+
return Path(res) if res is not None else None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Package(DKPKGPackage):
|
|
18
|
+
overridables = DKPKGPackage.KEYS | {'version'}
|
|
19
|
+
|
|
20
|
+
def overrides(self, **res):
|
|
21
|
+
setup_py = pfind('.', 'setup.py')
|
|
22
|
+
if setup_py:
|
|
23
|
+
root = setup_py.dirname()
|
|
24
|
+
with root.abspath().cd():
|
|
25
|
+
res['version'] = self.ctx.run(
|
|
26
|
+
'python setup.py --version',
|
|
27
|
+
hide=True
|
|
28
|
+
).stdout.strip()
|
|
29
|
+
|
|
30
|
+
res.update(self._read_dkbuild_ini())
|
|
31
|
+
|
|
32
|
+
package_json = pfind('.', 'package.json')
|
|
33
|
+
if package_json:
|
|
34
|
+
with open(package_json, 'r') as fp:
|
|
35
|
+
pj = json.load(fp)
|
|
36
|
+
for k, v in pj.items():
|
|
37
|
+
if k in Package.overridables:
|
|
38
|
+
res[k] = v
|
|
39
|
+
|
|
40
|
+
return res
|
|
41
|
+
|
|
42
|
+
def _read_dkbuild_ini(self):
|
|
43
|
+
dkbuild_ini = pfind('.', 'dkbuild.ini')
|
|
44
|
+
if not dkbuild_ini:
|
|
45
|
+
return {}
|
|
46
|
+
cp = RawConfigParser()
|
|
47
|
+
cp.read(dkbuild_ini)
|
|
48
|
+
return dict((k, v) for k, v in cp.items('dkbuild')
|
|
49
|
+
if k in Package.overridables)
|
|
50
|
+
|
|
51
|
+
def __init__(self, ctx=None):
|
|
52
|
+
self.ctx = ctx or invoke.Context()
|
|
53
|
+
pkgdir = pfind('.',
|
|
54
|
+
'setup.py',
|
|
55
|
+
'dkbuild.ini',
|
|
56
|
+
'package.json')
|
|
57
|
+
if pkgdir is None:
|
|
58
|
+
raise IOError("Didn't find setup.py|dkbuild.ini|package.json in "
|
|
59
|
+
"any parent directory up to, and including root.")
|
|
60
|
+
root = pkgdir.dirname()
|
|
61
|
+
ispkg = 'setup.py' in root
|
|
62
|
+
overrides = self.overrides() if ispkg else self.overrides(source=root)
|
|
63
|
+
super().__init__(root, **overrides)
|
|
64
|
+
|
|
65
|
+
def vcs(self):
|
|
66
|
+
"""Return the name of the version control system handling this package.
|
|
67
|
+
"""
|
|
68
|
+
if (self.root / '.svn').exists():
|
|
69
|
+
return 'svn'
|
|
70
|
+
elif (self.root / '.git').exists():
|
|
71
|
+
return 'git'
|
|
72
|
+
elif (self.root / '.hg').exists():
|
|
73
|
+
return 'hg'
|
|
74
|
+
else:
|
|
75
|
+
return ''
|
|
76
|
+
|
|
77
|
+
# invoke'ism?
|
|
78
|
+
def config(self): # pragma: nocover
|
|
79
|
+
cfg = Config(dict(iter(self)))
|
|
80
|
+
cfg.name = self.name
|
|
81
|
+
cfg.root = self.root
|
|
82
|
+
cfg.source = self.source
|
|
83
|
+
cfg.docs = self.docs
|
|
84
|
+
cfg.django_static = self.django_static
|
|
85
|
+
return cfg
|
|
86
|
+
|
|
87
|
+
def __repr__(self):
|
|
88
|
+
return self.__class__.__name__
|
|
89
|
+
|
|
90
|
+
def __getitem__(self, key):
|
|
91
|
+
try:
|
|
92
|
+
return getattr(self, key)
|
|
93
|
+
except AttributeError as e:
|
|
94
|
+
raise KeyError(str(e))
|
|
95
|
+
|
|
96
|
+
def get(self, key, default=None):
|
|
97
|
+
try:
|
|
98
|
+
return self[key]
|
|
99
|
+
except KeyError:
|
|
100
|
+
return default
|
|
101
|
+
|
|
102
|
+
def __iter__(self):
|
|
103
|
+
return iter([])
|