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
master
pictuga 2014-05-22 22:44:59 +02:00
parent 16713e6d2a
commit b03d865b7b
2 changed files with 34 additions and 55 deletions

View File

@ -27,7 +27,7 @@ GPL3 code.
##Arguments ##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: 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 - `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 - `debug`: to have some feedback from the script execution. Useful for debugging
- `theforce`: force download the rss feed - `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) - `silent`: don't output the final RSS (useless on its own, but can be nice when debugging)
- http server only - 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 - `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 ####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` For example: `http://morss.example/:clip/https://twitter.com/pictuga`
*(Brackets indicate optional text)* *(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 ###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` For example: `python2.7 morss.py debug http://feeds.bbci.co.uk/news/rss.xml`
*(Brackets indicate optional text)* *(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 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` For example: `python2.7 PATH/TO/MORSS/morss.py http://feeds.bbci.co.uk/news/rss.xml`
*(Brackets indicate optional text)* *(Brackets indicate optional text)*
###As a python library ###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. 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.
However here is a quick draft of what your code should you like if you intend to use morss as a library.
```python ```python
import morss import morss
url = 'http://newspaper.example/feed.xml' 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 cache_path = '/tmp/morss-cache' # cache folder, needs write permission
url, cache = Init(url, cache_path, options) url, cache = Init(url, cache_path, options)

View File

@ -82,53 +82,18 @@ def countWord(txt):
else: else:
return 0 return 0
class ParseOptions: class Options:
def __init__(self, environ=False): def __init__(self, options=None):
self.url = '' self.options = options or []
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
def __getattr__(self, key): def __getattr__(self, key):
if key in self.options: return key in self.options
return self.options[key]
else: def __setitem__(self, key, value):
return False self.options[key] = value
def __contains__(self, key): def __contains__(self, key):
return self.options.__contains__(key) return key in self.options
class Cache: class Cache:
""" Light, error-prone caching system. """ """ Light, error-prone caching system. """
@ -682,8 +647,22 @@ def After(rss, options):
return rss.tostring(xml_declaration=True, encoding='UTF-8') return rss.tostring(xml_declaration=True, encoding='UTF-8')
def cgi_app(environ, start_response): def cgi_app(environ, start_response):
options = ParseOptions(environ) # get options
url = options.url 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 = {} headers = {}
global DEBUG global DEBUG
@ -697,6 +676,7 @@ def cgi_app(environ, start_response):
log('etag good') log('etag good')
return [] return []
# headers
headers['status'] = '200 OK' headers['status'] = '200 OK'
headers['etag'] = '"%s"' % int(time.time()) headers['etag'] = '"%s"' % int(time.time())
@ -719,6 +699,7 @@ def cgi_app(environ, start_response):
start_response(headers['status'], headers.items()) start_response(headers['status'], headers.items())
return return
# get the work done
RSS = Fetch(url, cache, options) RSS = Fetch(url, cache, options)
if headers['content-type'] == 'text/xml': if headers['content-type'] == 'text/xml':
@ -779,8 +760,8 @@ def cgi_wrapper(environ, start_response):
return 'Unknown Error: %s' % e.message return 'Unknown Error: %s' % e.message
def cli_app(): def cli_app():
options = ParseOptions() options = Options(sys.argv[1:-1])
url = options.url url = sys.argv[-1]
global DEBUG global DEBUG
DEBUG = options.debug DEBUG = options.debug