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"?>
|
||||
<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>
|
||||
<import addon="xbmc.python" version="2.0"/>
|
||||
</requires>
|
||||
<extension point="xbmc.python.script" library="default.py">
|
||||
<provides>executable</provides>
|
||||
</extension>
|
||||
<extension point="xbmc.service" library="scheduler.py" start="startup" />
|
||||
<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="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]
|
||||
|
||||
added more verbose error message for incorrect paths
|
||||
|
@ -97,8 +97,11 @@ class XbmcBackup:
|
||||
elif(utils.getSetting('remote_selection') == '0'):
|
||||
self.remote_path = utils.getSetting("remote_path")
|
||||
|
||||
#fix slashes
|
||||
self.remote_path = self.remote_path.replace("\\","/")
|
||||
|
||||
#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 + "/"
|
||||
|
||||
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 id="scheduling" label="30013">
|
||||
<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>
|
||||
</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