1
2 """
3 parsedatetime/context.py
4
5 Context related classes
6
7 """
8
9 from threading import local
10
11
12 -class pdtContextStack(object):
13 """
14 A thread-safe stack to store context(s)
15
16 Internally used by L{Calendar} object
17 """
18
20 self.__local = local()
21
22 @property
24 if not hasattr(self.__local, 'stack'):
25 self.__local.stack = []
26 return self.__local.stack
27
28 - def push(self, ctx):
29 self.__stack.append(ctx)
30
32 try:
33 return self.__stack.pop()
34 except IndexError:
35 return None
36
38 try:
39 return self.__stack[-1]
40 except IndexError:
41 raise RuntimeError('context stack is empty')
42
44 return not self.__stack
45
46
47 -class pdtContext(object):
48 """
49 Context contains accuracy flag detected by L{Calendar.parse()}
50
51 Accuracy flag uses bitwise-OR operation and is combined by:
52
53 ACU_YEAR - "next year", "2014"
54 ACU_MONTH - "March", "July 2014"
55 ACU_WEEK - "last week", "next 3 weeks"
56 ACU_DAY - "tomorrow", "July 4th 2014"
57 ACU_HALFDAY - "morning", "tonight"
58 ACU_HOUR - "18:00", "next hour"
59 ACU_MIN - "18:32", "next 10 minutes"
60 ACU_SEC - "18:32:55"
61 ACU_NOW - "now"
62
63 """
64
65 __slots__ = ('accuracy',)
66
67 ACU_YEAR = 2 ** 0
68 ACU_MONTH = 2 ** 1
69 ACU_WEEK = 2 ** 2
70 ACU_DAY = 2 ** 3
71 ACU_HALFDAY = 2 ** 4
72 ACU_HOUR = 2 ** 5
73 ACU_MIN = 2 ** 6
74 ACU_SEC = 2 ** 7
75 ACU_NOW = 2 ** 8
76
77 ACU_DATE = ACU_YEAR | ACU_MONTH | ACU_WEEK | ACU_DAY
78 ACU_TIME = ACU_HALFDAY | ACU_HOUR | ACU_MIN | ACU_SEC | ACU_NOW
79
80 _ACCURACY_MAPPING = [
81 (ACU_YEAR, 'year'),
82 (ACU_MONTH, 'month'),
83 (ACU_WEEK, 'week'),
84 (ACU_DAY, 'day'),
85 (ACU_HALFDAY, 'halfday'),
86 (ACU_HOUR, 'hour'),
87 (ACU_MIN, 'min'),
88 (ACU_SEC, 'sec'),
89 (ACU_NOW, 'now')]
90
91 _ACCURACY_REVERSE_MAPPING = {
92 'year': ACU_YEAR,
93 'years': ACU_YEAR,
94 'month': ACU_MONTH,
95 'months': ACU_MONTH,
96 'week': ACU_WEEK,
97 'weeks': ACU_WEEK,
98 'day': ACU_DAY,
99 'days': ACU_DAY,
100 'halfday': ACU_HALFDAY,
101 'morning': ACU_HALFDAY,
102 'afternoon': ACU_HALFDAY,
103 'evening': ACU_HALFDAY,
104 'night': ACU_HALFDAY,
105 'tonight': ACU_HALFDAY,
106 'midnight': ACU_HALFDAY,
107 'hour': ACU_HOUR,
108 'hours': ACU_HOUR,
109 'min': ACU_MIN,
110 'minute': ACU_MIN,
111 'mins': ACU_MIN,
112 'minutes': ACU_MIN,
113 'sec': ACU_SEC,
114 'second': ACU_SEC,
115 'secs': ACU_SEC,
116 'seconds': ACU_SEC,
117 'now': ACU_NOW}
118
119 - def __init__(self, accuracy=0):
120 """
121 Default constructor of L{pdtContext} class.
122
123 @type accuracy: integer
124 @param accuracy: Accuracy flag
125
126 @rtype: object
127 @return: L{pdtContext} instance
128 """
129 self.accuracy = accuracy
130
131 - def updateAccuracy(self, *accuracy):
132 """
133 Updates current accuracy flag
134 """
135 for acc in accuracy:
136 if not isinstance(acc, int):
137 acc = self._ACCURACY_REVERSE_MAPPING[acc]
138 self.accuracy |= acc
139
140 - def update(self, context):
141 """
142 Uses another L{pdtContext} instance to update current one
143 """
144 self.updateAccuracy(context.accuracy)
145
146 @property
148 """
149 Returns True if current context is accurate to date
150 """
151 return bool(self.accuracy & self.ACU_DATE)
152
153 @property
155 """
156 Returns True if current context is accurate to time
157 """
158 return bool(self.accuracy & self.ACU_TIME)
159
160 @property
161 - def dateTimeFlag(self):
162 """
163 Returns the old date/time flag code
164 """
165 return int(self.hasDate and 1) | int(self.hasTime and 2)
166
167 @property
168 - def hasDateOrTime(self):
169 """
170 Returns True if current context is accurate to date/time
171 """
172 return bool(self.accuracy)
173
174 - def __repr__(self):
175 accuracy_repr = []
176 for acc, name in self._ACCURACY_MAPPING:
177 if acc & self.accuracy:
178 accuracy_repr.append('pdtContext.ACU_%s' % name.upper())
179 if accuracy_repr:
180 accuracy_repr = 'accuracy=' + ' | '.join(accuracy_repr)
181 else:
182 accuracy_repr = ''
183
184 return 'pdtContext(%s)' % accuracy_repr
185
186 - def __eq__(self, ctx):
187 return self.accuracy == ctx.accuracy
188