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, categories=[], 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 event.set_categories(categories) 134 return event
135 136
137 -def a_subevent():
138 """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object.""" 139 return a_subevent_with()
140 141
142 -def a_subevent_with(start=None, end=None, time=ANY_TIME, text="sub", category=None, container=None):
143 """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object.""" 144 if start and end: 145 start = human_time_to_gregorian(start) 146 end = human_time_to_gregorian(end) 147 else: 148 start = human_time_to_gregorian(time) 149 end = human_time_to_gregorian(time) 150 event = Subevent().update(start, end, text, category=category) 151 event.container = container 152 return event
153 154
155 -def a_container(name, category, sub_events):
156 """Create a :doc:`Container <timelinelib_canvas_data_container>` object.""" 157 start = human_time_to_gregorian(ANY_TIME) 158 end = human_time_to_gregorian(ANY_TIME) 159 container = Container().update(start, end, name, category=category) 160 all_events = [] 161 all_events.append(container) 162 for (name, category) in sub_events: 163 event = Subevent().update(start, end, name, category=category) 164 event.container = container 165 all_events.append(event) 166 return all_events
167 168
169 -def a_container_with(text="container", category=None):
170 """Create a :doc:`Container <timelinelib_canvas_data_container>` object.""" 171 start = human_time_to_gregorian(ANY_TIME) 172 end = human_time_to_gregorian(ANY_TIME) 173 container = Container().update(start, end, text, category=category) 174 return container
175 176
177 -def a_category():
178 """Create a :doc:`Category <timelinelib_canvas_data_category>` object.""" 179 return a_category_with(name="category")
180 181
182 -def a_category_with(name, color=(255, 0, 0), font_color=(0, 255, 255), 183 parent=None):
184 """Create a :doc:`Category <timelinelib_canvas_data_category>` object.""" 185 return Category().update( 186 name=name, 187 color=color, 188 font_color=font_color, 189 parent=parent 190 )
191 192
193 -def a_gregorian_era():
194 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 195 return a_gregorian_era_with()
196 197
198 -def a_gregorian_era_with(start=None, end=None, time=ANY_TIME, name="foo", 199 color=(128, 128, 128), time_type=GregorianTimeType(), 200 ends_today=False):
201 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 202 if start and end: 203 start = human_time_to_gregorian(start) 204 end = human_time_to_gregorian(end) 205 else: 206 start = human_time_to_gregorian(time) 207 end = human_time_to_gregorian(time) 208 era = Era().update(start, end, name, color) 209 era.set_ends_today(ends_today) 210 return era
211 212
213 -def a_numeric_era():
214 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 215 return a_numeric_era_with()
216 217
218 -def a_numeric_era_with(start=None, end=None, time=ANY_NUM_TIME, name="foo", color=(128, 128, 128)):
219 """Create an :doc:`Era <timelinelib_canvas_data_era>` object.""" 220 if not (start or end): 221 start = time 222 end = time 223 return Era().update(start, end, name, color)
224 225
226 -def inc(number):
227 """Return the number + 1. If number is None return 8.""" 228 if number is None: 229 return 8 230 else: 231 return number + 1
232 233
234 -def new_cat(event):
235 """Return a new category.""" 236 if event.get_category() is None: 237 return a_category_with(name="new category") 238 else: 239 return a_category_with(name="was: %s" % event.get_category().get_name())
240 241
242 -def new_parent(category):
243 """Return a new category parent.""" 244 if category._get_parent() is None: 245 return a_category_with(name="new category") 246 else: 247 return a_category_with(name="was: %s" % category._get_parent().get_name())
248 249
250 -def new_progress(event):
251 """Return the event's progress + 1. If the event's progress is None, return 8.""" 252 if event.get_progress() is None: 253 return 8 254 else: 255 return (event.get_progress() + 1) % 100
256 257
258 -def modifier_change_ends_today(event):
259 """Toggle the event's ends-today property.""" 260 if event.get_locked(): 261 event.set_locked(False) 262 event.set_ends_today(not event.get_ends_today()) 263 event.set_locked(True) 264 else: 265 event.set_ends_today(not event.get_ends_today()) 266 return event
267 268 269 EVENT_MODIFIERS = [ 270 ("change fuzzy", lambda event: 271 event.set_fuzzy(not event.get_fuzzy())), 272 ("change locked", lambda event: 273 event.set_locked(not event.get_locked())), 274 ("change ends today", modifier_change_ends_today), 275 ("change id", lambda event: 276 event.set_id(inc(event.get_id()))), 277 ("change time period", lambda event: 278 event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))), 279 ("change text", lambda event: 280 event.set_text("was: %s" % event.get_text())), 281 ("change category", lambda event: 282 event.set_category(new_cat(event))), 283 ("change icon", lambda event: 284 event.set_icon("was: %s" % event.get_icon())), 285 ("change description", lambda event: 286 event.set_description("was: %s" % event.get_description())), 287 ("change hyperlink", lambda event: 288 event.set_hyperlink("was: %s" % event.get_hyperlink())), 289 ("change progress", lambda event: 290 event.set_progress(new_progress(event))), 291 ("change alert", lambda event: 292 event.set_alert("was: %s" % event.get_alert())), 293 ] 294 295 296 SUBEVENT_MODIFIERS = EVENT_MODIFIERS 297 298 299 CONTAINER_MODIFIERS = [ 300 ("change time period", lambda event: 301 event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))), 302 ("change text", lambda event: 303 event.set_text("was: %s" % event.get_text())), 304 ("change category", lambda event: 305 event.set_category(new_cat(event))), 306 ] 307 308 309 CATEGORY_MODIFIERS = [ 310 ("change name", lambda category: 311 category.set_name("was: %s" % category.get_name())), 312 ("change id", lambda category: 313 category.set_id(inc(category.get_id()))), 314 ("change color", lambda category: 315 category.set_color(category.get_color() + (1, 0, 3))), 316 ("change font color", lambda category: 317 category.set_font_color(category.get_font_color() + (1, 0, 3))), 318 ("change parent", lambda category: 319 category.set_parent(new_parent(category))), 320 ] 321 322 323 TIME_PERIOD_MODIFIERS = [ 324 ("zoom", lambda time_period: time_period.zoom(-1)), 325 ("move left", lambda time_period: time_period.move(-1)), 326 ("move right", lambda time_period: time_period.move(1)), 327 ] 328 329 330 ERA_MODIFIERS = [ 331 ("change id", lambda era: era.set_id(inc(era.get_id()))), 332 ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(GregorianDelta.from_days(1)))), 333 ("change text", lambda era: era.set_name("was: %s" % era.get_name())), 334 ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()]))) 335 ] 336 337 NUM_ERA_MODIFIERS = [ 338 ("change id", lambda era: era.set_id(inc(era.get_id()))), 339 ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(1))), 340 ("change text", lambda era: era.set_name("was: %s" % era.get_name())), 341 ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()]))) 342 ] 343 344 345 TIME_MODIFIERS = [ 346 ("add", lambda time: time + GregorianDelta(1)), 347 ] 348 349
350 -class ObjectWithTruthValue(object):
351 """An object of this class can be treated as a boolean."""
352 - def __init__(self, truth_value):
353 self.truth_value = truth_value
354
355 - def __bool__(self):
356 return self.truth_value
357 358
359 -def select_language(language):
360 """ 361 Select the system locale language. 362 This function is Windows specific. 363 """ 364 import platform 365 from timelinelib.config.paths import LOCALE_DIR 366 from timelinelib.meta.about import APPLICATION_NAME 367 if platform.system() == "Windows": 368 import gettext 369 import os 370 os.environ['LANG'] = language 371 gettext.install(APPLICATION_NAME.lower(), LOCALE_DIR)
372 373
374 -class _ANY(object):
375 """An object of this class is always considered equal to any other object.""" 376
377 - def __eq__(self, other):
378 return True
379 ANY = _ANY() 380 """This object is always considered equal to any other object.""" 381 382
383 -def svg_to_dict(xml):
384 def node_to_dict(node): 385 return { 386 "name": node.tag, 387 "attributes": {key: attribute(key, value) for key, value in node.attrib.items()}, 388 "children": [node_to_dict(child) for child in node] 389 }
390 def attribute(key, value): 391 if key == "style": 392 styles = {} 393 for style in value.strip().split(";"): 394 if style.strip(): 395 name, value = style.split(":") 396 styles[name.strip()] = value.strip() 397 return styles 398 else: 399 return value 400 return node_to_dict(ET.fromstring(xml)) 401