Mercurial > piecrust2
comparison piecrust/data/assetor.py @ 852:4850f8c21b6e
core: Start of the big refactor for PieCrust 3.0.
* Everything is a `ContentSource`, including assets directories.
* Most content sources are subclasses of the base file-system source.
* A source is processed by a "pipeline", and there are 2 built-in pipelines,
one for assets and one for pages. The asset pipeline is vaguely functional,
but the page pipeline is completely broken right now.
* Rewrite the baking process as just running appropriate pipelines on each
content item. This should allow for better parallelization.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Wed, 17 May 2017 00:11:48 -0700 |
parents | ad8f48a31c62 |
children | f070a4fc033c |
comparison
equal
deleted
inserted
replaced
851:2c7e57d80bba | 852:4850f8c21b6e |
---|---|
1 import os | 1 import os |
2 import os.path | 2 import os.path |
3 import shutil | 3 import shutil |
4 import logging | 4 import logging |
5 from piecrust import ASSET_DIR_SUFFIX | 5 from piecrust import ASSET_DIR_SUFFIX |
6 from piecrust.sources.base import REL_ASSETS | |
6 from piecrust.uriutil import multi_replace | 7 from piecrust.uriutil import multi_replace |
7 | 8 |
8 | 9 |
9 logger = logging.getLogger(__name__) | 10 logger = logging.getLogger(__name__) |
10 | 11 |
12 class UnsupportedAssetsError(Exception): | 13 class UnsupportedAssetsError(Exception): |
13 pass | 14 pass |
14 | 15 |
15 | 16 |
16 def build_base_url(app, uri, rel_assets_path): | 17 def build_base_url(app, uri, rel_assets_path): |
17 base_url_format = app.env.base_asset_url_format | 18 base_url_format = app.config.get('site/base_asset_url_format') |
18 rel_assets_path = rel_assets_path.replace('\\', '/') | 19 rel_assets_path = rel_assets_path.replace('\\', '/') |
19 | 20 |
20 # Remove any extension since we'll be copying assets into the 1st | 21 # Remove any extension since we'll be copying assets into the 1st |
21 # sub-page's folder. | 22 # sub-page's folder. |
22 pretty = app.config.get('site/pretty_urls') | 23 pretty = app.config.get('site/pretty_urls') |
23 if not pretty: | 24 if not pretty: |
24 uri, _ = os.path.splitext(uri) | 25 uri, _ = os.path.splitext(uri) |
25 | 26 |
26 base_url = multi_replace( | 27 base_url = multi_replace( |
27 base_url_format, | 28 base_url_format, |
28 { | 29 { |
29 '%path%': rel_assets_path, | 30 '%path%': rel_assets_path, |
30 '%uri%': uri}) | 31 '%uri%': uri}) |
31 | 32 |
32 return base_url.rstrip('/') + '/' | 33 return base_url.rstrip('/') + '/' |
33 | 34 |
34 | 35 |
35 class AssetorBase(object): | 36 class Assetor(object): |
37 debug_render_doc = """Helps render URLs to files in the current page's | |
38 asset folder.""" | |
39 debug_render = [] | |
40 debug_render_dynamic = ['_debugRenderAssetNames'] | |
41 | |
36 def __init__(self, page, uri): | 42 def __init__(self, page, uri): |
37 self._page = page | 43 self._page = page |
38 self._uri = uri | 44 self._uri = uri |
39 self._cache = None | 45 self._cache = None |
40 | 46 |
63 | 69 |
64 def _cacheAssets(self): | 70 def _cacheAssets(self): |
65 if self._cache is not None: | 71 if self._cache is not None: |
66 return | 72 return |
67 | 73 |
68 self._cache = dict(self.findAssets()) | 74 self._cache = self.findAssets() or {} |
69 | 75 |
70 def findAssets(self): | 76 def findAssets(self): |
71 raise NotImplementedError() | 77 content_item = self._page.content_item |
78 source = content_item.source | |
79 assets = source.getRelatedContent(content_item, REL_ASSETS) | |
80 if assets is None: | |
81 return {} | |
72 | 82 |
73 def copyAssets(self, dest_dir): | 83 app = source.app |
74 raise NotImplementedError() | 84 stack = app.env.render_ctx_stack |
85 cur_ctx = stack.current_ctx | |
86 if cur_ctx is not None: | |
87 cur_ctx.current_pass_info.used_assets = True | |
75 | 88 |
76 class Assetor(AssetorBase): | 89 # base_url = build_base_url(app, self._uri, rel_assets_dir) |
77 debug_render_doc = """Helps render URLs to files in the current page's | |
78 asset folder.""" | |
79 debug_render = [] | |
80 debug_render_dynamic = ['_debugRenderAssetNames'] | |
81 | |
82 def findAssets(self): | |
83 assets = {} | |
84 name, ext = os.path.splitext(self._page.path) | |
85 assets_dir = name + ASSET_DIR_SUFFIX | |
86 if not os.path.isdir(assets_dir): | |
87 return assets | |
88 | |
89 rel_assets_dir = os.path.relpath(assets_dir, self._page.app.root_dir) | |
90 base_url = build_base_url(self._page.app, self._uri, rel_assets_dir) | |
91 for fn in os.listdir(assets_dir): | |
92 full_fn = os.path.join(assets_dir, fn) | |
93 if not os.path.isfile(full_fn): | |
94 raise Exception("Skipping: %s" % full_fn) | |
95 continue | |
96 | |
97 name, ext = os.path.splitext(fn) | |
98 if name in assets: | |
99 raise UnsupportedAssetsError( | |
100 "Multiple asset files are named '%s'." % name) | |
101 assets[name] = (base_url + fn, full_fn) | |
102 | |
103 cpi = self._page.app.env.exec_info_stack.current_page_info | |
104 if cpi is not None: | |
105 cpi.render_ctx.current_pass_info.used_assets = True | |
106 | 90 |
107 return assets | 91 return assets |
108 | 92 |
109 def copyAssets(self, dest_dir): | 93 def copyAssets(self, dest_dir): |
110 page_pathname, _ = os.path.splitext(self._page.path) | 94 page_pathname, _ = os.path.splitext(self._page.path) |
113 full_fn = os.path.join(in_assets_dir, fn) | 97 full_fn = os.path.join(in_assets_dir, fn) |
114 if os.path.isfile(full_fn): | 98 if os.path.isfile(full_fn): |
115 dest_ap = os.path.join(dest_dir, fn) | 99 dest_ap = os.path.join(dest_dir, fn) |
116 logger.debug(" %s -> %s" % (full_fn, dest_ap)) | 100 logger.debug(" %s -> %s" % (full_fn, dest_ap)) |
117 shutil.copy(full_fn, dest_ap) | 101 shutil.copy(full_fn, dest_ap) |
102 |