8000 Build command: Add --parse-templates option. · woodcoder/flask-assets@e97f010 · GitHub
[go: up one dir, main page]

Skip to content

Commit e97f010

Browse files
committed
Build command: Add --parse-templates option.
Closes miracle2k#16. Close
1 parent b837d6b commit e97f010

File tree

3 files changed

+80
-10
lines changed

3 files changed

+80
-10
lines changed

src/flask_assets.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ def __delitem__(self, key):
8383
del self.env._app.config[self._transform_key(key)]
8484

8585

86-
8786
def get_static_folder(app_or_blueprint):
8887
"""Return the static folder of the given Flask app
8988
instance, or module/blueprint.
@@ -213,19 +212,65 @@ def init_app(self, app):
213212
pass
214213
else:
215214
import argparse
216-
from webassets.script import GenericArgparseImplementation
215+
from webassets.script import GenericArgparseImplementation, CommandError
217216

218217
class CatchAllParser(object):
219218
def parse_known_args(self, app_args):
220219
return argparse.Namespace(), app_args
221220

221+
class FlaskArgparseInterface(GenericArgparseImplementation):
222+
"""Subclass the CLI implementation to add a --parse-templates option."""
223+
224+
def _construct_parser(self, *a, **kw):
225+
super(FlaskArgparseInterface, self).\
226+
_construct_parser(*a, **kw)
227+
self.parser.add_argument(
228+
'--parse-templates', action='store_true',
229+
help='search project templates to find bundles')
230+
231+
def _setup_assets_env(self, ns, log):
232+
env = super(FlaskArgparseInterface, self)._setup_assets_env(ns, log)
233+
if env is not None:
234+
if ns.parse_templates:
235+
log.info('Searching templates...')
236+
# Note that we exclude container bundles. By their very nature,
237+
# they are guaranteed to have been created by solely referencing
238+
# other bundles which are already registered.
239+
env.add(*[b for b in self.load_from_templates(env)
240+
if not b.is_container])
241+
242+
if not len(env):
243+
raise CommandError(
244+
'No asset bundles were found. '
245+
'If you are defining assets directly within '
246+
'your templates, you want to use the '
247+
'--parse-templates option.')
248+
return env
249+
250+
def load_from_templates(self, env):
251+
from webassets.ext.jinja2 import Jinja2Loader, AssetsExtension
252+
from flask import current_app as app
253+
254+
# Use the application's Jinja environment to parse
255+
jinja2_env = app.jinja_env
256+
257+
# Get the template directories of app and blueprints
258+
template_dirs = [path.join(app.root_path, app.template_folder)]
259+
for blueprint in app.blueprints:
260+
template_dirs.append(
261+
path.join(blueprint.root_path, blueprint.template_folder))
262+
263+
return Jinja2Loader(env, template_dirs, [jinja2_env]).load_bundles()
264+
222265
class ManageAssets(script.Command):
223266
"""Manage assets."""
224267
capture_all_args = True
225268

226-
def __init__(self, assets_env=None, impl=GenericArgparseImplementation):
269+
def __init__(self, assets_env=None, impl=FlaskArgparseInterface,
270+
log=None):
227271
self.env = assets_env
228272
self.implementation = impl
273+
self.log = log
229274

230275
def create_parser(self, prog):
231276
return CatchAllParser()
@@ -248,6 +293,7 @@ def run(self, args):
248293
import sys, os.path
249294
prog = '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1])
250295

251-
return self.implementation(self.env, prog=prog).main(args)
296+
impl = self.implementation(self.env, prog=prog, log=self.log)
297+
impl.main(args)
252298

253299
__all__ = __all__ + ('ManageAssets',)

tests/helpers.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def _create_environment(self, **kwargs):
3737
return self.env
3838

3939

40-
4140
try:
4241
from test.test_support import check_warnings
4342
except ImportError:

tests/test_script.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@
55
from flask import Flask
66
from flask.ext.assets import Environment, ManageAssets
77
from webassets.script import GenericArgparseImplementation
8+
from helpers import TempEnvironmentHelper
89

910
try:
1011
from flaskext.script import Manager
1112
except:
1213
raise SkipTest()
1314

1415

15-
class TestScript:
16+
# The CLI likes to log to stderr, which isn't nice to the test output.
17+
import logging
18+
stdout_log = logging.getLogger(__name__)
19+
stdout_log.addHandler(logging.StreamHandler(sys.stdout))
1620

17-
def setup(self):
18-
self.app = Flask(__name__)
19-
self.env = Environment(self.app)
21+
22+
class TestScript(TempEnvironmentHelper):
2023

2124
def test_call(self):
2225
# Setup the webassets.script with a mock main() function,
@@ -50,9 +53,31 @@ def test_call_auto_env(self):
5053

5154
try:
5255
# Used to raise an error due to the env not being properly set.
53-
sys.argv = ['./manage.py', 'assets', 'rebuild']
56+
sys.argv = ['./manage.py', 'assets', 'build']
5457
mgmt.run()
5558
except SystemExit:
5659
# Always raised, regardless of success or failure of command
5760
pass
61+
62+
def test_parse_templates(self):
63+
"""Test the --parse-templates option.
64+
"""
65+
# Create a file in the app's templates directory
66+
self.app.template_folder = self.path('templates')
67+
self.create_files({
68+
'templates/template.html': """
69+
{% assets "in", output="output" %}
70+
{{ ASSET_URL }}
71+
{% endassets %}
72+
""",
73+
'in': "foo"
74+
})
75+
76+
# Run the build command with --parse-templates, which should pick
77+
# up the bundle we defined in above template.
78+
mgmt = Manager(self.app)
79+
mgmt.add_command('assets', ManageAssets(log=stdout_log))
80+
mgmt.handle('test', 'assets', ['--parse-templates', 'build'])
81+
82+
assert self.exists('output')
5883

0 commit comments

Comments
 (0)
0