# HG changeset patch # User Ludovic Chabant # Date 1407821807 25200 # Node ID 474c9882decf1a9c37ff345af5b7835531c09f2e # Parent 7dc71c2dc9a8511ff98f039d71c255580bf31cbe Upgrade to Python 3. diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/app.py --- a/piecrust/app.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/app.py Mon Aug 11 22:36:47 2014 -0700 @@ -58,7 +58,7 @@ self._values = self._validateAll({}) return - path_times = map(lambda p: os.path.getmtime(p), self.paths) + path_times = [os.path.getmtime(p) for p in self.paths] cache_key = hashlib.md5("version=%s&cache=%d" % ( APP_VERSION, CACHE_VERSION)).hexdigest() @@ -122,7 +122,7 @@ sitec = values.get('site') if sitec is None: sitec = {} - for key, val in default_sitec.iteritems(): + for key, val in default_sitec.items(): sitec.setdefault(key, val) values['site'] = sitec @@ -135,7 +135,7 @@ raise ConfigurationError("The 'site/auto_formats' setting must be a dictionary.") cachec['auto_formats_re'] = r"\.(%s)$" % ( '|'.join( - map(lambda i: re.escape(i), sitec['auto_formats'].keys()))) + [re.escape(i) for i in list(sitec['auto_formats'].keys())])) if sitec['default_auto_format'] not in sitec['auto_formats']: raise ConfigurationError("Default auto-format '%s' is not declared." % sitec['default_auto_format']) @@ -254,7 +254,7 @@ # Add the theme page source if no sources were defined in the theme # configuration itself. has_any_theme_source = False - for sn, sc in sourcesc.iteritems(): + for sn, sc in sourcesc.items(): if sc.get('realm') == REALM_THEME: has_any_theme_source = True break @@ -272,7 +272,7 @@ # Sources have the `default` scanner by default, duh. Also, a bunch # of other default values for other configuration stuff. - for sn, sc in sourcesc.iteritems(): + for sn, sc in sourcesc.items(): if not isinstance(sc, dict): raise ConfigurationError("All sources in 'site/sources' must be dictionaries.") sc.setdefault('type', 'default') @@ -296,7 +296,7 @@ raise ConfigurationError("Route URLs must start with '/'.") if rc.get('source') is None: raise ConfigurationError("Routes must specify a source.") - if rc['source'] not in sourcesc.keys(): + if rc['source'] not in list(sourcesc.keys()): raise ConfigurationError("Route is referencing unknown source: %s" % rc['source']) rc.setdefault('taxonomy', None) @@ -305,7 +305,7 @@ # Validate taxonomies. sitec.setdefault('taxonomies', {}) taxonomiesc = sitec.get('taxonomies') - for tn, tc in taxonomiesc.iteritems(): + for tn, tc in taxonomiesc.items(): tc.setdefault('multiple', False) tc.setdefault('term', tn) tc.setdefault('page', '_%s.%%ext%%' % tc['term']) @@ -314,7 +314,7 @@ reserved_endpoints = set(['piecrust', 'site', 'page', 'route', 'assets', 'pagination', 'siblings', 'family']) - for name, src in sitec['sources'].iteritems(): + for name, src in sitec['sources'].items(): endpoint = src['data_endpoint'] if endpoint in reserved_endpoints: raise ConfigurationError( @@ -366,10 +366,10 @@ tplc = sitec.get('templates_dirs') if tplc is None: return - if isinstance(tplc, types.StringTypes): + if isinstance(tplc, str): tplc = [tplc] - sitec['templates_dirs'] = filter(tplc, - lambda p: os.path.join(self.theme_dir, p)) + sitec['templates_dirs'] = list(filter(tplc, + lambda p: os.path.join(self.theme_dir, p))) config.fixups.append(_fixupThemeTemplatesDir) # We'll also need to flag all page sources as coming from @@ -383,7 +383,7 @@ config['site'] = sitec srcc = sitec.get('sources') if srcc is not None: - for sn, sc in srcc.iteritems(): + for sn, sc in srcc.items(): sc['realm'] = REALM_THEME config.fixups.append(_fixupThemeSources) @@ -425,7 +425,7 @@ defs[cls.SOURCE_NAME] = cls sources = [] - for n, s in self.config.get('site/sources').iteritems(): + for n, s in self.config.get('site/sources').items(): cls = defs.get(s['type']) if cls is None: raise ConfigurationError("No such page source type: %s" % s['type']) @@ -444,7 +444,7 @@ @cached_property def taxonomies(self): taxonomies = [] - for tn, tc in self.config.get('site/taxonomies').iteritems(): + for tn, tc in self.config.get('site/taxonomies').items(): tax = Taxonomy(self, tn, tc) taxonomies.append(tax) return taxonomies @@ -491,11 +491,10 @@ # Add custom directories from the configuration. conf_dirs = self.config.get(conf_name) if conf_dirs is not None: - if isinstance(conf_dirs, types.StringTypes): + if isinstance(conf_dirs, str): dirs.append(os.path.join(self.root_dir, conf_dirs)) else: - dirs += filter(lambda p: os.path.join(self.root_dir, p), - conf_dirs) + dirs += [p for p in conf_dirs if os.path.join(self.root_dir, p)] # Add the default directory if it exists. default_dir = os.path.join(self.root_dir, default_rel_dir) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/baking/baker.py --- a/piecrust/baking/baker.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/baking/baker.py Mon Aug 11 22:36:47 2014 -0700 @@ -1,11 +1,11 @@ import time import os.path import codecs -import urllib2 +import urllib.request, urllib.error, urllib.parse import hashlib import logging import threading -from Queue import Queue, Empty +from queue import Queue, Empty from piecrust.baking.records import TransitionalBakeRecord, BakeRecordPageEntry from piecrust.chefutil import format_timed from piecrust.data.filters import (PaginationFilter, HasFilterClause, @@ -61,7 +61,7 @@ def getOutputPath(self, uri): bake_path = [self.out_dir] - decoded_uri = urllib2.unquote(uri.lstrip('/')).decode('utf8') + decoded_uri = urllib.parse.unquote(uri.lstrip('/')).decode('utf8') if self.pretty_urls: bake_path.append(decoded_uri) bake_path.append('index.html') @@ -188,7 +188,7 @@ out_dir = os.path.dirname(out_path) if not os.path.isdir(out_dir): - os.makedirs(out_dir, 0755) + os.makedirs(out_dir, 0o755) with codecs.open(out_path, 'w', 'utf-8') as fp: fp.write(rp.content.decode('utf-8')) @@ -228,7 +228,7 @@ # Make sure the output directory exists. if not os.path.isdir(self.out_dir): - os.makedirs(self.out_dir, 0755) + os.makedirs(self.out_dir, 0o755) # Load/create the bake record. record = TransitionalBakeRecord() @@ -313,7 +313,7 @@ # Now see which ones are 'dirty' based on our bake record. logger.debug("Gathering dirty taxonomy terms") - for prev_entry, cur_entry in record.transitions.itervalues(): + for prev_entry, cur_entry in record.transitions.values(): for tax in self.app.taxonomies: changed_terms = None # Re-bake all taxonomy pages that include new or changed @@ -343,7 +343,7 @@ # Re-bake the combination pages for terms that are 'dirty'. known_combinations = set() logger.debug("Gathering dirty term combinations") - for prev_entry, cur_entry in record.transitions.itervalues(): + for prev_entry, cur_entry in record.transitions.values(): if cur_entry: known_combinations |= cur_entry.used_taxonomy_terms elif prev_entry: @@ -355,8 +355,8 @@ # Start baking those terms. pool, queue, abort = self._createWorkerPool(record, self.num_workers) - for source_name, source_taxonomies in buckets.iteritems(): - for tax_name, terms in source_taxonomies.iteritems(): + for source_name, source_taxonomies in buckets.items(): + for tax_name, terms in source_taxonomies.items(): if len(terms) == 0: continue diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/baking/records.py --- a/piecrust/baking/records.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/baking/records.py Mon Aug 11 22:36:47 2014 -0700 @@ -84,7 +84,7 @@ return None def collapseRecords(self): - for pair in self.transitions.itervalues(): + for pair in self.transitions.values(): prev = pair[0] cur = pair[1] diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/cache.py --- a/piecrust/cache.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/cache.py Mon Aug 11 22:36:47 2014 -0700 @@ -26,7 +26,7 @@ if c is None: c_dir = os.path.join(self.base_dir, name) if not os.path.isdir(c_dir): - os.makedirs(c_dir, 0755) + os.makedirs(c_dir, 0o755) c = SimpleCache(c_dir) self.caches[name] = c @@ -71,7 +71,7 @@ cache_path = self.getCachePath(path) cache_dir = os.path.dirname(cache_path) if not os.path.isdir(cache_dir): - os.makedirs(cache_dir, 0755) + os.makedirs(cache_dir, 0o755) with codecs.open(cache_path, 'w', 'utf-8') as fp: fp.write(content) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/commands/builtin/info.py --- a/piecrust/commands/builtin/info.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/commands/builtin/info.py Mon Aug 11 22:36:47 2014 -0700 @@ -106,7 +106,7 @@ sources = list(ctx.app.sources) if ctx.args.endpoint: endpoints = ctx.args.endpoint - sources = filter(lambda s: s.endpoint in endpoints, sources) + sources = [s for s in sources if s.endpoint in endpoints] for src in sources: page_facs = src.getPageFactories() for pf in page_facs: @@ -116,7 +116,7 @@ name = pf.path if ctx.args.metadata: logger.info("path:%s" % pf.path) - for key, val in pf.metadata.iteritems(): + for key, val in pf.metadata.items(): logger.info("%s:%s" % (key, val)) logger.info("---") else: diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/commands/builtin/util.py --- a/piecrust/commands/builtin/util.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/commands/builtin/util.py Mon Aug 11 22:36:47 2014 -0700 @@ -29,11 +29,11 @@ destination = os.getcwd() if not os.path.isdir(destination): - os.makedirs(destination, 0755) + os.makedirs(destination, 0o755) config_path = os.path.join(destination, CONFIG_PATH) if not os.path.isdir(os.path.dirname(config_path)): - os.makedirs(os.path.dirname(config_path), 0755) + os.makedirs(os.path.dirname(config_path), 0o755) config_text = yaml.dump({ 'site': { @@ -96,7 +96,7 @@ logger.info("Creating page: %s" % os.path.relpath(page_path, app.root_dir)) if not os.path.exists(os.path.dirname(page_path)): - os.makedirs(os.path.dirname(page_path), 0755) + os.makedirs(os.path.dirname(page_path), 0o755) with open(page_path, 'w') as f: f.write('---\n') f.write('title: %s\n' % 'Unknown title') diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/configuration.py --- a/piecrust/configuration.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/configuration.py Mon Aug 11 22:36:47 2014 -0700 @@ -89,7 +89,7 @@ def _recurse_merge_dicts(local_cur, incoming_cur, parent_path, validator): - for k, v in incoming_cur.iteritems(): + for k, v in incoming_cur.items(): key_path = k if parent_path is not None: key_path = parent_path + '/' + k @@ -113,7 +113,7 @@ def parse_config_header(text): m = header_regex.match(text) if m is not None: - header = unicode(m.group('header')) + header = str(m.group('header')) config = yaml.load(header, Loader=yaml.BaseLoader) offset = m.end() else: diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/assetor.py --- a/piecrust/data/assetor.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/assetor.py Mon Aug 11 22:36:47 2014 -0700 @@ -55,7 +55,7 @@ def _debugRenderAssetNames(self): self._cacheAssets() - return self._cache.keys() + return list(self._cache.keys()) def _cacheAssets(self): if self._cache is not None: diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/base.py --- a/piecrust/data/base.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/base.py Mon Aug 11 22:36:47 2014 -0700 @@ -96,7 +96,7 @@ logger.exception("Error rendering segments for '%s': %s" % (uri, e)) raise - for k, v in segs.iteritems(): + for k, v in segs.items(): data.mapLoader(k, None) data.setValue(k, v) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/builder.py --- a/piecrust/data/builder.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/builder.py Mon Aug 11 22:36:47 2014 -0700 @@ -59,7 +59,7 @@ def build_layout_data(page, page_data, contents): data = dict(page_data) - for name, txt in contents.iteritems(): + for name, txt in contents.items(): if name in data: logger.warning("Content segment '%s' will hide existing data." % name) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/debug.py --- a/piecrust/data/debug.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/debug.py Mon Aug 11 22:36:47 2014 -0700 @@ -1,8 +1,9 @@ import re import cgi import logging -import StringIO +import io from piecrust import APP_VERSION, PIECRUST_URL +import collections logger = logging.getLogger(__name__) @@ -49,7 +50,7 @@ def build_debug_info(page, data): """ Generates HTML debug info for the given page's data. """ - output = StringIO.StringIO() + output = io.StringIO() try: _do_build_debug_info(page, data, output) return output.getvalue() @@ -61,10 +62,10 @@ app = page.app exec_info = app.env.exec_info_stack.current_page_info - print >>output, '
' % CSS_DEBUGINFO + print('
' % CSS_DEBUGINFO, file=output) - print >>output, '
' - print >>output, '

