John Vandenberg has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/175404

Change subject: Permissive Timestamp fromX methods
......................................................................

Permissive Timestamp fromX methods

Several methods of site and page classes return a Timestamp where
previously they returned a string which should be passed to the
Timestamp class to create a Timestamp object.
In order to improve compatibility with old versions of pywikibot,
Timestamp should recognise it is being passed a Timestamp, and not
try to parse it.

Change-Id: Ifb850b3e52c0fb1b84f2da433f50cb142f854591
---
M pywikibot/__init__.py
A tests/timestamp_tests.py
2 files changed, 106 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/04/175404/1

diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index e20d7c4..d60e45e 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -112,6 +112,10 @@
 
     Use Timestamp.fromISOformat() and Timestamp.fromtimestampformat() to
     create Timestamp objects from MediaWiki string formats.
+    As these constructors are typically used to create objects using data
+    passed provided by site and page methods, some of which return a Timestamp
+    when previously they returned a MediaWiki string representation, these
+    methods also accept a Timestamp object, in which case they return a clone.
 
     Use Site.getcurrenttime() for the current time; this is more reliable
     than using Timestamp.utcnow().
@@ -124,11 +128,19 @@
     @classmethod
     def fromISOformat(cls, ts):
         """Convert an ISO 8601 timestamp to a Timestamp object."""
+        # If inadvertantly passed a Timestamp object, use replace()
+        # to create a clone.
+        if isinstance(ts, cls):
+            return ts.replace(microsecond=ts.microsecond)
         return cls.strptime(ts, cls.ISO8601Format)
 
     @classmethod
     def fromtimestampformat(cls, ts):
         """Convert a MediaWiki internal timestamp to a Timestamp object."""
+        # If inadvertantly passed a Timestamp object, use replace()
+        # to create a clone.
+        if isinstance(ts, cls):
+            return ts.replace(microsecond=ts.microsecond)
         return cls.strptime(ts, cls.mediawikiTSFormat)
 
     def toISOformat(self):
@@ -144,7 +156,8 @@
         return self.toISOformat()
 
     def __add__(self, other):
-        newdt = datetime.datetime.__add__(self, other)
+        """Perform addition, returning a Timestamp instead of datetime."""
+        newdt = super(Timestamp, self).__add__(other)
         if isinstance(newdt, datetime.datetime):
             return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour,
                              newdt.minute, newdt.second, newdt.microsecond,
@@ -153,7 +166,8 @@
             return newdt
 
     def __sub__(self, other):
-        newdt = datetime.datetime.__sub__(self, other)
+        """Perform substraction, returning a Timestamp instead of datetime."""
+        newdt = super(Timestamp, self).__sub__(other)
         if isinstance(newdt, datetime.datetime):
             return Timestamp(newdt.year, newdt.month, newdt.day, newdt.hour,
                              newdt.minute, newdt.second, newdt.microsecond,
diff --git a/tests/timestamp_tests.py b/tests/timestamp_tests.py
new file mode 100644
index 0000000..0018c01
--- /dev/null
+++ b/tests/timestamp_tests.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8  -*-
+"""Tests for the Timestamp class."""
+#
+# (C) Pywikibot team, 2014
+#
+# Distributed under the terms of the MIT license.
+#
+__version__ = '$Id$'
+
+import datetime
+
+from pywikibot import Timestamp as T
+
+from tests.aspects import unittest, TestCase
+
+
+class TestTimestamp(TestCase):
+
+    """Test Timestamp class comparisons."""
+
+    net = False
+
+    def test_instantiate_from_instance(self):
+        """Test passing instance to factory methods works."""
+        t1 = T.utcnow()
+        self.assertIsNot(t1, T.fromISOformat(t1))
+        self.assertEqual(t1, T.fromISOformat(t1))
+        self.assertIsInstance(T.fromISOformat(t1), T)
+        self.assertIsNot(t1, T.fromtimestampformat(t1))
+        self.assertEqual(t1, T.fromtimestampformat(t1))
+        self.assertIsInstance(T.fromtimestampformat(t1), T)
+
+    def test_iso_format(self):
+        t1 = T.utcnow()
+        ts1 = t1.toISOformat()
+        t2 = T.fromISOformat(ts1)
+        ts2 = t2.toISOformat()
+        # MediaWiki ISO format doesnt include microseconds
+        self.assertNotEqual(t1, t2)
+        t1 = t1.replace(microsecond=0)
+        self.assertEqual(t1, t2)
+        self.assertEqual(ts1, ts2)
+
+    def test_mediawiki_format(self):
+        t1 = T.utcnow()
+        ts1 = t1.totimestampformat()
+        t2 = T.fromtimestampformat(ts1)
+        ts2 = t2.totimestampformat()
+        self.assertNotEqual(t1, t2)
+        t1 = t1.replace(microsecond=0)
+        self.assertEqual(t1, t2)
+        self.assertEqual(ts1, ts2)
+
+    def test_add_timedelta(self):
+        t1 = T.utcnow()
+        t2 = t1 + datetime.timedelta(days=1)
+        self.assertEqual(t1.day + 1, t2.day)
+        self.assertIsInstance(t2, T)
+
+    def test_add_timedate(self):
+        """Test unsupported additions raise NotImplemented."""
+        t1 = datetime.datetime.utcnow()
+        t2 = t1 + datetime.timedelta(days=1)
+        t3 = t1.__add__(t2)
+        self.assertIs(t3, NotImplemented)
+
+        # Now use the pywikibot class
+        t1 = T.utcnow()
+        t2 = t1 + datetime.timedelta(days=1)
+        t3 = t1.__add__(t2)
+        self.assertIs(t3, NotImplemented)
+
+    def test_sub_timedelta(self):
+        t1 = T.utcnow()
+        t2 = t1 - datetime.timedelta(days=1)
+        self.assertEqual(t1.day - 1, t2.day)
+        self.assertIsInstance(t2, T)
+
+    def test_sub_timedate(self):
+        t1 = T.utcnow()
+        t2 = t1 - datetime.timedelta(days=1)
+        td = t1 - t2
+        self.assertIsInstance(td, datetime.timedelta)
+        self.assertEqual(t2 + td, t1)
+
+if __name__ == '__main__':
+    try:
+        unittest.main()
+    except SystemExit:
+        pass

-- 
To view, visit https://gerrit.wikimedia.org/r/175404
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifb850b3e52c0fb1b84f2da433f50cb142f854591
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jay...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to