mirror of
https://github.com/robweber/xbmcbackup.git
synced 2024-11-14 20:35:48 +01:00
added initial resources for scheduler.py to function
starte settings.xml modifications for timer intervals
This commit is contained in:
parent
0150e6a277
commit
0bb915ae3a
@ -1,12 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<addon id="script.xbmcbackup"
|
<addon id="script.xbmcbackup"
|
||||||
name="XBMC Backup" version="0.1.3" provider-name="robweber">
|
name="XBMC Backup" version="0.1.5" provider-name="robweber">
|
||||||
<requires>
|
<requires>
|
||||||
<import addon="xbmc.python" version="2.0"/>
|
<import addon="xbmc.python" version="2.0"/>
|
||||||
</requires>
|
</requires>
|
||||||
<extension point="xbmc.python.script" library="default.py">
|
<extension point="xbmc.python.script" library="default.py">
|
||||||
<provides>executable</provides>
|
<provides>executable</provides>
|
||||||
</extension>
|
</extension>
|
||||||
|
<extension point="xbmc.service" library="scheduler.py" start="startup" />
|
||||||
<extension point="xbmc.addon.metadata">
|
<extension point="xbmc.addon.metadata">
|
||||||
<summary lang="fr">Sauvegarder et restaurer vos bases de données XBMC et vos fichiers de configuration en cas de crash ou de fichiers corrompus.</summary>
|
<summary lang="fr">Sauvegarder et restaurer vos bases de données XBMC et vos fichiers de configuration en cas de crash ou de fichiers corrompus.</summary>
|
||||||
<summary lang="de">Die XBMC Datenbank sichern und bei Dateiverlust oder Beschädigung wiederherstellen.</summary>
|
<summary lang="de">Die XBMC Datenbank sichern und bei Dateiverlust oder Beschädigung wiederherstellen.</summary>
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
[b]Version 0.1.5[/b]
|
||||||
|
|
||||||
|
pulled xbmcbackup class into separate library
|
||||||
|
|
||||||
[b]Version 0.1.4[/b]
|
[b]Version 0.1.4[/b]
|
||||||
|
|
||||||
added more verbose error message for incorrect paths
|
added more verbose error message for incorrect paths
|
||||||
|
@ -97,8 +97,11 @@ class XbmcBackup:
|
|||||||
elif(utils.getSetting('remote_selection') == '0'):
|
elif(utils.getSetting('remote_selection') == '0'):
|
||||||
self.remote_path = utils.getSetting("remote_path")
|
self.remote_path = utils.getSetting("remote_path")
|
||||||
|
|
||||||
|
#fix slashes
|
||||||
|
self.remote_path = self.remote_path.replace("\\","/")
|
||||||
|
|
||||||
#check if trailing slash is included
|
#check if trailing slash is included
|
||||||
if(self.remote_path[-1:] != "/" and self.remote_path[-1:] != "\\"):
|
if(self.remote_path[-1:] != "/"):
|
||||||
self.remote_path = self.remote_path + "/"
|
self.remote_path = self.remote_path + "/"
|
||||||
|
|
||||||
utils.log(utils.getString(30046))
|
utils.log(utils.getString(30046))
|
||||||
|
308
resources/lib/croniter.py
Normal file
308
resources/lib/croniter.py
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import re
|
||||||
|
from time import time, mktime
|
||||||
|
from datetime import datetime, date
|
||||||
|
from relativedelta import relativedelta
|
||||||
|
|
||||||
|
search_re = re.compile(r'^([^-]+)-([^-/]+)(/(.*))?$')
|
||||||
|
only_int_re = re.compile(r'^\d+$')
|
||||||
|
any_int_re = re.compile(r'^\d+')
|
||||||
|
star_or_int_re = re.compile(r'^(\d+|\*)$')
|
||||||
|
|
||||||
|
__all__ = ('croniter',)
|
||||||
|
|
||||||
|
|
||||||
|
class croniter(object):
|
||||||
|
RANGES = (
|
||||||
|
(0, 59),
|
||||||
|
(0, 23),
|
||||||
|
(1, 31),
|
||||||
|
(1, 12),
|
||||||
|
(0, 6),
|
||||||
|
(0, 59)
|
||||||
|
)
|
||||||
|
DAYS = (
|
||||||
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||||
|
)
|
||||||
|
|
||||||
|
ALPHACONV = (
|
||||||
|
{ },
|
||||||
|
{ },
|
||||||
|
{ },
|
||||||
|
{ 'jan':1, 'feb':2, 'mar':3, 'apr':4, 'may':5, 'jun':6,
|
||||||
|
'jul':7, 'aug':8, 'sep':9, 'oct':10, 'nov':11, 'dec':12 },
|
||||||
|
{ 'sun':0, 'mon':1, 'tue':2, 'wed':3, 'thu':4, 'fri':5, 'sat':6 },
|
||||||
|
{ }
|
||||||
|
)
|
||||||
|
|
||||||
|
LOWMAP = (
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{0: 1},
|
||||||
|
{0: 1},
|
||||||
|
{7: 0},
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
|
||||||
|
bad_length = 'Exactly 5 or 6 columns has to be specified for iterator' \
|
||||||
|
'expression.'
|
||||||
|
|
||||||
|
def __init__(self, expr_format, start_time=time()):
|
||||||
|
if isinstance(start_time, datetime):
|
||||||
|
start_time = mktime(start_time.timetuple())
|
||||||
|
|
||||||
|
self.cur = start_time
|
||||||
|
self.exprs = expr_format.split()
|
||||||
|
|
||||||
|
if len(self.exprs) != 5 and len(self.exprs) != 6:
|
||||||
|
raise ValueError(self.bad_length)
|
||||||
|
|
||||||
|
expanded = []
|
||||||
|
|
||||||
|
for i, expr in enumerate(self.exprs):
|
||||||
|
e_list = expr.split(',')
|
||||||
|
res = []
|
||||||
|
|
||||||
|
while len(e_list) > 0:
|
||||||
|
e = e_list.pop()
|
||||||
|
t = re.sub(r'^\*(/.+)$', r'%d-%d\1' % (self.RANGES[i][0],
|
||||||
|
self.RANGES[i][1]),
|
||||||
|
str(e))
|
||||||
|
m = search_re.search(t)
|
||||||
|
|
||||||
|
if m:
|
||||||
|
(low, high, step) = m.group(1), m.group(2), m.group(4) or 1
|
||||||
|
|
||||||
|
if not any_int_re.search(low):
|
||||||
|
low = self.ALPHACONV[i][low.lower()]
|
||||||
|
|
||||||
|
if not any_int_re.search(high):
|
||||||
|
high = self.ALPHACONV[i][high.lower()]
|
||||||
|
|
||||||
|
if (not low or not high or int(low) > int(high)
|
||||||
|
or not only_int_re.search(str(step))):
|
||||||
|
raise ValueError("[%s] is not acceptable" %expr_format)
|
||||||
|
|
||||||
|
for j in xrange(int(low), int(high)+1):
|
||||||
|
if j % int(step) == 0:
|
||||||
|
e_list.append(j)
|
||||||
|
else:
|
||||||
|
if not star_or_int_re.search(t):
|
||||||
|
t = self.ALPHACONV[i][t.lower()]
|
||||||
|
|
||||||
|
try:
|
||||||
|
t = int(t)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if t in self.LOWMAP[i]:
|
||||||
|
t = self.LOWMAP[i][t]
|
||||||
|
|
||||||
|
if t != '*' and (int(t) < self.RANGES[i][0] or
|
||||||
|
int(t) > self.RANGES[i][1]):
|
||||||
|
raise ValueError("[%s] is not acceptable, out of range" % expr_format)
|
||||||
|
|
||||||
|
res.append(t)
|
||||||
|
|
||||||
|
res.sort()
|
||||||
|
expanded.append(['*'] if (len(res) == 1 and res[0] == '*') else res)
|
||||||
|
self.expanded = expanded
|
||||||
|
|
||||||
|
def get_next(self, ret_type=float):
|
||||||
|
return self._get_next(ret_type, is_prev=False)
|
||||||
|
|
||||||
|
def get_prev(self, ret_type=float):
|
||||||
|
return self._get_next(ret_type, is_prev=True)
|
||||||
|
|
||||||
|
def _get_next(self, ret_type=float, is_prev=False):
|
||||||
|
expanded = self.expanded[:]
|
||||||
|
|
||||||
|
if ret_type not in (float, datetime):
|
||||||
|
raise TypeError("Invalid ret_type, only 'float' or 'datetime' " \
|
||||||
|
"is acceptable.")
|
||||||
|
|
||||||
|
if expanded[2][0] != '*' and expanded[4][0] != '*':
|
||||||
|
bak = expanded[4]
|
||||||
|
expanded[4] = ['*']
|
||||||
|
t1 = self._calc(self.cur, expanded, is_prev)
|
||||||
|
expanded[4] = bak
|
||||||
|
expanded[2] = ['*']
|
||||||
|
|
||||||
|
t2 = self._calc(self.cur, expanded, is_prev)
|
||||||
|
if not is_prev:
|
||||||
|
result = t1 if t1 < t2 else t2
|
||||||
|
else:
|
||||||
|
result = t1 if t1 > t2 else t2
|
||||||
|
else:
|
||||||
|
result = self._calc(self.cur, expanded, is_prev)
|
||||||
|
self.cur = result
|
||||||
|
|
||||||
|
if ret_type == datetime:
|
||||||
|
result = datetime.fromtimestamp(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _calc(self, now, expanded, is_prev):
|
||||||
|
if is_prev:
|
||||||
|
nearest_method = self._get_prev_nearest
|
||||||
|
nearest_diff_method = self._get_prev_nearest_diff
|
||||||
|
sign = -1
|
||||||
|
else:
|
||||||
|
nearest_method = self._get_next_nearest
|
||||||
|
nearest_diff_method = self._get_next_nearest_diff
|
||||||
|
sign = 1
|
||||||
|
|
||||||
|
offset = len(expanded) == 6 and 1 or 60
|
||||||
|
dst = now = datetime.fromtimestamp(now + sign * offset)
|
||||||
|
|
||||||
|
day, month, year = dst.day, dst.month, dst.year
|
||||||
|
current_year = now.year
|
||||||
|
DAYS = self.DAYS
|
||||||
|
|
||||||
|
def proc_month(d):
|
||||||
|
if expanded[3][0] != '*':
|
||||||
|
diff_month = nearest_diff_method(month, expanded[3], 12)
|
||||||
|
days = DAYS[month - 1]
|
||||||
|
if month == 2 and self.is_leap(year) == True:
|
||||||
|
days += 1
|
||||||
|
|
||||||
|
reset_day = days if is_prev else 1
|
||||||
|
|
||||||
|
if diff_month != None and diff_month != 0:
|
||||||
|
if is_prev:
|
||||||
|
d += relativedelta(months=diff_month)
|
||||||
|
else:
|
||||||
|
d += relativedelta(months=diff_month, day=reset_day,
|
||||||
|
hour=0, minute=0, second=0)
|
||||||
|
return True, d
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
def proc_day_of_month(d):
|
||||||
|
if expanded[2][0] != '*':
|
||||||
|
days = DAYS[month - 1]
|
||||||
|
if month == 2 and self.is_leap(year) == True:
|
||||||
|
days += 1
|
||||||
|
|
||||||
|
diff_day = nearest_diff_method(d.day, expanded[2], days)
|
||||||
|
|
||||||
|
if diff_day != None and diff_day != 0:
|
||||||
|
if is_prev:
|
||||||
|
d += relativedelta(days=diff_day)
|
||||||
|
else:
|
||||||
|
d += relativedelta(days=diff_day, hour=0, minute=0, second=0)
|
||||||
|
return True, d
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
def proc_day_of_week(d):
|
||||||
|
if expanded[4][0] != '*':
|
||||||
|
diff_day_of_week = nearest_diff_method(d.isoweekday() % 7, expanded[4], 7)
|
||||||
|
if diff_day_of_week != None and diff_day_of_week != 0:
|
||||||
|
if is_prev:
|
||||||
|
d += relativedelta(days=diff_day_of_week)
|
||||||
|
else:
|
||||||
|
d += relativedelta(days=diff_day_of_week, hour=0, minute=0, second=0)
|
||||||
|
return True, d
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
def proc_hour(d):
|
||||||
|
if expanded[1][0] != '*':
|
||||||
|
diff_hour = nearest_diff_method(d.hour, expanded[1], 24)
|
||||||
|
if diff_hour != None and diff_hour != 0:
|
||||||
|
if is_prev:
|
||||||
|
d += relativedelta(hours = diff_hour)
|
||||||
|
else:
|
||||||
|
d += relativedelta(hours = diff_hour, minute=0, second=0)
|
||||||
|
return True, d
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
def proc_minute(d):
|
||||||
|
if expanded[0][0] != '*':
|
||||||
|
diff_min = nearest_diff_method(d.minute, expanded[0], 60)
|
||||||
|
if diff_min != None and diff_min != 0:
|
||||||
|
if is_prev:
|
||||||
|
d += relativedelta(minutes = diff_min)
|
||||||
|
else:
|
||||||
|
d += relativedelta(minutes = diff_min, second=0)
|
||||||
|
return True, d
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
def proc_second(d):
|
||||||
|
if len(expanded) == 6:
|
||||||
|
if expanded[5][0] != '*':
|
||||||
|
diff_sec = nearest_diff_method(d.second, expanded[5], 60)
|
||||||
|
if diff_sec != None and diff_sec != 0:
|
||||||
|
dst += relativedelta(seconds = diff_sec)
|
||||||
|
return True, d
|
||||||
|
else:
|
||||||
|
d += relativedelta(second = 0)
|
||||||
|
return False, d
|
||||||
|
|
||||||
|
if is_prev:
|
||||||
|
procs = [proc_second,
|
||||||
|
proc_minute,
|
||||||
|
proc_hour,
|
||||||
|
proc_day_of_week,
|
||||||
|
proc_day_of_month,
|
||||||
|
proc_month]
|
||||||
|
else:
|
||||||
|
procs = [proc_month,
|
||||||
|
proc_day_of_month,
|
||||||
|
proc_day_of_week,
|
||||||
|
proc_hour,
|
||||||
|
proc_minute,
|
||||||
|
proc_second]
|
||||||
|
|
||||||
|
while abs(year - current_year) <= 1:
|
||||||
|
next = False
|
||||||
|
for proc in procs:
|
||||||
|
(changed, dst) = proc(dst)
|
||||||
|
if changed:
|
||||||
|
next = True
|
||||||
|
break
|
||||||
|
if next:
|
||||||
|
continue
|
||||||
|
return mktime(dst.timetuple())
|
||||||
|
|
||||||
|
raise "failed to find prev date"
|
||||||
|
|
||||||
|
def _get_next_nearest(self, x, to_check):
|
||||||
|
small = [item for item in to_check if item < x]
|
||||||
|
large = [item for item in to_check if item >= x]
|
||||||
|
large.extend(small)
|
||||||
|
return large[0]
|
||||||
|
|
||||||
|
def _get_prev_nearest(self, x, to_check):
|
||||||
|
small = [item for item in to_check if item <= x]
|
||||||
|
large = [item for item in to_check if item > x]
|
||||||
|
small.reverse()
|
||||||
|
large.reverse()
|
||||||
|
small.extend(large)
|
||||||
|
return small[0]
|
||||||
|
|
||||||
|
def _get_next_nearest_diff(self, x, to_check, range_val):
|
||||||
|
for i, d in enumerate(to_check):
|
||||||
|
if d >= x:
|
||||||
|
return d - x
|
||||||
|
return to_check[0] - x + range_val
|
||||||
|
|
||||||
|
def _get_prev_nearest_diff(self, x, to_check, range_val):
|
||||||
|
candidates = to_check[:]
|
||||||
|
candidates.reverse()
|
||||||
|
for d in candidates:
|
||||||
|
if d <= x:
|
||||||
|
return d - x
|
||||||
|
return (candidates[0]) - x - range_val
|
||||||
|
|
||||||
|
def is_leap(self, year):
|
||||||
|
if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
base = datetime(2010, 1, 25)
|
||||||
|
itr = croniter('0 0 1 * *', base)
|
||||||
|
n1 = itr.get_next(datetime)
|
||||||
|
print n1
|
430
resources/lib/relativedelta.py
Normal file
430
resources/lib/relativedelta.py
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
"""
|
||||||
|
Copyright (c) 2003-2010 Gustavo Niemeyer <gustavo@niemeyer.net>
|
||||||
|
|
||||||
|
This module offers extensions to the standard python 2.3+
|
||||||
|
datetime module.
|
||||||
|
"""
|
||||||
|
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
|
||||||
|
__license__ = "PSF License"
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import calendar
|
||||||
|
|
||||||
|
__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"]
|
||||||
|
|
||||||
|
class weekday(object):
|
||||||
|
__slots__ = ["weekday", "n"]
|
||||||
|
|
||||||
|
def __init__(self, weekday, n=None):
|
||||||
|
self.weekday = weekday
|
||||||
|
self.n = n
|
||||||
|
|
||||||
|
def __call__(self, n):
|
||||||
|
if n == self.n:
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return self.__class__(self.weekday, n)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
try:
|
||||||
|
if self.weekday != other.weekday or self.n != other.n:
|
||||||
|
return False
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday]
|
||||||
|
if not self.n:
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
return "%s(%+d)" % (s, self.n)
|
||||||
|
|
||||||
|
MO, TU, WE, TH, FR, SA, SU = weekdays = tuple([weekday(x) for x in range(7)])
|
||||||
|
|
||||||
|
class relativedelta:
|
||||||
|
"""
|
||||||
|
The relativedelta type is based on the specification of the excelent
|
||||||
|
work done by M.-A. Lemburg in his mx.DateTime extension. However,
|
||||||
|
notice that this type does *NOT* implement the same algorithm as
|
||||||
|
his work. Do *NOT* expect it to behave like mx.DateTime's counterpart.
|
||||||
|
|
||||||
|
There's two different ways to build a relativedelta instance. The
|
||||||
|
first one is passing it two date/datetime classes:
|
||||||
|
|
||||||
|
relativedelta(datetime1, datetime2)
|
||||||
|
|
||||||
|
And the other way is to use the following keyword arguments:
|
||||||
|
|
||||||
|
year, month, day, hour, minute, second, microsecond:
|
||||||
|
Absolute information.
|
||||||
|
|
||||||
|
years, months, weeks, days, hours, minutes, seconds, microseconds:
|
||||||
|
Relative information, may be negative.
|
||||||
|
|
||||||
|
weekday:
|
||||||
|
One of the weekday instances (MO, TU, etc). These instances may
|
||||||
|
receive a parameter N, specifying the Nth weekday, which could
|
||||||
|
be positive or negative (like MO(+1) or MO(-2). Not specifying
|
||||||
|
it is the same as specifying +1. You can also use an integer,
|
||||||
|
where 0=MO.
|
||||||
|
|
||||||
|
leapdays:
|
||||||
|
Will add given days to the date found, if year is a leap
|
||||||
|
year, and the date found is post 28 of february.
|
||||||
|
|
||||||
|
yearday, nlyearday:
|
||||||
|
Set the yearday or the non-leap year day (jump leap days).
|
||||||
|
These are converted to day/month/leapdays information.
|
||||||
|
|
||||||
|
Here is the behavior of operations with relativedelta:
|
||||||
|
|
||||||
|
1) Calculate the absolute year, using the 'year' argument, or the
|
||||||
|
original datetime year, if the argument is not present.
|
||||||
|
|
||||||
|
2) Add the relative 'years' argument to the absolute year.
|
||||||
|
|
||||||
|
3) Do steps 1 and 2 for month/months.
|
||||||
|
|
||||||
|
4) Calculate the absolute day, using the 'day' argument, or the
|
||||||
|
original datetime day, if the argument is not present. Then,
|
||||||
|
subtract from the day until it fits in the year and month
|
||||||
|
found after their operations.
|
||||||
|
|
||||||
|
5) Add the relative 'days' argument to the absolute day. Notice
|
||||||
|
that the 'weeks' argument is multiplied by 7 and added to
|
||||||
|
'days'.
|
||||||
|
|
||||||
|
6) Do steps 1 and 2 for hour/hours, minute/minutes, second/seconds,
|
||||||
|
microsecond/microseconds.
|
||||||
|
|
||||||
|
7) If the 'weekday' argument is present, calculate the weekday,
|
||||||
|
with the given (wday, nth) tuple. wday is the index of the
|
||||||
|
weekday (0-6, 0=Mon), and nth is the number of weeks to add
|
||||||
|
forward or backward, depending on its signal. Notice that if
|
||||||
|
the calculated date is already Monday, for example, using
|
||||||
|
(0, 1) or (0, -1) won't change the day.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, dt1=None, dt2=None,
|
||||||
|
years=0, months=0, days=0, leapdays=0, weeks=0,
|
||||||
|
hours=0, minutes=0, seconds=0, microseconds=0,
|
||||||
|
year=None, month=None, day=None, weekday=None,
|
||||||
|
yearday=None, nlyearday=None,
|
||||||
|
hour=None, minute=None, second=None, microsecond=None):
|
||||||
|
if dt1 and dt2:
|
||||||
|
if not isinstance(dt1, datetime.date) or \
|
||||||
|
not isinstance(dt2, datetime.date):
|
||||||
|
raise TypeError, "relativedelta only diffs datetime/date"
|
||||||
|
if type(dt1) is not type(dt2):
|
||||||
|
if not isinstance(dt1, datetime.datetime):
|
||||||
|
dt1 = datetime.datetime.fromordinal(dt1.toordinal())
|
||||||
|
elif not isinstance(dt2, datetime.datetime):
|
||||||
|
dt2 = datetime.datetime.fromordinal(dt2.toordinal())
|
||||||
|
self.years = 0
|
||||||
|
self.months = 0
|
||||||
|
self.days = 0
|
||||||
|
self.leapdays = 0
|
||||||
|
self.hours = 0
|
||||||
|
self.minutes = 0
|
||||||
|
self.seconds = 0
|
||||||
|
self.microseconds = 0
|
||||||
|
self.year = None
|
||||||
|
self.month = None
|
||||||
|
self.day = None
|
||||||
|
self.weekday = None
|
||||||
|
self.hour = None
|
||||||
|
self.minute = None
|
||||||
|
self.second = None
|
||||||
|
self.microsecond = None
|
||||||
|
self._has_time = 0
|
||||||
|
|
||||||
|
months = (dt1.year*12+dt1.month)-(dt2.year*12+dt2.month)
|
||||||
|
self._set_months(months)
|
||||||
|
dtm = self.__radd__(dt2)
|
||||||
|
if dt1 < dt2:
|
||||||
|
while dt1 > dtm:
|
||||||
|
months += 1
|
||||||
|
self._set_months(months)
|
||||||
|
dtm = self.__radd__(dt2)
|
||||||
|
else:
|
||||||
|
while dt1 < dtm:
|
||||||
|
months -= 1
|
||||||
|
self._set_months(months)
|
||||||
|
dtm = self.__radd__(dt2)
|
||||||
|
delta = dt1 - dtm
|
||||||
|
self.seconds = delta.seconds+delta.days*86400
|
||||||
|
self.microseconds = delta.microseconds
|
||||||
|
else:
|
||||||
|
self.years = years
|
||||||
|
self.months = months
|
||||||
|
self.days = days+weeks*7
|
||||||
|
self.leapdays = leapdays
|
||||||
|
self.hours = hours
|
||||||
|
self.minutes = minutes
|
||||||
|
self.seconds = seconds
|
||||||
|
self.microseconds = microseconds
|
||||||
|
self.year = year
|
||||||
|
self.month = month
|
||||||
|
self.day = day
|
||||||
|
self.hour = hour
|
||||||
|
self.minute = minute
|
||||||
|
self.second = second
|
||||||
|
self.microsecond = microsecond
|
||||||
|
|
||||||
|
if type(weekday) is int:
|
||||||
|
self.weekday = weekdays[weekday]
|
||||||
|
else:
|
||||||
|
self.weekday = weekday
|
||||||
|
|
||||||
|
yday = 0
|
||||||
|
if nlyearday:
|
||||||
|
yday = nlyearday
|
||||||
|
elif yearday:
|
||||||
|
yday = yearday
|
||||||
|
if yearday > 59:
|
||||||
|
self.leapdays = -1
|
||||||
|
if yday:
|
||||||
|
ydayidx = [31,59,90,120,151,181,212,243,273,304,334,366]
|
||||||
|
for idx, ydays in enumerate(ydayidx):
|
||||||
|
if yday <= ydays:
|
||||||
|
self.month = idx+1
|
||||||
|
if idx == 0:
|
||||||
|
self.day = yday
|
||||||
|
else:
|
||||||
|
self.day = yday-ydayidx[idx-1]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise ValueError, "invalid year day (%d)" % yday
|
||||||
|
|
||||||
|
self._fix()
|
||||||
|
|
||||||
|
def _fix(self):
|
||||||
|
if abs(self.microseconds) > 999999:
|
||||||
|
s = self.microseconds//abs(self.microseconds)
|
||||||
|
div, mod = divmod(self.microseconds*s, 1000000)
|
||||||
|
self.microseconds = mod*s
|
||||||
|
self.seconds += div*s
|
||||||
|
if abs(self.seconds) > 59:
|
||||||
|
s = self.seconds//abs(self.seconds)
|
||||||
|
div, mod = divmod(self.seconds*s, 60)
|
||||||
|
self.seconds = mod*s
|
||||||
|
self.minutes += div*s
|
||||||
|
if abs(self.minutes) > 59:
|
||||||
|
s = self.minutes//abs(self.minutes)
|
||||||
|
div, mod = divmod(self.minutes*s, 60)
|
||||||
|
self.minutes = mod*s
|
||||||
|
self.hours += div*s
|
||||||
|
if abs(self.hours) > 23:
|
||||||
|
s = self.hours//abs(self.hours)
|
||||||
|
div, mod = divmod(self.hours*s, 24)
|
||||||
|
self.hours = mod*s
|
||||||
|
self.days += div*s
|
||||||
|
if abs(self.months) > 11:
|
||||||
|
s = self.months//abs(self.months)
|
||||||
|
div, mod = divmod(self.months*s, 12)
|
||||||
|
self.months = mod*s
|
||||||
|
self.years += div*s
|
||||||
|
if (self.hours or self.minutes or self.seconds or self.microseconds or
|
||||||
|
self.hour is not None or self.minute is not None or
|
||||||
|
self.second is not None or self.microsecond is not None):
|
||||||
|
self._has_time = 1
|
||||||
|
else:
|
||||||
|
self._has_time = 0
|
||||||
|
|
||||||
|
def _set_months(self, months):
|
||||||
|
self.months = months
|
||||||
|
if abs(self.months) > 11:
|
||||||
|
s = self.months//abs(self.months)
|
||||||
|
div, mod = divmod(self.months*s, 12)
|
||||||
|
self.months = mod*s
|
||||||
|
self.years = div*s
|
||||||
|
else:
|
||||||
|
self.years = 0
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
if not isinstance(other, datetime.date):
|
||||||
|
raise TypeError, "unsupported type for add operation"
|
||||||
|
elif self._has_time and not isinstance(other, datetime.datetime):
|
||||||
|
other = datetime.datetime.fromordinal(other.toordinal())
|
||||||
|
year = (self.year or other.year)+self.years
|
||||||
|
month = self.month or other.month
|
||||||
|
if self.months:
|
||||||
|
assert 1 <= abs(self.months) <= 12
|
||||||
|
month += self.months
|
||||||
|
if month > 12:
|
||||||
|
year += 1
|
||||||
|
month -= 12
|
||||||
|
elif month < 1:
|
||||||
|
year -= 1
|
||||||
|
month += 12
|
||||||
|
day = min(calendar.monthrange(year, month)[1],
|
||||||
|
self.day or other.day)
|
||||||
|
repl = {"year": year, "month": month, "day": day}
|
||||||
|
for attr in ["hour", "minute", "second", "microsecond"]:
|
||||||
|
value = getattr(self, attr)
|
||||||
|
if value is not None:
|
||||||
|
repl[attr] = value
|
||||||
|
days = self.days
|
||||||
|
if self.leapdays and month > 2 and calendar.isleap(year):
|
||||||
|
days += self.leapdays
|
||||||
|
ret = (other.replace(**repl)
|
||||||
|
+ datetime.timedelta(days=days,
|
||||||
|
hours=self.hours,
|
||||||
|
minutes=self.minutes,
|
||||||
|
seconds=self.seconds,
|
||||||
|
microseconds=self.microseconds))
|
||||||
|
if self.weekday:
|
||||||
|
weekday, nth = self.weekday.weekday, self.weekday.n or 1
|
||||||
|
jumpdays = (abs(nth)-1)*7
|
||||||
|
if nth > 0:
|
||||||
|
jumpdays += (7-ret.weekday()+weekday)%7
|
||||||
|
else:
|
||||||
|
jumpdays += (ret.weekday()-weekday)%7
|
||||||
|
jumpdays *= -1
|
||||||
|
ret += datetime.timedelta(days=jumpdays)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
return self.__neg__().__radd__(other)
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if not isinstance(other, relativedelta):
|
||||||
|
raise TypeError, "unsupported type for add operation"
|
||||||
|
return relativedelta(years=other.years+self.years,
|
||||||
|
months=other.months+self.months,
|
||||||
|
days=other.days+self.days,
|
||||||
|
hours=other.hours+self.hours,
|
||||||
|
minutes=other.minutes+self.minutes,
|
||||||
|
seconds=other.seconds+self.seconds,
|
||||||
|
microseconds=other.microseconds+self.microseconds,
|
||||||
|
leapdays=other.leapdays or self.leapdays,
|
||||||
|
year=other.year or self.year,
|
||||||
|
month=other.month or self.month,
|
||||||
|
day=other.day or self.day,
|
||||||
|
weekday=other.weekday or self.weekday,
|
||||||
|
hour=other.hour or self.hour,
|
||||||
|
minute=other.minute or self.minute,
|
||||||
|
second=other.second or self.second,
|
||||||
|
microsecond=other.second or self.microsecond)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
if not isinstance(other, relativedelta):
|
||||||
|
raise TypeError, "unsupported type for sub operation"
|
||||||
|
return relativedelta(years=other.years-self.years,
|
||||||
|
months=other.months-self.months,
|
||||||
|
days=other.days-self.days,
|
||||||
|
hours=other.hours-self.hours,
|
||||||
|
minutes=other.minutes-self.minutes,
|
||||||
|
seconds=other.seconds-self.seconds,
|
||||||
|
microseconds=other.microseconds-self.microseconds,
|
||||||
|
leapdays=other.leapdays or self.leapdays,
|
||||||
|
year=other.year or self.year,
|
||||||
|
month=other.month or self.month,
|
||||||
|
day=other.day or self.day,
|
||||||
|
weekday=other.weekday or self.weekday,
|
||||||
|
hour=other.hour or self.hour,
|
||||||
|
minute=other.minute or self.minute,
|
||||||
|
second=other.second or self.second,
|
||||||
|
microsecond=other.second or self.microsecond)
|
||||||
|
|
||||||
|
def __neg__(self):
|
||||||
|
return relativedelta(years=-self.years,
|
||||||
|
months=-self.months,
|
||||||
|
days=-self.days,
|
||||||
|
hours=-self.hours,
|
||||||
|
minutes=-self.minutes,
|
||||||
|
seconds=-self.seconds,
|
||||||
|
microseconds=-self.microseconds,
|
||||||
|
leapdays=self.leapdays,
|
||||||
|
year=self.year,
|
||||||
|
month=self.month,
|
||||||
|
day=self.day,
|
||||||
|
weekday=self.weekday,
|
||||||
|
hour=self.hour,
|
||||||
|
minute=self.minute,
|
||||||
|
second=self.second,
|
||||||
|
microsecond=self.microsecond)
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
return not (not self.years and
|
||||||
|
not self.months and
|
||||||
|
not self.days and
|
||||||
|
not self.hours and
|
||||||
|
not self.minutes and
|
||||||
|
not self.seconds and
|
||||||
|
not self.microseconds and
|
||||||
|
not self.leapdays and
|
||||||
|
self.year is None and
|
||||||
|
self.month is None and
|
||||||
|
self.day is None and
|
||||||
|
self.weekday is None and
|
||||||
|
self.hour is None and
|
||||||
|
self.minute is None and
|
||||||
|
self.second is None and
|
||||||
|
self.microsecond is None)
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
f = float(other)
|
||||||
|
return relativedelta(years=self.years*f,
|
||||||
|
months=self.months*f,
|
||||||
|
days=self.days*f,
|
||||||
|
hours=self.hours*f,
|
||||||
|
minutes=self.minutes*f,
|
||||||
|
seconds=self.seconds*f,
|
||||||
|
microseconds=self.microseconds*f,
|
||||||
|
leapdays=self.leapdays,
|
||||||
|
year=self.year,
|
||||||
|
month=self.month,
|
||||||
|
day=self.day,
|
||||||
|
weekday=self.weekday,
|
||||||
|
hour=self.hour,
|
||||||
|
minute=self.minute,
|
||||||
|
second=self.second,
|
||||||
|
microsecond=self.microsecond)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, relativedelta):
|
||||||
|
return False
|
||||||
|
if self.weekday or other.weekday:
|
||||||
|
if not self.weekday or not other.weekday:
|
||||||
|
return False
|
||||||
|
if self.weekday.weekday != other.weekday.weekday:
|
||||||
|
return False
|
||||||
|
n1, n2 = self.weekday.n, other.weekday.n
|
||||||
|
if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)):
|
||||||
|
return False
|
||||||
|
return (self.years == other.years and
|
||||||
|
self.months == other.months and
|
||||||
|
self.days == other.days and
|
||||||
|
self.hours == other.hours and
|
||||||
|
self.minutes == other.minutes and
|
||||||
|
self.seconds == other.seconds and
|
||||||
|
self.leapdays == other.leapdays and
|
||||||
|
self.year == other.year and
|
||||||
|
self.month == other.month and
|
||||||
|
self.day == other.day and
|
||||||
|
self.hour == other.hour and
|
||||||
|
self.minute == other.minute and
|
||||||
|
self.second == other.second and
|
||||||
|
self.microsecond == other.microsecond)
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def __div__(self, other):
|
||||||
|
return self.__mul__(1/float(other))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
l = []
|
||||||
|
for attr in ["years", "months", "days", "leapdays",
|
||||||
|
"hours", "minutes", "seconds", "microseconds"]:
|
||||||
|
value = getattr(self, attr)
|
||||||
|
if value:
|
||||||
|
l.append("%s=%+d" % (attr, value))
|
||||||
|
for attr in ["year", "month", "day", "weekday",
|
||||||
|
"hour", "minute", "second", "microsecond"]:
|
||||||
|
value = getattr(self, attr)
|
||||||
|
if value is not None:
|
||||||
|
l.append("%s=%s" % (attr, `value`))
|
||||||
|
return "%s(%s)" % (self.__class__.__name__, ", ".join(l))
|
@ -18,5 +18,9 @@
|
|||||||
</category>
|
</category>
|
||||||
<category id="scheduling" label="30013">
|
<category id="scheduling" label="30013">
|
||||||
<setting id="enable_scheduler" type="bool" label="30060" default="false" />
|
<setting id="enable_scheduler" type="bool" label="30060" default="false" />
|
||||||
|
<setting id="schedule_interval" type="enum" label="Schedule" values="Every Day|Every Week|First Day of Month|Custom Schedule" default="0" enable="eq(-1,true)"/>
|
||||||
|
<setting id="schedule_time" type="labelenum" label="Hour of Day" values="00:00|01:00|02:00|03:00|04:00|05:00|06:00|07:00|08:00|09:00|10:00|11:00|12:00|13:00|14:00|15:00|16:00|17:00|18:00|19:00|20:00|21:00|22:00|23:00" default="00:00" visible="!eq(-1,3)" enable="eq(-2,true)"/>
|
||||||
|
<setting id="day_of_week" type="enum" label="Day of Week" values="Sun|Mon|Tue|Wed|Thurs|Fri|Sat" default="0" visible="eq(-2,1)" enable="eq(-3,true)"/>
|
||||||
|
<setting id="cron_schedule" type="text" label="Cron Schedule" default="0 0 * * *" visible="eq(-3,3)" enable="eq(-4,true)"/>
|
||||||
</category>
|
</category>
|
||||||
</settings>
|
</settings>
|
||||||
|
43
scheduler.py
Normal file
43
scheduler.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import xbmc
|
||||||
|
import time
|
||||||
|
import resources.lib.utils as utils
|
||||||
|
from resources.lib.backup import XbmcBackup
|
||||||
|
|
||||||
|
class BackupScheduler:
|
||||||
|
enabled = "false"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.enabled = utils.getSetting("enable_scheduler")
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
while(not xbmc.abortRequested):
|
||||||
|
if(self.enabled == "true"):
|
||||||
|
cron_exp = self.parseSchedule()
|
||||||
|
utils.log(cron_exp)
|
||||||
|
else:
|
||||||
|
utils.log("backup not enabled")
|
||||||
|
self.enabled = utils.getSetting("enable_scheduler")
|
||||||
|
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
def parseSchedule(self):
|
||||||
|
schedule_type = int(utils.getSetting("schedule_interval"))
|
||||||
|
cron_exp = utils.getSetting("cron_schedule")
|
||||||
|
|
||||||
|
hour_of_day = utils.getSetting("schedule_time")
|
||||||
|
hour_of_day = int(hour_of_day[0:2])
|
||||||
|
if(schedule_type == 0):
|
||||||
|
#every day
|
||||||
|
|
||||||
|
cron_exp = "0 " + str(hour_of_day) + " * * *"
|
||||||
|
elif(schedule_type == 1):
|
||||||
|
#once a week
|
||||||
|
day_of_week = utils.getSetting("day_of_week")
|
||||||
|
cron_exp = "0 " + str(hour_of_day) + " * * " + day_of_week
|
||||||
|
elif(schedule_type == 2):
|
||||||
|
#first day of month
|
||||||
|
cron_exp = "0 " + str(hour_of_day) + " 1 * *"
|
||||||
|
|
||||||
|
return cron_exp
|
||||||
|
|
||||||
|
BackupScheduler().start()
|
Loading…
Reference in New Issue
Block a user