simpleparse 3.0.0a3__cp313-cp313-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. simpleparse/__init__.py +8 -0
  2. simpleparse/baseparser.py +90 -0
  3. simpleparse/common/__init__.py +19 -0
  4. simpleparse/common/calendar_names.py +103 -0
  5. simpleparse/common/chartypes.py +89 -0
  6. simpleparse/common/comments.py +72 -0
  7. simpleparse/common/escapeutils.py +21 -0
  8. simpleparse/common/iso_date.py +153 -0
  9. simpleparse/common/iso_date_loose.py +141 -0
  10. simpleparse/common/numbers.py +166 -0
  11. simpleparse/common/phonetics.py +76 -0
  12. simpleparse/common/strings.py +158 -0
  13. simpleparse/common/timezone_names.py +218 -0
  14. simpleparse/dispatchprocessor.py +107 -0
  15. simpleparse/error.py +55 -0
  16. simpleparse/generator.py +151 -0
  17. simpleparse/objectgenerator.py +780 -0
  18. simpleparse/parser.py +49 -0
  19. simpleparse/printers.py +58 -0
  20. simpleparse/processor.py +49 -0
  21. simpleparse/simpleparsegrammar.py +755 -0
  22. simpleparse/stt/COPYRIGHT +11 -0
  23. simpleparse/stt/Doc/eGenix-mx-Extensions.html +1708 -0
  24. simpleparse/stt/Doc/mxLicense.html +868 -0
  25. simpleparse/stt/Doc/mxTextTools.html +2677 -0
  26. simpleparse/stt/LICENSE +16 -0
  27. simpleparse/stt/TextTools/COPYRIGHT +19 -0
  28. simpleparse/stt/TextTools/Constants/Sets.py +58 -0
  29. simpleparse/stt/TextTools/Constants/TagTables.py +32 -0
  30. simpleparse/stt/TextTools/Constants/__init__.py +0 -0
  31. simpleparse/stt/TextTools/LICENSE +106 -0
  32. simpleparse/stt/TextTools/TextTools.py +818 -0
  33. simpleparse/stt/TextTools/__init__.py +63 -0
  34. simpleparse/stt/TextTools/mxTextTools/__init__.py +23 -0
  35. simpleparse/stt/TextTools/mxTextTools/highcommands.h +266 -0
  36. simpleparse/stt/TextTools/mxTextTools/lowlevelcommands.h +814 -0
  37. simpleparse/stt/TextTools/mxTextTools/mx.h +721 -0
  38. simpleparse/stt/TextTools/mxTextTools/mxTextTools.c +5364 -0
  39. simpleparse/stt/TextTools/mxTextTools/mxTextTools.cp313-win32.pyd +0 -0
  40. simpleparse/stt/TextTools/mxTextTools/mxTextTools.def +2 -0
  41. simpleparse/stt/TextTools/mxTextTools/mxTextTools.h +327 -0
  42. simpleparse/stt/TextTools/mxTextTools/mxbm_modern.c +581 -0
  43. simpleparse/stt/TextTools/mxTextTools/mxbm_modern.h +160 -0
  44. simpleparse/stt/TextTools/mxTextTools/mxbmse.c +218 -0
  45. simpleparse/stt/TextTools/mxTextTools/mxbmse.h +65 -0
  46. simpleparse/stt/TextTools/mxTextTools/mxh.h +60 -0
  47. simpleparse/stt/TextTools/mxTextTools/mxpyapi.h +35 -0
  48. simpleparse/stt/TextTools/mxTextTools/mxstdlib.h +225 -0
  49. simpleparse/stt/TextTools/mxTextTools/mxte.c +47 -0
  50. simpleparse/stt/TextTools/mxTextTools/mxte_impl.h +878 -0
  51. simpleparse/stt/TextTools/mxTextTools/mxte_modern.c +383 -0
  52. simpleparse/stt/TextTools/mxTextTools/mxte_modern.h +806 -0
  53. simpleparse/stt/TextTools/mxTextTools/mxte_smart.c +113 -0
  54. simpleparse/stt/TextTools/mxTextTools/recursecommands.h +119 -0
  55. simpleparse/stt/TextTools/mxTextTools/speccommands.h +101 -0
  56. simpleparse/stt/__init__.py +22 -0
  57. simpleparse/stt/mxLicense.html +691 -0
  58. simpleparse/xmlparser/__init__.py +11 -0
  59. simpleparse/xmlparser/xml_parser.py +200 -0
  60. simpleparse-3.0.0a3.dist-info/METADATA +72 -0
  61. simpleparse-3.0.0a3.dist-info/RECORD +64 -0
  62. simpleparse-3.0.0a3.dist-info/WHEEL +5 -0
  63. simpleparse-3.0.0a3.dist-info/licenses/license.txt +31 -0
  64. simpleparse-3.0.0a3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,8 @@