PieCrust %s — ' % (CSS_P, APP_VERSION) + print('

', file=output) + print('

PieCrust %s — ' % (CSS_P, APP_VERSION), file=output) # If we have some execution info in the environment, # add more information. @@ -91,25 +92,25 @@ else: output.write('no timing information available') - print >>output, '

' - print >>output, '
' + print('

', file=output) + print('
', file=output) if data: - print >>output, '
' - print >>output, ('

' % CSS_P) - print >>output, ('Template engine data ' - '— click to toggle.

' % CSS_BIGHEADER) + '\'block\'; else l.style.display = \'none\';">' % CSS_P), file=output) + print(('Template engine data ' + '— click to toggle.

' % CSS_BIGHEADER), file=output) - print >>output, '' + print('
', file=output) + print('
', file=output) - print >>output, '
' + print('', file=output) class DebugDataRenderer(object): @@ -174,7 +175,7 @@ self._write('%4.2f' % (CSS_VALUE, data)) return - if data_type in (str, unicode): + if data_type in (str, str): if data_type == str: data = data.decode('utf8') if len(data) > DebugDataRenderer.MAX_VALUE_LENGTH: @@ -203,7 +204,7 @@ self._renderDoc(data, path) self._renderAttributes(data, path) rendered_count = self._renderIterable(data, path, - lambda d: sorted(d.iteritems(), key=lambda i: i[0])) + lambda d: sorted(iter(d.items()), key=lambda i: i[0])) if rendered_count == 0: self._writeLine('

(empty dictionary)

' % (CSS_P, CSS_DOC)) self._writeLine('') @@ -289,7 +290,7 @@ # dynamic attribute. attr = getattr(data, name) - if callable(attr): + if isinstance(attr, collections.Callable): attr_func = getattr(data, name) argcount = attr_func.__code__.co_argcount var_names = attr_func.__code__.co_varnames diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/filters.py --- a/piecrust/data/filters.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/filters.py Mon Aug 11 22:36:47 2014 -0700 @@ -30,7 +30,7 @@ self.root_clause = AndBooleanClause() def _addClausesFromConfigRecursive(self, config, parent_clause): - for key, val in config.iteritems(): + for key, val in config.items(): if key == 'and': if not isinstance(val, list) or len(val) == 0: raise Exception("The given boolean 'AND' filter clause " @@ -145,7 +145,7 @@ return False if self.coercer: - actual_value = map(self.coercer, actual_value) + actual_value = list(map(self.coercer, actual_value)) return self.value in actual_value diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/paginator.py --- a/piecrust/data/paginator.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/paginator.py Mon Aug 11 22:36:47 2014 -0700 @@ -152,7 +152,7 @@ return [] if radius <= 0 or total_page_count < (2 * radius + 1): - return range(1, total_page_count) + return list(range(1, total_page_count)) first_num = self._page_num - radius last_num = self._page_num + radius @@ -164,7 +164,7 @@ last_num = total_page_count first_num = max(1, first_num) last_num = min(total_page_count, last_num) - return range(first_num, last_num) + return list(range(first_num, last_num)) def page(self, index): return self._getPageUri(index) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/data/provider.py --- a/piecrust/data/provider.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/data/provider.py Mon Aug 11 22:36:47 2014 -0700 @@ -28,7 +28,7 @@ def _debugRenderUserData(self): if self._user_data: - return self._user_data.keys() + return list(self._user_data.keys()) return [] @@ -121,7 +121,7 @@ year = post.datetime.strftime('%Y') posts_this_year = next( - itertools.ifilter(lambda y: y.name == year, self._yearly), + filter(lambda y: y.name == year, self._yearly), None) if posts_this_year is None: timestamp = time.mktime( @@ -146,7 +146,7 @@ month = post.datetime.strftime('%B %Y') posts_this_month = next( - itertools.ifilter(lambda m: m.name == month, self._monthly), + filter(lambda m: m.name == month, self._monthly), None) if posts_this_month is None: timestamp = time.mktime( @@ -177,7 +177,7 @@ posts_by_tax_value[val].append(post) entries = [] - for value, ds in posts_by_tax_value.iteritems(): + for value, ds in posts_by_tax_value.items(): source = ArraySource(self._page.app, ds) entries.append(BlogTaxonomyEntry(self._page, source, value)) self._taxonomies[tax_name] = sorted(entries, key=lambda k: k.name) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/page.py --- a/piecrust/page.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/page.py Mon Aug 11 22:36:47 2014 -0700 @@ -135,7 +135,7 @@ def json_load_segments(data): segments = {} - for key, seg_data in data.iteritems(): + for key, seg_data in data.items(): seg = ContentSegment() for p_data in seg_data: part = ContentSegmentPart(p_data['c'], p_data['f'], p_data['l']) @@ -146,7 +146,7 @@ def json_save_segments(segments): data = {} - for key, seg in segments.iteritems(): + for key, seg in segments.items(): seg_data = [] for part in seg.parts: p_data = {'c': part.content, 'f': part.fmt, 'l': part.line} @@ -162,7 +162,7 @@ logger.exception("Error loading page: %s" % os.path.relpath(path, app.root_dir)) _, __, traceback = sys.exc_info() - raise PageLoadingError(path, e), None, traceback + raise PageLoadingError(path, e).with_traceback(traceback) def _do_load_page(app, path): @@ -197,7 +197,7 @@ config = PageConfiguration(header) content = parse_segments(raw, offset) - config.set('segments', list(content.iterkeys())) + config.set('segments', list(content.keys())) # Save to the cache. cache_data = { diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/processing/base.py --- a/piecrust/processing/base.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/processing/base.py Mon Aug 11 22:36:47 2014 -0700 @@ -4,7 +4,7 @@ import os.path import logging import threading -from Queue import Queue, Empty +from queue import Queue, Empty from piecrust.chefutil import format_timed from piecrust.processing.tree import (ProcessingTreeBuilder, ProcessingTreeRunner, STATE_DIRTY, print_node) @@ -183,7 +183,7 @@ # Process only the given path. # Find out if this source directory is in a mount point. base_dir = self.app.root_dir - for name, path in self.mounts.iteritems(): + for name, path in self.mounts.items(): if src_dir_or_file[:len(path)] == path: base_dir = path @@ -200,7 +200,7 @@ logger.debug("Initiating processing pipeline on: %s" % self.app.root_dir) self.processDirectory(ctx, self.app.root_dir) ctx.is_multi_mount = True - for name, path in self.mounts.iteritems(): + for name, path in self.mounts.items(): mount_ctx = ProcessingContext(path, queue, record) logger.debug("Initiating processing pipeline on: %s" % path) self.processDirectory(mount_ctx, path) @@ -325,7 +325,7 @@ .replace(r'\*', r'[^/\\]*') .replace(r'\?', r'[^/\\]')) re_patterns.append(escaped_pat) - return map(lambda p: re.compile(p), re_patterns) + return [re.compile(p) for p in re_patterns] def re_matchany(filename, patterns): diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/processing/less.py --- a/piecrust/processing/less.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/processing/less.py Mon Aug 11 22:36:47 2014 -0700 @@ -35,7 +35,7 @@ path_dir = os.path.dirname(path) def _makeAbs(p): return os.path.join(path_dir, p) - return map(_makeAbs, source[:-1]) + return list(map(_makeAbs, source[:-1])) except IOError: # Map file not found... rebuild. logger.debug("No map file found for LESS file '%s' at '%s'. " diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/processing/tree.py --- a/piecrust/processing/tree.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/processing/tree.py Mon Aug 11 22:36:47 2014 -0700 @@ -150,7 +150,7 @@ except Exception as e: import sys _, __, traceback = sys.exc_info() - raise Exception("Error processing: %s" % node.path, e), None, traceback + raise Exception("Error processing: %s" % node.path, e).with_traceback(traceback) # All outputs of a node must go to the same directory, so we can get # the output directory off of the first output. @@ -161,9 +161,9 @@ if self.lock: with self.lock: if not os.path.isdir(out_dir): - os.makedirs(out_dir, 0755) + os.makedirs(out_dir, 0o755) else: - os.makedirs(out_dir, 0755) + os.makedirs(out_dir, 0o755) try: start_time = time.clock() @@ -180,7 +180,7 @@ except Exception as e: import sys _, __, traceback = sys.exc_info() - raise Exception("Error processing: %s" % node.path, e), None, traceback + raise Exception("Error processing: %s" % node.path, e).with_traceback(traceback) def _computeNodeState(self, node): if node.state != STATE_UNKNOWN: diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/records.py --- a/piecrust/records.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/records.py Mon Aug 11 22:36:47 2014 -0700 @@ -5,7 +5,7 @@ from piecrust.events import Event try: - import cPickle as pickle + import pickle as pickle except ImportError: import pickle @@ -33,7 +33,7 @@ def save(self, path): path_dir = os.path.dirname(path) if not os.path.isdir(path_dir): - os.makedirs(path_dir, 0755) + os.makedirs(path_dir, 0o755) with open(path, 'w') as fp: pickle.dump(self, fp, pickle.HIGHEST_PROTOCOL) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/rendering.py --- a/piecrust/rendering.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/rendering.py Mon Aug 11 22:36:47 2014 -0700 @@ -136,8 +136,8 @@ raise PageRenderingError("Can't find template engine '%s'." % engine_name) formatted_content = {} - for seg_name, seg in page.raw_content.iteritems(): - seg_text = u'' + for seg_name, seg in page.raw_content.items(): + seg_text = '' for seg_part in seg.parts: part_format = seg_part.fmt or format_name part_text = engine.renderString(seg_part.content, page_data, diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/serving.py --- a/piecrust/serving.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/serving.py Mon Aug 11 22:36:47 2014 -0700 @@ -4,7 +4,7 @@ import os.path import hashlib import logging -import StringIO +import io from werkzeug.exceptions import (NotFound, MethodNotAllowed, InternalServerError) from werkzeug.serving import run_simple @@ -237,7 +237,7 @@ if ('gzip' in request.accept_encodings and app.config.get('site/enable_gzip')): try: - gzip_buffer = StringIO.StringIO() + gzip_buffer = io.StringIO() gzip_file = gzip.GzipFile( mode='wb', compresslevel=9, diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/sources/base.py --- a/piecrust/sources/base.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/sources/base.py Mon Aug 11 22:36:47 2014 -0700 @@ -103,7 +103,7 @@ self._page_ref = page_ref self._paths = None self._first_valid_path_index = -2 - self._exts = app.config.get('site/auto_formats').keys() + self._exts = list(app.config.get('site/auto_formats').keys()) @property def exists(self): @@ -266,7 +266,7 @@ super(SimplePageSource, self).__init__(app, name, config) self.fs_endpoint = config.get('fs_endpoint', name) self.fs_endpoint_path = os.path.join(self.root_dir, CONTENT_DIR, self.fs_endpoint) - self.supported_extensions = app.config.get('site/auto_formats').keys() + self.supported_extensions = list(app.config.get('site/auto_formats').keys()) def buildPageFactories(self): logger.debug("Scanning for pages in: %s" % self.fs_endpoint_path) @@ -275,7 +275,7 @@ for dirpath, dirnames, filenames in os.walk(self.fs_endpoint_path): rel_dirpath = os.path.relpath(dirpath, self.fs_endpoint_path) - dirnames[:] = filter(self._filterPageDirname, dirnames) + dirnames[:] = list(filter(self._filterPageDirname, dirnames)) for f in filter(self._filterPageFilename, filenames): slug, ext = os.path.splitext(os.path.join(rel_dirpath, f)) if slug.startswith('./') or slug.startswith('.\\'): diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/sources/posts.py --- a/piecrust/sources/posts.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/sources/posts.py Mon Aug 11 22:36:47 2014 -0700 @@ -20,7 +20,7 @@ super(PostsSource, self).__init__(app, name, config) self.fs_endpoint = config.get('fs_endpoint', name) self.fs_endpoint_path = os.path.join(self.root_dir, CONTENT_DIR, self.fs_endpoint) - self.supported_extensions = app.config.get('site/auto_formats').keys() + self.supported_extensions = list(app.config.get('site/auto_formats').keys()) @property def path_format(self): @@ -105,9 +105,7 @@ today = datetime.date.today() year, month, day = today.year, today.month, today.day if args.date: - year, month, day = filter( - lambda s: int(s), - args.date.split('/')) + year, month, day = [s for s in args.date.split('/') if int(s)] return {'year': year, 'month': month, 'day': day, 'slug': args.slug} def _checkFsEndpointPath(self): @@ -163,7 +161,7 @@ year_pattern = re.compile(r'(\d{4})$') file_pattern = re.compile(r'(\d{2})-(\d{2})_(.*)\.(\w+)$') _, year_dirs, __ = next(os.walk(self.fs_endpoint_path)) - year_dirs = filter(lambda d: year_pattern.match(d), year_dirs) + year_dirs = [d for d in year_dirs if year_pattern.match(d)] for yd in year_dirs: if year_pattern.match(yd) is None: logger.warning("'%s' is not formatted as 'YYYY' and will be ignored. " @@ -201,13 +199,13 @@ month_pattern = re.compile(r'(\d{2})$') file_pattern = re.compile(r'(\d{2})_(.*)\.(\w+)$') _, year_dirs, __ = next(os.walk(self.fs_endpoint_path)) - year_dirs = filter(lambda d: year_pattern.match(d), year_dirs) + year_dirs = [d for d in year_dirs if year_pattern.match(d)] for yd in year_dirs: year = int(yd) year_dir = os.path.join(self.fs_endpoint_path, yd) _, month_dirs, __ = next(os.walk(year_dir)) - month_dirs = filter(lambda d: month_pattern.match(d), month_dirs) + month_dirs = [d for d in month_dirs if month_pattern.match(d)] for md in month_dirs: month = int(md) month_dir = os.path.join(year_dir, md) diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/templating/jinjaengine.py --- a/piecrust/templating/jinjaengine.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/templating/jinjaengine.py Mon Aug 11 22:36:47 2014 -0700 @@ -36,7 +36,7 @@ tse.filename = filename import sys _, __, traceback = sys.exc_info() - raise tse, None, traceback + raise tse.with_traceback(traceback) def renderFile(self, paths, data): self._ensureLoaded() diff -r 7dc71c2dc9a8 -r 474c9882decf piecrust/uriutil.py --- a/piecrust/uriutil.py Mon Aug 11 22:36:36 2014 -0700 +++ b/piecrust/uriutil.py Mon Aug 11 22:36:47 2014 -0700 @@ -49,7 +49,7 @@ uri = '/' + uri.strip('/') - for rn, rc in routes.iteritems(): + for rn, rc in routes.items(): pattern = route_to_pattern(rn) m = re.match(pattern, uri) if m is not None: @@ -68,7 +68,7 @@ def multi_replace(text, replacements): - reps = dict((re.escape(k), v) for k, v in replacements.iteritems()) - pattern = re.compile("|".join(reps.keys())) + reps = dict((re.escape(k), v) for k, v in replacements.items()) + pattern = re.compile("|".join(list(reps.keys()))) return pattern.sub(lambda m: reps[re.escape(m.group(0))], text) diff -r 7dc71c2dc9a8 -r 474c9882decf tests/test_page.py --- a/tests/test_page.py Mon Aug 11 22:36:36 2014 -0700 +++ b/tests/test_page.py Mon Aug 11 22:36:47 2014 -0700 @@ -58,8 +58,8 @@ def test_parse_segments(text, expected): actual = parse_segments(text) assert actual is not None - assert actual.keys() == expected.keys() - for key, val in expected.iteritems(): + assert list(actual.keys()) == list(expected.keys()) + for key, val in expected.items(): if isinstance(val, str): assert len(actual[key].parts) == 1 assert actual[key].parts[0].content == val diff -r 7dc71c2dc9a8 -r 474c9882decf tests/test_uriutil.py --- a/tests/test_uriutil.py Mon Aug 11 22:36:36 2014 -0700 +++ b/tests/test_uriutil.py Mon Aug 11 22:36:47 2014 -0700 @@ -17,7 +17,7 @@ def test_parse_uri(routes, uri, expected): if expected is not None: expected.uri = uri - for pattern, args in routes.iteritems(): + for pattern, args in routes.items(): if 'taxonomy' not in args: args['taxonomy'] = None