diff --git a/rdiffweb/librdiff.py b/rdiffweb/librdiff.py index cb28a4b81932d398ef61a7b13b4be918ca658161..77d94fe1ff64c47ea429d6e13ae9756620bc5f96 100755 --- a/rdiffweb/librdiff.py +++ b/rdiffweb/librdiff.py @@ -21,9 +21,12 @@ from __future__ import unicode_literals import bisect from builtins import bytes +from builtins import map from builtins import object from builtins import str +import calendar from collections import OrderedDict +from datetime import timedelta import encodings from future.utils import iteritems from future.utils import python_2_unicode_compatible @@ -32,6 +35,8 @@ import gzip import io import logging import os +from past.builtins import cmp +from past.utils import old_div import psutil import re from shutil import copyfileobj @@ -39,6 +44,7 @@ import shutil import sys import tempfile import threading +import time import weakref import zlib @@ -47,7 +53,6 @@ from rdiffweb.archiver import archive, ARCHIVERS from rdiffweb.i18n import ugettext as _ from rdiffweb.rdw_config import Configuration - try: import subprocess32 as subprocess # @UnresolvedImport @UnusedImport except: @@ -105,6 +110,166 @@ class UnknownError(FileError): pass +@python_2_unicode_compatible +class RdiffTime(object): + + """Time information has two components: the local time, stored in GMT as + seconds since Epoch, and the timezone, stored as a seconds offset. Since + the server may not be in the same timezone as the user, we cannot rely on + the built-in localtime() functions, but look at the rdiff-backup string + for timezone information. As a general rule, we always display the + "local" time, but pass the timezone information on to rdiff-backup, so + it can restore to the correct state""" + + def __init__(self, value=None, tz_offset=None): + assert value is None or isinstance(value, int) or isinstance(value, str) + if value is None: + # Get GMT time. + self.timeInSeconds = int(time.time()) + self.tzOffset = tz_offset or 0 + elif isinstance(value, int): + self.timeInSeconds = value + self.tzOffset = tz_offset or 0 + else: + self._initFromString(value) + + def initFromMidnightUTC(self, daysFromToday): + self.timeInSeconds = time.time() + self.timeInSeconds -= self.timeInSeconds % (24 * 60 * 60) + self.timeInSeconds += daysFromToday * 24 * 60 * 60 + self.tzOffset = 0 + + def _initFromString(self, timeString): + try: + date, daytime = timeString[:19].split("T") + year, month, day = list(map(int, date.split("-"))) + hour, minute, second = list(map(int, daytime.split(":"))) + assert 1900 < year < 2100, year + assert 1 <= month <= 12 + assert 1 <= day <= 31 + assert 0 <= hour <= 23 + assert 0 <= minute <= 59 + assert 0 <= second <= 61 # leap seconds + + timetuple = (year, month, day, hour, minute, second, -1, -1, 0) + self.timeInSeconds = calendar.timegm(timetuple) + self.tzOffset = self._tzdtoseconds(timeString[19:]) + self.getTimeZoneString() # to get assertions there + + except (TypeError, ValueError, AssertionError): + raise ValueError(timeString) + + def getLocalDaysSinceEpoch(self): + return self.getLocalSeconds() // (24 * 60 * 60) + + def getLocalSeconds(self): + return self.timeInSeconds + + def getSeconds(self): + return self.timeInSeconds - self.tzOffset + + def getDisplayString(self): + value = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(self.getLocalSeconds())) + if isinstance(value, bytes): + value = value.decode(encoding='latin1') + return value + + def getTimeZoneString(self): + if self.tzOffset: + tzinfo = self._getTimeZoneDisplayInfo() + return "%s%s:%s" % (tzinfo["plusMinus"], tzinfo["hours"], tzinfo["minutes"]) + else: + return "Z" + + def setTime(self, hour, minute, second): + year = time.gmtime(self.timeInSeconds)[0] + month = time.gmtime(self.timeInSeconds)[1] + day = time.gmtime(self.timeInSeconds)[2] + self.timeInSeconds = calendar.timegm( + (year, month, day, hour, minute, second, -1, -1, 0)) + + def _getTimeZoneDisplayInfo(self): + hours, minutes = divmod(old_div(abs(self.tzOffset), 60), 60) + assert 0 <= hours <= 23 + assert 0 <= minutes <= 59 + + if self.tzOffset > 0: + plusMinus = "+" + else: + plusMinus = "-" + return {"plusMinus": plusMinus, + "hours": "%02d" % hours, + "minutes": "%02d" % minutes} + + def _tzdtoseconds(self, tzd): + """Given w3 compliant TZD, converts it to number of seconds from UTC""" + if tzd == "Z": + return 0 + assert len(tzd) == 6 # only accept forms like +08:00 for now + assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":" + + if tzd[0] == "+": + plusMinus = 1 + else: + plusMinus = -1 + + return plusMinus * 60 * (60 * int(tzd[1:3]) + int(tzd[4:])) + + def __add__(self, other): + """Support plus (+) timedelta""" + assert isinstance(other, timedelta) + return RdiffTime(self.timeInSeconds + int(other.total_seconds()), self.tzOffset) + + def __sub__(self, other): + """Support minus (-) timedelta""" + assert isinstance(other, timedelta) or isinstance(other, RdiffTime) + # Sub with timedelta, return RdiffTime + if isinstance(other, timedelta): + return RdiffTime(self.timeInSeconds - int(other.total_seconds()), self.tzOffset) + + # Sub with RdiffTime, return timedelta + if isinstance(other, RdiffTime): + return timedelta(seconds=self.timeInSeconds - other.timeInSeconds) + + def __int__(self): + """Return this date as seconds since epoch.""" + return self.timeInSeconds + + def __lt__(self, other): + assert isinstance(other, RdiffTime) + return self.getSeconds() < other.getSeconds() + + def __le__(self, other): + assert isinstance(other, RdiffTime) + return self.getSeconds() <= other.getSeconds() + + def __gt__(self, other): + assert isinstance(other, RdiffTime) + return self.getSeconds() > other.getSeconds() + + def __ge__(self, other): + assert isinstance(other, RdiffTime) + return self.getSeconds() >= other.getSeconds() + + def __cmp__(self, other): + assert isinstance(other, RdiffTime) + return cmp(self.getSeconds(), other.getSeconds()) + + def __eq__(self, other): + return (isinstance(other, RdiffTime) and + self.getSeconds() == other.getSeconds()) + + def __hash__(self): + return hash(self.getSeconds()) + + def __str__(self): + """return utf-8 string""" + return self.getDisplayString() + + def __repr__(self): + """return second since epoch""" + return str(self.getSeconds()) + # Interfaced objects # class DirEntry(object): @@ -299,7 +464,7 @@ class HistoryEntry(object): def __init__(self, repo, date): assert isinstance(repo, RdiffRepo) - assert isinstance(date, rdw_helpers.rdwTime) + assert isinstance(date, RdiffTime) self._repo = weakref.proxy(repo) self.date = date @@ -677,7 +842,7 @@ class RdiffRepo(object): # Unquote string date_string = self.unquote(date_string) try: - return rdw_helpers.rdwTime(date_string.decode()) + return RdiffTime(date_string.decode()) except: logger.warn('fail to parse date [%r]', date_string, exc_info=1) return None @@ -727,9 +892,9 @@ class RdiffRepo(object): assert isinstance(numLatestEntries, int) assert (earliestDate is None or - isinstance(earliestDate, rdw_helpers.rdwTime)) + isinstance(earliestDate, RdiffTime)) assert (latestDate is None or - isinstance(latestDate, rdw_helpers.rdwTime)) + isinstance(latestDate, RdiffTime)) logger.debug("get history entries for [%r]", self.full_path) @@ -831,7 +996,7 @@ class RdiffRepo(object): def restore(self, path, restore_date, kind='zip'): """Used to restore the given file located in this path.""" assert isinstance(path, bytes) or isinstance(path, DirEntry) - assert isinstance(restore_date, rdw_helpers.rdwTime) or isinstance(restore_date, int) + assert isinstance(restore_date, RdiffTime) or isinstance(restore_date, int) assert kind in ARCHIVERS # Get the info we need from DirEntry @@ -848,7 +1013,7 @@ class RdiffRepo(object): file_to_restore = self.unquote(file_to_restore) # Convert the date into epoch. - if isinstance(restore_date, rdw_helpers.rdwTime): + if isinstance(restore_date, RdiffTime): restore_date = restore_date.getSeconds() # Define a nice filename for the archive or file to be created. diff --git a/rdiffweb/page_restore.py b/rdiffweb/page_restore.py index f65fb87b89ed679e962f7a273fe6b6d886980bd5..e1eb477df2f6d459e468b277614fb83113fc5e49 100644 --- a/rdiffweb/page_restore.py +++ b/rdiffweb/page_restore.py @@ -26,12 +26,11 @@ from cherrypy.lib.static import _serve_fileobj import logging from rdiffweb import page_main -from rdiffweb import rdw_helpers import rdiffweb +from rdiffweb.archiver import ARCHIVERS from rdiffweb.i18n import ugettext as _ +from rdiffweb.librdiff import RdiffTime from rdiffweb.rdw_helpers import quote_url -from rdiffweb.archiver import ARCHIVERS - # Define the logger logger = logging.getLogger(__name__) @@ -78,7 +77,7 @@ class RestorePage(page_main.MainPage): # Get the restore date try: - rdw_helpers.rdwTime(int(date)) + RdiffTime(int(date)) except: logger.warning("invalid date %s", date) raise cherrypy.HTTPError(400, _("Invalid date.")) diff --git a/rdiffweb/page_status.py b/rdiffweb/page_status.py index 9cc846f102e2e0e4420357e56885caf3a36b47b4..620062fcfe7074e8cf8211c502a94517f1a72f4e 100644 --- a/rdiffweb/page_status.py +++ b/rdiffweb/page_status.py @@ -19,8 +19,8 @@ from __future__ import absolute_import from __future__ import unicode_literals -from builtins import str from builtins import bytes +from builtins import str import cherrypy import logging @@ -62,7 +62,7 @@ class StatusPage(page_main.MainPage): self.assertIsInstance(date, str) # Validate date try: - entry_time = rdw_helpers.rdwTime(int(date)) + entry_time = librdiff.RdiffTime(int(date)) except: logger.exception("invalid date") raise cherrypy.HTTPError(400, _("Invalid date.")) @@ -122,12 +122,12 @@ class StatusPage(page_main.MainPage): # Set the start and end time to be the start and end of the day, # respectively, to get all entries for that day - startTime = rdw_helpers.rdwTime() + startTime = librdiff.RdiffTime() startTime.timeInSeconds = date.timeInSeconds startTime.tzOffset = date.tzOffset startTime.setTime(0, 0, 0) - endTime = rdw_helpers.rdwTime() + endTime = librdiff.RdiffTime() endTime.timeInSeconds = date.timeInSeconds endTime.tzOffset = date.tzOffset endTime.setTime(23, 59, 59) @@ -137,7 +137,7 @@ class StatusPage(page_main.MainPage): def _get_recent_user_messages(self, failuresOnly): user_repos = self.app.currentuser.repos - asOfDate = rdw_helpers.rdwTime() + asOfDate = librdiff.RdiffTime() asOfDate.initFromMidnightUTC(-5) return self._getUserMessages(user_repos, not failuresOnly, True, diff --git a/rdiffweb/plugins/notification/__init__.py b/rdiffweb/plugins/notification/__init__.py index 419cd6a58be163d768f1e66709a03880a628922b..1d219e39036bc080188c650da20152371cd4f3ff 100644 --- a/rdiffweb/plugins/notification/__init__.py +++ b/rdiffweb/plugins/notification/__init__.py @@ -37,7 +37,6 @@ from xml.etree.ElementTree import fromstring, tostring from rdiffweb import librdiff from rdiffweb.core import RdiffError, RdiffWarning from rdiffweb.i18n import ugettext as _ -from rdiffweb.rdw_helpers import rdwTime from rdiffweb.rdw_plugin import IPreferencesPanelProvider, JobPlugin, \ IUserChangeListener @@ -203,7 +202,7 @@ class NotificationPlugin(IPreferencesPanelProvider, JobPlugin, IUserChangeListen Loop trough all the user repository and send notifications. """ - now = rdwTime() + now = librdiff.RdiffTime() def _user_repos(): """Return a generator trought user repos to be notified.""" diff --git a/rdiffweb/plugins/remove_older/__init__.py b/rdiffweb/plugins/remove_older/__init__.py index dfca669641b7ac801e9ac288e6acaa2b33e7943f..9e6d9d3da5a069ca9ee8dbee6778b3ec0eac1015 100644 --- a/rdiffweb/plugins/remove_older/__init__.py +++ b/rdiffweb/plugins/remove_older/__init__.py @@ -34,7 +34,6 @@ from rdiffweb import rdw_spider_repos, page_main, librdiff from rdiffweb.dispatch import poppath from rdiffweb.i18n import ugettext as _ from rdiffweb.page_main import MainPage -from rdiffweb.rdw_helpers import rdwTime from rdiffweb.rdw_plugin import IPreferencesPanelProvider, ITemplateFilterPlugin, \ IDeamonPlugin, JobPlugin @@ -126,7 +125,7 @@ class RemoveOlderPlugin(ITemplateFilterPlugin, JobPlugin): if not r.last_backup_date: _logger.info("no backup dates for [%r]", r.full_path) return - d = rdwTime() - r.last_backup_date + d = librdiff.RdiffTime() - r.last_backup_date d = d.days + keepdays _logger.info("execute rdiff-backup --force --remove-older-than=%sD %r", d, r.full_path) diff --git a/rdiffweb/plugins/set_encoding/__init__.py b/rdiffweb/plugins/set_encoding/__init__.py index 65f3b2b5a15dfdb81d235861297a377ffae29c59..6e05406cf18039974cae6aad152e11a9d195c80b 100644 --- a/rdiffweb/plugins/set_encoding/__init__.py +++ b/rdiffweb/plugins/set_encoding/__init__.py @@ -35,7 +35,6 @@ from rdiffweb import rdw_spider_repos, page_main, librdiff from rdiffweb.dispatch import poppath from rdiffweb.i18n import ugettext as _ from rdiffweb.page_main import MainPage -from rdiffweb.rdw_helpers import rdwTime from rdiffweb.rdw_plugin import IPreferencesPanelProvider, ITemplateFilterPlugin, \ IDeamonPlugin diff --git a/rdiffweb/rdw_helpers.py b/rdiffweb/rdw_helpers.py index 6a083b6abceda70c78a4ab94945c4d5d4be4f9cc..ebee2f1a4e56442bc5eccdac96169e0eb632dc9b 100755 --- a/rdiffweb/rdw_helpers.py +++ b/rdiffweb/rdw_helpers.py @@ -20,17 +20,8 @@ from __future__ import division from __future__ import unicode_literals from builtins import bytes -from builtins import map -from builtins import object from builtins import str -import calendar from future.utils import iteritems -from future.utils import python_2_unicode_compatible -from past.builtins import cmp -from past.utils import old_div -import time -from datetime import timedelta, datetime - try: from urllib.parse import quote, unquote @@ -78,166 +69,6 @@ def unquote_url(url): return val -@python_2_unicode_compatible -class rdwTime(object): - - """Time information has two components: the local time, stored in GMT as - seconds since Epoch, and the timezone, stored as a seconds offset. Since - the server may not be in the same timezone as the user, we cannot rely on - the built-in localtime() functions, but look at the rdiff-backup string - for timezone information. As a general rule, we always display the - "local" time, but pass the timezone information on to rdiff-backup, so - it can restore to the correct state""" - - def __init__(self, value=None, tz_offset=None): - assert value is None or isinstance(value, int) or isinstance(value, str) - if value is None: - # Get GMT time. - self.timeInSeconds = int(time.time()) - self.tzOffset = tz_offset or 0 - elif isinstance(value, int): - self.timeInSeconds = value - self.tzOffset = tz_offset or 0 - else: - self._initFromString(value) - - def initFromMidnightUTC(self, daysFromToday): - self.timeInSeconds = time.time() - self.timeInSeconds -= self.timeInSeconds % (24 * 60 * 60) - self.timeInSeconds += daysFromToday * 24 * 60 * 60 - self.tzOffset = 0 - - def _initFromString(self, timeString): - try: - date, daytime = timeString[:19].split("T") - year, month, day = list(map(int, date.split("-"))) - hour, minute, second = list(map(int, daytime.split(":"))) - assert 1900 < year < 2100, year - assert 1 <= month <= 12 - assert 1 <= day <= 31 - assert 0 <= hour <= 23 - assert 0 <= minute <= 59 - assert 0 <= second <= 61 # leap seconds - - timetuple = (year, month, day, hour, minute, second, -1, -1, 0) - self.timeInSeconds = calendar.timegm(timetuple) - self.tzOffset = self._tzdtoseconds(timeString[19:]) - self.getTimeZoneString() # to get assertions there - - except (TypeError, ValueError, AssertionError): - raise ValueError(timeString) - - def getLocalDaysSinceEpoch(self): - return self.getLocalSeconds() // (24 * 60 * 60) - - def getLocalSeconds(self): - return self.timeInSeconds - - def getSeconds(self): - return self.timeInSeconds - self.tzOffset - - def getDisplayString(self): - value = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(self.getLocalSeconds())) - if isinstance(value, bytes): - value = value.decode(encoding='latin1') - return value - - def getTimeZoneString(self): - if self.tzOffset: - tzinfo = self._getTimeZoneDisplayInfo() - return "%s%s:%s" % (tzinfo["plusMinus"], tzinfo["hours"], tzinfo["minutes"]) - else: - return "Z" - - def setTime(self, hour, minute, second): - year = time.gmtime(self.timeInSeconds)[0] - month = time.gmtime(self.timeInSeconds)[1] - day = time.gmtime(self.timeInSeconds)[2] - self.timeInSeconds = calendar.timegm( - (year, month, day, hour, minute, second, -1, -1, 0)) - - def _getTimeZoneDisplayInfo(self): - hours, minutes = divmod(old_div(abs(self.tzOffset), 60), 60) - assert 0 <= hours <= 23 - assert 0 <= minutes <= 59 - - if self.tzOffset > 0: - plusMinus = "+" - else: - plusMinus = "-" - return {"plusMinus": plusMinus, - "hours": "%02d" % hours, - "minutes": "%02d" % minutes} - - def _tzdtoseconds(self, tzd): - """Given w3 compliant TZD, converts it to number of seconds from UTC""" - if tzd == "Z": - return 0 - assert len(tzd) == 6 # only accept forms like +08:00 for now - assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":" - - if tzd[0] == "+": - plusMinus = 1 - else: - plusMinus = -1 - - return plusMinus * 60 * (60 * int(tzd[1:3]) + int(tzd[4:])) - - def __add__(self, other): - """Support plus (+) timedelta""" - assert isinstance(other, timedelta) - return rdwTime(self.timeInSeconds + int(other.total_seconds()), self.tzOffset) - - def __sub__(self, other): - """Support minus (-) timedelta""" - assert isinstance(other, timedelta) or isinstance(other, rdwTime) - # Sub with timedelta, return rdwTime - if isinstance(other, timedelta): - return rdwTime(self.timeInSeconds - int(other.total_seconds()), self.tzOffset) - - # Sub with rdwTime, return timedelta - if isinstance(other, rdwTime): - return timedelta(seconds=self.timeInSeconds - other.timeInSeconds) - - def __int__(self): - """Return this date as seconds since epoch.""" - return self.timeInSeconds - - def __lt__(self, other): - assert isinstance(other, rdwTime) - return self.getSeconds() < other.getSeconds() - - def __le__(self, other): - assert isinstance(other, rdwTime) - return self.getSeconds() <= other.getSeconds() - - def __gt__(self, other): - assert isinstance(other, rdwTime) - return self.getSeconds() > other.getSeconds() - - def __ge__(self, other): - assert isinstance(other, rdwTime) - return self.getSeconds() >= other.getSeconds() - - def __cmp__(self, other): - assert isinstance(other, rdwTime) - return cmp(self.getSeconds(), other.getSeconds()) - - def __eq__(self, other): - return (isinstance(other, rdwTime) and - self.getSeconds() == other.getSeconds()) - - def __hash__(self): - return hash(self.getSeconds()) - - def __str__(self): - """return utf-8 string""" - return self.getDisplayString() - - def __repr__(self): - """return second since epoch""" - return str(self.getSeconds()) - # Taken from ASPN: # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/259173 diff --git a/rdiffweb/rdw_templating.py b/rdiffweb/rdw_templating.py index 34550258634f6ee7d01711118b91f08d0d2cf2f4..224ed708d21dcded802e14d7d6f854548293678c 100755 --- a/rdiffweb/rdw_templating.py +++ b/rdiffweb/rdw_templating.py @@ -24,13 +24,14 @@ from builtins import object from builtins import str from io import StringIO from jinja2 import Environment, PackageLoader +from jinja2.filters import do_mark_safe from jinja2.loaders import ChoiceLoader, FileSystemLoader import logging import time from rdiffweb import i18n +from rdiffweb import librdiff from rdiffweb import rdw_helpers -from jinja2.filters import do_mark_safe # Define the logger @@ -98,7 +99,7 @@ def do_format_datetime(value, dateformat='%Y-%m-%d %H:%M'): if not value: return "" - if isinstance(value, rdw_helpers.rdwTime): + if isinstance(value, librdiff.RdiffTime): value = value.getSeconds() # TODO Try to figure out the time zone name (it's a ) @@ -173,7 +174,7 @@ def url_for_history(repo): def url_for_restore(repo, path, date, kind=None): assert isinstance(repo, bytes) assert path is None or isinstance(path, bytes) - assert isinstance(date, rdw_helpers.rdwTime) + assert isinstance(date, librdiff.RdiffTime) url = [] url.append("/restore/") if repo: @@ -202,7 +203,7 @@ def url_for_settings(repo): def url_for_status_entry(date, repo=None): - assert isinstance(date, rdw_helpers.rdwTime) + assert isinstance(date, librdiff.RdiffTime) url = [] url.append("/status/entry/") if repo: diff --git a/rdiffweb/tests/test_librdiff.py b/rdiffweb/tests/test_librdiff.py index f1c396a67292b5ceb03828c57dd93fab02ad29dd..d71eb8daf4d16cfc9e8483b26f2ad9244a33618a 100644 --- a/rdiffweb/tests/test_librdiff.py +++ b/rdiffweb/tests/test_librdiff.py @@ -26,18 +26,20 @@ Module used to test the librdiff. from __future__ import unicode_literals from builtins import bytes +from builtins import str +import datetime from future.utils import native_str import os import pkg_resources import shutil import tarfile import tempfile +import time import unittest from rdiffweb.librdiff import FileStatisticsEntry, RdiffRepo, \ DirEntry, IncrementEntry, SessionStatisticsEntry, HistoryEntry, \ - AccessDeniedError, DoesNotExistError, FileError, UnknownError -from rdiffweb.rdw_helpers import rdwTime + AccessDeniedError, DoesNotExistError, FileError, UnknownError, RdiffTime class MockRdiffRepo(RdiffRepo): @@ -64,13 +66,13 @@ class IncrementEntryTest(unittest.TestCase): 1414873850, 1414879639, 1414887165, 1414887491, 1414889478, 1414937803, 1414939853, 1414967021, 1415047607, 1415059497, 1415221262, 1415221470, 1415221495, 1415221507] - self.repo._backup_dates = [rdwTime(x) for x in backup_dates] + self.repo._backup_dates = [RdiffTime(x) for x in backup_dates] self.root_path = self.repo.root_path def test_init(self): increment = IncrementEntry(self.root_path, b'my_filename.txt.2014-11-02T17:23:41-05:00.diff.gz') - self.assertEqual(rdwTime(1414967021), increment.date) + self.assertEqual(RdiffTime(1414967021), increment.date) self.assertEqual(b'my_filename.txt', increment.filename) self.assertIsNotNone(increment.repo) @@ -84,7 +86,7 @@ class DirEntryTest(unittest.TestCase): 1414873850, 1414879639, 1414887165, 1414887491, 1414889478, 1414937803, 1414939853, 1414967021, 1415047607, 1415059497, 1415221262, 1415221470, 1415221495, 1415221507] - self.repo._backup_dates = [rdwTime(x) for x in backup_dates] + self.repo._backup_dates = [RdiffTime(x) for x in backup_dates] self.root_path = self.repo.root_path def test_init(self): @@ -103,9 +105,9 @@ class DirEntryTest(unittest.TestCase): entry = DirEntry(self.root_path, b'my_filename.txt', False, increments) self.assertEqual( - [rdwTime(1414939853), - rdwTime(1414967021), - rdwTime(1415059497)], + [RdiffTime(1414939853), + RdiffTime(1414967021), + RdiffTime(1415059497)], entry.change_dates) def test_change_dates_with_exists(self): @@ -117,10 +119,10 @@ class DirEntryTest(unittest.TestCase): entry = DirEntry(self.root_path, b'my_filename.txt', True, increments) self.assertEqual( - [rdwTime(1414939853), - rdwTime(1414967021), - rdwTime(1415059497), - rdwTime(1415221507)], + [RdiffTime(1414939853), + RdiffTime(1414967021), + RdiffTime(1415059497), + RdiffTime(1415221507)], entry.change_dates) def test_display_name(self): @@ -221,11 +223,11 @@ class RdiffRepoTest(unittest.TestCase): def test_extract_date(self): - self.assertEqual(rdwTime(1414967021), self.repo._extract_date(b'my_filename.txt.2014-11-02T17:23:41-05:00.diff.gz')) + self.assertEqual(RdiffTime(1414967021), self.repo._extract_date(b'my_filename.txt.2014-11-02T17:23:41-05:00.diff.gz')) # Check if date with quoted characther are proerply parsed. # On NTFS, colon (:) are not supported. - self.assertEqual(rdwTime(1483443123), self.repo._extract_date(b'my_filename.txt.2017-01-03T06;05832;05803-05;05800.diff.gz')) + self.assertEqual(RdiffTime(1483443123), self.repo._extract_date(b'my_filename.txt.2017-01-03T06;05832;05803-05;05800.diff.gz')) def test_init(self): self.assertEqual('testcases', self.repo.display_name) @@ -347,6 +349,63 @@ class SessionStatisticsEntryTest(unittest.TestCase): self.assertEqual(0, entry.errors) +class RdiffTimeTest(unittest.TestCase): + + def test_add(self): + """Check if addition with timedelta is working as expected.""" + # Without timezone + self.assertEqual(RdiffTime('2014-11-08T21:04:30Z'), + RdiffTime('2014-11-05T21:04:30Z') + datetime.timedelta(days=3)) + # With timezone + self.assertEqual(RdiffTime('2014-11-08T21:04:30-04:00'), + RdiffTime('2014-11-05T21:04:30-04:00') + datetime.timedelta(days=3)) + + def test_compare(self): + """Check behaviour of comparison operator operator.""" + + self.assertTrue(RdiffTime('2014-11-07T21:04:30-04:00') < RdiffTime('2014-11-08T21:04:30Z')) + self.assertTrue(RdiffTime('2014-11-08T21:04:30Z') < RdiffTime('2014-11-08T21:50:30Z')) + self.assertFalse(RdiffTime('2014-11-08T22:04:30Z') < RdiffTime('2014-11-08T21:50:30Z')) + + self.assertFalse(RdiffTime('2014-11-07T21:04:30-04:00') > RdiffTime('2014-11-08T21:04:30Z')) + self.assertFalse(RdiffTime('2014-11-08T21:04:30Z') > RdiffTime('2014-11-08T21:50:30Z')) + self.assertTrue(RdiffTime('2014-11-08T22:04:30Z') > RdiffTime('2014-11-08T21:50:30Z')) + + def test_init(self): + """ + Check various constructor. + """ + t0 = RdiffTime() + self.assertAlmostEqual(int(time.time()), t0.timeInSeconds, delta=5000) + + t1 = RdiffTime(1415221470) + self.assertEqual(1415221470, t1.timeInSeconds) + + t2 = RdiffTime('2014-11-05T21:04:30Z') + self.assertEqual(1415221470, t2.timeInSeconds) + + def test_int(self): + """Check if int(RdiffTime) return expected value.""" + self.assertEqual(1415221470, int(RdiffTime(1415221470))) + + def test_str(self): + """Check if __str__ is working.""" + self.assertEqual('2014-11-05 21:04:30', str(RdiffTime(1415221470))) + + def test_sub(self): + """Check if addition with timedelta is working as expected.""" + # Without timezone + self.assertEqual(RdiffTime('2014-11-02T21:04:30Z'), + RdiffTime('2014-11-05T21:04:30Z') - datetime.timedelta(days=3)) + # With timezone + self.assertEqual(RdiffTime('2014-11-02T21:04:30-04:00'), + RdiffTime('2014-11-05T21:04:30-04:00') - datetime.timedelta(days=3)) + + # With datetime + self.assertTrue((RdiffTime('2014-11-02T21:04:30Z') - RdiffTime()).days < 0) + self.assertTrue((RdiffTime() - RdiffTime('2014-11-02T21:04:30Z')).days > 0) + + if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName'] unittest.main() diff --git a/rdiffweb/tests/test_rdw_helpers.py b/rdiffweb/tests/test_rdw_helpers.py index e5296d7cfd02ce16573a6f0bcc01fa46305ec66a..38cb7f22d7f329607223acf67ec213074815fc02 100644 --- a/rdiffweb/tests/test_rdw_helpers.py +++ b/rdiffweb/tests/test_rdw_helpers.py @@ -23,12 +23,9 @@ Created on Dec 26, 2015 from __future__ import unicode_literals -from builtins import str -import datetime -import time import unittest -from rdiffweb.rdw_helpers import quote_url, unquote_url, rdwTime +from rdiffweb.rdw_helpers import quote_url, unquote_url class Test(unittest.TestCase): @@ -44,63 +41,6 @@ class Test(unittest.TestCase): self.assertEqual(b'this is some path', unquote_url(b'this%20is%20some%20path')) -class RdwTimeTest(unittest.TestCase): - - def test_add(self): - """Check if addition with timedelta is working as expected.""" - # Without timezone - self.assertEqual(rdwTime('2014-11-08T21:04:30Z'), - rdwTime('2014-11-05T21:04:30Z') + datetime.timedelta(days=3)) - # With timezone - self.assertEqual(rdwTime('2014-11-08T21:04:30-04:00'), - rdwTime('2014-11-05T21:04:30-04:00') + datetime.timedelta(days=3)) - - def test_compare(self): - """Check behaviour of comparison operator operator.""" - - self.assertTrue(rdwTime('2014-11-07T21:04:30-04:00') < rdwTime('2014-11-08T21:04:30Z')) - self.assertTrue(rdwTime('2014-11-08T21:04:30Z') < rdwTime('2014-11-08T21:50:30Z')) - self.assertFalse(rdwTime('2014-11-08T22:04:30Z') < rdwTime('2014-11-08T21:50:30Z')) - - self.assertFalse(rdwTime('2014-11-07T21:04:30-04:00') > rdwTime('2014-11-08T21:04:30Z')) - self.assertFalse(rdwTime('2014-11-08T21:04:30Z') > rdwTime('2014-11-08T21:50:30Z')) - self.assertTrue(rdwTime('2014-11-08T22:04:30Z') > rdwTime('2014-11-08T21:50:30Z')) - - def test_init(self): - """ - Check various constructor. - """ - t0 = rdwTime() - self.assertAlmostEqual(int(time.time()), t0.timeInSeconds, delta=5000) - - t1 = rdwTime(1415221470) - self.assertEqual(1415221470, t1.timeInSeconds) - - t2 = rdwTime('2014-11-05T21:04:30Z') - self.assertEqual(1415221470, t2.timeInSeconds) - - def test_int(self): - """Check if int(rdwTime) return expected value.""" - self.assertEqual(1415221470, int(rdwTime(1415221470))) - - def test_str(self): - """Check if __str__ is working.""" - self.assertEqual('2014-11-05 21:04:30', str(rdwTime(1415221470))) - - def test_sub(self): - """Check if addition with timedelta is working as expected.""" - # Without timezone - self.assertEqual(rdwTime('2014-11-02T21:04:30Z'), - rdwTime('2014-11-05T21:04:30Z') - datetime.timedelta(days=3)) - # With timezone - self.assertEqual(rdwTime('2014-11-02T21:04:30-04:00'), - rdwTime('2014-11-05T21:04:30-04:00') - datetime.timedelta(days=3)) - - # With datetime - self.assertTrue((rdwTime('2014-11-02T21:04:30Z') - rdwTime()).days < 0) - self.assertTrue((rdwTime() - rdwTime('2014-11-02T21:04:30Z')).days > 0) - - if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName'] unittest.main() diff --git a/rdiffweb/tests/test_rdw_templating.py b/rdiffweb/tests/test_rdw_templating.py index 82d65ea7bccf83bd1605e4668c814a81e4938a28..6c3045ab3c2b671d07386936775e999f12b1f46d 100644 --- a/rdiffweb/tests/test_rdw_templating.py +++ b/rdiffweb/tests/test_rdw_templating.py @@ -21,7 +21,7 @@ from __future__ import unicode_literals from future.builtins import str import unittest -from rdiffweb.rdw_helpers import rdwTime +from rdiffweb.librdiff import RdiffTime from rdiffweb.rdw_templating import do_format_filesize, url_for_browse, \ url_for_history, url_for_restore, attrib @@ -103,13 +103,13 @@ class TemplateManagerTest(unittest.TestCase): url_for_history('testcases') def test_url_for_restore(self): - self.assertEqual('/restore/testcases?date=1414967021', url_for_restore(b'testcases', path=b'', date=rdwTime(1414967021))) - self.assertEqual('/restore/testcases/Revisions?date=1414967021', url_for_restore(b'testcases', path=b'Revisions', date=rdwTime(1414967021))) + self.assertEqual('/restore/testcases?date=1414967021', url_for_restore(b'testcases', path=b'', date=RdiffTime(1414967021))) + self.assertEqual('/restore/testcases/Revisions?date=1414967021', url_for_restore(b'testcases', path=b'Revisions', date=RdiffTime(1414967021))) self.assertEqual('/restore/testcases/R%C3%A9pertoire%20%28%40vec%29%20%7Bc%C3%A0ra%C3%A7t%23%C3%A8r%C3%AB%7D%20%24%C3%A9p%C3%AAcial?date=1414967021', - url_for_restore(b'testcases', path=b'R\xc3\xa9pertoire (@vec) {c\xc3\xa0ra\xc3\xa7t#\xc3\xa8r\xc3\xab} $\xc3\xa9p\xc3\xaacial', date=rdwTime(1414967021))) + url_for_restore(b'testcases', path=b'R\xc3\xa9pertoire (@vec) {c\xc3\xa0ra\xc3\xa7t#\xc3\xa8r\xc3\xab} $\xc3\xa9p\xc3\xaacial', date=RdiffTime(1414967021))) # Check if failing with unicode with self.assertRaises(AssertionError): - url_for_restore('testcases', path='', date=rdwTime(1414967021)) + url_for_restore('testcases', path='', date=RdiffTime(1414967021)) if __name__ == "__main__": # import sys;sys.argv = ['', 'Test.testName']