← Back to team overview

launchpad-reviewers team mailing list archive

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

 

Robert Collins has proposed merging lp:~lifeless/python-oops-datedir-repo/extraction into lp:python-oops-datedir-repo.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~lifeless/python-oops-datedir-repo/extraction/+merge/71633

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.
-- 
https://code.launchpad.net/~lifeless/python-oops-datedir-repo/extraction/+merge/71633
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~lifeless/python-oops-datedir-repo/extraction into lp:python-oops-datedir-repo.
=== modified file 'README'
--- README	2011-08-15 05:30:39 +0000
+++ README	2011-08-16 02:31:36 +0000
@@ -35,6 +35,8 @@
 Testing Dependencies
 ====================
 
+* fixtures (http://pypi.python.org/pypi/fixtures)
+
 * subunit (http://pypi.python.org/pypi/python-subunit) (optional)
 
 * testtools (http://pypi.python.org/pypi/testtools)
@@ -42,11 +44,27 @@
 Usage
 =====
 
-An OOPS report can be written to a disk file via the serializer_rfc822.write()
-function, and read via the matching read() function. The uniquefileallocator
-module provides a system for allocating file names on disk.
-
-More coming soon.
+oops_datedir_repo is an extension package for the oops package.
+
+The DateDirRepo class provides an OOPS publisher (``DateDirRepo.publish``)
+which will write OOPSes into the repository.
+
+Retrieving OOPSes can be done by using the low level serializer_rfc822
+functions : an OOPS report can be written to a disk file via the
+serializer_rfc822.write() function, and read via the matching read() function.
+
+The uniquefileallocator module is used by the repository implementation and
+provides a system for allocating file names on disk.
+
+Typical usage::
+
+  >>> config = oops.Config()
+  >>> with fixtures.TempDir() as tempdir:
+  ...    repo = oops_datedir_repo.DateDirRepo('/tmp/demo', 'servername')
+  ...    config.publishers.append(repo.publish)
+  ...    ids = config.publish({'oops': '!!!'})
+
+For more information see the oops package documentation or the api docs.
 
 Installation
 ============

=== modified file 'oops_datedir_repo/__init__.py'
--- oops_datedir_repo/__init__.py	2011-08-15 05:30:39 +0000
+++ oops_datedir_repo/__init__.py	2011-08-16 02:31:36 +0000
@@ -25,8 +25,10 @@
 # established at this point, and setup.py will use a version of next-$(revno).
 # If the releaselevel is 'final', then the tarball will be major.minor.micro.
 # Otherwise it is major.minor.micro~$(revno).
-__version__ = (0, 0, 3, 'beta', 0)
+__version__ = (0, 0, 2, 'beta', 0)
 
 __all__ = [
+    'DateDirRepo',
     ]
 
+from oops_datedir_repo.repository import DateDirRepo

=== added file 'oops_datedir_repo/repository.py'
--- oops_datedir_repo/repository.py	1970-01-01 00:00:00 +0000
+++ oops_datedir_repo/repository.py	2011-08-16 02:31:36 +0000
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2011, Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""The primary interface to oopses stored on disk - the DateDirRepo."""
+
+__metaclass__ = type
+
+__all__ = [
+    'DateDirRepo',
+    ]
+
+import datetime
+import os
+import stat
+
+from pytz import utc
+
+import serializer_rfc822
+from uniquefileallocator import UniqueFileAllocator
+
+
+class DateDirRepo:
+    """Publish oopses to a date-dir repository."""
+
+    def __init__(self, error_dir, instance_id):
+        self.log_namer = UniqueFileAllocator(
+            output_root=error_dir,
+            log_type="OOPS",
+            log_subtype=instance_id,
+            )
+
+    def publish(self, report, now=None):
+        """Write the report to disk.
+
+        :param now: The datetime to use as the current time.  Will be
+            determined if not supplied.  Useful for testing.
+        """
+        if now is not None:
+            now = now.astimezone(utc)
+        else:
+            now = datetime.datetime.now(utc)
+        oopsid, filename = self.log_namer.newId(now)
+        report['id'] = oopsid
+        serializer_rfc822.write(report, open(filename, 'wb'))
+        # Set file permission to: rw-r--r-- (so that reports from
+        # umask-restricted services can be gathered by a tool running as
+        # another user).
+        wanted_permission = (
+            stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
+        os.chmod(filename, wanted_permission)
+        return report['id']

=== modified file 'oops_datedir_repo/tests/__init__.py'
--- oops_datedir_repo/tests/__init__.py	2011-08-15 05:30:39 +0000
+++ oops_datedir_repo/tests/__init__.py	2011-08-16 02:31:36 +0000
@@ -21,6 +21,7 @@
 
 def test_suite():
     test_mod_names = [
+        'repository',
         'uniquefileallocator',
         'serializer_rfc822',
         ]

=== added file 'oops_datedir_repo/tests/test_repository.py'
--- oops_datedir_repo/tests/test_repository.py	1970-01-01 00:00:00 +0000
+++ oops_datedir_repo/tests/test_repository.py	2011-08-16 02:31:36 +0000
@@ -0,0 +1,61 @@
+# Copyright (c) 2010, 2011, Canonical Ltd
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for the date-directory based repository."""
+
+__metaclass__ = type
+
+import datetime
+import os.path
+import stat
+
+from fixtures import TempDir
+from pytz import utc
+import testtools
+
+from oops_datedir_repo import DateDirRepo
+from oops_datedir_repo.uniquefileallocator import UniqueFileAllocator
+
+
+class TestDateDirRepo(testtools.TestCase):
+
+    def test_publish_permissions(self):
+        errordir = self.useFixture(TempDir()).path
+        repo = DateDirRepo(errordir, 'T')
+        report = {'id': 'OOPS-91T1'}
+        now = datetime.datetime(2006, 04, 01, 00, 30, 00, tzinfo=utc)
+
+        # Set up default file creation mode to rwx------ as some restrictive
+        # servers do.
+        umask_permission = stat.S_IRWXG | stat.S_IRWXO
+        old_umask = os.umask(umask_permission)
+        self.addCleanup(os.umask, old_umask)
+        repo.publish(report, now)
+
+        errorfile = os.path.join(repo.log_namer.output_dir(now), '01800.T1')
+        self.assertTrue(os.path.exists(errorfile))
+
+        # Check errorfile is set with the correct permission: rw-r--r--
+        st = os.stat(errorfile)
+        wanted_permission = (
+            stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
+        # Get only the permission bits for this file.
+        file_permission = stat.S_IMODE(st.st_mode)
+        self.assertEqual(file_permission, wanted_permission)
+
+    def test_sets_log_namer_to_a_UniqueFileAllocator(self):
+        repo = DateDirRepo(self.useFixture(TempDir()).path, 'T')
+        self.assertIsInstance(repo.log_namer, UniqueFileAllocator)

=== modified file 'setup.py'
--- setup.py	2011-08-15 05:30:39 +0000
+++ setup.py	2011-08-16 02:31:36 +0000
@@ -22,7 +22,7 @@
 description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
 
 setup(name="oops_datedir_repo",
-      version="0.0.1",
+      version="0.0.2",
       description="OOPS disk serialisation and repository management.",
       long_description=description,
       maintainer="Launchpad Developers",