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: Created Sept. 25, 2017, 7:12 p.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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 325
326 def __exit__(self, exc_type, exc_value, tb): 326 def __exit__(self, exc_type, exc_value, tb):
327 return any(base.__exit__(exc_type, exc_value, tb) 327 return any(base.__exit__(exc_type, exc_value, tb)
328 for base in self._bases) 328 for base in self._bases)
329 329
330 def close(self): 330 def close(self):
331 for base in self._bases: 331 for base in self._bases:
332 base.close() 332 base.close()
333 333
334 def has_file(self, filename): 334 def has_file(self, filename):
335 for base in self._bases: 335 return any(base.has_file(filename) for base in self._bases)
Sebastian Noack 2017/09/27 02:47:53 Nit: You could use any() here as well: return a
Vasily Kuznetsov 2017/09/27 11:34:39 Done.
336 if base.has_file(filename):
337 return True
338 return False
339 336
340 def read_file(self, filename, binary=False): 337 def read_file(self, filename, binary=False):
341 for base in self._bases: 338 for base in self._bases:
342 if base.has_file(filename): 339 if base.has_file(filename):
343 return base.read_file(filename, binary) 340 return base.read_file(filename, binary)
344 raise KeyError('File not found {}'.format(filename)) 341 raise KeyError('File not found {}'.format(filename))
345 342
346 def list_files(self, subdir): 343 def list_files(self, subdir):
347 files = set() 344 return {f for base in self._bases for f in base.list_files(subdir)}
348 for base in self._bases:
349 files.update(base.list_files(subdir))
350 return sorted(files)
Sebastian Noack 2017/09/27 02:47:53 Nit: This could be written as a set literal one-li
Vasily Kuznetsov 2017/09/27 11:34:39 Done. Thanks for this suggestion. Having thought
Sebastian Noack 2017/09/27 15:55:22 The type returned here doesn't seem to be importan
Vasily Kuznetsov 2017/09/28 09:08:17 Fair enough. Done.
351 345
352 346
353 def _memoize(func): 347 def _memoize(func):
354 """Cache results of functions calls.""" 348 """Cache results of functions calls."""
355 memoized = {} 349 memoized = {}
356 350
357 def wrapper(*args): 351 def wrapper(*args):
358 try: 352 try:
359 return memoized[args] 353 return memoized[args]
360 except KeyError: 354 except KeyError:
361 return memoized.setdefault(args, func(*args)) 355 return memoized.setdefault(args, func(*args))
362 wrapper.cache_clear = memoized.clear 356 wrapper.cache_clear = memoized.clear
363 return wrapper 357 return wrapper
364 358
365 359
366 def create_source(path, static=False, revision='default'): 360 def create_source(path, cached=False, revision=None):
Sebastian Noack 2017/09/27 02:47:53 I would rather implement this in Source.__new__, s
Vasily Kuznetsov 2017/09/27 11:34:38 Here I prefer my implementation for the following
367 """Create a source from path and optional revision. 361 """Create a source from path and optional revision.
368 362
369 `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
370 its caching behavior: 364 if no changes are expected on the filesystem after the source was created.
371 - If `static` is `True`, we use version-control-aware `MercurialSource`, 365 This is usually the case with static generation (as opposed to dynamic
372 pass the revision and cache the results of most used functions. 366 preview).
373 - If `static` is `False` (as is the case with the preview server), we use 367
374 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
375 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.
376 372
377 If `settings.ini` in the source contains `[paths]` section with an 373 If `settings.ini` in the source contains `[paths]` section with an
378 `additional-paths` key that contains the list of additional root folders, 374 `additional-paths` key that contains the list of additional root folders,
379 `MultiSource` will be instantiated and its bases will be the original 375 `MultiSource` will be instantiated and its bases will be the original
380 source plus an additional source for each additional root folder. 376 source plus an additional source for each additional root folder.
381 `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
382 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
383 original source doesn't contain that file. 379 original source doesn't contain that file.
384 """ 380 """
385 if static: 381 if revision is not None:
386 source = MercurialSource(path, revision) 382 source = MercurialSource(path, revision)
387 else: 383 else:
388 source = FileSource(path) 384 source = FileSource(path)
389 385
390 config = source.read_config() 386 config = source.read_config()
391 try: 387 try:
392 ap = config.get('paths', 'additional-paths').strip() 388 ap = config.get('paths', 'additional-paths').strip()
393 additional_paths = filter(None, ap.split()) 389 additional_paths = filter(None, ap.split())
394 except ConfigParser.NoSectionError: 390 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
395 additional_paths = [] 391 additional_paths = []
396 392
397 if additional_paths: 393 if additional_paths:
398 additional_sources = [ 394 additional_sources = [
399 create_source(os.path.join(path, p)) 395 create_source(os.path.join(path, p))
400 for p in additional_paths 396 for p in additional_paths
401 ] 397 ]
402 source = MultiSource([source] + additional_sources) 398 source = MultiSource([source] + additional_sources)
403 399
404 if static: 400 if cached:
405 for fname in [ 401 for fname in [
406 'resolve_link', 402 'resolve_link',
407 'read_config', 403 'read_config',
408 'read_template', 404 'read_template',
409 'read_locale', 405 'read_locale',
410 'read_include', 406 'read_include',
411 'exec_file', 407 'exec_file',
412 ]: 408 ]:
413 setattr(source, fname, _memoize(getattr(source, fname))) 409 setattr(source, fname, _memoize(getattr(source, fname)))
414 410
415 return source 411 return source
LEFTRIGHT

Powered by Google App Engine
This is Rietveld