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
     29  from timelinelib.calendar.gregorian.gregorian import GregorianDateTime
     30  from timelinelib.calendar.gregorian.monthnames import ABBREVIATED_ENGLISH_MONTH_NAMES
     31  from timelinelib.calendar.gregorian.time import GregorianDelta
     32  from timelinelib.calendar.gregorian.timetype import GregorianTimeType
     33  from timelinelib.canvas.data import Category
     34  from timelinelib.canvas.data import Container
     35  from timelinelib.canvas.data import Era
     36  from timelinelib.canvas.data import Event
     37  from timelinelib.canvas.data import Subevent
     38  from timelinelib.canvas.data import TimePeriod
     39
     40
     41  ANY_TIME = "1 Jan 2010"
     42  ANY_NUM_TIME = 10
     43
     44
     45 -def gregorian_period(human_start_time, human_end_time):
     46      """
     47      Create a gregorian TimePeriod object.
     48      The start and end times are strings in a human readable format.
     49      """
     50      return TimePeriod(human_time_to_gregorian(human_start_time),
     51                        human_time_to_gregorian(human_end_time))
     52
     53
     54 -def numeric_period(start, end):
     55      """
     56      Create a numeric TimePeriod object.
     57      The start and end are numeric values.
     58      """
     59      return TimePeriod(start, end)
     60
     61
     62 -def human_time_to_gregorian(human_time):
     63      """
     64      Create a :doc:`GregorianTime <timelinelib.calendar.gregorian.time>` object
     65      from a human readable date and time string.
     66      """
     67      (year, month, day, hour, minute, seconds) = human_time_to_ymdhm(human_time)
     68      return GregorianDateTime(year, month, day, hour, minute, seconds).to_time()
     69
     70
     71 -def a_time_period():
     72      """Create a random :doc:`TimePeriod <timelinelib_canvas_data_timeperiod>` object."""
     73      year = random.randint(1, 4000)
     74      month = random.randint(1, 12)
     75      day = random.randint(1, 28)
     76      end_year = year + random.randint(1, 5)
     77      end_month = random.randint(1, 12)
     78      end_day = random.randint(1, 28)
     79      return TimePeriod(GregorianDateTime(year, month, day, 0, 0, 0).to_time(),
     80                        GregorianDateTime(end_year, end_month, end_day, 0, 0, 0).to_time())
     81
     82
     83 -def human_time_to_ymdhm(human_time):
     84      """
     85      Convert a human readable date and time string into a tuple of
     86      numeric values.
     87      """
     88      parts = human_time.split(" ")
     89      day_part, month_part, year_part = parts[0], parts[1], parts[2]
     90      day = int(day_part)
     91      month = ABBREVIATED_ENGLISH_MONTH_NAMES.index(month_part) + 1
     92      year = int(year_part)
     93      if len(parts) == 4:
     94          hour = int(parts[3][:2])
     95          minute = int(parts[3][3:5])
     96          if len(parts[3]) == 8:
     97              seconds = int(parts[3][6:8])
     98          else:
     99              seconds = 0
    100      else:
    101          hour = 0
    102          minute = 0
    103          seconds = 0
    104      return (year, month, day, hour, minute, seconds)
    105
    106
    107 -def an_event():
    108      """Create an :doc:`Event <timelinelib_canvas_data_event>` object."""
    109      return an_event_with(time=ANY_TIME)
    110
    111
    112 -def an_event_with(human_start_time=None, human_end_time=None, time=ANY_TIME,
    113                    text="foo", fuzzy=False, locked=False, ends_today=False,
    114                    category=None, default_color=None):
    115      """Create an :doc:`Event <timelinelib_canvas_data_event>` object."""
    116      if human_start_time and human_end_time:
    117          start = human_time_to_gregorian(human_start_time)
    118          end = human_time_to_gregorian(human_end_time)
    119      else:
    120          start = human_time_to_gregorian(time)
    121          end = human_time_to_gregorian(time)
    122      event = Event().update(
    123          start,
    124          end,
    125          text,
    126          category=category,
    127          fuzzy=fuzzy,
    128          locked=locked,
    129          ends_today=ends_today
    130      )
    131      event.set_default_color(default_color)
    132      return event
    133
    134
    135 -def a_subevent():
    136      """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object."""
    137      return a_subevent_with()
    138
    139
    140 -def a_subevent_with(start=None, end=None, time=ANY_TIME, text="sub", category=None, container=None):
    141      """Create a :doc:`Subevent <timelinelib_canvas_data_subevent>` object."""
    142      if start and end:
    143          start = human_time_to_gregorian(start)
    144          end = human_time_to_gregorian(end)
    145      else:
    146          start = human_time_to_gregorian(time)
    147          end = human_time_to_gregorian(time)
    148      event = Subevent().update(start, end, text, category=category)
    149      event.container = container
    150      return event
    151
    152
    153 -def a_container(name, category, sub_events):
    154      """Create a :doc:`Container <timelinelib_canvas_data_container>` object."""
    155      start = human_time_to_gregorian(ANY_TIME)
    156      end = human_time_to_gregorian(ANY_TIME)
    157      container = Container().update(start, end, name, category=category)
    158      all_events = []
    159      all_events.append(container)
    160      for (name, category) in sub_events:
    161          event = Subevent().update(start, end, name, category=category)
    162          event.container = container
    163          all_events.append(event)
    164      return all_events
    165
    166
    167 -def a_container_with(text="container", category=None):
    168      """Create a :doc:`Container <timelinelib_canvas_data_container>` object."""
    169      start = human_time_to_gregorian(ANY_TIME)
    170      end = human_time_to_gregorian(ANY_TIME)
    171      container = Container().update(start, end, text, category=category)
    172      return container
    173
    174
    175 -def a_category():
    176      """Create a :doc:`Category <timelinelib_canvas_data_category>` object."""
    177      return a_category_with(name="category")
    178
    179
    180 -def a_category_with(name, color=(255, 0, 0), font_color=(0, 255, 255),
    181                      parent=None):
    182      """Create a :doc:`Category <timelinelib_canvas_data_category>` object."""
    183      return Category().update(
    184          name=name,
    185          color=color,
    186          font_color=font_color,
    187          parent=parent
    188      )
    189
    190
    191 -def a_gregorian_era():
    192      """Create an :doc:`Era <timelinelib_canvas_data_era>` object."""
    193      return a_gregorian_era_with()
    194
    195
    196 -def a_gregorian_era_with(start=None, end=None, time=ANY_TIME, name="foo",
    197                           color=(128, 128, 128), time_type=GregorianTimeType(),
    198                           ends_today=False):
    199      """Create an :doc:`Era <timelinelib_canvas_data_era>` object."""
    200      if start and end:
    201          start = human_time_to_gregorian(start)
    202          end = human_time_to_gregorian(end)
    203      else:
    204          start = human_time_to_gregorian(time)
    205          end = human_time_to_gregorian(time)
    206      era = Era().update(start, end, name, color)
    207      era.set_ends_today(ends_today)
    208      return era
    209
    210
    211 -def a_numeric_era():
    212      """Create an :doc:`Era <timelinelib_canvas_data_era>` object."""
    213      return a_numeric_era_with()
    214
    215
    216 -def a_numeric_era_with(start=None, end=None, time=ANY_NUM_TIME, name="foo", color=(128, 128, 128)):
    217      """Create an :doc:`Era <timelinelib_canvas_data_era>` object."""
    218      if not (start or end):
    219          start = time
    220          end = time
    221      return Era().update(start, end, name, color)
    222
    223
    224 -def inc(number):
    225      """Return the number + 1. If number is None return 8."""
    226      if number is None:
    227          return 8
    228      else:
    229          return number + 1
    230
    231
    232 -def new_cat(event):
    233      """Return a new category."""
    234      if event.get_category() is None:
    235          return a_category_with(name="new category")
    236      else:
    237          return a_category_with(name="was: %s" % event.get_category().get_name())
    238
    239
    240 -def new_parent(category):
    241      """Return a new category parent."""
    242      if category._get_parent() is None:
    243          return a_category_with(name="new category")
    244      else:
    245          return a_category_with(name="was: %s" % category._get_parent().get_name())
    246
    247
    248 -def new_progress(event):
    249      """Return the event's progress + 1. If the event's progress is None, return 8."""
    250      if event.get_progress() is None:
    251          return 8
    252      else:
    253          return (event.get_progress() + 1) % 100
    254
    255
    256 -def modifier_change_ends_today(event):
    257      """Toggle the event's ends-today property."""
    258      if event.get_locked():
    259          event.set_locked(False)
    260          event.set_ends_today(not event.get_ends_today())
    261          event.set_locked(True)
    262      else:
    263          event.set_ends_today(not event.get_ends_today())
    264      return event
    265
    266
    267  EVENT_MODIFIERS = [
    268      ("change fuzzy", lambda event:
    269          event.set_fuzzy(not event.get_fuzzy())),
    270      ("change locked", lambda event:
    271          event.set_locked(not event.get_locked())),
    272      ("change ends today", modifier_change_ends_today),
    273      ("change id", lambda event:
    274          event.set_id(inc(event.get_id()))),
    275      ("change time period", lambda event:
    276          event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))),
    277      ("change text", lambda event:
    278          event.set_text("was: %s" % event.get_text())),
    279      ("change category", lambda event:
    280          event.set_category(new_cat(event))),
    281      ("change icon", lambda event:
    282          event.set_icon("was: %s" % event.get_icon())),
    283      ("change description", lambda event:
    284          event.set_description("was: %s" % event.get_description())),
    285      ("change hyperlink", lambda event:
    286          event.set_hyperlink("was: %s" % event.get_hyperlink())),
    287      ("change progress", lambda event:
    288          event.set_progress(new_progress(event))),
    289      ("change alert", lambda event:
    290          event.set_alert("was: %s" % event.get_alert())),
    291  ]
    292
    293
    294  SUBEVENT_MODIFIERS = EVENT_MODIFIERS
    295
    296
    297  CONTAINER_MODIFIERS = [
    298      ("change time period", lambda event:
    299          event.set_time_period(event.get_time_period().move_delta(GregorianDelta.from_days(1)))),
    300      ("change text", lambda event:
    301          event.set_text("was: %s" % event.get_text())),
    302      ("change category", lambda event:
    303          event.set_category(new_cat(event))),
    304  ]
    305
    306
    307  CATEGORY_MODIFIERS = [
    308      ("change name", lambda category:
    309          category.set_name("was: %s" % category.get_name())),
    310      ("change id", lambda category:
    311          category.set_id(inc(category.get_id()))),
    312      ("change color", lambda category:
    313          category.set_color(category.get_color() + (1, 0, 3))),
    314      ("change font color", lambda category:
    315          category.set_font_color(category.get_font_color() + (1, 0, 3))),
    316      ("change parent", lambda category:
    317          category.set_parent(new_parent(category))),
    318  ]
    319
    320
    321  TIME_PERIOD_MODIFIERS = [
    322      ("zoom", lambda time_period: time_period.zoom(-1)),
    323      ("move left", lambda time_period: time_period.move(-1)),
    324      ("move right", lambda time_period: time_period.move(1)),
    325  ]
    326
    327
    328  ERA_MODIFIERS = [
    329      ("change id", lambda era: era.set_id(inc(era.get_id()))),
    330      ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(GregorianDelta.from_days(1)))),
    331      ("change text", lambda era: era.set_name("was: %s" % era.get_name())),
    332      ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()])))
    333  ]
    334
    335  NUM_ERA_MODIFIERS = [
    336      ("change id", lambda era: era.set_id(inc(era.get_id()))),
    337      ("change time period", lambda era: era.set_time_period(era.get_time_period().move_delta(1))),
    338      ("change text", lambda era: era.set_name("was: %s" % era.get_name())),
    339      ("change color", lambda era: era.set_color(tuple([x + 1 for x in era.get_color()])))
    340  ]
    341
    342
    343  TIME_MODIFIERS = [
    344      ("add", lambda time: time + GregorianDelta(1)),
    345  ]
    346
    347
    348 -class ObjectWithTruthValue(object):
    349      """An object of this class can be treated as a boolean."""
    350 -    def __init__(self, truth_value):
    351          self.truth_value = truth_value
    352
    353 -    def __nonzero__(self):
    354          return self.truth_value
    355
    356
    357 -def select_language(language):
    358      """
    359      Select the system locale language.
    360      This function is Windows specific.
    361      """
    362      import platform
    363      from timelinelib.config.paths import LOCALE_DIR
    364      from timelinelib.meta.about import APPLICATION_NAME
    365      if platform.system() == "Windows":
    366          import gettext
    367          import os
    368          os.environ['LANG'] = language
    369          gettext.install(APPLICATION_NAME.lower(), LOCALE_DIR, unicode=True)
    370
    371
    372 -class _ANY(object):
    373      """An object of this class is always considered equal to any other object."""
    374
    375 -    def __eq__(self, other):
    376          return True
    377  ANY = _ANY()
    378  """This object is always considered equal to any other object."""
    379