annotate tests/conftest.py @ 27:c898b4df0f29

Use context for html stripping, with support for custom URL sizes For instance in Twitter URLs are 23 characters long since they use their own URL shortening service. Without taking this into account, post lengths would not be calculated correctly.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 19 Apr 2023 12:46:58 -0700
parents d3c4c5082bbc
children b404445082f8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
1 import io
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
2 import os
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
3 import os.path
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
4 import re
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
5 import logging
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
6 import tempfile
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
7 import pytest
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
8 import silorider.main
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
9
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
10
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
11 logger = logging.getLogger(__name__)
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
12
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
13
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
14 # def pytest_collect_file(parent, path):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
15 # if path.ext == ".html" and path.basename.startswith("feeds"):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
16 # return FeedFile(path, parent)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
17
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
18
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
19 re_feed_test_sep = re.compile(r'^---$')
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
20
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
21
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
22 class FeedFile(pytest.File):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
23 def collect(self):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
24 with self.fspath.open() as fp:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
25 markup = fp.read()
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
26
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
27 name = self.fspath.basename
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
28 html_markup, yaml_markup = re_feed_test_sep.split(markup, 1)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
29 yield FeedItem(name, self, html_markup, yaml_markup)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
30
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
31
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
32 class FeedItem(pytest.Item):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
33 def __init__(self, name, parent, in_spec, out_spec):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
34 super().__init__(name, parent)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
35 self.in_spec = in_spec
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
36 self.out_spec = out_spec
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
37
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
38 def runtest(self):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
39 pass
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
40
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
41
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
42 @pytest.fixture
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
43 def cli():
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
44 return CliRunner()
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
45
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
46
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
47 class CliRunner:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
48 def __init__(self):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
49 self._cfgtxt = """
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
50 [cache]
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
51 uri=memory://for_test
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
52 """
18
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
53 self._feedcfg = []
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
54 self._pre_hooks = []
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
55 self._cleanup = []
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
56
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
57 def getFeedPath(self, name):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
58 return os.path.join(os.path.dirname(__file__),
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
59 'feeds',
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
60 '%s.html' % name)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
61
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
62 def createTempFeed(self, contents):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
63 tmpfd, tmpname = tempfile.mkstemp()
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
64 with os.fdopen(tmpfd, 'w', encoding='utf8') as tmpfp:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
65 tmpfp.write(contents)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
66 self._cleanup.append(tmpname)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
67 return tmpname
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
68
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
69 def setConfig(self, cfgtxt):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
70 self._cfgtxt = cfgtxt
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
71 return self
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
72
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
73 def appendConfig(self, cfgtxt):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
74 self._cfgtxt += cfgtxt
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
75 return self
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
76
18
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
77 def appendFeedConfig(self, feed_name, feed_url):
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
78 self._feedcfg.append((feed_name, feed_url))
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
79 return self
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
80
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
81 def setFeedConfig(self, feed_name, feed_url):
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
82 self._feedcfg = []
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
83 return self.appendFeedConfig(feed_name, feed_url)
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
84
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
85 def appendSiloConfig(self, silo_name, silo_type, **options):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
86 cfgtxt = '[silo:%s]\n' % silo_name
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
87 cfgtxt += 'type=%s\n' % silo_type
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
88 if options is not None:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
89 for n, v in options.items():
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
90 cfgtxt += '%s=%s\n' % (n, v)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
91 return self.appendConfig(cfgtxt)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
92
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
93 def preExecHook(self, hook):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
94 self._pre_hooks.append(hook)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
95
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
96 def run(self, *args):
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
97 pre_args = ['-v']
18
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
98 if self._cfgtxt or self._feedcfg:
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
99 cfgtxt = self._cfgtxt
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
100 cfgtxt += '\n\n[urls]\n'
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
101 for n, u in self._feedcfg:
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
102 cfgtxt += '%s=%s\n' % (n, u)
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
103
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
104 tmpfd, tmpcfg = tempfile.mkstemp()
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
105 logger.info("Creating temporary configuration file: %s" % tmpcfg)
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
106 with os.fdopen(tmpfd, 'w') as tmpfp:
18
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
107 tmpfp.write(cfgtxt)
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
108 self._cleanup.append(tmpcfg)
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
109 pre_args += ['-c', tmpcfg]
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
110
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
111 captured = io.StringIO()
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
112 handler = logging.StreamHandler(captured)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
113 handler.setLevel(logging.INFO)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
114 silorider_logger = logging.getLogger('silorider')
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
115 silorider_logger.addHandler(handler)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
116
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
117 main_ctx = None
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
118 main_res = None
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
119
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
120 def pre_exec_hook(ctx):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
121 for h in self._pre_hooks:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
122 h(ctx)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
123
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
124 def post_exec_hook(ctx, res):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
125 nonlocal main_ctx, main_res
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
126 main_ctx = ctx
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
127 main_res = res
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
128
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
129 silorider.main.pre_exec_hook = pre_exec_hook
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
130 silorider.main.post_exec_hook = post_exec_hook
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
131
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
132 args = pre_args + list(args)
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
133 logger.info("Running command: %s" % list(args))
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
134 try:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
135 silorider.main._unsafe_main(args)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
136 finally:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
137 silorider.main.pre_exec_hook = None
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
138 silorider.main.post_exec_hook = None
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
139
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
140 silorider_logger.removeHandler(handler)
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
141
19
d3c4c5082bbc Add Webmention silo.
Ludovic Chabant <ludovic@chabant.com>
parents: 18
diff changeset
142 logger.info("Cleaning %d temporary files." % len(self._cleanup))
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
143 for tmpname in self._cleanup:
18
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
144 try:
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
145 os.remove(tmpname)
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
146 except FileNotFoundError:
a921cc2306bc Do our own HTML parsing/stripping of micropost contents.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
147 pass
0
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
148
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
149 return main_ctx, main_res
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
150
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
151
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
152 @pytest.fixture
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
153 def feedutil():
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
154 return FeedUtil()
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
155
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
156
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
157 class FeedUtil:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
158 def makeFeed(self, *entries):
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
159 feed = '<html><body>\n'
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
160 for e in entries:
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
161 feed += '<article class="h-entry">\n'
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
162 feed += e
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
163 feed += '</article>\n'
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
164 feed += '</body></html>'
a1b7a459326a Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
165 return feed