1
+ """Simple parsing using mxTextTools
2
+
3
+ See the /doc subdirectory for introductory and
4
+ general documentation. See license.txt for licensing
5
+ information. (This is a BSD-licensed package).
6
+ """
7
+
8
+ __version__ = "3.0.0a3"
@@ -0,0 +1,90 @@
1
+ """Base class for real-world parsers (such as parser.Parser)"""
2
+
3
+ from simpleparse.stt.TextTools.TextTools import tag
4
+ from simpleparse.generator import Generator
5
+
6
+
7
+ class BaseParser:
8
+ """Class on which real-world parsers build
9
+
10
+ Normally you use a sub-class of this class, such as
11
+ simpleparser.parser.Parser
12
+ """
13
+
14
+ _rootProduction = ""
15
+
16
+ # primary API...
17
+ def parse(
18
+ self, data, production=None, processor=None, start=0, stop=None, encoding=None
19
+ ):
20
+ """Parse data with production "production" of this parser
21
+
22
+ data -- data to be parsed, a Python string or bytes
23
+ production -- optional string specifying a non-default production to use
24
+ for parsing data
25
+ processor -- optional pointer to a Processor or MethodSource object for
26
+ use in determining reporting format and/or post-processing the results
27
+ of the parsing pass. Can be None if neither is desired (default)
28
+ start -- starting index for the parsing, default 0
29
+ stop -- stoping index for the parsing, default len(data)
30
+ encoding -- optional encoding for bytes input (e.g., 'utf-8', 'latin-1').
31
+ When specified with bytes input, the grammar patterns are compiled
32
+ to match the encoded byte sequences. Supported encodings:
33
+ - Single-byte: latin-1, iso-8859-*, windows-1252, ascii, etc.
34
+ - Multi-byte: utf-8 only (other multi-byte encodings not supported)
35
+ Positions in the result are byte positions when encoding is used.
36
+ """
37
+ self.resetBeforeParse()
38
+ if processor is None:
39
+ processor = self.buildProcessor()
40
+ if stop is None:
41
+ stop = len(data)
42
+ value = tag(
43
+ data,
44
+ self.buildTagger(production, processor),
45
+ start,
46
+ stop,
47
+ encoding=encoding,
48
+ )
49
+ if processor and callable(processor):
50
+ return processor(value, data)
51
+ else:
52
+ return value
53
+
54
+ # abstract methods
55
+ def buildProcessor(self):
56
+ """Build default processor object for this parser class
57
+
58
+ The default implementation returns None. The processor
59
+ can either implement the "method source" API (just provides
60
+ information about Callouts and the like), or the processor
61
+ API and the method-source API. The processor API merely
62
+ requires that the object be callable, and have the signature:
63
+
64
+ object( (success, children, nextPosition), buffer)
65
+
66
+ (Note: your object can treat the first item as a single tuple
67
+ if it likes).
68
+
69
+ See: simpleparse.processor module for details.
70
+ """
71
+ return None
72
+
73
+ def buildTagger(self, name, processor):
74
+ """Build the tag-table for the parser
75
+
76
+ This method must be implemented by your base class and _not_
77
+ call the implementation here.
78
+ """
79
+ raise NotImplementedError(
80
+ """Parser sub-class %s hasn't implemented a buildTagger method"""
81
+ % (self.__class__.__name__)
82
+ )
83
+
84
+ def resetBeforeParse(self):
85
+ """Called just before the parser's parse method starts working,
86
+
87
+ Allows you to set up special-purpose structures, such as stacks
88
+ or local storage values. There is no base implementation. The
89
+ base implementation does nothing.
90
+ """
@@ -0,0 +1,19 @@
1
+ """Common (library) definitions
2
+
3
+ You normally use this module by importing one of our
4
+ sub-modules (which automatically registers itself with
5
+ the SOURCES list defined here).
6
+
7
+ Calling common.share( dictionary ) with a dictionary
8
+ mapping string names to element token instances will
9
+ make the element tokens available under those string
10
+ names in default parsers. Note: a Parser can override
11
+ this by specifying an explicit definitionSources
12
+ parameter in its initialiser.
13
+ """
14
+
15
+ def share( dictionary ):
16
+ SOURCES.append( dictionary)
17
+
18
+ SOURCES = [
19
+ ]
@@ -0,0 +1,103 @@
1
+ """Locale-specific calendar names (day-of-week and month-of-year)
2
+
3
+ These values are those returned by the calendar module. Available
4
+ productions:
5
+
6
+ locale_day_names
7
+ locale_day_names_uc
8
+ locale_day_names_lc
9
+ Names for the days of the week
10
+
11
+ locale_day_abbrs
12
+ locale_day_abbrs_uc
13
+ locale_day_abbrs_lc
14
+ Short-forms (3 characters normally) for
15
+ the days of the week.
16
+
17
+ locale_month_names
18
+ locale_month_names_uc
19
+ locale_month_names_lc
20
+ Names for the months of the year
21
+
22
+ locale_month_abbrs
23
+ locale_month_abbrs_uc
24
+ locale_month_abbrs_lc
25
+ Short-forms (3 characters normally) for
26
+ the months of the year
27
+
28
+ Interpreters:
29
+ MonthNameInterpreter
30
+ DayNameInterpreter
31
+ Both offer the ability to set an index other
32
+ than the default (of 1) for the first item in
33
+ the list.
34
+ """
35
+ import calendar
36
+ from simpleparse import objectgenerator, common
37
+
38
+ c = {}
39
+
40
+ da = calendar.day_abbr[:]
41
+ dn = calendar.day_name[:]
42
+ ma = calendar.month_abbr[:]
43
+ mn = calendar.month_name[:]
44
+
45
+ def _build( name, set ):
46
+ # make sure longest equal-prefix items are first
47
+ set = set[:]
48
+ set.sort()
49
+ set.reverse()
50
+ l,u,r = [],[],[]
51
+ for item in set:
52
+ l.append( objectgenerator.Literal( value = item.lower() ))
53
+ u.append( objectgenerator.Literal( value = item.upper() ))
54
+ r.append( objectgenerator.Literal( value = item ))
55
+ c[ name + '_lc' ] = objectgenerator.FirstOfGroup( children = l )
56
+ c[ name + '_uc' ] = objectgenerator.FirstOfGroup( children = u )
57
+ c[ name ] = objectgenerator.FirstOfGroup( children = r )
58
+
59
+ _build( 'locale_day_names', dn )
60
+ _build( 'locale_day_abbrs', da )
61
+
62
+
63
+ _build( 'locale_month_names', mn )
64
+ _build( 'locale_month_abbrs', ma )
65
+
66
+ da = [s.lower() for s in da]
67
+ dn = [s.lower() for s in dn]
68
+ ma = [s.lower() for s in ma]
69
+ mn = [s.lower() for s in mn]
70
+
71
+
72
+ common.share( c )
73
+
74
+ class NameInterpreter:
75
+ offset = 1
76
+ def __init__( self, offset = 1 ):
77
+ self.offset = offset
78
+ def __call__( self, info, buffer ):
79
+ (tag, left, right, children) = info
80
+ value = buffer[left:right].lower()
81
+ for table in self.tables:
82
+ try:
83
+ return table.index( value )+ self.offset
84
+ except ValueError:
85
+ pass
86
+ raise ValueError( """Unrecognised (but parsed) %s name %s at character %s"""%( self.nameType, value, left))
87
+
88
+ class MonthNameInterpreter( NameInterpreter):
89
+ """Interpret a month-of-year name as an integer index
90
+
91
+ Pass an "offset" value to __init__ to use an offset other
92
+ than 1 (Monday = 1), normally 0 (Monday = 0)
93
+ """
94
+ nameType = "Month"
95
+ tables = (mn,ma)
96
+ class DayNameInterpreter( NameInterpreter ):
97
+ """Interpret a day-of-week name as an integer index
98
+
99
+ Pass an "offset" value to __init__ to use an offset other
100
+ than 1 (January = 1), normally 0 (January = 0)
101
+ """
102
+ nameType = "Day"
103
+ tables = (dn,da)
@@ -0,0 +1,89 @@
1
+ """Common locale-specific character types
2
+
3
+ Following productions are all based on string module,
4
+ with the default locale specified. The first production
5
+ is a single character of the class and the second a
6
+ repeating character version:
7
+
8
+ digit, digits
9
+ uppercasechar, uppercase
10
+ lowercasechar, lowercase
11
+ letter, letters
12
+ whitespacechar, whitespace
13
+ punctuationchar, punctuation
14
+ octdigit, octdigits
15
+ hexdigit, hexdigits
16
+ printablechar, printable
17
+
18
+ For Python versions with the constants in the string module:
19
+ ascii_letter, ascii_letters
20
+ ascii_lowercasechar, ascii_lowercase
21
+ ascii_uppercasechar, ascii_uppercase
22
+
23
+
24
+ Following are locale-specific values, both are
25
+ single-character values:
26
+
27
+ locale_decimal_point -- locale-specific decimal seperator
28
+ locale_thousands_seperator -- locale-specific "thousands" seperator
29
+
30
+ Others:
31
+
32
+ EOF -- Matches iff parsing has reached the end of the buffer
33
+
34
+ There are no interpreters provided (the types are considered
35
+ too common to provide meaningful interpreters).
36
+ """
37
+ from simpleparse import objectgenerator, common
38
+ import string, locale
39
+ try:
40
+ locale.setlocale(locale.LC_ALL, "" )
41
+ except locale.Error:
42
+ # Environment requests a locale that isn't installed (common in minimal
43
+ # containers). localeconv() still works against the default C locale, so
44
+ # the only consequence is C-locale decimal/thousands conventions below.
45
+ pass
46
+
47
+ c = {}
48
+
49
+ # string-module items...
50
+
51
+ for source,single,repeat in [
52
+ ("digits","digit","digits"),
53
+ ("ascii_uppercase", "uppercasechar", "uppercase"),
54
+ ("ascii_lowercase", "lowercasechar", "lowercase"),
55
+ ("ascii_letters", "letter", "letters" ),
56
+ ("ascii_letters", "ascii_letter", "ascii_letters" ), # alias
57
+ ("ascii_lowercase", "ascii_lowercasechar", "ascii_lowercase"),
58
+ ("ascii_uppercase", "ascii_uppercasechar", "ascii_uppercase"),
59
+ ("whitespace", "whitespacechar", "whitespace"),
60
+ ("punctuation", "punctuationchar", "punctuation"),
61
+ ("octdigits", "octdigit", "octdigits"),
62
+ ("hexdigits", "hexdigit", "hexdigits"),
63
+ ("printable", "printablechar", "printable"),
64
+ ]:
65
+ try:
66
+ value = getattr( string, source )
67
+ c[ single ] = objectgenerator.Range( value = value )
68
+ c[ repeat ] = objectgenerator.Range( value = value, repeating =1 )
69
+ except AttributeError:
70
+ pass
71
+
72
+ # locale-module items
73
+ _lc = locale.localeconv()
74
+ c[ "locale_decimal_point" ] = objectgenerator.Literal( value = _lc["decimal_point"] )
75
+ c[ "locale_thousands_seperator" ] = objectgenerator.Literal( value = _lc["thousands_sep"] )
76
+
77
+ del _lc
78
+
79
+ # common, but not really well defined sets
80
+ # this is the set of characters which are interpreted
81
+ # specially by Python's string-escaping when they
82
+ # follow a \\ char.
83
+
84
+ from simpleparse.stt import TextTools
85
+ c[ "EOF" ] = objectgenerator.Prebuilt( value = (
86
+ (None, TextTools.EOF, TextTools.Here),
87
+ ) )
88
+
89
+ common.share( c )
@@ -0,0 +1,72 @@
1
+ """Common comment formats
2
+
3
+ To process, handle the "comment" production,
4
+ (the specific named comment formats are all
5
+ expanded productions, so you won't get them
6
+ returned for processing).
7
+
8
+ hash_comment
9
+ # to EOL comments
10
+ slashslash_comment
11
+ // to EOL comments
12
+ semicolon_comment
13
+ ; to EOL comments
14
+ slashbang_comment
15
+ c_comment
16
+ non-nesting /* */ comments
17
+ slashbang_nest_comment
18
+ c_nest_comment
19
+ nesting /* /* */ */ comments
20
+ """
21
+ from simpleparse.parser import Parser
22
+ from simpleparse import common, objectgenerator
23
+ from simpleparse.common import chartypes
24
+
25
+ c = {}
26
+
27
+ eolcomments = r"""
28
+ ### comment formats where the comment goes
29
+ ### from a marker to the end of the line
30
+
31
+ comment := -'\012'*
32
+ <EOL> := ('\r'?,'\n')/EOF
33
+
34
+ >hash_comment< := '#', comment, EOL
35
+ >semicolon_comment< := ';', comment, EOL
36
+ >slashslash_comment< := '//', comment, EOL
37
+ """
38
+
39
+ _p = Parser( eolcomments )
40
+ for name in ["hash_comment", "semicolon_comment", "slashslash_comment"]:
41
+ c[ name ] = objectgenerator.LibraryElement(
42
+ generator = _p._generator,
43
+ production = name,
44
+ )
45
+
46
+ ccomments = r"""
47
+ ### comments in format /* comment */ with no recursion allowed
48
+ comment := -"*/"*
49
+ >slashbang_comment< := '/*', comment, '*/'
50
+ """
51
+ _p = Parser( ccomments )
52
+ for name in ["c_comment","slashbang_comment"]:
53
+ c[ name ] = objectgenerator.LibraryElement(
54
+ generator = _p._generator,
55
+ production = "slashbang_comment",
56
+ )
57
+
58
+ nccomments = r"""
59
+ ### nestable C comments of form /* comment /* innercomment */ back to previous */
60
+ <comment_start> := '/*'
61
+ <comment_stop> := '*/'
62
+ comment := (-(comment_stop/comment_start)+/slashbang_nest_comment)*
63
+ >slashbang_nest_comment< := comment_start, comment, comment_stop
64
+ """
65
+ _p = Parser( nccomments )
66
+ for name in ["c_nest_comment","slashbang_nest_comment"]:
67
+ c[ name ] = objectgenerator.LibraryElement(
68
+ generator = _p._generator,
69
+ production = "slashbang_nest_comment",
70
+ )
71
+
72
+ common.share(c)
@@ -0,0 +1,21 @@
1
+ """Shared escape sequence utilities for SimpleParse
2
+
3
+ This module provides common escape sequence mappings used by both
4
+ the grammar parser and string literal processing.
5
+ """
6
+
7
+ # Map of escape sequences to their corresponding characters
8
+ # Used for interpreting backslash escapes in string literals and grammar definitions
9
+ SPECIAL_ESCAPED_MAP = {
10
+ 'a': '\a', # Bell
11
+ 'b': '\b', # Backspace
12
+ 'f': '\f', # Form feed
13
+ 'n': '\n', # Newline
14
+ 'r': '\r', # Carriage return
15
+ 't': '\t', # Tab
16
+ 'v': '\v', # Vertical tab
17
+ '\\': '\\', # Backslash
18
+ '\n': '', # Escaped newline (line continuation)
19
+ '"': '"', # Double quote
20
+ "'": "'", # Single quote
21
+ }
@@ -0,0 +1,153 @@
1
+ """Canonical ISO date format YYYY-MM-DDTHH:mm:SS+HH:mm
2
+
3
+ This parser is _extremely_ strict, and the dates that match it,
4
+ though really easy to work with for the computer, are not particularly
5
+ readable. See the iso_date_loose module for a slightly relaxed
6
+ definition which allows the "T" character to be replaced by a
7
+ " " character, and allows a space before the timezone offset, as well
8
+ as allowing the integer values to use non-0-padded integers.
9
+
10
+
11
+ ISO_date -- YYYY-MM-DD format, with a month and date optional
12
+ ISO_time -- HH:mm:SS format, with minutes and seconds optional
13
+ ISO_date_time -- YYYY-MM-DD HH:mm:SS+HH:mm format,
14
+ with time optional and TimeZone offset optional
15
+
16
+ Interpreter:
17
+ MxInterpreter
18
+ Interprets the parse tree as mx.DateTime values
19
+ ISO_date and ISO_time
20
+ returns DateTime objects
21
+ Time only
22
+ returns RelativeDateTime object which, when
23
+ added to a DateTime gives you the given time
24
+ within that day
25
+ """
26
+ try:
27
+ from mx import DateTime
28
+ haveMX = 1
29
+ except ImportError:
30
+ haveMX = 0
31
+ from simpleparse.parser import Parser
32
+ from simpleparse import common, objectgenerator
33
+ from simpleparse.common import chartypes, numbers
34
+ from simpleparse.dispatchprocessor import *
35
+
36
+ c = {}
37
+
38
+ declaration ="""
39
+ year := digit,digit,digit,digit
40
+ month := digit,digit
41
+ day := digit,digit
42
+
43
+ hour := digit,digit
44
+ minute := digit,digit
45
+ second := digit,digit
46
+ offset_sign := [-+]
47
+ offset := offset_sign, hour, time_separator?, minute
48
+
49
+ <date_separator> := '-'
50
+ <time_separator> := ':'
51
+
52
+ ISO_date := year, (date_separator, month, (date_separator, day)?)?
53
+ ISO_time := hour, (time_separator, minute, (time_separator, second)?)?
54
+ ISO_date_time := ISO_date, ([T], ISO_time)?, offset?
55
+ """
56
+
57
+
58
+
59
+
60
+ _p = Parser( declaration )
61
+ for name in ["ISO_time","ISO_date", "ISO_date_time"]:
62
+ c[ name ] = objectgenerator.LibraryElement(
63
+ generator = _p._generator,
64
+ production = name,
65
+ )
66
+ common.share( c )
67
+
68
+ if haveMX:
69
+ class MxInterpreter(DispatchProcessor):
70
+ """Interpret a parsed ISO_date_time_loose in GMT/UTC time or localtime
71
+ """
72
+ def __init__(
73
+ self,
74
+ inputLocal = 1,
75
+ returnLocal = 1,
76
+ ):
77
+ self.inputLocal = inputLocal
78
+ self.returnLocal = returnLocal
79
+ dateName = 'ISO_date'
80
+ timeName = 'ISO_time'
81
+ def ISO_date_time( self, info, buffer):
82
+ """Interpret the loose ISO date + time format"""
83
+ (tag, left, right, sublist) = info
84
+ set = singleMap( sublist, self, buffer )
85
+ base, time, offset = (
86
+ set.get(self.dateName),
87
+ set.get(self.timeName) or DateTime.RelativeDateTime(hour=0,minute=0,second=0),
88
+ set.get( "offset" ),
89
+ )
90
+ base = base + time
91
+ offset = set.get( "offset" )
92
+ if offset is not None:
93
+ # an explicit timezone was entered, convert to gmt and return as appropriate...
94
+ gmt = base - offset
95
+ if self.returnLocal:
96
+ return gmt.localtime()
97
+ else:
98
+ return gmt
99
+ # was in the default input locale (either gmt or local)
100
+ if self.inputLocal and self.returnLocal:
101
+ return base
102
+ elif not self.inputLocal and not self.returnLocal:
103
+ return base
104
+ elif self.inputLocal and not self.returnLocal:
105
+ # return gmt from local...
106
+ return base.gmtime()
107
+ else:
108
+ return base.localtime()
109
+ def ISO_date( self, info, buffer):
110
+ """Interpret the ISO date format"""
111
+ (tag, left, right, sublist) = info
112
+ set = {}
113
+ for item in sublist:
114
+ set[ item[0] ] = dispatch( self, item, buffer)
115
+ return DateTime.DateTime(
116
+ set.get("year") or now().year,
117
+ set.get("month") or 1,
118
+ set.get("day") or 1,
119
+ )
120
+ def ISO_time( self, info, buffer):
121
+ """Interpret the ISO time format"""
122
+ (tag, left, right, sublist) = info
123
+ set = {}
124
+ for item in sublist:
125
+ set[ item[0] ] = dispatch( self, item, buffer)
126
+ return DateTime.RelativeDateTime(
127
+ hour = set.get("hour") or 0,
128
+ minute = set.get("minute") or 0,
129
+ second = set.get("second") or 0,
130
+ )
131
+
132
+ integer = numbers.IntInterpreter()
133
+ second = offset_minute = offset_hour = year = month = day = hour =minute =integer
134
+
135
+ def offset( self, info, buffer):
136
+ """Calculate the time zone offset as a date-time delta"""
137
+ (tag, left, right, sublist) = info
138
+ set = singleMap( sublist, self, buffer )
139
+ direction = set.get('offset_sign',1)
140
+ hour = set.get( "hour", 0)
141
+ minute = set.get( "minute", 0)
142
+ delta = DateTime.DateTimeDelta( 0, hour*direction, minute*direction)
143
+ return delta
144
+
145
+ def offset_sign( self , info, buffer):
146
+ """Interpret the offset sign as a multiplier"""
147
+ (tag, left, right, sublist) = info
148
+ v = buffer [left: right]
149
+ if v in ' +':
150
+ return 1
151
+ else:
152
+ return -1
153
+