# -*- coding: utf-8 -*- """This module globally bundles some utility functions for my ctdo plugins""" from sys import maxint from datetime import datetime, date, time from trac.util.datefmt import utc, timezone from re import match from trac.wiki import WikiPage from trac.web.chrome import ITemplateProvider from trac.core import Component, implements, TracError class CTDOTools(Component): implements(ITemplateProvider) # ITemplateProvider methods def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] def get_htdocs_dirs(self): """Return a list of directories with static resources (such as style sheets, images, etc.) Each item in the list must be a `(prefix, abspath)` tuple. The `prefix` part defines the path in the URL that requests to these resources are prefixed with. The `abspath` is the absolute path to the directory containing the resources on the local file system. """ from pkg_resources import resource_filename return [('hw', resource_filename(__name__, 'htdocs'))] class ValidationError(ValueError): """simple exception class""" def __str__(self): return "ValidationError: value out of bounds!" def validate_id(value): """type and range check""" if (0 > int(value) > maxint): raise ValidationError("invalid argument") def validate_email(addr): """validates email against rfc822""" rfc822_specials = '()<>@,;:\\"[]' # First we validate the name portion (name@domain) mychar = 0 while mychar < len(addr): if addr[mychar] == '"' and ( not mychar or addr[mychar - 1] == '.' or addr[mychar - 1] == '"'): mychar = mychar + 1 while mychar < len(addr): if addr[mychar] == '"': break if addr[mychar] == '\\' and addr[mychar + 1] == ' ': mychar += 2 continue if ord(addr[mychar]) < 32 or ord(addr[mychar]) >= 127: return 0 mychar += 1 else: return False if addr[mychar] == '@': break if addr[mychar] != '.': return False mychar += 1 continue if addr[mychar] == '@': break if ord(addr[mychar]) <= 32 or ord(addr[mychar]) >= 127: return False if addr[mychar] in rfc822_specials: return False mychar += 1 if not mychar or addr[mychar - 1] == '.': return False # Next we validate the domain portion (name@domain) domain = mychar = mychar + 1 if domain >= len(addr): return False count = 0 while mychar < len(addr): if addr[mychar] == '.': if mychar == domain or addr[mychar - 1] == '.': return False count += 1 if ord(addr[mychar]) <= 32 or ord(addr[mychar]) >= 127: return False if addr[mychar] in rfc822_specials: return False mychar += 1 return count >= 1 def gen_wiki_page(env, authname, page_name, content, remote_addr): """programatically creates a wiki page""" page = WikiPage(env) page.name = page_name page.version = 1 page.text = content page.save(authname, 'initially created by TracRendezVous', remote_addr) def date_cmp(left, right): """compares two dates""" if left.time_begin < right.time_begin: return -1 elif left.time_begin > right.time_begin: return 1 else: return 0 def date_parse(arg): """converts a date string of form dd.mm.yyyy into a datetime.date obj""" groups = match("^(\d{1,2}).(\d{1,2}).(\d{4})$", arg).groups() return date(int(groups[2]), int(groups[1]), int(groups[0])) def time_parse(arg): """converts a time string of form MM:HH into a datetime.time obj""" matched = match("^(\d{1,2}):(\d{1,2})$", arg).groups() return time(int(matched[0]), int(matched[1])) def datetime_parse(arg, tzinfo=utc): """converts a datetime string of form dd.mm.yyyy MM:HH into a localized datetime.datetime obj""" # get real tzinfo for the date taking dst into account astimezone = tzinfo.localize(datetime.strptime(arg, "%d.%m.%Y %H:%M")).astimezone(utc) return astimezone def get_tz(session_tzname): """returns the timezone name and the timezone of the actual trac session""" if session_tzname == 'UTC': selected_tz = utc else: try: selected_tz = timezone(session_tzname) except Exception: selected_tz = utc return session_tzname, selected_tz