Ticket #6749: python3-logfile-6749-1.patch

File python3-logfile-6749-1.patch, 13.5 KB (added by multani, 3 years ago)
  • setup3.py

    diff --git setup3.py setup3.py
    index ca27cbe..505c3e6 100644
    modules = [ 
    7676    "twisted.python.filepath",
    7777    "twisted.python.lockfile",
    7878    "twisted.python.log",
     79    "twisted.python.logfile",
    7980    "twisted.python.monkey",
    8081    "twisted.python.randbytes",
    8182    "twisted.python._reflectpy3",
    testModules = [ 
    168169    "twisted.test.test_iutils",
    169170    "twisted.test.test_lockfile",
    170171    "twisted.test.test_log",
     172    "twisted.test.test_logfile",
    171173    "twisted.test.test_loopback",
    172174    "twisted.test.test_monkey",
    173175    "twisted.test.test_paths",
  • twisted/python/logfile.py

    diff --git twisted/python/logfile.py twisted/python/logfile.py
    index f652271..1c9a633 100644
    class BaseLogFile: 
    3939            self.defaultMode = defaultMode
    4040        self._openFile()
    4141
     42    def __del__(self):
     43        try:
     44            self.close()
     45        except: # File might be already closed
     46            pass
     47
    4248    def fromFullPath(cls, filename, *args, **kwargs):
    4349        """
    4450        Construct a log file from a full file path.
    class BaseLogFile: 
    6167        """
    6268        self.closed = False
    6369        if os.path.exists(self.path):
    64             self._file = file(self.path, "r+", 1)
     70            self._file = open(self.path, "r+", 1)
    6571            self._file.seek(0, 2)
    6672        else:
    6773            if self.defaultMode is not None:
    6874                # Set the lowest permissions
    69                 oldUmask = os.umask(0777)
     75                oldUmask = os.umask(0o777)
    7076                try:
    71                     self._file = file(self.path, "w+", 1)
     77                    self._file = open(self.path, "w+", 1)
    7278                finally:
    7379                    os.umask(oldUmask)
    7480            else:
    75                 self._file = file(self.path, "w+", 1)
     81                self._file = open(self.path, "w+", 1)
    7682        if self.defaultMode is not None:
    7783            try:
    7884                os.chmod(self.path, self.defaultMode)
    class LogFile(BaseLogFile): 
    178184        """
    179185        filename = "%s.%d" % (self.path, identifier)
    180186        if not os.path.exists(filename):
    181             raise ValueError, "no such logfile exists"
     187            raise ValueError("no such logfile exists")
    182188        return LogReader(filename)
    183189
    184190    def write(self, data):
    class DailyLogFile(BaseLogFile): 
    266272            return self.getCurrentLog()
    267273        filename = "%s.%s" % (self.path, self.suffix(identifier))
    268274        if not os.path.exists(filename):
    269             raise ValueError, "no such logfile exists"
     275            raise ValueError("no such logfile exists")
    270276        return LogReader(filename)
    271277
    272278    def write(self, data):
    class LogReader: 
    304310    """Read from a log file."""
    305311
    306312    def __init__(self, name):
    307         self._file = file(name, "r")
     313        self._file = open(name, "r")
     314
     315    def __del__(self):
     316        self.close()
    308317
    309318    def readLines(self, lines=10):
    310319        """Read a list of lines from the log file.
  • twisted/test/test_logfile.py

    diff --git twisted/test/test_logfile.py twisted/test/test_logfile.py
    index e7db238..e456e2b 100644
     
    11# Copyright (c) Twisted Matrix Laboratories.
    22# See LICENSE for details.
    33
    4 import os, time, stat, errno
     4import datetime
     5import os, time, stat, errno, pickle
    56
    67from twisted.trial import unittest
    78from twisted.python import logfile, runtime
    class LogFileTestCase(unittest.TestCase): 
    2425        Restore back write rights on created paths: if tests modified the
    2526        rights, that will allow the paths to be removed easily afterwards.
    2627        """
    27         os.chmod(self.dir, 0777)
     28        os.chmod(self.dir, 0o777)
    2829        if os.path.exists(self.path):
    29             os.chmod(self.path, 0777)
     30            os.chmod(self.path, 0o777)
     31
     32
     33    def test_abstractShouldRotate(self):
     34        """
     35        L{BaseLogFile.shouldRotate} is abstract and must be implemented by
     36        subclass.
     37        """
     38        log = logfile.BaseLogFile(self.name, self.dir)
     39        self.assertRaises(NotImplementedError, log.shouldRotate)
    3040
    3141
    3242    def testWriting(self):
    class LogFileTestCase(unittest.TestCase): 
    6272        log.rotate()
    6373        self.assert_(os.path.exists("%s.3" % self.path))
    6474        self.assert_(not os.path.exists("%s.4" % self.path))
    65         log.close()
    6675
    6776        self.assertEqual(log.listLogs(), [1, 2, 3])
    6877
    class LogFileTestCase(unittest.TestCase): 
    8089        f = log._file
    8190        f.seek(0, 0)
    8291        self.assertEqual(f.read(), "0123456789abc")
    83         log.close()
    8492
    8593    def testLogReader(self):
    8694        log = logfile.LogFile(self.name, self.dir)
    class LogFileTestCase(unittest.TestCase): 
    96104        reader._file.seek(0)
    97105        self.assertEqual(reader.readLines(), ["ghi\n"])
    98106        self.assertEqual(reader.readLines(), [])
    99         reader.close()
    100107        reader = log.getLog(1)
    101108        self.assertEqual(reader.readLines(), ["abc\n", "def\n"])
    102109        self.assertEqual(reader.readLines(), [])
    103         reader.close()
    104110
    105111        # check getting illegal log readers
    106112        self.assertRaises(ValueError, log.getLog, 2)
    class LogFileTestCase(unittest.TestCase): 
    113119        reader._file.seek(0)
    114120        self.assertEqual(reader.readLines(), ["ghi\n"])
    115121        self.assertEqual(reader.readLines(), [])
    116         reader.close()
    117122        reader = log.getLog(2)
    118123        self.assertEqual(reader.readLines(), ["abc\n", "def\n"])
    119124        self.assertEqual(reader.readLines(), [])
    120         reader.close()
    121125
    122126    def testModePreservation(self):
    123127        """
    124128        Check rotated files have same permissions as original.
    125129        """
    126130        f = open(self.path, "w").close()
    127         os.chmod(self.path, 0707)
     131        os.chmod(self.path, 0o707)
    128132        mode = os.stat(self.path)[stat.ST_MODE]
    129133        log = logfile.LogFile(self.name, self.dir)
    130134        log.write("abc")
    class LogFileTestCase(unittest.TestCase): 
    140144        log.write("abc")
    141145
    142146        # change permissions so rotation would fail
    143         os.chmod(self.dir, 0555)
     147        os.chmod(self.dir, 0o555)
    144148
    145149        # if this succeeds, chmod doesn't restrict us, so we can't
    146150        # do the test
    class LogFileTestCase(unittest.TestCase): 
    149153        except (OSError, IOError):
    150154            pass
    151155        else:
    152             f.close()
    153156            return
    154157
    155158        log.rotate() # this should not fail
    class LogFileTestCase(unittest.TestCase): 
    161164        self.assertEqual(f.tell(), 6)
    162165        f.seek(0, 0)
    163166        self.assertEqual(f.read(), "abcdef")
    164         log.close()
    165167
    166168
    167169    def test_maxNumberOfLog(self):
    class LogFileTestCase(unittest.TestCase): 
    180182
    181183        log.write("4" * 11)
    182184        self.failUnless(os.path.exists("%s.3" % self.path))
    183         self.assertEqual(file("%s.3" % self.path).read(), "1" * 11)
     185        with open("%s.3" % self.path) as fp:
     186            self.assertEqual(fp.read(), "1" * 11)
    184187
    185188        log.write("5" * 11)
    186         self.assertEqual(file("%s.3" % self.path).read(), "2" * 11)
     189        with open("%s.3" % self.path) as fp:
     190            self.assertEqual(fp.read(), "2" * 11)
    187191        self.failUnless(not os.path.exists("%s.4" % self.path))
    188192
    189193    def test_fromFullPath(self):
    190194        """
    191195        Test the fromFullPath method.
    192196        """
    193         log1 = logfile.LogFile(self.name, self.dir, 10, defaultMode=0777)
    194         log2 = logfile.LogFile.fromFullPath(self.path, 10, defaultMode=0777)
     197        log1 = logfile.LogFile(self.name, self.dir, 10, defaultMode=0o777)
     198        log2 = logfile.LogFile.fromFullPath(self.path, 10, defaultMode=0o777)
    195199        self.assertEqual(log1.name, log2.name)
    196200        self.assertEqual(os.path.abspath(log1.path), log2.path)
    197201        self.assertEqual(log1.rotateLength, log2.rotateLength)
    class LogFileTestCase(unittest.TestCase): 
    202206        Test the default permission of the log file: if the file exist, it
    203207        should keep the permission.
    204208        """
    205         f = file(self.path, "w")
    206         os.chmod(self.path, 0707)
     209        f = open(self.path, "w")
     210        os.chmod(self.path, 0o707)
    207211        currentMode = stat.S_IMODE(os.stat(self.path)[stat.ST_MODE])
    208212        f.close()
    209213        log1 = logfile.LogFile(self.name, self.dir)
    class LogFileTestCase(unittest.TestCase): 
    215219        """
    216220        Test specifying the permissions used on the log file.
    217221        """
    218         log1 = logfile.LogFile(self.name, self.dir, defaultMode=0066)
     222        log1 = logfile.LogFile(self.name, self.dir, defaultMode=0o066)
    219223        mode = stat.S_IMODE(os.stat(self.path)[stat.ST_MODE])
    220224        if runtime.platform.isWindows():
    221225            # The only thing we can get here is global read-only
    222             self.assertEqual(mode, 0444)
     226            self.assertEqual(mode, 0o444)
    223227        else:
    224             self.assertEqual(mode, 0066)
     228            self.assertEqual(mode, 0o066)
    225229
    226230
    227231    def test_reopen(self):
    class LogFileTestCase(unittest.TestCase): 
    257261        self.assertEqual(e.errno, errno.ENOENT)
    258262
    259263
     264    def test_persistence(self):
     265        """
     266        L{LogFile} objects can be pickled and unpickled, which preserves all the
     267        various attributes of the log file.
     268        """
     269        rotateLength = 12345
     270        defaultMode = 0o642
     271        maxRotatedFiles = 42
     272
     273        log = logfile.LogFile(self.name, self.dir,
     274                              rotateLength, defaultMode,
     275                              maxRotatedFiles)
     276        log.write("123")
     277        log.close()
     278
     279        copy = pickle.loads(pickle.dumps(log))
     280
     281        # Check that the unpickled log is the same as the original one.
     282        self.assertEqual(self.name, copy.name)
     283        self.assertEqual(self.dir, copy.directory)
     284        self.assertEqual(self.path, copy.path)
     285        self.assertEqual(rotateLength, copy.rotateLength)
     286        self.assertEqual(defaultMode, copy.defaultMode)
     287        self.assertEqual(maxRotatedFiles, copy.maxRotatedFiles)
     288        self.assertEqual(log.size, copy.size)
     289
     290
     291    def test_cantChangeFileMode(self):
     292        """
     293        Opening a L{LogFile} which can be read and write but whose mode can't
     294        be changed doesn't trigger an error.
     295        """
     296        log = logfile.LogFile("null", "/dev", defaultMode=0o555)
     297
     298        self.assertEqual(log.path, "/dev/null")
     299        self.assertEqual(log.defaultMode, 0o555)
     300
     301
     302    def test_listLogsWithBadlyNamedFiles(self):
     303        """
     304        L{LogFile.listLogs} doesn't choke if it encounters a file with an
     305        unexpected name.
     306        """
     307        log = logfile.LogFile(self.name, self.dir)
     308
     309        with open("%s.1" % log.path, "w") as fp:
     310            fp.write("123")
     311        with open("%s.bad-file" % log.path, "w") as fp:
     312            fp.write("123")
     313
     314        self.assertEqual([1], log.listLogs())
     315
    260316
    261317class RiggedDailyLogFile(logfile.DailyLogFile):
    262318    _clock = 0.0
    class DailyLogFileTestCase(unittest.TestCase): 
    318374        log.write("3")
    319375        self.assert_(not os.path.exists(days[2]))
    320376
     377    def test_getLog(self):
     378        log = RiggedDailyLogFile(self.name, self.dir)
     379        log.write("1\n")
     380        log.write("2\n")
     381        log.write("3\n")
     382
     383        r = log.getLog(0.0)
     384        self.assertEqual(["1\n", "2\n", "3\n"], r.readLines())
     385
     386        self.assertRaises(ValueError, log.getLog, 86400)
     387
     388        log._clock = 86401 # New day
     389        log.rotate()
     390        r = log.getLog(0) # We get the previous log
     391        self.assertEqual(["1\n", "2\n", "3\n"], r.readLines())
     392
     393
     394    def test_rotateAlreadyExists(self):
     395        """
     396        L{DailyLogFile.rotate} doesn't do anything if they new log file already
     397        exists on the disk.
     398        """
     399        log = RiggedDailyLogFile(self.name, self.dir)
     400        # Build a new file with the same name as the file which would be created
     401        # if the log file is to be rotated.
     402        with open("%s.%s" % (log.path, log.suffix(log.lastDate)), "w") as fp:
     403            fp.write("123")
     404        previous_file = log._file
     405        log.rotate()
     406        self.assertEqual(previous_file, log._file)
     407
     408
     409    def test_toDate(self):
     410        """
     411        Test that L{DailyLogFile.toDate} converts its timestamp argument to a
     412        time tuple (year, month, day).
     413        """
     414        log = logfile.DailyLogFile(self.name, self.dir)
     415
     416        timestamp = time.mktime((2000, 1, 1, 0, 0, 0, 0, 0, 0))
     417        self.assertEqual((2000, 1, 1), log.toDate(timestamp))
     418
     419
     420    def test_toDateDefaultToday(self):
     421        """
     422        Test that L{DailyLogFile.toDate} returns today's date by default.
     423        """
     424        log = logfile.DailyLogFile(self.name, self.dir)
     425
     426        # XXX: this might break if by chance, current's date changes between the
     427        # two functions runs.
     428        today = datetime.date.today()
     429        log_date = log.toDate()
     430
     431        self.assertEqual(today.timetuple()[:3], log_date)
     432
     433
     434    def test_persistence(self):
     435        """
     436        L{DailyLogFile} objects can be pickled and unpickled, which preserves
     437        all the various attributes of the log file.
     438        """
     439        defaultMode = 0o642
     440
     441        log = logfile.DailyLogFile(self.name, self.dir,
     442                                   defaultMode)
     443        log.write("123")
     444
     445        # Check that the unpickled log is the same as the original one.
     446        copy = pickle.loads(pickle.dumps(log))
     447
     448        self.assertEqual(self.name, copy.name)
     449        self.assertEqual(self.dir, copy.directory)
     450        self.assertEqual(self.path, copy.path)
     451        self.assertEqual(defaultMode, copy.defaultMode)
     452        self.assertEqual(log.lastDate, copy.lastDate)