def db_open(path, timetype=None): """ Create timeline database that can read and write timeline data from and to persistent storage identified by path. Throw a TimelineIOError exception if not able to read from the given path. Valid values for path: - special string ":tutorial:" - string with suffix .timeline - string with suffix .ics - string denoting a directory """ if path == ":tutorial:": return open_gregorian_tutorial_timeline(path) elif path == ":numtutorial:": return open_numeric_tutorial_timeline(path) elif os.path.isdir(path): return open_directory_timeline(path) elif path.endswith(".timeline"): return db_open_timeline(path, timetype) elif path.endswith(".ics"): return db_open_ics(path) else: msg_template = (_("Unable to open timeline '%s'.") + "\n\n" + _("Unknown format.")) raise TimelineIOError(msg_template % path)
def _read_calendar_object(self, file_contents): try: return Calendar.from_ical(file_contents) except Exception as pe: msg1 = _("Unable to read calendar data.") msg2 = "\n\n" + ex_msg(pe) raise TimelineIOError(msg1 + msg2)
def _convert_to_datetime(self, d): if isinstance(d, datetime): return GregorianDateTime(d.year, d.month, d.day, d.hour, d.minute, d.second).to_time() elif isinstance(d, date): return GregorianDateTime.from_ymd(d.year, d.month, d.day).to_time() else: raise TimelineIOError("Unknown date.")
def save_events(self, events): try: with self.transaction("Save events"): for event in events: event.db = self event.save() except Exception as e: raise TimelineIOError("Saving event failed: %s" % e)
def db_open_timeline(path, timetype=None): if (os.path.exists(path) and file_starts_with(path, "# Written by Timeline ")): raise TimelineIOError( _("You are trying to open an old file with a new version of timeline. Please install version 0.21.1 of timeline to convert it to the new format." )) else: return db_open_newtype_timeline(path, timetype)
def delete_event(self, event_or_id): try: if isinstance(event_or_id, Event): event = event_or_id else: event = self.find_event_with_id(event_or_id) event.db = self event.delete() except Exception as e: raise TimelineIOError("Deleting event failed: %s" % e)
def save_view_properties(self, view_properties): if view_properties.displayed_period is not None: if not view_properties.displayed_period.is_period(): raise TimelineIOError(_("Displayed period must be > 0.")) self.displayed_period = view_properties.displayed_period self._hidden_category_ids = [] for cat in self.get_categories(): if not view_properties.is_category_visible(cat): self._hidden_category_ids.append(cat.id) self._save()
def read_first_line(path): try: f = open(path) try: line = f.readline() return line finally: f.close() except IOError: raise TimelineIOError("Unable to read data from '%s'." % path)
def db_open_ics(path): try: import icalendar from timelinelib.wxgui.dialogs.importics.view import ImportIcsDialog except ImportError: raise TimelineIOError( _("Could not find iCalendar Python package. It is required for working with ICS files." )) else: from timelinelib.dataimport.ics import import_db_from_ics return import_db_from_ics(path, ImportIcsDialog)
def _read_file_content(self, path): ics_file = None try: ics_file = open(path, "rb") return ics_file.read() except IOError as e: msg = _("Unable to read from file '%s'.") whole_msg = (msg + "\n\n%s") % (abspath(path), e) raise TimelineIOError(whole_msg) finally: if ics_file is not None: ics_file.close()
def delete_category(self, category_or_id): try: if isinstance(category_or_id, Category): category = category_or_id else: with self._query() as query: category = query.get_category(category_or_id) if category.id in self._hidden_category_ids: self._hidden_category_ids.remove(category.id) category.db = self category.delete() except Exception as e: raise TimelineIOError("Deleting category failed: %s" % e)
def _load(self): try: # _parse_version will create the rest of the schema dynamically partial_schema = Tag("timeline", SINGLE, None, [Tag("version", SINGLE, self._parse_version)]) tmp_dict = { "partial_schema": partial_schema, "category_map": {}, "hidden_categories": [], } parse(self.path, partial_schema, tmp_dict) except Exception as e: msg = _("Unable to read timeline data from '%s'.") whole_msg = (msg + "\n\n%s") % (abspath(self.path), ex_msg(e)) raise TimelineIOError(whole_msg)
def _load(db, dir_path): """ Load timeline data from the given directory. Each filename inside the directory (at any level) becomes an event where the text is the filename name and the time is the modification time for the filename. For each sub-directory a category is created and all events (files) belong the category (directory) in which they are. """ if not os.path.exists(dir_path): # Nothing to load return if not os.path.isdir(dir_path): # Nothing to load return try: color_ranges = {} # Used to color categories color_ranges[dir_path] = (0.0, 1.0, 1.0) all_cats = [] parents = {} for (dirpath, dirnames, filenames) in os.walk(dir_path): # Assign color ranges (rstart, rend, b) = color_ranges[dirpath] step = (rend - rstart) / (len(dirnames) + 1) next_start = rstart + step new_b = b - 0.2 if new_b < 0: new_b = 0 for dirname in dirnames: next_end = next_start + step color_ranges[os.path.join(dirpath, dirname)] = (next_start, next_end, new_b) next_start = next_end # Create the stuff p = parents.get(os.path.normpath(os.path.join(dirpath, "..")), None) cat = Category().update(dirpath, (233, 233, 233), None, parent=p) parents[os.path.normpath(dirpath)] = cat all_cats.append(cat) db.save_category(cat) for filename in filenames: path_inner = os.path.join(dirpath, filename) evt = _event_from_path(db, path_inner) db.save_event(evt) # Hide all categories but the first db.set_hidden_categories(all_cats[1:]) # Set colors and change names used_names = [] for cat in db.get_categories(): cat.color = _color_from_range(color_ranges[cat.name]) cat.name = get_unique_cat_name(os.path.basename(cat.name), used_names) db.save_category(cat) except Exception as e: msg = _("Unable to read from filename '%s'.") % dir_path whole_msg = "%s\n\n%s" % (msg, e) print(whole_msg) raise TimelineIOError(whole_msg)
def save_category(self, category): try: category.db = self category.save() except Exception as e: raise TimelineIOError("Saving category failed: %s" % e)
def delete_era(self, era): try: era.db = self era.delete() except Exception as e: raise TimelineIOError("Deleting Era failed: %s" % e)
def save_era(self, era): try: era.db = self era.save() except Exception as e: raise TimelineIOError("Saving Era failed: %s" % e)
def raise_error(specific_msg, cause_exception): err_general = _("Unable to save timeline data to '%s'. File left unmodified.") % path err_template = "%s\n\n%%s\n\n%%s" % err_general raise TimelineIOError(err_template % (to_unicode(specific_msg), to_unicode(cause_exception)))