Skip to content
This repository was archived by the owner on Apr 21, 2021. It is now read-only.

Commit f5a6056

Browse files
authored
Merge pull request #7 from ifosch/add-entry
Leave picot ready for publish to PyPI
2 parents 6995b78 + 8b4676d commit f5a6056

File tree

8 files changed

+110
-89
lines changed

8 files changed

+110
-89
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) [year] [fullname]
3+
Copyright (c) 2019 Ignasi Fosch
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Pipfile

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ verify_ssl = true
77
pytest = "*"
88
pycodestyle = "*"
99
flake8 = "*"
10+
autopep8 = "*"
1011

1112
[packages]
1213
feedparser = "*"

Pipfile.lock

+26-19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
Picot is a library to read, select and extract information from RSS feeds.
44

5+
## Installation
6+
7+
You can install it using `pip install` as usual:
8+
```bash
9+
pip install picot
10+
```
11+
512
## Usage
613

714
### As a module
@@ -33,5 +40,5 @@ entries = picot.feed.Feed(url, format_func=lambda x: '{} {}'.format(x['title'],
3340

3441
While intended to be used as a library, Picot can be invoked as a command line tool to get the titles of the entries in an RSS:
3542
```bash
36-
$ pipenv run bin/picot <RSS URL>
43+
$ picot <RSS URL>
3744
```

picot/entry.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Entry(dict):
2+
"""This class encapsulates a feed's entry providing formatting.
3+
4+
Example:
5+
entry = Entry(raw_entry)
6+
formatted_entry = Entry(
7+
raw_entry,
8+
format_func=lambda x: '{}'.format(x['title']
9+
)
10+
"""
11+
12+
def __init__(self, *args, **kwargs):
13+
"""This initializes the the Entry object with corresponding
14+
format function.
15+
"""
16+
super(Entry, self).__init__(args[0])
17+
self._format_func = super(Entry, self).__repr__
18+
if 'format_func' in kwargs:
19+
self._format_func = kwargs['format_func']
20+
21+
def __repr__(self):
22+
"""This generates a representation of the entry."""
23+
if self._format_func is None:
24+
return super().__repr__()
25+
else:
26+
return self._format_func(self)

picot/feed.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import feedparser
22

3+
from picot.entry import Entry
4+
35

46
def _ok_to_all_filter(x):
57
"""This is the default filter function."""
@@ -40,7 +42,8 @@ def _update_entries(self):
4042
function.
4143
"""
4244
if self._entries is None:
43-
self._entries = [entry for entry in self._feed.entries if
45+
self._entries = [Entry(entry, format_func=self.format_func)
46+
for entry in self._feed.entries if
4447
self.filter_func(entry)]
4548

4649
def __iter__(self):
@@ -57,11 +60,8 @@ def __len__(self):
5760
return len(self._entries)
5861

5962
def __repr__(self):
60-
"""This generates a representation of the feed, according to
61-
the format function."""
62-
if self.format_func is None:
63-
return "{} ({})".format(
64-
self._feed.feed.title,
65-
self._feed.feed.link
66-
)
67-
return '\n'.join([self.format_func(entry) for entry in list(self)])
63+
"""This generates a representation of the feed."""
64+
return "{} ({})".format(
65+
self._feed.feed.title,
66+
self._feed.feed.link
67+
)

test/picot/test_entry.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import pytest
2+
3+
import picot.entry
4+
5+
6+
raw_entry = {
7+
'title': 'Some entry',
8+
'link': 'https://some.site/entry',
9+
}
10+
11+
12+
@pytest.mark.parametrize(
13+
'format_func,expected_output',
14+
[
15+
(
16+
None,
17+
repr(raw_entry),
18+
),
19+
(
20+
lambda x: x['title'],
21+
raw_entry['title'],
22+
),
23+
(
24+
lambda x: '{} {}'.format(x['title'], x['link']),
25+
'{} {}'.format(raw_entry['title'], raw_entry['link']),
26+
),
27+
],
28+
ids=[
29+
'No format function',
30+
'Simple format function',
31+
'Field combining format function',
32+
],
33+
)
34+
def test_entry_format(
35+
format_func,
36+
expected_output,
37+
):
38+
entry = picot.entry.Entry(raw_entry, format_func=format_func)
39+
assert(repr(entry) == expected_output)

test/picot/test_feed.py

-59
Original file line numberDiff line numberDiff line change
@@ -112,62 +112,3 @@ def mocked_parse(url):
112112
feed = picot.feed.Feed('https://some.url', filter_func=filter_func)
113113
assert(len(feed) == len(expected_entries))
114114
assert(list(feed) == expected_entries)
115-
116-
117-
@pytest.mark.parametrize(
118-
'original_entries,format_func,expected_output',
119-
[
120-
(
121-
single_entry,
122-
None,
123-
'Feed at https://some.url (https://some.url)',
124-
),
125-
(
126-
single_entry,
127-
lambda x: '',
128-
'',
129-
),
130-
(
131-
single_entry,
132-
lambda x: x['title'],
133-
'Some entry',
134-
),
135-
(
136-
multiple_entries,
137-
None,
138-
'Feed at https://some.url (https://some.url)',
139-
),
140-
(
141-
multiple_entries,
142-
lambda x: '',
143-
'''\n''',
144-
),
145-
(
146-
multiple_entries,
147-
lambda x: x['title'],
148-
'Some entry\nSome other entry',
149-
),
150-
],
151-
ids=[
152-
'Single entry - No format',
153-
'Single entry - Blank format',
154-
'Single entry - Simple format',
155-
'Multiple entry - No format',
156-
'Multiple entry - Blank format',
157-
'Multiple entry - Simple format',
158-
],
159-
)
160-
def test_feed_format(
161-
original_entries,
162-
format_func,
163-
expected_output,
164-
monkeypatch,
165-
):
166-
def mocked_parse(url):
167-
return MockFeed(
168-
url,
169-
entries=original_entries,
170-
)
171-
monkeypatch.setattr(feedparser, 'parse', mocked_parse)
172-
feed = picot.feed.Feed('https://some.url', format_func=format_func)
173-
assert(repr(feed) == expected_output)

0 commit comments

Comments
 (0)