Merge lp:~lifeless/python-oops-datedir-repo/extraction into lp:python-oops-datedir-repo

Proposed by Robert Collins
Status: Merged
Merged at revision: 2
Proposed branch: lp:~lifeless/python-oops-datedir-repo/extraction
Merge into: lp:python-oops-datedir-repo
Diff against target: 221 lines (+153/-7)
6 files modified
README (+23/-5)
oops_datedir_repo/__init__.py (+3/-1)
oops_datedir_repo/repository.py (+64/-0)
oops_datedir_repo/tests/__init__.py (+1/-0)
oops_datedir_repo/tests/test_repository.py (+61/-0)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~lifeless/python-oops-datedir-repo/extraction
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code Approve
Review via email: mp+71633@code.launchpad.net

Description of the change

This adds the core write-to-disk aspect of errorlog.py from Launchpad as 'DateDirRepo'.publish, along with the tests from Launchpad that I was able to delete as a side effect of this move.

To post a comment you must log in.
Revision history for this message
Steve Kowalik (stevenk) wrote :

A little confusing, since at the top of the diff, you move *backward* from 0.0.3 to 0.0.2, and at the end, you move forward from 0.0.1 to 0.0.2.

review: Approve (code)
Revision history for this message
Robert Collins (lifeless) wrote :

