comparison piecrust/data/assetor.py @ 862:fddaf43424e2

refactor: Get the page assets to work again in the server.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 08 Jun 2017 23:09:34 -0700
parents f070a4fc033c
children 757fba54bfd3
comparison
equal deleted inserted replaced
861:d214918d4d2c 862:fddaf43424e2
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 import collections.abc
5 from piecrust import ASSET_DIR_SUFFIX 6 from piecrust import ASSET_DIR_SUFFIX
6 from piecrust.sources.base import REL_ASSETS 7 from piecrust.sources.base import REL_ASSETS
7 from piecrust.uriutil import multi_replace 8 from piecrust.uriutil import multi_replace
8 9
9 10
12 13
13 class UnsupportedAssetsError(Exception): 14 class UnsupportedAssetsError(Exception):
14 pass 15 pass
15 16
16 17
17 def build_base_url(app, uri, rel_assets_path): 18 class _AssetInfo:
18 base_url_format = app.config.get('site/base_asset_url_format') 19 def __init__(self, content_item, uri):
19 rel_assets_path = rel_assets_path.replace('\\', '/') 20 self.content_item = content_item
20 21 self.uri = uri
21 # Remove any extension since we'll be copying assets into the 1st
22 # sub-page's folder.
23 pretty = app.config.get('site/pretty_urls')
24 if not pretty:
25 uri, _ = os.path.splitext(uri)
26
27 base_url = multi_replace(
28 base_url_format,
29 {
30 '%path%': rel_assets_path,
31 '%uri%': uri})
32
33 return base_url.rstrip('/') + '/'
34 22
35 23
36 class Assetor: 24 class Assetor(collections.abc.Mapping):
37 debug_render_doc = """Helps render URLs to files in the current page's 25 debug_render_doc = """Helps render URLs to files in the current page's
38 asset folder.""" 26 asset folder."""
39 debug_render = [] 27 debug_render = []
40 debug_render_dynamic = ['_debugRenderAssetNames'] 28 debug_render_dynamic = ['_debugRenderAssetNames']
41 29
44 self._cache = None 32 self._cache = None
45 33
46 def __getattr__(self, name): 34 def __getattr__(self, name):
47 try: 35 try:
48 self._cacheAssets() 36 self._cacheAssets()
49 return self._cache[name][0] 37 return self._cache[name].uri
50 except KeyError: 38 except KeyError:
51 raise AttributeError() 39 raise AttributeError()
52 40
53 def __getitem__(self, key): 41 def __getitem__(self, key):
54 self._cacheAssets() 42 self._cacheAssets()
55 return self._cache[key][0] 43 return self._cache[key].uri
56 44
57 def __iter__(self): 45 def __iter__(self):
58 self._cacheAssets() 46 self._cacheAssets()
59 return map(lambda i: i[0], self._cache.values()) 47 return self._cache.keys()
60 48
61 def allNames(self): 49 def __len__(self):
62 self._cacheAssets() 50 self._cacheAssets()
63 return list(self._cache.keys()) 51 return len(self._cache)
64 52
65 def _debugRenderAssetNames(self): 53 def _debugRenderAssetNames(self):
66 self._cacheAssets() 54 self._cacheAssets()
67 return list(self._cache.keys()) 55 return list(self._cache.keys())
68 56
69 def _cacheAssets(self): 57 def _cacheAssets(self):
70 if self._cache is not None: 58 if self._cache is not None:
71 return 59 return
72 60
73 self._cache = self.findAssets() or {} 61 source = self._page.source
62 content_item = self._page.content_item
74 63
75 def findAssets(self): 64 assets = source.getRelatedContents(content_item, REL_ASSETS)
76 content_item = self._page.content_item
77 source = content_item.source
78 assets = source.getRelatedContent(content_item, REL_ASSETS)
79 if assets is None: 65 if assets is None:
80 return {} 66 self._cache = {}
67 return
68
69 self._cache = {}
81 70
82 app = source.app 71 app = source.app
72 root_dir = app.root_dir
73 asset_url_format = app.config.get('site/asset_url_format')
74
75 page_uri = self._page.getUri()
76 pretty_urls = app.config.get('site/pretty_urls')
77 if not pretty_urls:
78 page_uri, _ = os.path.splitext(page_uri)
79
80 uri_build_tokens = {
81 '%path%': None,
82 '%filename%': None,
83 '%page_uri%': page_uri
84 }
85
86 for a in assets:
87 name = a.metadata['name']
88 if name in self._cache:
89 raise UnsupportedAssetsError(
90 "An asset with name '%s' already exists for item '%s'. "
91 "Do you have multiple assets with colliding names?" %
92 (name, content_item.spec))
93
94 # TODO: this assumes a file-system source!
95 uri_build_tokens['%path%'] = (
96 os.path.relpath(a.spec, root_dir).replace('\\', '/'))
97 uri_build_tokens['%filename%'] = a.metadata['filename'],
98 uri = multi_replace(asset_url_format, uri_build_tokens)
99
100 self._cache[name] = _AssetInfo(a, uri)
101
83 stack = app.env.render_ctx_stack 102 stack = app.env.render_ctx_stack
84 cur_ctx = stack.current_ctx 103 cur_ctx = stack.current_ctx
85 if cur_ctx is not None: 104 if cur_ctx is not None:
86 cur_ctx.current_pass_info.used_assets = True 105 cur_ctx.current_pass_info.used_assets = True
87
88 # base_url = build_base_url(app, self._uri, rel_assets_dir)
89
90 return assets
91 106
92 def copyAssets(self, dest_dir): 107 def copyAssets(self, dest_dir):
93 page_pathname, _ = os.path.splitext(self._page.path) 108 page_pathname, _ = os.path.splitext(self._page.path)
94 in_assets_dir = page_pathname + ASSET_DIR_SUFFIX 109 in_assets_dir = page_pathname + ASSET_DIR_SUFFIX
95 for fn in os.listdir(in_assets_dir): 110 for fn in os.listdir(in_assets_dir):