mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
merging issue-38
This commit is contained in:
commit
0747a96cb4
|
@ -69,10 +69,8 @@ class Tag(object):
|
||||||
|
|
||||||
def set(self, tclass, tnum, tlvt=0, tdata=''):
|
def set(self, tclass, tnum, tlvt=0, tdata=''):
|
||||||
"""set the values of the tag."""
|
"""set the values of the tag."""
|
||||||
if isinstance(tdata, bytearray):
|
if not isinstance(tdata, str):
|
||||||
tdata = bytes(tdata)
|
raise TypeError("tag data must be str")
|
||||||
elif not isinstance(tdata, bytes):
|
|
||||||
raise TypeError("tag data must be bytes or bytearray")
|
|
||||||
|
|
||||||
self.tagClass = tclass
|
self.tagClass = tclass
|
||||||
self.tagNumber = tnum
|
self.tagNumber = tnum
|
||||||
|
@ -81,10 +79,8 @@ class Tag(object):
|
||||||
|
|
||||||
def set_app_data(self, tnum, tdata):
|
def set_app_data(self, tnum, tdata):
|
||||||
"""set the values of the tag."""
|
"""set the values of the tag."""
|
||||||
if isinstance(tdata, bytearray):
|
if not isinstance(tdata, str):
|
||||||
tdata = bytes(tdata)
|
raise TypeError("tag data must be str")
|
||||||
elif not isinstance(tdata, bytes):
|
|
||||||
raise TypeError("tag data must be bytes or bytearray")
|
|
||||||
|
|
||||||
self.tagClass = Tag.applicationTagClass
|
self.tagClass = Tag.applicationTagClass
|
||||||
self.tagNumber = tnum
|
self.tagNumber = tnum
|
||||||
|
@ -174,7 +170,7 @@ class Tag(object):
|
||||||
|
|
||||||
# application tagged boolean now has data
|
# application tagged boolean now has data
|
||||||
if (self.tagNumber == Tag.booleanAppTag):
|
if (self.tagNumber == Tag.booleanAppTag):
|
||||||
return ContextTag(context, bytearray([self.tagLVT]))
|
return ContextTag(context, chr(self.tagLVT))
|
||||||
else:
|
else:
|
||||||
return ContextTag(context, self.tagData)
|
return ContextTag(context, self.tagData)
|
||||||
|
|
||||||
|
@ -563,11 +559,11 @@ class Unsigned(Atomic):
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# rip apart the number
|
# rip apart the number
|
||||||
data = bytearray(struct.pack('>L', self.value))
|
data = struct.pack('>L', self.value)
|
||||||
|
|
||||||
# reduce the value to the smallest number of octets
|
# reduce the value to the smallest number of octets
|
||||||
while (len(data) > 1) and (data[0] == 0):
|
while (len(data) > 1) and (data[0] == '\x00'):
|
||||||
del data[0]
|
data = data[1:]
|
||||||
|
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.unsignedAppTag, data)
|
tag.set_app_data(Tag.unsignedAppTag, data)
|
||||||
|
@ -613,24 +609,24 @@ class Integer(Atomic):
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# rip apart the number
|
# rip apart the number
|
||||||
data = bytearray(struct.pack('>I', self.value & 0xFFFFFFFF))
|
data = struct.pack('>I', self.value & 0xFFFFFFFF)
|
||||||
|
|
||||||
# reduce the value to the smallest number of bytes, be
|
# reduce the value to the smallest number of bytes, be
|
||||||
# careful about sign extension
|
# careful about sign extension
|
||||||
if self.value < 0:
|
if self.value < 0:
|
||||||
while (len(data) > 1):
|
while (len(data) > 1):
|
||||||
if (data[0] != 255):
|
if (data[0] != '\xFF'):
|
||||||
break
|
break
|
||||||
if (data[1] < 128):
|
if (data[1] < '\x80'):
|
||||||
break
|
break
|
||||||
del data[0]
|
data = data[1:]
|
||||||
else:
|
else:
|
||||||
while (len(data) > 1):
|
while (len(data) > 1):
|
||||||
if (data[0] != 0):
|
if (data[0] != '\x00'):
|
||||||
break
|
break
|
||||||
if (data[1] >= 128):
|
if (data[1] >= '\x80'):
|
||||||
break
|
break
|
||||||
del data[0]
|
data = data[1:]
|
||||||
|
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.integerAppTag, data)
|
tag.set_app_data(Tag.integerAppTag, data)
|
||||||
|
@ -640,7 +636,7 @@ class Integer(Atomic):
|
||||||
raise ValueError("integer application tag required")
|
raise ValueError("integer application tag required")
|
||||||
|
|
||||||
# byte array easier to deal with
|
# byte array easier to deal with
|
||||||
tag_data = bytearray(tag.tagData)
|
tag_data = [ord(c) for c in tag.tagData]
|
||||||
|
|
||||||
# get the data
|
# get the data
|
||||||
rslt = tag_data[0]
|
rslt = tag_data[0]
|
||||||
|
@ -746,8 +742,8 @@ class OctetString(Atomic):
|
||||||
pass
|
pass
|
||||||
elif isinstance(arg, Tag):
|
elif isinstance(arg, Tag):
|
||||||
self.decode(arg)
|
self.decode(arg)
|
||||||
elif isinstance(arg, (bytes, bytearray)):
|
elif isinstance(arg, str):
|
||||||
self.value = bytes(arg)
|
self.value = arg
|
||||||
elif isinstance(arg, OctetString):
|
elif isinstance(arg, OctetString):
|
||||||
self.value = arg.value
|
self.value = arg.value
|
||||||
else:
|
else:
|
||||||
|
@ -800,11 +796,10 @@ class CharacterString(Atomic):
|
||||||
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.characterStringAppTag):
|
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.characterStringAppTag):
|
||||||
raise ValueError("character string application tag required")
|
raise ValueError("character string application tag required")
|
||||||
|
|
||||||
# byte array easier to deal with
|
tag_data = tag.tagData
|
||||||
tag_data = bytearray(tag.tagData)
|
|
||||||
|
|
||||||
# extract the data
|
# extract the data
|
||||||
self.strEncoding = tag_data[0]
|
self.strEncoding = ord(tag_data[0])
|
||||||
self.strValue = tag_data[1:]
|
self.strValue = tag_data[1:]
|
||||||
|
|
||||||
# normalize the value
|
# normalize the value
|
||||||
|
@ -870,7 +865,7 @@ class BitString(Atomic):
|
||||||
unused = used and (8 - used) or 0
|
unused = used and (8 - used) or 0
|
||||||
|
|
||||||
# start with the number of unused bits
|
# start with the number of unused bits
|
||||||
data = bytearray([unused])
|
data = [unused]
|
||||||
|
|
||||||
# build and append each packed octet
|
# build and append each packed octet
|
||||||
bits = self.value + [0] * unused
|
bits = self.value + [0] * unused
|
||||||
|
@ -881,13 +876,13 @@ class BitString(Atomic):
|
||||||
data.append(x)
|
data.append(x)
|
||||||
|
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.bitStringAppTag, data)
|
tag.set_app_data(Tag.bitStringAppTag, ''.join(chr(i) for i in data))
|
||||||
|
|
||||||
def decode(self, tag):
|
def decode(self, tag):
|
||||||
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.bitStringAppTag):
|
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.bitStringAppTag):
|
||||||
raise ValueError("bit string application tag required")
|
raise ValueError("bit string application tag required")
|
||||||
|
|
||||||
tag_data = bytearray(tag.tagData)
|
tag_data = [ord(c) for c in tag.tagData]
|
||||||
|
|
||||||
# extract the number of unused bits
|
# extract the number of unused bits
|
||||||
unused = tag_data[0]
|
unused = tag_data[0]
|
||||||
|
@ -1055,11 +1050,11 @@ class Enumerated(Atomic):
|
||||||
raise TypeError("%s is an invalid enumeration value datatype" % (type(self.value),))
|
raise TypeError("%s is an invalid enumeration value datatype" % (type(self.value),))
|
||||||
|
|
||||||
# rip apart the number
|
# rip apart the number
|
||||||
data = bytearray(struct.pack('>L', value))
|
data = struct.pack('>L', value)
|
||||||
|
|
||||||
# reduce the value to the smallest number of octets
|
# reduce the value to the smallest number of octets
|
||||||
while (len(data) > 1) and (data[0] == 0):
|
while (len(data) > 1) and (data[0] == '\x00'):
|
||||||
del data[0]
|
data = data[1:]
|
||||||
|
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.enumeratedAppTag, data)
|
tag.set_app_data(Tag.enumeratedAppTag, data)
|
||||||
|
@ -1108,87 +1103,177 @@ def expand_enumerations(klass):
|
||||||
# Date
|
# Date
|
||||||
#
|
#
|
||||||
|
|
||||||
|
_mm = r'(?P<month>0?[1-9]|1[0-4]|odd|even|255|[*])'
|
||||||
|
_dd = r'(?P<day>[0-3]?\d|last|odd|even|255|[*])'
|
||||||
|
_yy = r'(?P<year>\d{2}|255|[*])'
|
||||||
|
_yyyy = r'(?P<year>\d{4}|255|[*])'
|
||||||
|
_dow = r'(?P<dow>[1-7]|mon|tue|wed|thu|fri|sat|sun|255|[*])'
|
||||||
|
|
||||||
|
_special_mon = {'*': 255, 'odd': 13, 'even': 14, None: 255}
|
||||||
|
_special_mon_inv = {255: '*', 13: 'odd', 14: 'even'}
|
||||||
|
|
||||||
|
_special_day = {'*': 255, 'last': 32, 'odd': 33, 'even': 34, None: 255}
|
||||||
|
_special_day_inv = {255: '*', 32: 'last', 33: 'odd', 34: 'even'}
|
||||||
|
|
||||||
|
_special_dow = {'*': 255, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6, 'sun': 7}
|
||||||
|
_special_dow_inv = {255: '*', 1: 'mon', 2: 'tue', 3: 'wed', 4: 'thu', 5: 'fri', 6: 'sat', 7: 'sun'}
|
||||||
|
|
||||||
|
|
||||||
|
def _merge(*args):
|
||||||
|
"""Create a composite pattern and compile it."""
|
||||||
|
return re.compile(r'^' + r'[/-]'.join(args) + r'(?:\s+' + _dow + ')?$')
|
||||||
|
|
||||||
|
|
||||||
|
# make a list of compiled patterns
|
||||||
|
_date_patterns = [
|
||||||
|
_merge(_yyyy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yyyy),
|
||||||
|
_merge(_dd, _mm, _yyyy),
|
||||||
|
_merge(_yy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yy),
|
||||||
|
_merge(_dd, _mm, _yy),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Date(Atomic):
|
class Date(Atomic):
|
||||||
|
|
||||||
_app_tag = Tag.dateAppTag
|
def __init__(self, arg=None, year=255, month=255, day=255, day_of_week=255):
|
||||||
_date_regex = re.compile(r"^([*]|\d+)[/]([*]|\d+)[/]([*]|\d+)(?:\s([*]|\w+))?$")
|
self.value = (year, month, day, day_of_week)
|
||||||
_day_names = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
||||||
|
|
||||||
DONT_CARE = 255
|
|
||||||
|
|
||||||
def __init__(self, arg=None, year=255, month=255, day=255, dayOfWeek=255):
|
|
||||||
self.value = (year, month, day, dayOfWeek)
|
|
||||||
|
|
||||||
if arg is None:
|
if arg is None:
|
||||||
pass
|
pass
|
||||||
elif isinstance(arg,Tag):
|
elif isinstance(arg, Tag):
|
||||||
self.decode(arg)
|
self.decode(arg)
|
||||||
elif isinstance(arg, tuple):
|
elif isinstance(arg, tuple):
|
||||||
self.value = arg
|
self.value = arg
|
||||||
elif isinstance(arg, str):
|
elif isinstance(arg, str):
|
||||||
date_match = Date._date_regex.match(arg)
|
# lower case everything
|
||||||
if not date_match:
|
arg = arg.lower()
|
||||||
raise ValueError("invalid date pattern")
|
|
||||||
date_groups = date_match.groups()
|
|
||||||
|
|
||||||
# day/month/year
|
# make a list of the contents from matching patterns
|
||||||
tup_list = []
|
matches = []
|
||||||
for s in date_groups[:3]:
|
for p in _date_patterns:
|
||||||
if s == '*':
|
m = p.match(arg)
|
||||||
tup_list.append(255)
|
if m:
|
||||||
elif s in None:
|
matches.append(m.groupdict())
|
||||||
tup_list.append(0)
|
|
||||||
else:
|
|
||||||
tup_list.append(int(s))
|
|
||||||
|
|
||||||
# clean up the year
|
# try to find a good one
|
||||||
if (tup_list[2] < 100):
|
match = None
|
||||||
tup_list[2] += 2000
|
if not matches:
|
||||||
tup_list[2] -= 1900
|
raise ValueError("unmatched")
|
||||||
|
|
||||||
# day-of-week madness
|
# if there is only one, success
|
||||||
dow = date_groups[3]
|
if len(matches) == 1:
|
||||||
if dow is None:
|
match = matches[0]
|
||||||
tup_list.append(0)
|
|
||||||
elif (dow == '*'):
|
|
||||||
tup_list.append(255)
|
|
||||||
elif dow.isdigit():
|
|
||||||
tup_list.append(int(dow))
|
|
||||||
else:
|
else:
|
||||||
dow = dow.title()
|
# check to see if they really are the same
|
||||||
if dow not in Date._day_names:
|
for a, b in zip(matches[:-1],matches[1:]):
|
||||||
raise ValueError("invalid day name")
|
if a != b:
|
||||||
tup_list.append(Date._day_names.index(dow))
|
raise ValueError("ambiguous")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
match = matches[0]
|
||||||
|
|
||||||
|
# extract the year and normalize
|
||||||
|
year = match['year']
|
||||||
|
if (year == '*') or (not year):
|
||||||
|
year = 255
|
||||||
|
else:
|
||||||
|
year = int(year)
|
||||||
|
if (year == 255):
|
||||||
|
pass
|
||||||
|
elif year < 35:
|
||||||
|
year += 2000
|
||||||
|
elif year < 100:
|
||||||
|
year += 1900
|
||||||
|
elif year < 1900:
|
||||||
|
raise ValueError("invalid year")
|
||||||
|
|
||||||
|
# extract the month and normalize
|
||||||
|
month = match['month']
|
||||||
|
if month in _special_mon:
|
||||||
|
month = _special_mon[month]
|
||||||
|
else:
|
||||||
|
month = int(month)
|
||||||
|
if (month == 255):
|
||||||
|
pass
|
||||||
|
elif (month == 0) or (month > 14):
|
||||||
|
raise ValueError("invalid month")
|
||||||
|
|
||||||
|
# extract the day and normalize
|
||||||
|
day = match['day']
|
||||||
|
if day in _special_day:
|
||||||
|
day = _special_day[day]
|
||||||
|
else:
|
||||||
|
day = int(day)
|
||||||
|
if (day == 255):
|
||||||
|
pass
|
||||||
|
elif (day == 0) or (day > 34):
|
||||||
|
raise ValueError("invalid day")
|
||||||
|
|
||||||
|
# extract the day-of-week and normalize
|
||||||
|
day_of_week = match['dow']
|
||||||
|
if day_of_week in _special_dow:
|
||||||
|
day_of_week = _special_dow[day_of_week]
|
||||||
|
elif not day_of_week:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
day_of_week = int(day_of_week)
|
||||||
|
if (day_of_week == 255):
|
||||||
|
pass
|
||||||
|
elif (day_of_week == 0) or (day_of_week > 7):
|
||||||
|
raise ValueError("invalid day of week")
|
||||||
|
|
||||||
|
# year becomes the correct octet
|
||||||
|
if year != 255:
|
||||||
|
year -= 1900
|
||||||
|
|
||||||
|
# save the value
|
||||||
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
# calculate the day of the week
|
||||||
|
if not day_of_week:
|
||||||
|
self.CalcDayOfWeek()
|
||||||
|
|
||||||
self.value = tuple(tup_list)
|
|
||||||
elif isinstance(arg, Date):
|
elif isinstance(arg, Date):
|
||||||
self.value = arg.value
|
self.value = arg.value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("invalid constructor datatype")
|
raise TypeError("invalid constructor datatype")
|
||||||
|
|
||||||
def now(self):
|
|
||||||
tup = time.localtime()
|
|
||||||
|
|
||||||
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
def CalcDayOfWeek(self):
|
def CalcDayOfWeek(self):
|
||||||
"""Calculate the correct day of the week."""
|
"""Calculate the correct day of the week."""
|
||||||
# rip apart the value
|
# rip apart the value
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
# make sure all the components are defined
|
# assume the worst
|
||||||
if (year != 255) and (month != 255) and (day != 255):
|
day_of_week = 255
|
||||||
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
|
||||||
dayOfWeek = time.gmtime(today)[6] + 1
|
# check for special values
|
||||||
|
if year == 255:
|
||||||
|
pass
|
||||||
|
elif month in _special_mon_inv:
|
||||||
|
pass
|
||||||
|
elif day in _special_day_inv:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
||||||
|
day_of_week = time.gmtime(today)[6] + 1
|
||||||
|
except OverflowError:
|
||||||
|
pass
|
||||||
|
|
||||||
# put it back together
|
# put it back together
|
||||||
self.value = (year, month, day, dayOfWeek)
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
def now(self):
|
||||||
|
tup = time.localtime()
|
||||||
|
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
||||||
|
return self
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.dateAppTag, bytearray(self.value))
|
tag.set_app_data(Tag.dateAppTag, ''.join(chr(i) for i in self.value))
|
||||||
|
|
||||||
def decode(self, tag):
|
def decode(self, tag):
|
||||||
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.dateAppTag):
|
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.dateAppTag):
|
||||||
|
@ -1198,28 +1283,21 @@ class Date(Atomic):
|
||||||
self.value = tuple(ord(c) for c in tag.tagData)
|
self.value = tuple(ord(c) for c in tag.tagData)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
"""String representation of the date."""
|
||||||
# rip it apart
|
# rip it apart
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
rslt = "Date("
|
|
||||||
if month == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (month,)
|
|
||||||
if day == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (day,)
|
|
||||||
if year == 255:
|
if year == 255:
|
||||||
rslt += "* "
|
year = "*"
|
||||||
else:
|
else:
|
||||||
rslt += "%d " % (year + 1900,)
|
year = str(year + 1900)
|
||||||
if dayOfWeek == 255:
|
|
||||||
rslt += "*)"
|
month = _special_mon_inv.get(month, str(month))
|
||||||
else:
|
day = _special_day_inv.get(day, str(day))
|
||||||
rslt += Date._day_names[dayOfWeek] + ")"
|
day_of_week = _special_dow_inv.get(day_of_week, str(day_of_week))
|
||||||
|
|
||||||
|
return "%s(%s-%s-%s %s)" % (self.__class__.__name__, year, month, day, day_of_week)
|
||||||
|
|
||||||
return rslt
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Time
|
# Time
|
||||||
|
@ -1280,7 +1358,7 @@ class Time(Atomic):
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# encode the tag
|
# encode the tag
|
||||||
tag.set_app_data(Tag.timeAppTag, bytearray(self.value))
|
tag.set_app_data(Tag.timeAppTag, ''.join(chr(c) for c in self.value))
|
||||||
|
|
||||||
def decode(self, tag):
|
def decode(self, tag):
|
||||||
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.timeAppTag):
|
if (tag.tagClass != Tag.applicationTagClass) or (tag.tagNumber != Tag.timeAppTag):
|
||||||
|
|
|
@ -824,7 +824,7 @@ class CharacterString(Atomic):
|
||||||
self.value = '### unknown encoding: %d ###' % (self.strEncoding,)
|
self.value = '### unknown encoding: %d ###' % (self.strEncoding,)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "CharacterString(%d," % (self.strEncoding,) + repr(self.strValue) + ")"
|
return "CharacterString(%d,X'%s')" % (self.strEncoding, btox(self.strValue))
|
||||||
|
|
||||||
#
|
#
|
||||||
# BitString
|
# BitString
|
||||||
|
@ -1104,87 +1104,178 @@ def expand_enumerations(klass):
|
||||||
# save the dictionary in the class
|
# save the dictionary in the class
|
||||||
setattr(klass, '_xlate_table', xlateTable)
|
setattr(klass, '_xlate_table', xlateTable)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Date
|
# Date
|
||||||
#
|
#
|
||||||
|
|
||||||
|
_mm = r'(?P<month>0?[1-9]|1[0-4]|odd|even|255|[*])'
|
||||||
|
_dd = r'(?P<day>[0-3]?\d|last|odd|even|255|[*])'
|
||||||
|
_yy = r'(?P<year>\d{2}|255|[*])'
|
||||||
|
_yyyy = r'(?P<year>\d{4}|255|[*])'
|
||||||
|
_dow = r'(?P<dow>[1-7]|mon|tue|wed|thu|fri|sat|sun|255|[*])'
|
||||||
|
|
||||||
|
_special_mon = {'*': 255, 'odd': 13, 'even': 14, None: 255}
|
||||||
|
_special_mon_inv = {255: '*', 13: 'odd', 14: 'even'}
|
||||||
|
|
||||||
|
_special_day = {'*': 255, 'last': 32, 'odd': 33, 'even': 34, None: 255}
|
||||||
|
_special_day_inv = {255: '*', 32: 'last', 33: 'odd', 34: 'even'}
|
||||||
|
|
||||||
|
_special_dow = {'*': 255, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6, 'sun': 7}
|
||||||
|
_special_dow_inv = {255: '*', 1: 'mon', 2: 'tue', 3: 'wed', 4: 'thu', 5: 'fri', 6: 'sat', 7: 'sun'}
|
||||||
|
|
||||||
|
|
||||||
|
def _merge(*args):
|
||||||
|
"""Create a composite pattern and compile it."""
|
||||||
|
return re.compile(r'^' + r'[/-]'.join(args) + r'(?:\s+' + _dow + ')?$')
|
||||||
|
|
||||||
|
|
||||||
|
# make a list of compiled patterns
|
||||||
|
_date_patterns = [
|
||||||
|
_merge(_yyyy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yyyy),
|
||||||
|
_merge(_dd, _mm, _yyyy),
|
||||||
|
_merge(_yy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yy),
|
||||||
|
_merge(_dd, _mm, _yy),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Date(Atomic):
|
class Date(Atomic):
|
||||||
|
|
||||||
_app_tag = Tag.dateAppTag
|
def __init__(self, arg=None, year=255, month=255, day=255, day_of_week=255):
|
||||||
_date_regex = re.compile(r"^([*]|\d+)[/]([*]|\d+)[/]([*]|\d+)(?:\s([*]|\w+))?$")
|
self.value = (year, month, day, day_of_week)
|
||||||
_day_names = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
||||||
|
|
||||||
DONT_CARE = 255
|
|
||||||
|
|
||||||
def __init__(self, arg=None, year=255, month=255, day=255, dayOfWeek=255):
|
|
||||||
self.value = (year, month, day, dayOfWeek)
|
|
||||||
|
|
||||||
if arg is None:
|
if arg is None:
|
||||||
pass
|
pass
|
||||||
elif isinstance(arg,Tag):
|
elif isinstance(arg, Tag):
|
||||||
self.decode(arg)
|
self.decode(arg)
|
||||||
elif isinstance(arg, tuple):
|
elif isinstance(arg, tuple):
|
||||||
self.value = arg
|
self.value = arg
|
||||||
elif isinstance(arg, str):
|
elif isinstance(arg, str):
|
||||||
date_match = Date._date_regex.match(arg)
|
# lower case everything
|
||||||
if not date_match:
|
arg = arg.lower()
|
||||||
raise ValueError("invalid date pattern")
|
|
||||||
date_groups = date_match.groups()
|
|
||||||
|
|
||||||
# day/month/year
|
# make a list of the contents from matching patterns
|
||||||
tup_list = []
|
matches = []
|
||||||
for s in date_groups[:3]:
|
for p in _date_patterns:
|
||||||
if s == '*':
|
m = p.match(arg)
|
||||||
tup_list.append(255)
|
if m:
|
||||||
elif s in None:
|
matches.append(m.groupdict())
|
||||||
tup_list.append(0)
|
|
||||||
else:
|
|
||||||
tup_list.append(int(s))
|
|
||||||
|
|
||||||
# clean up the year
|
# try to find a good one
|
||||||
if (tup_list[2] < 100):
|
match = None
|
||||||
tup_list[2] += 2000
|
if not matches:
|
||||||
tup_list[2] -= 1900
|
raise ValueError("unmatched")
|
||||||
|
|
||||||
# day-of-week madness
|
# if there is only one, success
|
||||||
dow = date_groups[3]
|
if len(matches) == 1:
|
||||||
if dow is None:
|
match = matches[0]
|
||||||
tup_list.append(0)
|
|
||||||
elif (dow == '*'):
|
|
||||||
tup_list.append(255)
|
|
||||||
elif dow.isdigit():
|
|
||||||
tup_list.append(int(dow))
|
|
||||||
else:
|
else:
|
||||||
dow = dow.title()
|
# check to see if they really are the same
|
||||||
if dow not in Date._day_names:
|
for a, b in zip(matches[:-1],matches[1:]):
|
||||||
raise ValueError("invalid day name")
|
if a != b:
|
||||||
tup_list.append(Date._day_names.index(dow))
|
raise ValueError("ambiguous")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
match = matches[0]
|
||||||
|
|
||||||
|
# extract the year and normalize
|
||||||
|
year = match['year']
|
||||||
|
if (year == '*') or (not year):
|
||||||
|
year = 255
|
||||||
|
else:
|
||||||
|
year = int(year)
|
||||||
|
if (year == 255):
|
||||||
|
pass
|
||||||
|
elif year < 35:
|
||||||
|
year += 2000
|
||||||
|
elif year < 100:
|
||||||
|
year += 1900
|
||||||
|
elif year < 1900:
|
||||||
|
raise ValueError("invalid year")
|
||||||
|
|
||||||
|
# extract the month and normalize
|
||||||
|
month = match['month']
|
||||||
|
if month in _special_mon:
|
||||||
|
month = _special_mon[month]
|
||||||
|
else:
|
||||||
|
month = int(month)
|
||||||
|
if (month == 255):
|
||||||
|
pass
|
||||||
|
elif (month == 0) or (month > 14):
|
||||||
|
raise ValueError("invalid month")
|
||||||
|
|
||||||
|
# extract the day and normalize
|
||||||
|
day = match['day']
|
||||||
|
if day in _special_day:
|
||||||
|
day = _special_day[day]
|
||||||
|
else:
|
||||||
|
day = int(day)
|
||||||
|
if (day == 255):
|
||||||
|
pass
|
||||||
|
elif (day == 0) or (day > 34):
|
||||||
|
raise ValueError("invalid day")
|
||||||
|
|
||||||
|
# extract the day-of-week and normalize
|
||||||
|
day_of_week = match['dow']
|
||||||
|
if day_of_week in _special_dow:
|
||||||
|
day_of_week = _special_dow[day_of_week]
|
||||||
|
elif not day_of_week:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
day_of_week = int(day_of_week)
|
||||||
|
if (day_of_week == 255):
|
||||||
|
pass
|
||||||
|
elif day_of_week > 7:
|
||||||
|
raise ValueError("invalid day of week")
|
||||||
|
|
||||||
|
# year becomes the correct octet
|
||||||
|
if year != 255:
|
||||||
|
year -= 1900
|
||||||
|
|
||||||
|
# save the value
|
||||||
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
# calculate the day of the week
|
||||||
|
if not day_of_week:
|
||||||
|
self.CalcDayOfWeek()
|
||||||
|
|
||||||
self.value = tuple(tup_list)
|
|
||||||
elif isinstance(arg, Date):
|
elif isinstance(arg, Date):
|
||||||
self.value = arg.value
|
self.value = arg.value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("invalid constructor datatype")
|
raise TypeError("invalid constructor datatype")
|
||||||
|
|
||||||
def now(self):
|
|
||||||
tup = time.localtime()
|
|
||||||
|
|
||||||
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
def CalcDayOfWeek(self):
|
def CalcDayOfWeek(self):
|
||||||
"""Calculate the correct day of the week."""
|
"""Calculate the correct day of the week."""
|
||||||
# rip apart the value
|
# rip apart the value
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
# make sure all the components are defined
|
# assume the worst
|
||||||
if (year != 255) and (month != 255) and (day != 255):
|
day_of_week = 255
|
||||||
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
|
||||||
dayOfWeek = time.gmtime(today)[6] + 1
|
# check for special values
|
||||||
|
if year == 255:
|
||||||
|
pass
|
||||||
|
elif month in _special_mon_inv:
|
||||||
|
pass
|
||||||
|
elif day in _special_day_inv:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
||||||
|
day_of_week = time.gmtime(today)[6] + 1
|
||||||
|
except OverflowError:
|
||||||
|
pass
|
||||||
|
|
||||||
# put it back together
|
# put it back together
|
||||||
self.value = (year, month, day, dayOfWeek)
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
def now(self):
|
||||||
|
tup = time.localtime()
|
||||||
|
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
||||||
|
return self
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# encode the tag
|
# encode the tag
|
||||||
|
@ -1198,28 +1289,21 @@ class Date(Atomic):
|
||||||
self.value = tuple(ord(c) for c in tag.tagData)
|
self.value = tuple(ord(c) for c in tag.tagData)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
"""String representation of the date."""
|
||||||
# rip it apart
|
# rip it apart
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
rslt = "Date("
|
|
||||||
if month == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (month,)
|
|
||||||
if day == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (day,)
|
|
||||||
if year == 255:
|
if year == 255:
|
||||||
rslt += "* "
|
year = "*"
|
||||||
else:
|
else:
|
||||||
rslt += "%d " % (year + 1900,)
|
year = str(year + 1900)
|
||||||
if dayOfWeek == 255:
|
|
||||||
rslt += "*)"
|
month = _special_mon_inv.get(month, str(month))
|
||||||
else:
|
day = _special_day_inv.get(day, str(day))
|
||||||
rslt += Date._day_names[dayOfWeek] + ")"
|
day_of_week = _special_dow_inv.get(day_of_week, str(day_of_week))
|
||||||
|
|
||||||
|
return "%s(%s-%s-%s %s)" % (self.__class__.__name__, year, month, day, day_of_week)
|
||||||
|
|
||||||
return rslt
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Time
|
# Time
|
||||||
|
|
|
@ -472,7 +472,7 @@ class Atomic(object):
|
||||||
return (self.value < other.value)
|
return (self.value < other.value)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
sys.stderr.write("__eq__ %r %r\n" % (self, other))
|
# sys.stderr.write("__eq__ %r %r\n" % (self, other))
|
||||||
|
|
||||||
# hoop jump it
|
# hoop jump it
|
||||||
if not isinstance(other, self.__class__):
|
if not isinstance(other, self.__class__):
|
||||||
|
@ -837,7 +837,7 @@ class CharacterString(Atomic):
|
||||||
self.value = '### unknown encoding: %d ###' % (self.strEncoding,)
|
self.value = '### unknown encoding: %d ###' % (self.strEncoding,)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "CharacterString(%d," % (self.strEncoding,) + repr(self.value) + ")"
|
return "CharacterString(%d,X'%s')" % (self.strEncoding, btox(self.strValue))
|
||||||
|
|
||||||
#
|
#
|
||||||
# BitString
|
# BitString
|
||||||
|
@ -1026,7 +1026,7 @@ class Enumerated(Atomic):
|
||||||
def keylist(self):
|
def keylist(self):
|
||||||
"""Return a list of names in order by value."""
|
"""Return a list of names in order by value."""
|
||||||
items = self.enumerations.items()
|
items = self.enumerations.items()
|
||||||
items.sort(lambda a, b: cmp(a[1], b[1]))
|
items.sort(lambda a, b: self.cmp(a[1], b[1]))
|
||||||
|
|
||||||
# last item has highest value
|
# last item has highest value
|
||||||
rslt = [None] * (items[-1][1] + 1)
|
rslt = [None] * (items[-1][1] + 1)
|
||||||
|
@ -1119,83 +1119,171 @@ def expand_enumerations(klass):
|
||||||
# Date
|
# Date
|
||||||
#
|
#
|
||||||
|
|
||||||
|
_mm = r'(?P<month>0?[1-9]|1[0-4]|odd|even|255|[*])'
|
||||||
|
_dd = r'(?P<day>[0-3]?\d|last|odd|even|255|[*])'
|
||||||
|
_yy = r'(?P<year>\d{2}|255|[*])'
|
||||||
|
_yyyy = r'(?P<year>\d{4}|255|[*])'
|
||||||
|
_dow = r'(?P<dow>[1-7]|mon|tue|wed|thu|fri|sat|sun|255|[*])'
|
||||||
|
|
||||||
|
_special_mon = {'*': 255, 'odd': 13, 'even': 14, None: 255}
|
||||||
|
_special_mon_inv = {255: '*', 13: 'odd', 14: 'even'}
|
||||||
|
|
||||||
|
_special_day = {'*': 255, 'last': 32, 'odd': 33, 'even': 34, None: 255}
|
||||||
|
_special_day_inv = {255: '*', 32: 'last', 33: 'odd', 34: 'even'}
|
||||||
|
|
||||||
|
_special_dow = {'*': 255, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6, 'sun': 7}
|
||||||
|
_special_dow_inv = {255: '*', 1: 'mon', 2: 'tue', 3: 'wed', 4: 'thu', 5: 'fri', 6: 'sat', 7: 'sun'}
|
||||||
|
|
||||||
|
def _merge(*args):
|
||||||
|
"""Create a composite pattern and compile it."""
|
||||||
|
return re.compile(r'^' + r'[/-]'.join(args) + r'(?:\s+' + _dow + ')?$')
|
||||||
|
|
||||||
|
# make a list of compiled patterns
|
||||||
|
_date_patterns = [
|
||||||
|
_merge(_yyyy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yyyy),
|
||||||
|
_merge(_dd, _mm, _yyyy),
|
||||||
|
_merge(_yy, _mm, _dd),
|
||||||
|
_merge(_mm, _dd, _yy),
|
||||||
|
_merge(_dd, _mm, _yy),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Date(Atomic):
|
class Date(Atomic):
|
||||||
|
|
||||||
_app_tag = Tag.dateAppTag
|
def __init__(self, arg=None, year=255, month=255, day=255, day_of_week=255):
|
||||||
_date_regex = re.compile(r"^([*]|\d+)[/]([*]|\d+)[/]([*]|\d+)(?:\s([*]|\w+))?$")
|
self.value = (year, month, day, day_of_week)
|
||||||
_day_names = ['', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
||||||
|
|
||||||
DONT_CARE = 255
|
|
||||||
|
|
||||||
def __init__(self, arg=None, year=255, month=255, day=255, dayOfWeek=255):
|
|
||||||
self.value = (year, month, day, dayOfWeek)
|
|
||||||
|
|
||||||
if arg is None:
|
if arg is None:
|
||||||
pass
|
pass
|
||||||
elif isinstance(arg,Tag):
|
elif isinstance(arg, Tag):
|
||||||
self.decode(arg)
|
self.decode(arg)
|
||||||
elif isinstance(arg, tuple):
|
elif isinstance(arg, tuple):
|
||||||
self.value = arg
|
self.value = arg
|
||||||
elif isinstance(arg, str):
|
elif isinstance(arg, str):
|
||||||
date_match = Date._date_regex.match(arg)
|
# lower case everything
|
||||||
if not date_match:
|
arg = arg.lower()
|
||||||
raise ValueError("invalid date pattern")
|
|
||||||
date_groups = date_match.groups()
|
|
||||||
|
|
||||||
# day/month/year
|
# make a list of the contents from matching patterns
|
||||||
tup_list = []
|
matches = []
|
||||||
for s in date_groups[:3]:
|
for p in _date_patterns:
|
||||||
if s == '*':
|
m = p.match(arg)
|
||||||
tup_list.append(255)
|
if m:
|
||||||
elif s in None:
|
matches.append(m.groupdict())
|
||||||
tup_list.append(0)
|
|
||||||
else:
|
|
||||||
tup_list.append(int(s))
|
|
||||||
|
|
||||||
# clean up the year
|
# try to find a good one
|
||||||
if (tup_list[2] < 100):
|
match = None
|
||||||
tup_list[2] += 2000
|
if not matches:
|
||||||
tup_list[2] -= 1900
|
raise ValueError("unmatched")
|
||||||
|
|
||||||
# day-of-week madness
|
# if there is only one, success
|
||||||
dow = date_groups[3]
|
if len(matches) == 1:
|
||||||
if dow is None:
|
match = matches[0]
|
||||||
tup_list.append(0)
|
|
||||||
elif (dow == '*'):
|
|
||||||
tup_list.append(255)
|
|
||||||
elif dow.isdigit():
|
|
||||||
tup_list.append(int(dow))
|
|
||||||
else:
|
else:
|
||||||
dow = dow.title()
|
# check to see if they really are the same
|
||||||
if dow not in Date._day_names:
|
for a, b in zip(matches[:-1],matches[1:]):
|
||||||
raise ValueError("invalid day name")
|
if a != b:
|
||||||
tup_list.append(Date._day_names.index(dow))
|
raise ValueError("ambiguous")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
match = matches[0]
|
||||||
|
|
||||||
|
# extract the year and normalize
|
||||||
|
year = match['year']
|
||||||
|
if (year == '*') or (not year):
|
||||||
|
year = 255
|
||||||
|
else:
|
||||||
|
year = int(year)
|
||||||
|
if (year == 255):
|
||||||
|
pass
|
||||||
|
elif year < 35:
|
||||||
|
year += 2000
|
||||||
|
elif year < 100:
|
||||||
|
year += 1900
|
||||||
|
elif year < 1900:
|
||||||
|
raise ValueError("invalid year")
|
||||||
|
|
||||||
|
# extract the month and normalize
|
||||||
|
month = match['month']
|
||||||
|
if month in _special_mon:
|
||||||
|
month = _special_mon[month]
|
||||||
|
else:
|
||||||
|
month = int(month)
|
||||||
|
if (month == 255):
|
||||||
|
pass
|
||||||
|
elif (month == 0) or (month > 14):
|
||||||
|
raise ValueError("invalid month")
|
||||||
|
|
||||||
|
# extract the day and normalize
|
||||||
|
day = match['day']
|
||||||
|
if day in _special_day:
|
||||||
|
day = _special_day[day]
|
||||||
|
else:
|
||||||
|
day = int(day)
|
||||||
|
if (day == 255):
|
||||||
|
pass
|
||||||
|
elif (day == 0) or (day > 34):
|
||||||
|
raise ValueError("invalid day")
|
||||||
|
|
||||||
|
# extract the day-of-week and normalize
|
||||||
|
day_of_week = match['dow']
|
||||||
|
if day_of_week in _special_dow:
|
||||||
|
day_of_week = _special_dow[day_of_week]
|
||||||
|
elif not day_of_week:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
day_of_week = int(day_of_week)
|
||||||
|
if (day_of_week == 255):
|
||||||
|
pass
|
||||||
|
elif day_of_week > 7:
|
||||||
|
raise ValueError("invalid day of week")
|
||||||
|
|
||||||
|
# year becomes the correct octet
|
||||||
|
if year != 255:
|
||||||
|
year -= 1900
|
||||||
|
|
||||||
|
# save the value
|
||||||
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
# calculate the day of the week
|
||||||
|
if not day_of_week:
|
||||||
|
self.CalcDayOfWeek()
|
||||||
|
|
||||||
self.value = tuple(tup_list)
|
|
||||||
elif isinstance(arg, Date):
|
elif isinstance(arg, Date):
|
||||||
self.value = arg.value
|
self.value = arg.value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("invalid constructor datatype")
|
raise TypeError("invalid constructor datatype")
|
||||||
|
|
||||||
def now(self):
|
|
||||||
tup = time.localtime()
|
|
||||||
|
|
||||||
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
def CalcDayOfWeek(self):
|
def CalcDayOfWeek(self):
|
||||||
"""Calculate the correct day of the week."""
|
"""Calculate the correct day of the week."""
|
||||||
# rip apart the value
|
# rip apart the value
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
# make sure all the components are defined
|
# assume the worst
|
||||||
if (year != 255) and (month != 255) and (day != 255):
|
day_of_week = 255
|
||||||
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
|
||||||
dayOfWeek = time.gmtime(today)[6] + 1
|
# check for special values
|
||||||
|
if year == 255:
|
||||||
|
pass
|
||||||
|
elif month in _special_mon_inv:
|
||||||
|
pass
|
||||||
|
elif day in _special_day_inv:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
today = time.mktime( (year + 1900, month, day, 0, 0, 0, 0, 0, -1) )
|
||||||
|
day_of_week = time.gmtime(today)[6] + 1
|
||||||
|
except OverflowError:
|
||||||
|
pass
|
||||||
|
|
||||||
# put it back together
|
# put it back together
|
||||||
self.value = (year, month, day, dayOfWeek)
|
self.value = (year, month, day, day_of_week)
|
||||||
|
|
||||||
|
def now(self):
|
||||||
|
tup = time.localtime()
|
||||||
|
self.value = (tup[0]-1900, tup[1], tup[2], tup[6] + 1)
|
||||||
|
return self
|
||||||
|
|
||||||
def encode(self, tag):
|
def encode(self, tag):
|
||||||
# encode the tag
|
# encode the tag
|
||||||
|
@ -1209,28 +1297,21 @@ class Date(Atomic):
|
||||||
self.value = tuple(tag.tagData)
|
self.value = tuple(tag.tagData)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
"""String representation of the date."""
|
||||||
# rip it apart
|
# rip it apart
|
||||||
year, month, day, dayOfWeek = self.value
|
year, month, day, day_of_week = self.value
|
||||||
|
|
||||||
rslt = "Date("
|
|
||||||
if month == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (month,)
|
|
||||||
if day == 255:
|
|
||||||
rslt += "*/"
|
|
||||||
else:
|
|
||||||
rslt += "%d/" % (day,)
|
|
||||||
if year == 255:
|
if year == 255:
|
||||||
rslt += "* "
|
year = "*"
|
||||||
else:
|
else:
|
||||||
rslt += "%d " % (year + 1900,)
|
year = str(year + 1900)
|
||||||
if dayOfWeek == 255:
|
|
||||||
rslt += "*)"
|
month = _special_mon_inv.get(month, str(month))
|
||||||
else:
|
day = _special_day_inv.get(day, str(day))
|
||||||
rslt += Date._day_names[dayOfWeek] + ")"
|
day_of_week = _special_dow_inv.get(day_of_week, str(day_of_week))
|
||||||
|
|
||||||
|
return "%s(%s-%s-%s %s)" % (self.__class__.__name__, year, month, day, day_of_week)
|
||||||
|
|
||||||
return rslt
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Time
|
# Time
|
||||||
|
|
33
samples/date_string_patterns.py
Normal file
33
samples/date_string_patterns.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from bacpypes.primitivedata import Date
|
||||||
|
|
||||||
|
year_group = ('04', '75', '1929', '255', '*')
|
||||||
|
month_group = ('1', '12', 'odd', 'even', '255', '*')
|
||||||
|
day_group = ('1', '22', 'last', 'odd', 'even', '255', '*')
|
||||||
|
dow_group = ('1', 'mon', '255', '*')
|
||||||
|
|
||||||
|
patterns = [
|
||||||
|
"%(year)s-%(month)s-%(day)s %(day_of_week)s",
|
||||||
|
"%(month)s/%(day)s/%(year)s %(day_of_week)s",
|
||||||
|
"%(day)s/%(month)s/%(year)s %(day_of_week)s",
|
||||||
|
]
|
||||||
|
|
||||||
|
def permutation(**kwargs):
|
||||||
|
for pattern in patterns:
|
||||||
|
test_string = pattern % kwargs
|
||||||
|
try:
|
||||||
|
test_date = Date(test_string)
|
||||||
|
test_value = test_date.value
|
||||||
|
except Exception as why:
|
||||||
|
test_value = str(why)
|
||||||
|
print(test_string + '\t' + str(test_value))
|
||||||
|
print()
|
||||||
|
|
||||||
|
for year in year_group:
|
||||||
|
for month in month_group:
|
||||||
|
for day in day_group:
|
||||||
|
for day_of_week in dow_group:
|
||||||
|
permutation(
|
||||||
|
year=year, month=month, day=day, day_of_week=day_of_week,
|
||||||
|
)
|
|
@ -88,7 +88,7 @@ class TestCharacterString(unittest.TestCase):
|
||||||
|
|
||||||
obj = CharacterString("hello")
|
obj = CharacterString("hello")
|
||||||
assert obj.value == "hello"
|
assert obj.value == "hello"
|
||||||
assert str(obj) == "CharacterString(0,'hello')"
|
assert str(obj) == "CharacterString(0,X'68656c6c6f')"
|
||||||
|
|
||||||
def test_character_string_tag(self):
|
def test_character_string_tag(self):
|
||||||
if _debug: TestCharacterString._debug("test_character_string_tag")
|
if _debug: TestCharacterString._debug("test_character_string_tag")
|
||||||
|
|
|
@ -9,7 +9,7 @@ Test Primitive Data Date
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
|
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
|
||||||
from bacpypes.primitivedata import Date, Tag, DecodingError
|
from bacpypes.primitivedata import Date, Tag
|
||||||
|
|
||||||
# some debugging
|
# some debugging
|
||||||
_debug = 0
|
_debug = 0
|
||||||
|
@ -18,7 +18,7 @@ _log = ModuleLogger(globals())
|
||||||
|
|
||||||
@bacpypes_debugging
|
@bacpypes_debugging
|
||||||
def date_tag(x):
|
def date_tag(x):
|
||||||
"""Convert a hex string to an date application tag."""
|
"""Convert a hex string to a date application tag."""
|
||||||
if _debug: date_tag._debug("date_tag %r", x)
|
if _debug: date_tag._debug("date_tag %r", x)
|
||||||
|
|
||||||
b = xtob(x)
|
b = xtob(x)
|
||||||
|
@ -41,7 +41,7 @@ def date_encode(obj):
|
||||||
|
|
||||||
@bacpypes_debugging
|
@bacpypes_debugging
|
||||||
def date_decode(tag):
|
def date_decode(tag):
|
||||||
"""Decode an date application tag into an date."""
|
"""Decode a date application tag into a date."""
|
||||||
if _debug: date_decode._debug("date_decode %r", tag)
|
if _debug: date_decode._debug("date_decode %r", tag)
|
||||||
|
|
||||||
obj = Date(tag)
|
obj = Date(tag)
|
||||||
|
@ -70,7 +70,7 @@ def date_endec(v, x):
|
||||||
class TestDate(unittest.TestCase):
|
class TestDate(unittest.TestCase):
|
||||||
|
|
||||||
def test_date(self):
|
def test_date(self):
|
||||||
if _debug: TestDate._debug("test_date")
|
if _debug: TestInteger._debug("test_date")
|
||||||
|
|
||||||
# default values is all dont care
|
# default values is all dont care
|
||||||
obj = Date()
|
obj = Date()
|
||||||
|
@ -82,32 +82,16 @@ class TestDate(unittest.TestCase):
|
||||||
Date(1.0)
|
Date(1.0)
|
||||||
|
|
||||||
def test_date_tuple(self):
|
def test_date_tuple(self):
|
||||||
if _debug: TestDate._debug("test_date_tuple")
|
if _debug: TestInteger._debug("test_date_tuple")
|
||||||
|
|
||||||
obj = Date((1,2,3,4))
|
obj = Date((1,2,3,4))
|
||||||
assert obj.value == (1, 2, 3, 4)
|
assert obj.value == (1,2,3,4)
|
||||||
assert str(obj) == "Date(2/3/1901 Thu)"
|
assert str(obj) == "Date(1901-2-3 thu)"
|
||||||
|
|
||||||
### issue-48
|
|
||||||
# obj = Date("1/2/3")
|
|
||||||
# assert obj.value == (1, 2, x, y)
|
|
||||||
|
|
||||||
# obj = Date("*/2/3")
|
|
||||||
# assert obj.value == (255, 2, x, 255)
|
|
||||||
|
|
||||||
# obj = Date("1/*/3")
|
|
||||||
# assert obj.value == (1, 255, x, 255)
|
|
||||||
|
|
||||||
# obj = Date("1/2/*")
|
|
||||||
# assert obj.value == (1, 2, 255, 255)
|
|
||||||
|
|
||||||
# obj = Date("1/2/3 *")
|
|
||||||
# assert obj.value == (1, 2, 3, 255)
|
|
||||||
|
|
||||||
def test_date_tag(self):
|
def test_date_tag(self):
|
||||||
if _debug: TestDate._debug("test_date_tag")
|
if _debug: TestInteger._debug("test_date_tag")
|
||||||
|
|
||||||
tag = Tag(Tag.applicationTagClass, Tag.dateAppTag, 1, xtob('01020304'))
|
tag = Tag(Tag.applicationTagClass, Tag.dateAppTag, 4, xtob('01020304'))
|
||||||
obj = Date(tag)
|
obj = Date(tag)
|
||||||
assert obj.value == (1, 2, 3, 4)
|
assert obj.value == (1, 2, 3, 4)
|
||||||
|
|
||||||
|
@ -124,27 +108,68 @@ class TestDate(unittest.TestCase):
|
||||||
Date(tag)
|
Date(tag)
|
||||||
|
|
||||||
def test_date_copy(self):
|
def test_date_copy(self):
|
||||||
if _debug: TestDate._debug("test_date_copy")
|
if _debug: TestInteger._debug("test_date_copy")
|
||||||
|
|
||||||
date_value = (2, 3, 4, 5)
|
value = (1, 2, 3, 4)
|
||||||
obj1 = Date(date_value)
|
obj1 = Date(value)
|
||||||
obj2 = Date(obj1)
|
obj2 = Date(obj1)
|
||||||
assert obj2.value == date_value
|
assert obj2.value == value
|
||||||
|
|
||||||
def test_date_now(self):
|
|
||||||
if _debug: TestDate._debug("test_date_now")
|
|
||||||
|
|
||||||
# obj = Date().now()
|
|
||||||
### how to test?
|
|
||||||
|
|
||||||
def test_date_endec(self):
|
def test_date_endec(self):
|
||||||
if _debug: TestDate._debug("test_date_endec")
|
if _debug: TestInteger._debug("test_date_endec")
|
||||||
|
|
||||||
# with self.assertRaises(DecodingError):
|
# with self.assertRaises(IndexError):
|
||||||
# obj = Date(date_tag(''))
|
# obj = Date(date_tag(''))
|
||||||
|
|
||||||
date_endec((0, 0, 0, 0), '00000000')
|
def old_tests(self):
|
||||||
date_endec((1, 0, 0, 0), '01000000')
|
self.test_values = [
|
||||||
date_endec((0, 2, 0, 0), '00020000')
|
#('1/2/3', 1903, 2, 1, 0),
|
||||||
date_endec((0, 0, 3, 0), '00000300')
|
#('1/2/3', 1903, 2, 1, 0),
|
||||||
date_endec((0, 0, 0, 4), '00000004')
|
("1/2/2003", 2003, 2, 1, 6),
|
||||||
|
("1/20/2003", 2003, 1, 20, 1),
|
||||||
|
("01/20/2004", 2004, 1, 20, 2),
|
||||||
|
("11/12/2005", 2005, 12, 11, 7),
|
||||||
|
("30/1/2006", 2006, 1, 30, 1),
|
||||||
|
("30/1/1230", 1230, 1, 30, 255),
|
||||||
|
("30/1/98", 1998, 1, 30, 5),
|
||||||
|
("2015/8/31", 2015, 8, 31, 1),
|
||||||
|
("2015/08/30", 2015, 8, 30, 7),
|
||||||
|
("2015/*/30", 2015,255,30,255),
|
||||||
|
("2015/1/*",2015,1,255,255),
|
||||||
|
("*/1/*", 255,1,255,255),
|
||||||
|
("*/*/*",255,255,255,255),
|
||||||
|
("1-2-2003", 2003, 2, 1, 6),
|
||||||
|
("1-20-2003", 2003, 1, 20, 1),
|
||||||
|
("01-20-2004", 2004, 1, 20, 2),
|
||||||
|
("11-12-2005", 2005, 12, 11, 7),
|
||||||
|
("30-1-2006", 2006, 1, 30, 1),
|
||||||
|
("30-1-1230", 1230, 1, 30, 255),
|
||||||
|
("30-1-98", 1998, 1, 30, 5),
|
||||||
|
("2015-8-31", 2015, 8, 31, 1),
|
||||||
|
("2015-08-30", 2015, 8, 30, 7),
|
||||||
|
("2015-*-30", 2015,255,30,255),
|
||||||
|
("2015-1-*",2015,1,255,255),
|
||||||
|
("*-1-*", 255,1,255,255),
|
||||||
|
("*-*-*",255,255,255,255)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.notEnoughPreciseOrWrong = [
|
||||||
|
('1/31/1'),
|
||||||
|
('0/1/4'),
|
||||||
|
('99/13/41'),
|
||||||
|
("2015/30/*")
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_Date_from_str(self):
|
||||||
|
for each in self.test_values:
|
||||||
|
new_date = Date(each[0])
|
||||||
|
y, m, d, dow = new_date.value
|
||||||
|
self.assertEqual(y,each[1])
|
||||||
|
self.assertEqual(m,each[2])
|
||||||
|
self.assertEqual(d,each[3])
|
||||||
|
self.assertEqual(dow,each[4])
|
||||||
|
|
||||||
|
def test_Wrong(self):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
for each in self.notEnoughPreciseOrWrong:
|
||||||
|
new_date = Date(each[0])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user