Remove egenix-mx-base and replace it by python-dateutil
This commit is contained in:
1 parent
9a59d09556
commit
cae0a76a3d
16 files changed
+112
-63
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Remove egenix-mx-base and replace it by python-dateutil
|
||||
* Add cache to safe_eval
|
||||
* Rename HttpDaemon into XMLRPCDaemon
|
||||
* Improve TranslateFactory to fetch all translations for a report in one query
|
||||
|
||||
@@ -6,8 +6,8 @@ Prerequisites
|
||||
|
||||
* Python 2.4 or later (http://www.python.org/)
|
||||
* lxml (http://codespeak.net/lxml/)
|
||||
* egenix-mx-base (http://www.egenix.com/products/python/)
|
||||
* relatorio 0.2.0 or later (http://relatorio.openhex.org/)
|
||||
* python-dateutil (http://labix.org/python-dateutil)
|
||||
* Optional: psycopg 2 or later (http://www.initd.org/)
|
||||
* Optional: pywebdav 0.9.3 or later (http://code.google.com/p/pywebdav/)
|
||||
* Optional: pydot (http://code.google.com/p/pydot/)
|
||||
|
||||
@@ -43,9 +43,9 @@ setup(name=PACKAGE,
|
||||
license=LICENSE,
|
||||
install_requires=[
|
||||
'lxml',
|
||||
'egenix-mx-base',
|
||||
'relatorio >= 0.2.0',
|
||||
'Genshi',
|
||||
'python-dateutil',
|
||||
],
|
||||
extras_require={
|
||||
'PostgreSQL': ['psycopg2 >= 2.0'],
|
||||
|
||||
@@ -7,9 +7,9 @@ from trytond.session import Session
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import mx.DateTime
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
import time
|
||||
|
||||
_FIX_ROWCOUNT = False
|
||||
try:
|
||||
@@ -35,37 +35,37 @@ def extract(lookup_type, date):
|
||||
hours, minutes, seconds = map(int, timepart_full[0].split(":"))
|
||||
if len(timepart_full) == 2:
|
||||
microseconds = int(timepart_full[1])
|
||||
seconds += microseconds / 1000000.0
|
||||
date = mx.DateTime.DateTime(year, month, day, hours, minutes, seconds)
|
||||
date = datetime.datetime(year, month, day, hours, minutes, seconds,
|
||||
microseconds)
|
||||
except:
|
||||
return None
|
||||
if lookup_type.lower() == 'century':
|
||||
return date.year / 100 + (date.year % 100 and 1 or 0)
|
||||
elif lookup_type.lower() == 'decade':
|
||||
return date.year.year / 10
|
||||
return date.year / 10
|
||||
elif lookup_type.lower() == 'dow':
|
||||
return (date.weekday() + 1) % 7
|
||||
elif lookup_type.lower() == 'doy':
|
||||
return date.day_of_year
|
||||
return date.timetuple().tm_yday
|
||||
elif lookup_type.lower() == 'epoch':
|
||||
return date.ticks()
|
||||
return int(time.mktime(date.timetuple()))
|
||||
elif lookup_type.lower() == 'microseconds':
|
||||
return int(a.second * 1000000)
|
||||
return date.microsecond
|
||||
elif lookup_type.lower() == 'millennium':
|
||||
return date.year / 1000 + (date.year % 1000 and 1 or 0)
|
||||
elif lookup_type.lower() == 'milliseconds':
|
||||
return int(a.second * 1000)
|
||||
return a.microsecond / 1000
|
||||
elif lookup_type.lower() == 'quarter':
|
||||
return date.month / 4 + 1
|
||||
elif lookup_type.lower() == 'week':
|
||||
return date.iso_week[1]
|
||||
return date.isocalendar()[1]
|
||||
return getattr(date, lookup_type)
|
||||
|
||||
def date_trunc(_type, date):
|
||||
if _type == 'second':
|
||||
return date
|
||||
try:
|
||||
date = mx.DateTime.strptime(date, '%Y-%m-%d %H:%M:%S')
|
||||
time.strptime(date, '%Y-%m-%d %H:%M:%S')
|
||||
except:
|
||||
return None
|
||||
if _type == 'year':
|
||||
|
||||
+11
-14
@@ -11,18 +11,18 @@ SPEC: Execute "model.function(*eval(args))" periodically
|
||||
from trytond.backend import Database
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.tools import safe_eval
|
||||
from mx import DateTime
|
||||
import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
_INTERVALTYPES = {
|
||||
'work_days': lambda interval: DateTime.RelativeDateTime(days=interval),
|
||||
'days': lambda interval: DateTime.RelativeDateTime(days=interval),
|
||||
'hours': lambda interval: DateTime.RelativeDateTime(hours=interval),
|
||||
'weeks': lambda interval: DateTime.RelativeDateTime(days=7*interval),
|
||||
'months': lambda interval: DateTime.RelativeDateTime(months=interval),
|
||||
'minutes': lambda interval: DateTime.RelativeDateTime(minutes=interval),
|
||||
'work_days': lambda interval: relativedelta(days=interval),
|
||||
'days': lambda interval: relativedelta(days=interval),
|
||||
'hours': lambda interval: relativedelta(hours=interval),
|
||||
'weeks': lambda interval: relativedelta(weeks=interval),
|
||||
'months': lambda interval: relativedelta(months=interval),
|
||||
'minutes': lambda interval: relativedelta(minutes=interval),
|
||||
}
|
||||
|
||||
class Cron(ModelSQL, ModelView):
|
||||
@@ -147,7 +147,7 @@ class Cron(ModelSQL, ModelView):
|
||||
cursor.rollback()
|
||||
|
||||
def pool_jobs(self, db_name):
|
||||
now = DateTime.now()
|
||||
now = datetime.datetime.now()
|
||||
try:
|
||||
database = Database(db_name).connect()
|
||||
cursor = database.cursor()
|
||||
@@ -168,9 +168,7 @@ class Cron(ModelSQL, ModelView):
|
||||
for cron in crons:
|
||||
cursor.execute('UPDATE ir_cron SET running = %s ' \
|
||||
'WHERE id = %s', (True, cron['id']))
|
||||
nextcall = DateTime.strptime(
|
||||
cron['nextcall'].strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
nextcall = cron['nextcall']
|
||||
numbercall = cron['numbercall']
|
||||
done = False
|
||||
|
||||
@@ -191,9 +189,8 @@ class Cron(ModelSQL, ModelView):
|
||||
addsql_param = [False]
|
||||
cursor.execute("UPDATE ir_cron SET nextcall = %s, " \
|
||||
"running = %s, numbercall = %s" + addsql + " " \
|
||||
"WHERE id = %s",
|
||||
[nextcall.strftime('%Y-%m-%d %H:%M:%S'), False,
|
||||
numbercall] + addsql_param + [cron['id']])
|
||||
"WHERE id = %s", [nextcall, False, numbercall] \
|
||||
+ addsql_param + [cron['id']])
|
||||
cursor.commit()
|
||||
except Exception, e:
|
||||
cursor.rollback()
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.tools import Cache, safe_eval
|
||||
from decimal import Decimal
|
||||
import mx.DateTime
|
||||
import datetime
|
||||
import time
|
||||
|
||||
|
||||
class Default(ModelSQL, ModelView):
|
||||
@@ -59,15 +59,11 @@ class Default(ModelSQL, ModelView):
|
||||
elif default.field.ttype == 'numeric':
|
||||
res[default.field.name] = Decimal(default.value)
|
||||
elif default.field.ttype == 'date':
|
||||
date = mx.DateTime.strptime(default.value, '%Y-%m-%d')
|
||||
res[default.field.name] = datetime.date(date.year,
|
||||
date.month, date.day)
|
||||
res[default.field.name] = datetime.date(*time.strptime(
|
||||
default.value, '%Y-%m-%d')[:3])
|
||||
elif default.field.ttype == 'datetime':
|
||||
date = mx.DateTime.strptime(default.value,
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
res[default.field.name] = datetime.datetime(date.year,
|
||||
date.month, date.day, date.hour, date.minute,
|
||||
int(date.second))
|
||||
res[default.field.name] = datetime.datetime(*time.strptime(
|
||||
default.value, '%Y-%m-%d %H:%M:%S')[:6])
|
||||
else:
|
||||
res[default.field.name] = safe_eval(default.value)
|
||||
return res
|
||||
|
||||
+9
-8
@@ -3,7 +3,7 @@
|
||||
"Lang"
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.model.cacheable import Cacheable
|
||||
from trytond.tools import safe_eval
|
||||
from trytond.tools import safe_eval, datetime_strftime
|
||||
import time
|
||||
from time_locale import TIME_LOCALE
|
||||
|
||||
@@ -114,7 +114,7 @@ class Lang(ModelSQL, ModelView, Cacheable):
|
||||
'''
|
||||
for lang in self.browse(cursor, user, ids):
|
||||
try:
|
||||
time.strftime(lang.date, time.localtime())
|
||||
datetime_strftime(datetime.datetime.now(), lang.date)
|
||||
except:
|
||||
return False
|
||||
if '%Y' not in lang.date:
|
||||
@@ -326,20 +326,21 @@ class Lang(ModelSQL, ModelView, Cacheable):
|
||||
|
||||
return s.replace('<', '').replace('>', '')
|
||||
|
||||
def strftime(self, timetuple, code, format):
|
||||
def strftime(self, datetime, code, format):
|
||||
'''
|
||||
Convert timetuple to a string as specified by the format argument.
|
||||
Convert datetime to a string as specified by the format argument.
|
||||
|
||||
:param timetuple: a tuple or struct_time representing a time
|
||||
:param datetime: a datetime
|
||||
:param code: locale code
|
||||
:param format: a string
|
||||
:return: a unicode string
|
||||
'''
|
||||
if code in TIME_LOCALE:
|
||||
for f, i in (('%a', 6), ('%A', 6), ('%b', 1), ('%B', 1)):
|
||||
format = format.replace(f, TIME_LOCALE[code][f][timetuple[i]])
|
||||
format = format.replace(f,
|
||||
TIME_LOCALE[code][f][datetime.timetuple()[i]])
|
||||
format = format.replace('%p', TIME_LOCALE[code]['%p']\
|
||||
[timetuple[3] < 12 and 0 or 1]).encode('utf-8')
|
||||
return time.strftime(format, timetuple).decode('utf-8')
|
||||
[datetime.timetuple()[3] < 12 and 0 or 1]).encode('utf-8')
|
||||
return datetime_strftime(datetime, format).decode('utf-8')
|
||||
|
||||
Lang()
|
||||
+2
-2
@@ -5,7 +5,7 @@ from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.tools import Cache
|
||||
from trytond.report import Report
|
||||
from trytond.wizard import Wizard
|
||||
import time
|
||||
import datetime
|
||||
import base64
|
||||
import re
|
||||
IDENTIFIER = re.compile(r'^[a-zA-z_][a-zA-Z0-9_]*$')
|
||||
@@ -320,7 +320,7 @@ class ModelData(ModelSQL, ModelView):
|
||||
]
|
||||
|
||||
def default_date_init(self, cursor, user, context=None):
|
||||
return time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
return datetime.datetime.now()
|
||||
|
||||
def default_inherit(self, cursor, user, context=None):
|
||||
return False
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import time
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from string import Template
|
||||
import datetime
|
||||
from trytond.tools import datetime_strftime
|
||||
|
||||
|
||||
class SequenceType(ModelSQL, ModelView):
|
||||
@@ -82,9 +82,9 @@ class Sequence(ModelSQL, ModelView):
|
||||
date_obj = self.pool.get('ir.date')
|
||||
if not date:
|
||||
date = date_obj.today(cursor, user, context=context)
|
||||
year = date.strftime('%Y')
|
||||
month = date.strftime('%m')
|
||||
day = date.strftime('%d')
|
||||
year = datetime_strftime(date, '%Y')
|
||||
month = datetime_strftime(date, '%m')
|
||||
day = datetime_strftime(date, '%d')
|
||||
return Template(string or '').substitute(
|
||||
year=year,
|
||||
month=month,
|
||||
|
||||
@@ -28,7 +28,6 @@ import traceback
|
||||
from trytond.config import CONFIG
|
||||
from trytond.backend import DatabaseIntegrityError
|
||||
import inspect
|
||||
import mx.DateTime
|
||||
import logging
|
||||
|
||||
PARENTS = {
|
||||
@@ -311,10 +310,11 @@ class Report(object):
|
||||
value = str(value)[:19]
|
||||
locale_format = locale_format + ' %H:%M:%S'
|
||||
string_pattern = '%Y-%m-%d %H:%M:%S'
|
||||
date = mx.DateTime.strptime(str(value), string_pattern)
|
||||
date = datetime.datetime(*time.strptime(str(value),
|
||||
string_pattern)[:6])
|
||||
else:
|
||||
date = mx.DateTime.DateTime(*(value.timetuple()[:6]))
|
||||
return lang_obj.strftime(date.tuple(), code, locale_format)
|
||||
date = datetime.datetime(*(value.timetuple()[:6]))
|
||||
return lang_obj.strftime(date, code, locale_format)
|
||||
if currency:
|
||||
return lang_obj.currency(lang, value, currency, grouping=grouping)
|
||||
return lang_obj.format(lang, '%.' + str(digits) + 'f', value,
|
||||
|
||||
@@ -118,7 +118,7 @@ class Request(ModelSQL, ModelView):
|
||||
request_history_obj.create(cursor, user, values, context=context)
|
||||
self.write(cursor, user, ids, {
|
||||
'state': 'waiting',
|
||||
'date_send': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_send': datetime.datetime.now(),
|
||||
}, context=context)
|
||||
return True
|
||||
|
||||
|
||||
@@ -11,12 +11,6 @@ import logging.handlers
|
||||
import sys, os, signal
|
||||
import time
|
||||
from config import CONFIG
|
||||
import mx.DateTime
|
||||
|
||||
if not hasattr(mx.DateTime, 'strptime'):
|
||||
mx.DateTime.strptime = lambda x, y: mx.DateTime.mktime(
|
||||
time.strptime(x, y))
|
||||
|
||||
from getpass import getpass
|
||||
try:
|
||||
import hashlib
|
||||
|
||||
@@ -13,7 +13,7 @@ import unittest
|
||||
import time
|
||||
from decimal import Decimal
|
||||
from trytond import pysocket
|
||||
from trytond.tools import reduce_ids, safe_eval
|
||||
from trytond.tools import reduce_ids, safe_eval, datetime_strftime
|
||||
from lxml import etree
|
||||
import datetime
|
||||
|
||||
@@ -130,6 +130,15 @@ class ToolsTestCase(unittest.TestCase):
|
||||
self.assertRaises(Exception, safe_eval,
|
||||
"().__class__.mro()[1].__subclasses__()")
|
||||
|
||||
def test0070datetime_strftime(self):
|
||||
'''
|
||||
Test datetime_strftime
|
||||
'''
|
||||
self.assert_(datetime_strftime(datetime.date(2005, 3, 2),
|
||||
'%Y-%m-%d'), '2005-03-02')
|
||||
self.assert_(datetime_strftime(datetime.date(1805, 3, 2),
|
||||
'%Y-%m-%d'), '1805-03-02')
|
||||
|
||||
|
||||
class FieldsTestCase(unittest.TestCase):
|
||||
'''
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from misc import *
|
||||
from convert import *
|
||||
from datetime_strftime import *
|
||||
@@ -815,7 +815,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
'module': module,
|
||||
'db_id': db_id,
|
||||
'values': values,
|
||||
'date_update': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_update': datetime.datetime.now(),
|
||||
})
|
||||
for table, inherit_mdata_id in inherit_mdata_ids:
|
||||
self.modeldata_obj.write(cursor, user, inherit_mdata_id, {
|
||||
@@ -824,7 +824,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
'module': module,
|
||||
'db_id': inherit_db_ids[table],
|
||||
'values': values,
|
||||
'date_update': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_update': datetime.datetime.now(),
|
||||
})
|
||||
# reset_browsercord to keep cache memory low
|
||||
self.fs2db.reset_browsercord(module, object_ref._name, db_id)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
#Copyright (c) 2002-2007 John D. Hunter; All Rights Reserved
|
||||
import time
|
||||
|
||||
def datetime_strftime(dt, fmt):
|
||||
'''
|
||||
Allow datetime strftime formatting for years before 1900.
|
||||
See http://bugs.python.org/issue1777412
|
||||
'''
|
||||
if dt.year > 1900:
|
||||
return dt.strftime(fmt)
|
||||
|
||||
def _findall(text, substr):
|
||||
# Also finds overlaps
|
||||
sites = []
|
||||
i = 0
|
||||
while True:
|
||||
j = text.find(substr, i)
|
||||
if j == -1:
|
||||
break
|
||||
sites.append(j)
|
||||
i = j + 1
|
||||
return sites
|
||||
|
||||
year = dt.year
|
||||
# For every non-leap year century, advance by
|
||||
# 6 years to get into the 28-year repeat cycle
|
||||
delta = 2000 - year
|
||||
off = 6 * (delta // 100 + delta // 400)
|
||||
year = year + off
|
||||
# Move to around the year 2000
|
||||
year = year + ((2000 - year) // 28) * 28
|
||||
timetuple = dt.timetuple()
|
||||
s1 = time.strftime(fmt, (year,) + timetuple[1:])
|
||||
sites1 = _findall(s1, str(year))
|
||||
|
||||
s2 = time.strftime(fmt, (year + 28,) + timetuple[1:])
|
||||
sites2 = _findall(s2, str(year + 28))
|
||||
|
||||
sites = []
|
||||
for site in sites1:
|
||||
if site in sites2:
|
||||
sites.append(site)
|
||||
|
||||
s = s1
|
||||
syear = "%4d" % (dt.year,)
|
||||
for site in sites:
|
||||
s = s[:site] + syear + s[site+4:]
|
||||
return s
|
||||
Reference in new issue
Block a user