Usuari:TronaBot/Python/common.py
< Usuari:TronaBot | Python
#!/usr/bin/python2.7
#-*- coding:utf8 -*-
#
# Copyrleft (!C) 2013 Coet@cawiki
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
u"""
Funcions comunes per als scripts pywikimedia en català.
Empre pywikimedia i pywikilib en lloc de pywikipedia per considerar
injusta la tercera ja que exclou els altres projectes germans.
--Coet 2013-03-22_21:47:17
"""
import argparse, bz2, codecs as cs, difflib, json, locale, os, pickle
import re, shlex, sys, time
from platform import system as platfsys
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta as rdelta, SU
from math import floor
on_win = platfsys().lower() == "windows"
#l'arquitectura que he creat per als meus scripts és ficar una carpeta
#al mateix nivell que la carpeta del pywikimedia, així que he de
#carregar els mòduls amb les següents línies.
home = on_win and r"E:\\iShare\SugarSync\My Python scripts" \
or "/home/pasqual/public_html/"
for folder in ("pywikilib", "pyuserlib"):
sys.path.append(os.path.join(home, folder))
#from pywikipedia
import query as api, wikipedia as pywikilib, pagegenerators as pg, config as cfg
class File(object):
def __init__(self, fname, pref=False, timestamp=False, path=None, sep="-", ext=None):
if pref is True: pref = "llista1000_llista{sep}".format(sep=sep)
elif pref is False: pref=""
else: pref = "{pref}{sep}".format(pref=pref, sep=sep)
self._filename = "{pref}{name}{suff}{ext}".format(
pref=pref,
name= fname,
suff= timestamp and time.strftime("_%y%m%d_%H%M%S") or "",
ext= ext and ".%s" % ext or ".log"
)
self._path = path or os.path.join(home, "pywikilab", "logs")
self._fullname = os.path.join(self._path, self._filename)
#file info
def exists(self):
return os.path.exists(self._fullname)
def size(self):
return os.path.getsize(self._fullname)
def mtime(self):
return datetime.fromtimestamp(os.path.getmtime(self._fullname)).strftime("%Y-%m-%d %H:%M:%S") #last modified
def atime(self):
return datetime.fromtimestamp(os.path.getatime(self._fullname)).strftime("%Y-%m-%d %H:%M:%S") #last access
def ctime(self):
return datetime.fromtimestamp(os.path.getctime(self._fullname)).strftime("%Y-%m-%d %H:%M:%S") #last change
#data methods
def backup(self, data):
"""
use this method to save data as an object and recover
this with load() method"""
f = cs.open(self._fullname, "w", "utf8")
pywikilib.query.json.dump(data, f, indent=4, encoding="utf8")
f.close()
def load(self):
"""data recover"""
f = cs.open(self._fullname, "r", "utf8")
data = pywikilib.query.json.load(f, encoding="utf8")
f.close()
return data
#binary files
def quick_read(self):
stream = bz2.BZ2File(self._fullname, 'r')
obj = pickle.load(stream)
stream.close()
return obj
def quick_write(self, obj):
stream = bz2.BZ2File(self._fullname, 'w')
pickle.dump(obj, stream, protocol=pickle.HIGHEST_PROTOCOL)
stream.close()
#flash instances
def read(self):
"""read a text file and return its content"""
if not self.exists():
return ""
f = cs.open(self._fullname, "r", "utf8")
data = f.read()
f.close()
return data
def read_lines(self):
"""read a text file and return its content splitted by new line characters"""
#f.readlines() keeps the new line char,
#I prefer data.splitlines() after data=f.read().
data = self.read()
return data.splitlines()
def save(self, data):
"""overwrite a text file"""
f = cs.open(self._fullname, "w", "utf8")
data = f.write(data)
f.close()
def prepend(self, data):
"""prepend text before the content of a text file"""
old_data = self.read()
new_data = "%s\n%s" % (new_data, old_data)
self.save(new_data)
def append(self, new_data):
"""append text after the content of a text file"""
if not new_data.startswith("\n"):new_data = "\n%s" % new_data
old_data = self.read()
self.save("%s%s" % (old_data, new_data))
def open(self):
if not on_win: return
#Only available on windows.
os.startfile(self._fullname)
#streaming methods
def prepare(self):
self._stream = cs.open(self._fullname, "w", "utf8")
def flush(self):
self._stream.flush()
def write(self, string):
self._stream.write(string)
def write_line(self, line="", newlineb4=False):
if newlineb4: line = "\n%s" % line
if not newlineb4 and not line.endswith("\n"): line = "%s\n" % line
self._stream.write(line)
def close(self):
self._stream.close()
class Chrono(object):
def __init__(self):
self.start_time = datetime.now()
self.lapses=[]
def to_string(self, et):
eltime = et.years, et.months, et.days, et.hours, et.minutes, et.seconds, et.microseconds
units = ('year', 'months', 'day', 'hour', 'minute', "second", "microsecond")
parts = ['%d %s%s' % (quant, unit, ('', 's')[quant > 1]) for quant, unit in zip(eltime, units) if quant]
return ' and '.join(c for c in [', '.join(parts[:-1]), parts[-1]] if c)
def pause(self):
self.lapses.append(datetime.now())
return len(self.lapses)-1
def elapsed(self, lapseid=None):
lapseid = lapseid and self.lapses[lapseid]
elapsed = time_diff(lapseid or datetime.now(), self.start_time)
print "elapsed time:", self.to_string(elapsed)
def running_time(self):
td = rdelta(datetime.now(), self.start_time)
self.years = td.years
self.months = td.months
self.days = td.days
self.hours = td.hours
self.minutes = td.minutes
self.seconds = td.seconds
self.microseconds = td.microseconds
def stop(self):
stop_time = datetime.now()
elapsed = rdelta(stop_time, self.start_time)
return (
u"began at: %s\nended at:%s\nelapsed time: %s" % (
yellow(self.start_time.strftime("%H:%M:%S")),
purple(stop_time.strftime("%H:%M:%S")),
self.to_string(elapsed)
)
)
class DateFormatError:
"""Error unknow format for the given date."""
class Date(object):
"""
This class pretends to convert any expression to a valid datetime class.
There are several formats and types to realize it:
* A string in different formats:
- 2013-12-03 21:34
- 2013-12-03 21:34:56
- 2013-12-03T21:34:57Z
- 2013/12/03 21:34
- 2013/12/03 21:34:56
- ...
* A time.struct_time object
* A tuple or list
- 3-tuple/list as a datetime/date object
- between 7 and 3 tuple/list as a datetime object
* A datetime object
* A float will be treated as a timestamp
* An integer will be treated as a ordinal
"""
def __init__(self, obj=None):
locale.setlocale(locale.LC_TIME, on_win and "Catalan_Spain.1252" or "ca_ES")
self._obj = None
if not obj:
self._obj = datetime.now()
if isinstance(obj, basestring):
obj = obj.replace("/","-")
date_fmt = {
#2013-03-23 20:24
"\d{4}[/-][0-3]?\d?[/-]\d\d? (?:2[0-3]|[01]?\d):[0-5]?\d": "%Y-%m-%d %H:%M",
#2013-03-23 20:24:45
"\d{4}[/-][0-3]?\d?[/-]\d\d? (?:2[0-3]|[01]?\d):[0-5]?\d:[0-5]?\d": "%Y-%m-%d %H:%M:%S",
#2013-03-23T20:24:45Z
"\d{4}[/-][0-3]\d[/-]\d\dT(?:2[0-3]|[01]\d):[0-5]?\d:[0-5]?\dZ": "%Y-%m-%dT%H:%M:%SZ",
#11:58, 27 març 2010
ur"(?:2[0-3]|[01]?\d):[0-5]?\d, [1-3]?\d \w{2,4} \d{4}": u"%H:%M, %d %b %Y",
#27 març 2010
ur"[1-3]?\d \w{3,4} \d{4}": u"%d %b %Y",
#2013-03-23
"\d{4}-[0-3]?\d-\d?\d": "%Y-%m-%d",
#2013-03-23 20:24
"\d{4}-\d?\d-[0-3]?\d? (?:2[0-3]|[01]?\d):[0-5]?\d": "%Y-%m-%d %H:%M",
}
for key in date_fmt:
if re.match(key, obj, re.U):
self._obj = datetime.strptime(obj.encode("cp1252"), date_fmt[key])
break
elif isinstance(obj, time.struct_time):
self._obj = datetime.fromtimestamp(time.mktime(obj))
elif isinstance(obj, (list, tuple)):
if 7>=len(tpl)>=3:
self._obj = datetime(*obj)
elif len(tpl)==9:
self._obj = datetime.fromtimestamp(time.mktime(obj))
elif isinstance(obj, datetime):
self._obj = obj
elif isinstance(obj, float):
self._obj = datetime.fromtimestamp(obj)
elif isinstance(obj, int):
self._obj = datetime.fromordinal(obj)
if not self._obj: raise DateFormatError
t = self._obj.timetuple()
self.year = t.tm_year
self.month = t.tm_mon
self.day = t.tm_mday
self.hour = t.tm_hour
self.min = t.tm_min
self.sec = t.tm_sec
self.weekday = t.tm_wday
self.yearday = t.tm_yday
self.isdst = t.tm_isdst
self.weeknum = int(self._obj.strftime("%W"))
def __sub__(self, other):
if isinstance(self._obj, datetime) and isinstance(other, (timedelta, rdelta)):
if isinstance(other, timedelta):
return self._obj - other
elif isinstance(other, rdelta):
return self._obj - other
dates = sorted([self._obj, other._obj])
return dates[1] - dates[0]
def __add__(self, other):
if isinstance(self._obj, datetime) and isinstance(other, (timedelta, rdelta)):
if isinstance(other, timedelta):
return self._obj + other
elif isinstance(other, rdelta):
return self._obj + other
return self._obj + other._obj
def __call__(self):
return self._obj
def time_diff(self, other=None):
if not other:
other = Date()
elif not isinstance(other, datetime):
other = Date()
dates = sorted([self._obj, other._obj])
return rdelta(dates[1], dates[0])
def time_delta(self):
return time_diff(self._obj)
def local_month(self):
return self._obj.strftime("%B")
def short_local_month(self):
return self._obj.strftime("%b")
def local_weekday(self):
return self._obj.strftime("%A")
def short_local_weekday(self):
return self._obj.strftime("%a")
def local_time(self):
return self._obj.strftime("%X")
def local_date(self):
return self._obj.strftime("%x")
def weeknum(self):
#Week number of the year
return self._obj.strftime("%W")
def to_datetime(self):
return self._obj
def to_tuple(self):
t = self._obj.timetuple()
return t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_wday, t.tm_yday, t.tm_isdst
def to_time_struct(self):
"""time.struct_time(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)"""
return self._obj.timetuple()
def to_timestamp(self):
"""Unix timestamp"""
return time.mktime(self._obj.timetuple())
def to_ordinal(self):
return self._obj.toordinal()
def to_cest(self):
begin = datetime.now()+rdelta(weekday=SU(-1), day=31, month=3, hour=2, minute=0, second=0)
end = datetime.now()+rdelta(weekday=SU(-1), day=31, month=10, hour=3, minute=0, second=0)
if self._obj > begin and self._obj < end: return self._obj+rdelta(hours=2)
else: return self._obj+rdelta(hours=1)
def to_api(self):
return self._obj.strftime("%Y-%m-%dT%H:%M:%SZ")
def to_long_string(self):
day = int(self._obj.strftime("%d"))
art = "l'" if day in (1,11) else "el "
prep = "d'" if self.local_month()[0] in "ao" else "de "
return self._obj.strftime("{}%A {} {}%B del %Y a les %H:%M:%S".format(art, day, prep))
def to_short_string(self):
return self._obj.strftime("%Y-%m-%d %H:%M")
def substract(self, **kwargs):
return self._obj - timedelta(**kwargs)
def add(self, **kwargs):
return self._obj + timedelta(**kwargs)
def replace(self, **kwargs):
return self._obj.replace(**kwargs)
def time_diff(td):
#get the object and returns also hours, minutes and seconds
#by accessing to .seconds atribute.
td = Date(time.time())-Date(td)
hours, remainder = divmod(td.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return td.days, hours, minutes, seconds, td.microseconds
class List(object):
def __init__(self, _list):
self._list = _list
self._sorting_pairs = {
u"àáâäãăǎąåā": "a", u'æǣ': "ae",
u'ḃɓ': "b",
u'çćčćĉċ': "c",
u'đḍďḋ': "d", u"ð": "dz",
u'èéêëẽēę': "e",
u'ḟƒ': "f",
u'ĝġģğ': "g",
u'ĥħ': "h",
u'ìíîïīį': "i", u'ij': "ij",
u'ĵ': "j",
u'ķ': "k",
u'ŀļḷḹľł': "l",
u'ñńň': "n",
u'òóôöõøōǫ': "o", u'œ': "oe",
u'ṗ': "p",
u'ŗřṛṝ': "r",
u'şṡšŝ': "s", u'ß': "sz",
u'ţṫṭ': "t", u'Þ': "tz",
u'ùúûüŭūų': "u",
u'ẁŵẅƿ': "w",
u'ýỳŷÿȳỹ': "y",
u'źžż': "z"
}
self._nakedletter_pairs = {
u"àáâäãăǎąåā": "a", u'æǣ': "ae",
u'ḃɓ': "b",
u'çćčćĉċ': "c",
u'đḍďḋð': "d",
u'èéêëẽēę': "e",
u'ḟƒ': "f",
u'ĝġģğ': "g",
u'ĥħ': "h",
u'ìíîïīį': "i", u'ij': "ij",
u'ĵ': "j",
u'ķ': "k",
u'ŀļḷḹľł': "l",
u'ñńň': "n",
u'òóôöõøōǫ': "o", u'œ': "oe",
u'ṗ': "p",
u'ŗřṛṝ': "r",
u'şṡšŝ': "s", u'ß': "sz",
u'ţṫṭ': "t", u'Þ': "th",
u'ùúûüŭūų': "u",
u'ẁŵẅƿ': "w",
u'ýỳŷÿȳỹ': "y",
u'źžż': "z"
}
def simplify_chars(self, word, sorting=True):
#simplifiquem els diacrítics per a l'ordre alfabètic
pairs = self._sorting_pairs if sorting else self._nakedletter_pairs
diacritics = "".join(pairs.keys())
word = word.lower()
for ch in word:
if ch in diacritics:
for keys in pairs:
if ch in keys:
word=word.replace(ch, pairs[keys])
break
word=word.replace(u"l·l","ll")
word = re.sub("\W","!", word)
return word
def sort_list(self):
#ordena una llista
simplifiedlist={}
for word in self._list:
simplifiedlist[self.simplify_chars(word)]=word
new_list=[]
for word in sorted(simplifiedlist.keys()):
new_list.append(simplifiedlist[word])
return new_list
#compat with old scripts
sort_list = lambda l: List(l).sort_list()
def get_diffs(new, old):
added=[]; removed=[]; kept=[]
for word in difflib.ndiff(old.split(), new.split()):
sign, word = word[0], word[2:]
if sign == "?": continue
elif sign == '+': added.append(word)
elif sign == '-': removed.append(word)
else: kept.append(word)
return added, removed, kept
def get_line_diffs(new, old):
"""returns added, removed, kept as tuple"""
added=[]; removed=[]; kept=[]
for line in difflib.ndiff(old.splitlines(), new.splitlines()):
sign, line = line[0], line[2:]
if sign == "?": continue
elif sign == "+": added.append(line)
elif sign == "-": removed.append(line)
else: kept.append(line)
return added, removed, kept
def printf(string, *args, **kwargs):
collect_args = re.findall("\$(\d+)(?:\[\d+\])??", string)
collect_kwargs = re.findall("\$(\D+)(?:\[\d+\])??", string)
string = re.sub(r"\$([^[.!: ]+(?:\[\d+\]|\.\w+)?(?:![sr])?(?::[\d,.><^=]+[bcdeEfFgGnosxX%])?)", r"{\1}", string)
print collect_args, collect_kwargs
args = list(args)
if args: args.insert(0,None)
if args and kwargs:
string = string.format(*args, **kwargs)
elif args:
string = string.format(*args)
elif kwargs:
string = string.format(**kwargs)
print string
#http://stackoverflow.com/a/10639990
def find_fixed_repeat(string, n):
l = len(string)
i = 0
while ((i + n -1) < l):
ss = string[i:i+n]
bb = string[i+n:]
try:
ff = bb.index(ss)
except:
ff = -1
if ff >= 0:
return ss;
i = i+1
return 0
def has_repeated_string(string):
rpt=False
for word in string.split():
if string.count(word)>1:
rpt=True
break
if not rpt:return False
n = len(string)
#find the maximum length of repeated string first
m = int(floor(n/2))
#start with maximum length
for i in range(m, 1, -1):
substr = find_fixed_repeat(string, i)
if substr:
return substr
return False
#01.05.2013
def decode(string):
try:
string = unicode(string, pywikilib.config.editor_encoding)
except:
pass
return string
format_color = lambda c, s: u"\3{light%s}%s\3{default}" % (c, s)
blue = lambda s: format_color("blue", s)
green = lambda s: format_color("green", s)
purple = lambda s: format_color("purple", s)
red = lambda s: format_color("red", s)
yellow = lambda s: format_color("yellow", s)
def format_string(string, *args, **kwargs):
"""
arguments:
arg number: $1 (for first arg)
arg name: $name
colors:
&b := lightblue
&g := lightgreen
&p := lightpurple
&r := lightred
&y := lightyellow
one word: &yword
more than one: &y(:word1 word2:)
Return a unicode object.
Complex formatting must use {}.
"""
#decoding to unicode each part of the string
string = decode(string)
args = [decode(arg) for arg in args]
kwargs = dict([(kwarg, decode(kwargs[kwarg])) for kwarg in kwargs])
#replacing template
if (args or kwargs) and re.search(r"\$[\d\w]+", string):
parsed_args = re.findall(r"\$([\d]+)", string)
parsed_kwargs = re.findall(r"\$([a-z]\w*)", string)
for arg in parsed_args:
index = int(arg)-1
if index > len(args) or index == -1:
continue
string = re.sub(r"\$(%s)" % arg, r"{%i}" % index, string)
for arg in parsed_kwargs:
if kwargs.has_key(arg):
string = re.sub(r"\$(%s)" % arg, r"{\1}", string)
string = string.format(*args, **kwargs)
#converting coloured string s for wikipedia.output() strings.
if re.search("&[bgpry]", string):
clr_str = re.finditer(r"(?P<replace>&(?P<color>[bgpry])(?:\(:(?P<string>[^:]+?):\)|(?P<word>[^\b]+?(?:\b|$))))", string)
for item in clr_str:
expr = item.group("string") or item.group("word")
if item.group("color") == "b":
string = string.replace(item.group("replace"), blue(expr))
elif item.group("color") == "g":
string = string.replace(item.group("replace"), green(expr))
elif item.group("color") == "p":
string = string.replace(item.group("replace"), purple(expr))
elif item.group("color") == "r":
string = string.replace(item.group("replace"), red(expr))
elif item.group("color") == "y":
string = string.replace(item.group("replace"), yellow(expr))
return string
class ArgumentHandler:
def __init__(self):
"""This class pretends to be a little string parser with many particularities.
programm.py string1 string2 -arg1 -arg2:string3 -arg3:3 -arg4:$4 -arg5:$$5 -arg6:A -arg6:B "string 4" -!arg7
the line above gives the following results:
args = ArgumentHandler()
args.parse_arguments()
args.positionals = ["string1", "string2", "string 4"]
args.arg1 -> True
args.arg2 -> "string3"
args.arg3 -> 3
args.arg4 -> "4"
args.arg5 -> "$5"
args.arg6 -> ["A", "B"]
args.arg7 -> False
args.arg8 -> False (not wrote in the command line)
"""
#01.05.2013
self.positional = []
self.optional = {}
self.raw = None
self._sep = ","
self._sh_delim = "-"
self._lng_delim = "--"
self._string_sign = "$"
self._digit_sign = "#"
self._param_sign = "+"
def __getattr__(self, attr, value=False):
if hasattr(self, attr):
return getattr(self, attr, value)
else:
setattr(self, attr, value)
return getattr(self, attr, value)
def __repr__(self):
return "<%s.%s>\n\tpositional: %r\n\toptional: %r" % (
self.__module__, self.__class__.__name__, self.positional, self.optional
)
def __str__(self):
return "<%s.%s>\n\tpositional: %r\n\toptional: %r" % (
self.__module__, self.__class__.__name__, self.positional, self.optional
)
def set_parameter(self, *aliases, **keywords):
param={}
aliases=list(aliases)
name =""
for alias in aliases:
if alias.startswith("--"):
name = alias[2:]
aliases.remove(alias)
break
if not name and len(aliases)>0:
name = aliases[0]
if name.startswith("-"):name=name.split("-",1)[1]
for alias in list(aliases):
if alias.startswith("-"):
aliases.remove(alias)
aliases.append(alias[1:])
dico = {
"name": name,
"aliases": aliases,
"choice": [],
"type": type,
"nargs": 0,
"default": True,
"required": False,
}
for keyword, value in keywords.items():
if dico.has_key(keyword):
if isinstance(value, basestring) and value.isdigit():value=int(value)
dico[keyword]=value
setattr(self, name, dico)
def parse_as_unix(self, cmd_line=None):
arguments = [] #unnamed parameters /GNU positional arg
options = {} #named parameters /GNU optional arg
action=""
stack=[]
last_option=""
if not cmd_line:
cmd_line = sys.argv[1:]
elif isinstance(cmd_line, basestring):
cmd_line = shlex.split(cmd_line)
keys=[]
print "****** OK *******"
print vars(self).items()
for k, v in vars(self).items() :
print k, v
if isinstance(v, dict):
print v
keys.append((k, v['aliases']))
keys = [(k,v['aliases']) ]
for arg in cmd_line:
if arg.startswith("--"):
if arg[2]=="!":
arg = arg[3:]
options[arg] = False
else:
arg = arg[2:]
options[arg] = True
last_option=arg
elif arg.startswith("-"):
arg = arg[1:]
value = False if arg.startswith("!") else True
arg = arg[1:] if value == False else arg
for a in arg:
options[a]=value
last_option = a if len(arg)==1 else ""
else:
stack.append((last_option, arg))
for key, value in list(stack):
if isinstance(getattr(self, key), dict):
#option was defined with .set_parameter()
if getattr(self, key)["nargs"]>0:
limit = getattr(self, key)["nargs"]
if options.has_key(key):
if isinstance(options[key], bool):
options[key]=[value]
elif len(options[key])<limit:
options[key].append(value)
else:
arguments.append(value)
stack.remove((key,value))
elif options.has_key(key):
if isinstance(options[key], bool):
options[key]=[value]
else:
arguments.append(value)
stack.remove((key,value))
else:
arguments.append(value)
stack.remove((key, value))
for keyword in options:
setattr(self, keyword, options[keyword])
for k,v in vars(self).items():
if isinstance(v, dict) and v.has_key("name"):
if isinstance(v['nargs'], int):
if isinstance(v['default'], (tuple, list)) and len (v['default']) != v['nargs']:
v['default']= (","*v['nargs']).split(",")
setattr(self, k, v['default'])
self._optional = options
self._stack = stack
self._action = action
self.positional = arguments
return [(k,v) for k,v in vars(self).items() if not k.startswith("_")]
def parse_arguments(self, line=None):
if not line:
args = self.raw = pywikilib.handleArgs()
else:
args = self.raw = pywikilib.handleArgs(shlex.split(line))
for arg in args:
option="";idx=0
if arg.startswith("-"):
option = arg.split("-",1)[1].split(":",1)[0]
value = arg[len(option)+2:]
if value:
if not self.optional.has_key(option):
self.optional[option]=[]
self.optional[option].append(value)
else:
self.optional[option]=True
else:
self.positional.append(arg)
for option in self.optional.copy():
if isinstance(self.optional[option], bool) and option.startswith("!"):
# -!opt -> args.opt == False
self.optional.pop(option)
option = option[1:]
self.optional[option]=False
if isinstance(self.optional[option], list) and len(self.optional[option])==1:
#convert a 1-element-list to a simple basestring
self.optional[option]=decode(self.optional[option][0])
elif isinstance(self.optional[option], list) and len(self.optional[option])==0:
#convert an empty list to None
self.optional[option]=None
if isinstance(self.optional[option], basestring) and self.optional[option].isdigit():
#convert a string to a integer
self.optional[option]=int(self.optional[option])
elif isinstance(self.optional[option], basestring) and self.optional[option].replace(".","").isdigit():
#convert a string to a float
self.optional[option]=float(self.optional[option])
elif isinstance(self.optional[option], basestring) and self.optional[option].startswith("$"):
#a number preceded by $ gives a number into a string.
self.optional[option]=self.optional[option].replace("$","",1)
setattr(self, option, self.optional[option])
if __name__ == '__main__':
locale.setlocale(locale.LC_TIME, on_win and "Catalan_Spain.1252" or "ca_ES")
date1=Date(datetime(2009,3,4))
date2=Date("23 abr 2009")
print date1-date2
print time_diff(date1.to_datetime())
printf("$3 $2 $1 $f", 1, 2, 3, f="4 5")
printf("$f", f="4 5")
fnc = lambda : x
fnc.t= "mmm"
coord=("leslie","luant","minut", .876)
printf("$1[0] $1[1] $1[2] $1[3]:0.2f $2.t", coord, fnc)
print Date().substract(hours=5)
print Date(Date().replace(hour=5,year=2001)).to_api()
print ", ".join([datetime.strftime(datetime.now().replace(month=i), "%b") for i in range(1,13)]).decode("cp1252")