Package Gnumed :: Package timelinelib :: Package test :: Module utils
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.test.utils

  1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17   
 18  """ 
 19  Contains unit test utility functions. 
 20   
 21  Many functions use a human readable date and time string as argument. 
 22  Such a string has a day, month, year and an optional time like this:: 
 23   
 24     "1 Aug 2012" or "12 Jan 2017 12:05:30" 
 25  """ 
 26   
 27  import random 
 28  import xml.etree.ElementTree as ET 
 29   
 30  from timelinelib.calendar.gregorian.gregorian import GregorianDateTime 
 31  from timelinelib.calendar.gregorian.monthnames import ABBREVIATED_ENGLISH_MONTH_NAMES 
 32  from timelinelib.calendar.gregorian.time import GregorianDelta 
 33  from timelinelib.calendar.gregorian.timetype import GregorianTimeType 
 34  from timelinelib.canvas.data import Category 
 35  from timelinelib.canvas.data import Container 
 36  from timelinelib.canvas.data import Era 
 37  from timelinelib.canvas.data import Event 
 38  from timelinelib.canvas.data import Subevent 
 39  from timelinelib.canvas.data import TimePeriod 
 40   
 41   
 42  ANY_TIME = "1 Jan 2010" 
 43  ANY_NUM_TIME = 10 
 44   
 45   
