From 54d90fde91c241dc5bb2981ccd2dc47e2fd353f7 Mon Sep 17 00:00:00 2001 From: Arthur Koziel Date: Sat, 16 Apr 2011 13:20:00 +0200 Subject: [PATCH 1/9] use python-dateutil to parse the article date --- setup.py | 1 + src/pyll/app.py | 3 +-- src/pyll/parser.py | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 22837bc..bef6b45 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ 'markdown', 'docutils', 'Jinja2', + 'python-dateutil==1.5', ], ) diff --git a/src/pyll/app.py b/src/pyll/app.py index 5eea322..4eb5723 100644 --- a/src/pyll/app.py +++ b/src/pyll/app.py @@ -306,8 +306,7 @@ def main(): 'lib_dir': join(project_dir, '_lib'), 'url_path': join(project_dir, '_lib', 'urls.py'), 'settings_path': join(project_dir, '_lib', 'settings.cfg'), - 'build_time': datetime.today(), - 'date_format': '%Y-%m-%d'} + 'build_time': datetime.today()} # configure logging logging_level = LOGGING_LEVELS.get(options.logging, logging.INFO) diff --git a/src/pyll/parser.py b/src/pyll/parser.py index 5e43a9d..4530420 100644 --- a/src/pyll/parser.py +++ b/src/pyll/parser.py @@ -2,6 +2,9 @@ import re from os.path import splitext +from dateutil import parser + + class ParserException(Exception): """Exception raised for errors during the parsing.""" pass @@ -59,13 +62,10 @@ def _parse_tags_header(self, value): def _parse_date_header(self, value): """ - Parses the date header into a python datetime.datetime object. - The value must be in the format as specified by the 'date_format' - setting; otherwise a ParserException will be thrown. + Parses the date header string into a python datetime object. """ - format = self.settings['date_format'] try: - return datetime.datetime.strptime(value, format) + return parser.parse(value) except ValueError as error: raise ParserException(error) From 750a2ed96b75f3f134ac7896aa52ba95d281ec7e Mon Sep 17 00:00:00 2001 From: Arthur Koziel Date: Sat, 16 Apr 2011 13:33:53 +0200 Subject: [PATCH 2/9] use build_time in quickstart template atom feed updated tag --- src/pyll/quickstart.tar.gz | Bin 5330 -> 5203 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/pyll/quickstart.tar.gz b/src/pyll/quickstart.tar.gz index 5e867e259d32f8ebf293479338ff9aef07ff19ea..78341cd698286c851c773be997a84589ad12adff 100644 GIT binary patch literal 5203 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 kwW&>QYEzrq)TTDIsZDKaQ=8h(^b From 21b08ce2663815120a0c00b7e8027388d7814c5f Mon Sep 17 00:00:00 2001 From: Arthur Koziel Date: Sat, 16 Apr 2011 13:39:03 +0200 Subject: [PATCH 3/9] dont parse tags/updated headers --- src/pyll/parser.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/pyll/parser.py b/src/pyll/parser.py index 4530420..7610e9a 100644 --- a/src/pyll/parser.py +++ b/src/pyll/parser.py @@ -54,12 +54,6 @@ def _parse_headers(self): pass self.text = '\n'.join(lines) - def _parse_tags_header(self, value): - """ - Parses the value from the 'tags' header into a list. - """ - return [t.strip() for t in value.split(',')] - def _parse_date_header(self, value): """ Parses the date header string into a python datetime object. @@ -69,9 +63,6 @@ def _parse_date_header(self, value): except ValueError as error: raise ParserException(error) - def _parse_updated_header(self, value): - return self._parse_date_header(value) - def _parse_status_header(self, value): """ Checks that the value of the 'status' header is 'live', 'hidden' or From 119ba1e5ae5f3a6600c1b1037a3971253708f6c2 Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Mon, 2 May 2011 17:52:36 +0200 Subject: [PATCH 4/9] Add quickstart.tar.gz to setup.py package_data. --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index bef6b45..76bfc5c 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,10 @@ packages = find_packages('src'), package_dir = {'': 'src'}, - package_data={'pyll': ['templates/default.html'],}, + package_data={ + 'pyll': ['templates/default.html', + 'quickstart.tar.gz'], + }, zip_safe = False, test_suite = 'nose.collector', From 240c4a3a94ef21ae5c2a0f49c30e85c533d590b6 Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Mon, 2 May 2011 18:08:39 +0200 Subject: [PATCH 5/9] GIT to ignore Komodo's project file(s). --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bcbc199..7408ad0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ ve/ *.py[co] *.egg *.egg-info +*.komodo* From e7e20ff3e0bdbf7f523730913e05ec1326d56153 Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Mon, 2 May 2011 18:08:56 +0200 Subject: [PATCH 6/9] Encoding is set to 'utf-8' (was 'utf8') to have files encoded that way opened w/o errors. --- src/pyll/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyll/app.py b/src/pyll/app.py index 4eb5723..cb63628 100644 --- a/src/pyll/app.py +++ b/src/pyll/app.py @@ -126,7 +126,7 @@ def _parse(self, input_data): # parse the page parser_cls = parser.get_parser_for_filename(page['path']) - with open(path, 'r', encoding='utf8') as f: + with open(path, 'r', encoding='utf-8') as f: parser_inst = parser_cls(self.settings, f.read()) try: From cfe68b875597023a72c67170c0dcefd6b60d4aa2 Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Mon, 2 May 2011 18:35:02 +0200 Subject: [PATCH 7/9] ConfigParser has been replaced by YAML for 'settings.cfg'. --- setup.py | 1 + src/pyll/app.py | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 76bfc5c..6caa029 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,7 @@ 'docutils', 'Jinja2', 'python-dateutil==1.5', + 'PyYAML', ], ) diff --git a/src/pyll/app.py b/src/pyll/app.py index cb63628..f4df1bd 100644 --- a/src/pyll/app.py +++ b/src/pyll/app.py @@ -3,7 +3,7 @@ from datetime import datetime import imp import logging -import ConfigParser +import yaml from optparse import OptionParser from os import makedirs, getcwd, getlogin from os.path import splitext, join, dirname, split, abspath, getctime,\ @@ -257,23 +257,23 @@ def run(self): def quickstart(settings): login = getlogin() - config = ConfigParser.SafeConfigParser() - config.add_section('pyll') author_name = raw_input("Author Name [%s]: " % login) or login - config.set('pyll', 'author_name', author_name) author_email_default = '%s@example.org' % login author_email = raw_input("Author Email [%s]: " % author_email_default) or author_email_default - config.set('pyll', 'author_email', author_email) website_url_default = 'http://www.example.org' website_url = raw_input("Website URL [%s]: " % website_url_default) or website_url_default - config.set('pyll', 'website_url', website_url) + config = {'pyll': { + 'author_name': author_name, + 'author_email': author_email, + 'website_url': website_url, + }} # before writing the settings file, make sure the _lib dir exists if not exists(settings['lib_dir']): makedirs(settings['lib_dir']) - with open(settings['settings_path'], 'wb') as configfile: - config.write(configfile) + with open(settings['settings_path'], 'wb', encoding='utf-8') as configfile: + configfile.write(yaml.dump(config, default_flow_style=False)) # extract template tmpl_path = join(dirname(abspath(__file__)), 'quickstart.tar.gz') @@ -282,7 +282,7 @@ def quickstart(settings): tar.extractall(path=settings['project_dir']) tar.close() - return dict(config.items('pyll')) + return config['pyll'] def main(): parser = OptionParser(version="%prog " + __version__) @@ -321,9 +321,9 @@ def main(): # read settings file if exists(settings['settings_path']): - config = ConfigParser.SafeConfigParser() - config.read(settings['settings_path']) - settings.update(dict(config.items('pyll'))) + with open(settings['settings_path'], 'rb', encoding='utf-8') as configfile: + config = yaml.safe_load(configfile.read()) + settings.update(config['pyll']) logging.debug('settings %s', settings) # initialize site From fd7d953ccd9db3f5f966e4a1c29bfa5c9bed1b94 Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Mon, 2 May 2011 19:30:13 +0200 Subject: [PATCH 8/9] Pages' header is written in and parsed by (Py)YAML - has been a subset anyways. --- src/pyll/parser.py | 76 ++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/src/pyll/parser.py b/src/pyll/parser.py index 7610e9a..0d08cda 100644 --- a/src/pyll/parser.py +++ b/src/pyll/parser.py @@ -1,9 +1,6 @@ -import datetime -import re +import yaml from os.path import splitext -from dateutil import parser - class ParserException(Exception): """Exception raised for errors during the parsing.""" @@ -20,57 +17,12 @@ def __init__(self, settings, source): def _parse_headers(self): """ - Parses and removes the headers from the source. - """ - META_RE = re.compile( - r'^[ ]{0,3}(?P[A-Za-z0-9_-]+):\s*(?P.*)') - lines = self.source.splitlines() - for num, line in enumerate(lines): - match = META_RE.match(line) - if match: - key = match.group('key').strip().lower() - value = match.group('value').strip() - if value: - # custom header transformation - header_method = getattr(self, '_parse_%s_header' % key, - None) - if header_method: - value = header_method(value) - self.headers[key] = value - num_last_match = num - else: - break - # remove header lines from input source - try: - del lines[:num_last_match + 1] - except UnboundLocalError: - pass - - # check if a blank line followed the header lines and remove it - try: - if not lines[0]: - del lines[0] - except IndexError: - pass - self.text = '\n'.join(lines) - - def _parse_date_header(self, value): - """ - Parses the date header string into a python datetime object. + Parses the headers from the source. """ - try: - return parser.parse(value) - except ValueError as error: - raise ParserException(error) - - def _parse_status_header(self, value): - """ - Checks that the value of the 'status' header is 'live', 'hidden' or - 'draft'. If not 'live' is returned. - """ - if value in ('live', 'hidden', 'draft'): - return value - return 'live' + self.headers = yaml.safe_load(self.header_raw) if self.header_raw != '' else {} + if not 'status' in self.headers \ + or self.headers['status'] not in ('live', 'hidden', 'draft'): + self.headers['status'] = 'live' def _parse_text(self): """ @@ -79,7 +31,23 @@ def _parse_text(self): """ return self.text + def _split_input(self): + """ + Segregates header from actual text. + Used to later parse these parts a different way. + """ + parts = self.source.split("\n\n", 1) + if len(parts) < 2: + parts = self.source.split("---\n", 1) + if len(parts) >= 2: + self.header_raw = parts[0] + self.text = parts[-1] + else: + self.header_raw = '' + self.text = self.source + def parse(self): + self._split_input() self._parse_headers() self._parse_text() return (self.headers, self.text) From a8bea880688871e0b83973cb9456084204fc890f Mon Sep 17 00:00:00 2001 From: W-Mark Kubacki Date: Tue, 3 May 2011 15:04:10 +0200 Subject: [PATCH 9/9] Parser emits warning if no headers are found. --- src/pyll/app.py | 2 +- src/pyll/parser.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pyll/app.py b/src/pyll/app.py index f4df1bd..ef897a5 100644 --- a/src/pyll/app.py +++ b/src/pyll/app.py @@ -127,7 +127,7 @@ def _parse(self, input_data): # parse the page parser_cls = parser.get_parser_for_filename(page['path']) with open(path, 'r', encoding='utf-8') as f: - parser_inst = parser_cls(self.settings, f.read()) + parser_inst = parser_cls(self.settings, f.read(), page['path']) try: parsed = parser_inst.parse() diff --git a/src/pyll/parser.py b/src/pyll/parser.py index 0d08cda..e4f93f8 100644 --- a/src/pyll/parser.py +++ b/src/pyll/parser.py @@ -1,3 +1,4 @@ +import logging import yaml from os.path import splitext @@ -9,11 +10,12 @@ class ParserException(Exception): class Parser(object): output_ext = None - def __init__(self, settings, source): + def __init__(self, settings, source, filename): self.settings = settings self.source = source self.headers = {} self.text = '' + self.filename = filename def _parse_headers(self): """ @@ -43,6 +45,7 @@ def _split_input(self): self.header_raw = parts[0] self.text = parts[-1] else: + logging.warn("'%s' has no headers, only content - at least 'title' will be missing.", self.filename) self.header_raw = '' self.text = self.source