5 from xml.dom import minidom
9 class Optional(object):
12 Even you don't have to worry about knowing when to perform None checks
13 When the NULL object pattern just isn't good enough
18 >>> a.get_nothrow("Blacksheep")
23 >>> a.get_nothrow("Blacksheep"), a.get(), a()
24 ('Lamb', 'Lamb', 'Lamb')
28 >>> a.get_nothrow("Blacksheep")
31 >>> b = Optional("Lamb")
35 >>> a.get_nothrow("Blacksheep"), a.get(), a()
36 ('Lamb', 'Lamb', 'Lamb')
40 >>> a.get_nothrow("Blacksheep")
44 class NonExistent(object):
47 def __init__(self, value = NonExistent):
54 self._value = self.NonExistent
57 return self._value is not self.NonExistent
59 def get_nothrow(self, default = None):
60 return self._value if self.is_good() else default
63 if not self.is_good():
64 raise ReferenceError("Optional not initialized")
68 # Implemented to imitate weakref
72 return str(self.get_nothrow(""))
75 return "<Optional at %x; to %r>" % (
76 id(self), self.get_nothrow("Nothing")
80 return not self.is_good()
82 def __eq__(self, rhs):
83 return self._value == rhs._value
85 def __ne__(self, rhs):
86 return self._value != rhs._value
88 def __lt__(self, rhs):
89 return self._value < rhs._value
91 def __le__(self, rhs):
92 return self._value <= rhs._value
94 def __gt__(self, rhs):
95 return self._value > rhs._value
97 def __ge__(self, rhs):
98 return self._value >= rhs._value
101 def open_anything(source, alternative=None):
102 """URI, filename, or string --> stream
104 This function lets you define parsers that take any input source
105 (URL, pathname to local or network file, or actual data as a string)
106 and deal with it in a uniform manner. Returned object is guaranteed
107 to have all the basic stdio read methods (read, readline, readlines).
108 Just .close() the object when you're done with it.
110 if hasattr(source, "read"):
116 # try to open with urllib (if source is http, ftp, or file URL)
118 return urllib.urlopen(source)
119 except (IOError, OSError):
121 print "ERROR with URL ("+source+")!\n"
123 # try to open with native open function (if source is pathname)
126 except (IOError, OSError):
128 print "ERROR with file!\n"
130 # treat source as string
131 if alternative == None:
132 print 'LAST RESORT. String is "'+source+'"\n'
133 return StringIO.StringIO(str(source))
135 print 'LAST RESORT. String is "'+alternative+'"\n'
136 return StringIO.StringIO(str(alternative))
139 def load_xml(source, alternative=None):
140 """load XML input source, return parsed XML document
142 - a URL of a remote XML file ("http://diveintopython.org/kant.xml")
143 - a filename of a local XML file ("~/diveintopython/common/py/kant.xml")
144 - standard input ("-")
145 - the actual XML document, as a string
147 sock = open_anything(source, alternative)
149 xmldoc = minidom.parse(sock).documentElement
150 except (IOError, OSError):
151 print "ERROR with data"
153 sock = open_anything('<response method="getProjects"><project projName="ERROR!"/></response>')
154 xmldoc = minidom.parse(sock).documentElement
159 def abbreviate(text, expectedLen):
160 singleLine = " ".join(text.split("\n"))
161 lineLen = len(singleLine)
162 if lineLen <= expectedLen:
167 leftLen = expectedLen // 2 - 1
168 rightLen = max(expectedLen - leftLen - len(abbrev) + 1, 1)
170 abbrevText = singleLine[0:leftLen] + abbrev + singleLine[-rightLen:-1]
171 assert len(abbrevText) <= expectedLen, "Too long: '%s'" % abbrevText
175 def abbreviate_url(url, domainLength, pathLength):
176 urlParts = urlparse.urlparse(url)
178 netloc = urlParts.netloc
181 pathLength += max(domainLength - len(netloc), 0)
182 domainLength += max(pathLength - len(path), 0)
184 netloc = abbreviate(netloc, domainLength)
185 path = abbreviate(path, pathLength)
189 def is_same_year(targetDate, todaysDate = datetime.datetime.today()):
190 return targetDate.year == todaysDate.year
193 def is_same_month(targetDate, todaysDate = datetime.datetime.today()):
194 return targetDate.month == todaysDate.month
197 def is_same_day(targetDate, todaysDate = datetime.datetime.today()):
198 return targetDate.day == todaysDate.day
201 def to_fuzzy_date(targetDate, todaysDate = datetime.datetime.today()):
203 Conert a date/time/datetime object to a fuzzy date
205 >>> todaysDate = datetime.date(2009, 4, 16)
206 >>> to_fuzzy_date(datetime.date(1, 4, 6), todaysDate)
208 >>> to_fuzzy_date(datetime.date(2008, 4, 13), todaysDate)
210 >>> to_fuzzy_date(datetime.date(2009, 4, 13), todaysDate)
212 >>> to_fuzzy_date(datetime.date(2009, 4, 20), todaysDate)
214 >>> to_fuzzy_date(datetime.date(2010, 4, 13), todaysDate)
216 >>> to_fuzzy_date(datetime.date(2012, 12, 12), todaysDate)
219 delta = targetDate - todaysDate
220 days = abs(delta.days)
221 noDifference = datetime.timedelta()
222 isFuture = noDifference < delta
223 directionBy1 = "Next" if isFuture else "Last"
224 directionByN = "Later" if isFuture else "Earlier"
226 yearDelta = abs(targetDate.year - todaysDate.year)
228 directionByInf = "from now" if isFuture else "ago"
229 return "Forever %s" % directionByInf
231 return "%s year" % directionBy1
233 monthDelta = abs(targetDate.month - todaysDate.month)
235 return "%s this year" % directionByN
236 elif 1 == monthDelta:
237 return "%s month" % directionBy1
239 dayDelta = abs(targetDate.day - todaysDate.day)
241 return "%s this month" % directionByN
243 directionInWeek = "This" if isFuture else "Last"
244 days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
245 return "%s %s" % (directionInWeek, days[targetDate.weekday()])
247 return "%s day" % directionBy1