From b03d865b7bd40c2fd75afe149e773ec291fb61d5 Mon Sep 17 00:00:00 2001 From: pictuga Date: Thu, 22 May 2014 22:44:59 +0200 Subject: [PATCH] Get rid of ParseOptions() That thing wasn't nice, and depended too much on the various use case. The new approach is to turn morss into a library and turn the use cases into some pre-implemented lib usages --- README.md | 14 ++++------ morss/morss.py | 75 +++++++++++++++++++------------------------------- 2 files changed, 34 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index b7e3408..7426316 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ GPL3 code. ##Arguments -morss accepts some arguments, to lightly alter the output of morss. Arguments may need to have a value (usually a string or a number). In the different "Use cases" below is detailed how to pass those arguments to morss. +morss accepts some arguments, to lightly alter the output of morss. Arguments are all boolean. In the different "Use cases" below is detailed how to pass those arguments to morss. The arguments are: @@ -43,7 +43,6 @@ The arguments are: - `cache`: only take articles from the cache (ie. don't grab new articles' content), so as to save time - `debug`: to have some feedback from the script execution. Useful for debugging - `theforce`: force download the rss feed - - `al`: (takes an integer value, stands for *apparent limit*) only show `value` items in output (useful because browsers are actually super-slow to parse big JSON files) - `silent`: don't output the final RSS (useless on its own, but can be nice when debugging) - http server only - `html`: changes the http content-type to html, so that python cgi erros (written in html) are readable in a web browser @@ -70,7 +69,7 @@ Morss can run its own HTTP server. The later should start when you run morss wit ####Passing arguments -Then visit: **`http://PATH/TO/MORSS/[morss.py/][:argwithoutvalue[:argwithvalue=value[...]]]/FEEDURL`** +Then visit: **`http://PATH/TO/MORSS/[morss.py/][:argwithoutvalue[...]]/FEEDURL`** For example: `http://morss.example/:clip/https://twitter.com/pictuga` *(Brackets indicate optional text)* @@ -80,7 +79,7 @@ Works like a charm with [Tiny Tiny RSS](http://tt-rss.org/redmine/projects/tt-rs ###As a CLI application -Run: **`[python2.7] morss.py [argwithoutvalue] [argwithvalue=value] [...] FEEDURL`** +Run: **`[python2.7] morss.py [argwithoutvalue] [...] FEEDURL`** For example: `python2.7 morss.py debug http://feeds.bbci.co.uk/news/rss.xml` *(Brackets indicate optional text)* @@ -88,20 +87,19 @@ For example: `python2.7 morss.py debug http://feeds.bbci.co.uk/news/rss.xml` To use it, the newsreader [Liferea](http://lzone.de/liferea/) is required (unless other newsreaders provide the same kind of feature), since custom scripts can be run on top of the RSS feed, using its [output](http://lzone.de/liferea/scraping.htm) as an RSS feed. -To use this script, you have to enable "(Unix) command" in liferea feed settings, and use the command: **`[python2.7] PATH/TO/MORSS/morss.py [argwithoutvalue] [argwithvalue=value] [...] FEEDURL`** +To use this script, you have to enable "(Unix) command" in liferea feed settings, and use the command: **`[python2.7] PATH/TO/MORSS/morss.py [argwithoutvalue] [...] FEEDURL`** For example: `python2.7 PATH/TO/MORSS/morss.py http://feeds.bbci.co.uk/news/rss.xml` *(Brackets indicate optional text)* ###As a python library -The code was not optimized to be used as a library. Therefore you can't really pass options to morss (see Arguments above), unless you rewrite the `ParseOptions` class. -However here is a quick draft of what your code should you like if you intend to use morss as a library. +The code was not optimized to be used as a library. However here is a quick draft of what your code should you like if you intend to use morss as a library. ```python import morss url = 'http://newspaper.example/feed.xml' -options = morss.ParseOptions() # there's no easy way to pass arguments by hand from python so far... +options = morss.Options(['force', 'quiet']) # arguments cache_path = '/tmp/morss-cache' # cache folder, needs write permission url, cache = Init(url, cache_path, options) diff --git a/morss/morss.py b/morss/morss.py index 70fd776..9cb1600 100644 --- a/morss/morss.py +++ b/morss/morss.py @@ -82,53 +82,18 @@ def countWord(txt): else: return 0 -class ParseOptions: - def __init__(self, environ=False): - self.url = '' - self.options = {} - roptions = [] - - if environ: - if 'REQUEST_URI' in environ: - self.url = environ['REQUEST_URI'][1:] - else: - self.url = environ['PATH_INFO'][1:] - - if self.url.startswith('/morss.py'): - self.url = self.url[10:] - elif self.url.startswith('morss.py'): - self.url = self.url[9:] - - if self.url.startswith(':'): - roptions = self.url.split('/')[0].split(':')[1:] - self.url = self.url.split('/', 1)[1] - else: - if len(sys.argv) <= 1: - return - - roptions = sys.argv[1:-1] - self.url = sys.argv[-1] - - for option in roptions: - split = option.split('=', 1) - if len(split) > 1: - if split[0].lower() == 'true': - self.options[split[0]] = True - elif split[0].lower() == 'false': - self.options[split[0]] = False - else: - self.options[split[0]] = split[1] - else: - self.options[split[0]] = True +class Options: + def __init__(self, options=None): + self.options = options or [] def __getattr__(self, key): - if key in self.options: - return self.options[key] - else: - return False + return key in self.options + + def __setitem__(self, key, value): + self.options[key] = value def __contains__(self, key): - return self.options.__contains__(key) + return key in self.options class Cache: """ Light, error-prone caching system. """ @@ -682,8 +647,22 @@ def After(rss, options): return rss.tostring(xml_declaration=True, encoding='UTF-8') def cgi_app(environ, start_response): - options = ParseOptions(environ) - url = options.url + # get options + if 'REQUEST_URI' in environ: + url = environ['REQUEST_URI'][1:] + else: + url = environ['PATH_INFO'][1:] + + re.sub(r'^/?morss.py/', '', url) + + if url.startswith(':'): + options = url.split('/')[0].split(':')[1:] + url = url.split('/', 1)[1] + else: + options = [] + + # init + options = Options(options) headers = {} global DEBUG @@ -697,6 +676,7 @@ def cgi_app(environ, start_response): log('etag good') return [] + # headers headers['status'] = '200 OK' headers['etag'] = '"%s"' % int(time.time()) @@ -719,6 +699,7 @@ def cgi_app(environ, start_response): start_response(headers['status'], headers.items()) return + # get the work done RSS = Fetch(url, cache, options) if headers['content-type'] == 'text/xml': @@ -779,8 +760,8 @@ def cgi_wrapper(environ, start_response): return 'Unknown Error: %s' % e.message def cli_app(): - options = ParseOptions() - url = options.url + options = Options(sys.argv[1:-1]) + url = sys.argv[-1] global DEBUG DEBUG = options.debug