Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: cms/sources.py

Issue 29555839: Issue 5336 - Allow additional include, page, and template paths using CMS (Closed)
Left Patch Set: Address comments on PS1 Created Sept. 27, 2017, 11:33 a.m.
Right Patch Set: Rename 'static' parameter to 'cached' Created Oct. 2, 2017, 10:49 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « cms/bin/test_server.py ('k') | tests/__init__.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # This file is part of the Adblock Plus web scripts, 1 # This file is part of the Adblock Plus web scripts,
2 # Copyright (C) 2006-present eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 def has_file(self, filename): 334 def has_file(self, filename):
335 return any(base.has_file(filename) for base in self._bases) 335 return any(base.has_file(filename) for base in self._bases)
336 336
337 def read_file(self, filename, binary=False): 337 def read_file(self, filename, binary=False):
338 for base in self._bases: 338 for base in self._bases:
339 if base.has_file(filename): 339 if base.has_file(filename):
340 return base.read_file(filename, binary) 340 return base.read_file(filename, binary)
341 raise KeyError('File not found {}'.format(filename)) 341 raise KeyError('File not found {}'.format(filename))
342 342
343 def list_files(self, subdir): 343 def list_files(self, subdir):
344 return list({f for base in self._bases 344 return {f for base in self._bases for f in base.list_files(subdir)}
345 for f in base.list_files(subdir)})
346 345
347 346
348 def _memoize(func): 347 def _memoize(func):
349 """Cache results of functions calls.""" 348 """Cache results of functions calls."""
350 memoized = {} 349 memoized = {}
351 350
352 def wrapper(*args): 351 def wrapper(*args):
353 try: 352 try:
354 return memoized[args] 353 return memoized[args]
355 except KeyError: 354 except KeyError:
356 return memoized.setdefault(args, func(*args)) 355 return memoized.setdefault(args, func(*args))
357 wrapper.cache_clear = memoized.clear 356 wrapper.cache_clear = memoized.clear
358 return wrapper 357 return wrapper
359 358
360 359
361 def create_source(path, static=False, revision='default'): 360 def create_source(path, cached=False, revision=None):
362 """Create a source from path and optional revision. 361 """Create a source from path and optional revision.
363 362
364 `static` flag determines the type of the source that will be created and 363 `cached` flag activates caching. This can be used to optimize performance
365 its caching behavior: 364 if no changes are expected on the filesystem after the source was created.
366 - If `static` is `True`, we use version-control-aware `MercurialSource`, 365 This is usually the case with static generation (as opposed to dynamic
367 pass the revision and cache the results of most used functions. 366 preview).
368 - If `static` is `False` (as is the case with the preview server), we use 367
369 simpler `FileSource` and don't cache anything to be able to respond to 368 If `revision` option is provided, the `path` is assumed to be pointing to a
370 changes on the filesystem. 369 Mercurial repository. In this case the source will return the content of
370 selected revision (using `MercurialSource`) instead of the content of the
371 directory. Note that any local changes will be ignored in this case.
371 372
372 If `settings.ini` in the source contains `[paths]` section with an 373 If `settings.ini` in the source contains `[paths]` section with an
373 `additional-paths` key that contains the list of additional root folders, 374 `additional-paths` key that contains the list of additional root folders,
374 `MultiSource` will be instantiated and its bases will be the original 375 `MultiSource` will be instantiated and its bases will be the original
375 source plus an additional source for each additional root folder. 376 source plus an additional source for each additional root folder.
376 `MultiSource` looks up files in its base sources in the order they are 377 `MultiSource` looks up files in its base sources in the order they are
377 provided, so the files in the additional folders will only be used if the 378 provided, so the files in the additional folders will only be used if the
378 original source doesn't contain that file. 379 original source doesn't contain that file.
379 """ 380 """
380 if static: 381 if revision is not None:
381 source = MercurialSource(path, revision) 382 source = MercurialSource(path, revision)
382 else: 383 else:
383 source = FileSource(path) 384 source = FileSource(path)
384 385
385 config = source.read_config() 386 config = source.read_config()
386 try: 387 try:
387 ap = config.get('paths', 'additional-paths').strip() 388 ap = config.get('paths', 'additional-paths').strip()
388 additional_paths = filter(None, ap.split()) 389 additional_paths = filter(None, ap.split())
389 except ConfigParser.NoSectionError: 390 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
390 additional_paths = [] 391 additional_paths = []
391 392
392 if additional_paths: 393 if additional_paths:
393 additional_sources = [ 394 additional_sources = [
394 create_source(os.path.join(path, p)) 395 create_source(os.path.join(path, p))
395 for p in additional_paths 396 for p in additional_paths
396 ] 397 ]
397 source = MultiSource([source] + additional_sources) 398 source = MultiSource([source] + additional_sources)
398 399
399 if static: 400 if cached:
400 for fname in [ 401 for fname in [
401 'resolve_link', 402 'resolve_link',
402 'read_config', 403 'read_config',
403 'read_template', 404 'read_template',
404 'read_locale', 405 'read_locale',
405 'read_include', 406 'read_include',
406 'exec_file', 407 'exec_file',
407 ]: 408 ]:
408 setattr(source, fname, _memoize(getattr(source, fname))) 409 setattr(source, fname, _memoize(getattr(source, fname)))
409 410
410 return source 411 return source
LEFTRIGHT

Powered by Google App Engine
This is Rietveld