46 -def gregorian_period(human_start_time, human_end_time):
47 """ 48 Create a gregorian TimePeriod object. 49 The start and end times are strings in a human readable format. 50 """ 51 return TimePeriod(human_time_to_gregorian(human_start_time), 52 human_time_to_gregorian(human_end_time))
53 54
55 -def numeric_period(start, end):
56 """ 57 Create a numeric TimePeriod object. 58 The start and end are numeric values. 59 """ 60 return TimePeriod(start, end)
61 62
63 -def human_time_to_gregorian(human_time):
64 """ 65 Create a :doc:`GregorianTime <timelinelib.calendar.gregorian.time>` object 66 from a human readable date and time string. 67 """ 68 (year, month, day, hour, minute, seconds) = human_time_to_ymdhm(human_time) 69 return GregorianDateTime(year, month, day, hour, minute, seconds).to_time()
70 71
72 -def a_time_period():
73 """Create a random :doc:`TimePeriod <timelinelib_canvas_data_timeperiod>` object.""" 74 year = random.randint(1, 4000) 75 month = random.randint(1, 12) 76 day = random.randint(1, 28) 77 end_year = year + random.randint(1, 5) 78 end_month = random.randint(1, 12) 79 end_day = random.randint(1, 28) 80 return TimePeriod(GregorianDateTime(year, month, day, 0, 0, 0).to_time(), 81 GregorianDateTime(end_year, end_month, end_day, 0, 0, 0).to_time())
82 83
84 -def human_time_to_ymdhm(human_time):
85 """ 86 Convert a human readable date and time string into a tuple of 87 numeric values. 88 """ 89 parts = human_time.split(" ") 90 day_part, month_part, year_part = parts[0], parts[1], parts[2] 91 day = int(day_part) 92 month = ABBREVIATED_ENGLISH_MONTH_NAMES.index(month_part) + 1 93 year = int(year_part) 94 if len(parts) == 4: 95 hour = int(parts[3][:2]) 96 minute = int(parts[3][3:5]) 97 if len(parts[3]) == 8: 98 seconds = int(parts[3][6:8]) 99 else: 100 seconds = 0 101 else: 102 hour = 0 103 minute = 0 104 seconds = 0 105 return (year, month, day, hour, minute, seconds)
106 107
108 -def an_event():
109 """Create an :doc:`Event <timelinelib_canvas_data_event>` object.""" 110 return an_event_with(time=ANY_TIME)
111 112
113 -def an_event_with(human_start_time=None, human_end_time=None, time=ANY_TIME, 114 text="foo", fuzzy=False, locked=False, ends_today=False, 115 category=None, default_color=None):
116 """Create an :doc:`Event <timelinelib_canvas_data_event>` object.""" 117 if human_start_time and human_end_time: 118 start = human_time_to_gregorian(human_start_time) 119 end = human_time_to_gregorian(human_end_time) 120 else: 121 start = human_time_to_gregorian(time) 122 end = human_time_to_gregorian(time) 123 event = Event().update( 124 start, 125 end, 126 text, 127 category=category, 128 fuzzy=fuzzy, 129 locked=locked, 130 ends_today=ends_today 131 ) 132 event.set_default_color(default_color) 133 return event
134 135
136 -def a_subevent():
137 """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object.""" 138 return a_subevent_with()
139 140
141 -def a_subevent_with(start=None, end=None, time=ANY_TIME, text="sub", category=None, container=None):
142 """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object.""" 143 if start and end: 144 start = human_time_to_gregorian(start) 145 end = human_time_to_gregorian(end) 146 else: 147 start = human_time_to_gregorian(time) 148 end = human_time_to_gregorian(time) 149 event = Subevent().update(start, end, text, category=category) 150 event.container = container 151 return event
152 153
154 -def a_container(name, category, sub_events):
155 """Create a :doc:`Container <timelinelib_canvas_data_container>` object.""" 156 start = human_time_to_gregorian(ANY_TIME) 157 end = human_time_to_gregorian(ANY_TIME) 158 container = Container().update(start, end, name, category=category) 159 all_events = [] 160 all_events.append(container) 161 for (name, category) in sub_events: 162 event = Subevent().update(start, end, name, category=category) 163 event.container = container 164 all_events.append(event) 165 return all_events
166 167
168 -def a_container_with(text="container", category=None):
169 """Create a :doc:`Container <timelinelib_canvas_data_container>` object.""" 170 start = human_time_to_gregorian(ANY_TIME) 171 end = human_time_to_gregorian(ANY_TIME) 172 container = Container().update(start, end, text, category=category) 173 return container
174 175
176 -def a_category():
177 """Create a :doc:`Category <timelinelib_canvas_data_category>` object.""" 178 return a_category_with(name="category")
179 180
181 -def a_category_with(name, color=(255, 0, 0), font_color=(0, 255, 255), 182 parent=None):
183 """Create a :doc:`Category <timelinelib_canvas_data_category>` object.""" 184 return Category().update( 185 name=name, 186 color=color, 187 font_color=font_color, 188 parent=parent 189 )
190 191
192 -def a_gregorian_era():
193 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 194 return a_gregorian_era_with()
195 196
197 -def a_gregorian_era_with(start=None, end=None, time=ANY_TIME, name="foo", 198 color=(128, 128, 128), time_type=GregorianTimeType(), 199 ends_today=False):
200 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 201 if start and end: 202 start = human_time_to_gregorian(start) 203 end = human_time_to_gregorian(end) 204 else: 205 start = human_time_to_gregorian(time) 206 end = human_time_to_gregorian(time) 207 era = Era().update(start, end, name, color) 208 era.set_ends_today(ends_today) 209 return era
210 211
212 -def a_numeric_era():
213 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 214 return a_numeric_era_with()
215 216
217 -def a_numeric_era_with(start=None, end=None, time=ANY_NUM_TIME, name="foo", color=(128, 128, 128)):
218 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 219 if not (start or end): 220 start = time 221 end = time 222 return Era().update(start, end, name, color)
223 224
225 -def inc(number):
226 """Return the number + 1. If number is None return 8.""" 227 if number is None: 228 return 8 229 else: 230 return number + 1
231 232
233 -def new_cat(event):
234 """Return a new category.""" 235 if event.get_category() is None: 236 return a_category_with(name="new category") 237 else: 238 return a_category_with(name="was: %s" % event.get_category().get_name())
239 240
241 -def new_parent(category):
242 """Return a new category parent.""" 243 if category._get_parent() is None: 244 return a_category_with(name="new category") 245 else: 246 return a_category_with(name="was: %s" % category._get_parent().get_name())
247 248
249 -def new_progress(event):
250 """Return the event's progress + 1. If the event's progress is None, return 8.""" 251 if event.get_progress() is None: 252 return 8 253 else: 254 return (event.get_progress() + 1) % 100
255 256
257 -def modifier_change_ends_today(event):
258 """Toggle the event's ends-today property.""" 259 if event.get_locked(): 260 event.set_locked(False) 261 event.set_ends_today(not event.get_ends_today()) 262 event.set_locked(True) 263 else: 264 event.set_ends_today(not event.get_ends_today()) 265 return event
266 267 268 EVENT_MODIFIERS = [ 269 ("change fuzzy", lambda event: 270 event.set_fuzzy(not event.get_fuzzy())), 271 ("change locked", lambda event: 272 event.set_locked(not event.get_locked())), 273 ("change ends today", modifier_change_ends_today), 274 ("change id", lambda event: 275 event.set_id(inc(event.get_id()))), 276 ("change time period", lambda event: 277 event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))), 278 ("change text", lambda event: 279 event.set_text("was: %s" % event.get_text())), 280 ("change category", lambda event: 281 event.set_category(new_cat(event))), 282 ("change icon", lambda event: 283 event.set_icon("was: %s" % event.get_icon())), 284 ("change description", lambda event: 285 event.set_description("was: %s" % event.get_description())), 286 ("change hyperlink", lambda event: 287 event.set_hyperlink("was: %s" % event.get_hyperlink())), 288 ("change progress", lambda event: 289 event.set_progress(new_progress(event))), 290 ("change alert", lambda event: 291 event.set_alert("was: %s" % event.get_alert())), 292 ] 293 294 295 SUBEVENT_MODIFIERS = EVENT_MODIFIERS 296 297 298 CONTAINER_MODIFIERS = [ 299 ("change time period", lambda event: 300 event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))), 301 ("change text", lambda event: 302 event.set_text("was: %s" % event.get_text())), 303 ("change category", lambda event: 304 event.set_category(new_cat(event))), 305 ] 306 307 308 CATEGORY_MODIFIERS = [ 309 ("change name", lambda category: 310 category.set_name("was: %s" % category.get_name())), 311 ("change id", lambda category: 312 category.set_id(inc(category.get_id()))), 313 ("change color", lambda category: 314 category.set_color(category.get_color() + (1, 0, 3))), 315 ("change font color", lambda category: 316 category.set_font_color(category.get_font_color() + (1, 0, 3))), 317 ("change parent", lambda category: 318 category.set_parent(new_parent(category))), 319 ] 320 321 322 TIME_PERIOD_MODIFIERS = [ 323 ("zoom", lambda time_period: time_period.zoom(-1)), 324 ("move left", lambda time_period: time_period.move(-1)), 325 ("move right", lambda time_period: time_period.move(1)), 326 ] 327 328 329 ERA_MODIFIERS = [ 330 ("change id", lambda era: era.set_id(inc(era.get_id()))), 331 ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(GregorianDelta.from_days(1)))), 332 ("change text", lambda era: era.set_name("was: %s" % era.get_name())), 333 ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()]))) 334 ] 335 336 NUM_ERA_MODIFIERS = [ 337 ("change id", lambda era: era.set_id(inc(era.get_id()))), 338 ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(1))), 339 ("change text", lambda era: era.set_name("was: %s" % era.get_name())), 340 ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()]))) 341 ] 342 343 344 TIME_MODIFIERS = [ 345 ("add", lambda time: time + GregorianDelta(1)), 346 ] 347 348
349 -class ObjectWithTruthValue(object):
350 """An object of this class can be treated as a boolean."""
351 - def __init__(self, truth_value):
352 self.truth_value = truth_value
353
354 - def __bool__(self):
355 return self.truth_value
356 357
358 -def select_language(language):
359 """ 360 Select the system locale language. 361 This function is Windows specific. 362 """ 363 import platform 364 from timelinelib.config.paths import LOCALE_DIR 365 from timelinelib.meta.about import APPLICATION_NAME 366 if platform.system() == "Windows": 367 import gettext 368 import os 369 os.environ['LANG'] = language 370 gettext.install(APPLICATION_NAME.lower(), LOCALE_DIR)
371 372
373 -class _ANY(object):
374 """An object of this class is always considered equal to any other object.""" 375
376 - def __eq__(self, other):
377 return True
378 ANY = _ANY() 379 """This object is always considered equal to any other object.""" 380 381
382 -def svg_to_dict(xml):
383 def node_to_dict(node): 384 return { 385 "name": node.tag, 386 "attributes": {key: attribute(key, value) for key, value in node.attrib.items()}, 387 "children": [node_to_dict(child) for child in node] 388 }
389 def attribute(key, value): 390 if key == "style": 391 styles = {} 392 for style in value.strip().split(";"): 393 if style.strip(): 394 name, value = style.split(":") 395 styles[name.strip()] = value.strip() 396 return styles 397 else: 398 return value 399 return node_to_dict(ET.fromstring(xml)) 400