Yes, that was a fubar in the migration :(. Didn't affect tarball building, and is resolved with this version.
Thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README'
2--- README 2011-08-15 05:30:39 +0000
3+++ README 2011-08-16 02:31:36 +0000
4@@ -35,6 +35,8 @@
5 Testing Dependencies
6 ====================
7
8+* fixtures (http://pypi.python.org/pypi/fixtures)
9+
10 * subunit (http://pypi.python.org/pypi/python-subunit) (optional)
11
12 * testtools (http://pypi.python.org/pypi/testtools)
13@@ -42,11 +44,27 @@
14 Usage
15 =====
16
17-An OOPS report can be written to a disk file via the serializer_rfc822.write()
18-function, and read via the matching read() function. The uniquefileallocator
19-module provides a system for allocating file names on disk.
20-
21-More coming soon.
22+oops_datedir_repo is an extension package for the oops package.
23+
24+The DateDirRepo class provides an OOPS publisher (``DateDirRepo.publish``)
25+which will write OOPSes into the repository.
26+
27+Retrieving OOPSes can be done by using the low level serializer_rfc822
28+functions : an OOPS report can be written to a disk file via the
29+serializer_rfc822.write() function, and read via the matching read() function.
30+
31+The uniquefileallocator module is used by the repository implementation and
32+provides a system for allocating file names on disk.
33+
34+Typical usage::
35+
36+ >>> config = oops.Config()
37+ >>> with fixtures.TempDir() as tempdir:
38+ ... repo = oops_datedir_repo.DateDirRepo('/tmp/demo', 'servername')
39+ ... config.publishers.append(repo.publish)
40+ ... ids = config.publish({'oops': '!!!'})
41+
42+For more information see the oops package documentation or the api docs.
43
44 Installation
45 ============
46
47=== modified file 'oops_datedir_repo/__init__.py'
48--- oops_datedir_repo/__init__.py 2011-08-15 05:30:39 +0000
49+++ oops_datedir_repo/__init__.py 2011-08-16 02:31:36 +0000
50@@ -25,8 +25,10 @@
51 # established at this point, and setup.py will use a version of next-$(revno).
52 # If the releaselevel is 'final', then the tarball will be major.minor.micro.
53 # Otherwise it is major.minor.micro~$(revno).
54-__version__ = (0, 0, 3, 'beta', 0)
55+__version__ = (0, 0, 2, 'beta', 0)
56
57 __all__ = [
58+ 'DateDirRepo',
59 ]
60
61+from oops_datedir_repo.repository import DateDirRepo
62
63=== added file 'oops_datedir_repo/repository.py'
64--- oops_datedir_repo/repository.py 1970-01-01 00:00:00 +0000
65+++ oops_datedir_repo/repository.py 2011-08-16 02:31:36 +0000
66@@ -0,0 +1,64 @@
67+#
68+# Copyright (c) 2011, Canonical Ltd
69+#
70+# This program is free software: you can redistribute it and/or modify
71+# it under the terms of the GNU Affero General Public License as published by
72+# the Free Software Foundation, either version 3 of the License, or
73+# (at your option) any later version.
74+#
75+# This program is distributed in the hope that it will be useful,
76+# but WITHOUT ANY WARRANTY; without even the implied warranty of
77+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78+# GNU Affero General Public License for more details.
79+#
80+# You should have received a copy of the GNU Affero General Public License
81+# along with this program. If not, see <http://www.gnu.org/licenses/>.
82+
83+"""The primary interface to oopses stored on disk - the DateDirRepo."""
84+
85+__metaclass__ = type
86+
87+__all__ = [
88+ 'DateDirRepo',
89+ ]
90+
91+import datetime
92+import os
93+import stat
94+
95+from pytz import utc
96+
97+import serializer_rfc822
98+from uniquefileallocator import UniqueFileAllocator
99+
100+
101+class DateDirRepo:
102+ """Publish oopses to a date-dir repository."""
103+
104+ def __init__(self, error_dir, instance_id):
105+ self.log_namer = UniqueFileAllocator(
106+ output_root=error_dir,
107+ log_type="OOPS",
108+ log_subtype=instance_id,
109+ )
110+
111+ def publish(self, report, now=None):
112+ """Write the report to disk.
113+
114+ :param now: The datetime to use as the current time. Will be
115+ determined if not supplied. Useful for testing.
116+ """
117+ if now is not None:
118+ now = now.astimezone(utc)
119+ else:
120+ now = datetime.datetime.now(utc)
121+ oopsid, filename = self.log_namer.newId(now)
122+ report['id'] = oopsid
123+ serializer_rfc822.write(report, open(filename, 'wb'))
124+ # Set file permission to: rw-r--r-- (so that reports from
125+ # umask-restricted services can be gathered by a tool running as
126+ # another user).
127+ wanted_permission = (
128+ stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
129+ os.chmod(filename, wanted_permission)
130+ return report['id']
131
132=== modified file 'oops_datedir_repo/tests/__init__.py'
133--- oops_datedir_repo/tests/__init__.py 2011-08-15 05:30:39 +0000
134+++ oops_datedir_repo/tests/__init__.py 2011-08-16 02:31:36 +0000
135@@ -21,6 +21,7 @@
136
137 def test_suite():
138 test_mod_names = [
139+ 'repository',
140 'uniquefileallocator',
141 'serializer_rfc822',
142 ]
143
144=== added file 'oops_datedir_repo/tests/test_repository.py'
145--- oops_datedir_repo/tests/test_repository.py 1970-01-01 00:00:00 +0000
146+++ oops_datedir_repo/tests/test_repository.py 2011-08-16 02:31:36 +0000
147@@ -0,0 +1,61 @@
148+# Copyright (c) 2010, 2011, Canonical Ltd
149+#
150+# This program is free software: you can redistribute it and/or modify
151+# it under the terms of the GNU Affero General Public License as published by
152+# the Free Software Foundation, either version 3 of the License, or
153+# (at your option) any later version.
154+#
155+# This program is distributed in the hope that it will be useful,
156+# but WITHOUT ANY WARRANTY; without even the implied warranty of
157+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
158+# GNU Affero General Public License for more details.
159+#
160+# You should have received a copy of the GNU Affero General Public License
161+# along with this program. If not, see <http://www.gnu.org/licenses/>.
162+# GNU Affero General Public License version 3 (see the file LICENSE).
163+
164+"""Tests for the date-directory based repository."""
165+
166+__metaclass__ = type
167+
168+import datetime
169+import os.path
170+import stat
171+
172+from fixtures import TempDir
173+from pytz import utc
174+import testtools
175+
176+from oops_datedir_repo import DateDirRepo
177+from oops_datedir_repo.uniquefileallocator import UniqueFileAllocator
178+
179+
180+class TestDateDirRepo(testtools.TestCase):
181+
182+ def test_publish_permissions(self):
183+ errordir = self.useFixture(TempDir()).path
184+ repo = DateDirRepo(errordir, 'T')
185+ report = {'id': 'OOPS-91T1'}
186+ now = datetime.datetime(2006, 04, 01, 00, 30, 00, tzinfo=utc)
187+
188+ # Set up default file creation mode to rwx------ as some restrictive
189+ # servers do.
190+ umask_permission = stat.S_IRWXG | stat.S_IRWXO
191+ old_umask = os.umask(umask_permission)
192+ self.addCleanup(os.umask, old_umask)
193+ repo.publish(report, now)
194+
195+ errorfile = os.path.join(repo.log_namer.output_dir(now), '01800.T1')
196+ self.assertTrue(os.path.exists(errorfile))
197+
198+ # Check errorfile is set with the correct permission: rw-r--r--
199+ st = os.stat(errorfile)
200+ wanted_permission = (
201+ stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
202+ # Get only the permission bits for this file.
203+ file_permission = stat.S_IMODE(st.st_mode)
204+ self.assertEqual(file_permission, wanted_permission)
205+
206+ def test_sets_log_namer_to_a_UniqueFileAllocator(self):
207+ repo = DateDirRepo(self.useFixture(TempDir()).path, 'T')
208+ self.assertIsInstance(repo.log_namer, UniqueFileAllocator)
209
210=== modified file 'setup.py'
211--- setup.py 2011-08-15 05:30:39 +0000
212+++ setup.py 2011-08-16 02:31:36 +0000
213@@ -22,7 +22,7 @@
214 description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
215
216 setup(name="oops_datedir_repo",
217- version="0.0.1",
218+ version="0.0.2",
219 description="OOPS disk serialisation and repository management.",
220 long_description=description,
221 maintainer="Launchpad Developers",

Subscribers

People subscribed via source and target branches

to all changes: