diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py
index 27b68003aa2..7bb7d61d8ee 100644
--- a/addons/base_calendar/base_calendar.py
+++ b/addons/base_calendar/base_calendar.py
@@ -378,7 +378,6 @@ property or property parameter."),
}
_defaults = {
'state': 'needs-action',
- 'user_id': lambda self, cr, uid, ctx: uid,
'role': 'req-participant',
'rsvp': True,
'cutype': 'individual',
@@ -419,7 +418,11 @@ property or property parameter."),
event.add('location').value = event_obj.location
if event_obj.rrule:
event.add('rrule').value = event_obj.rrule
- if event_obj.user_id or event_obj.organizer_id:
+ if event_obj.organizer:
+ event_org = event.add('organizer')
+ event_org.params['CN'] = [event_obj.organizer]
+ event_org.value = 'MAILTO:' + (event_obj.organizer)
+ elif event_obj.user_id or event_obj.organizer_id:
event_org = event.add('organizer')
organizer = event_obj.organizer_id
if not organizer:
@@ -1111,6 +1114,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'vtimezone': fields.related('user_id', 'context_tz', type='char', size=24, \
string='Timezone', store=True),
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
+ 'organizer': fields.char("Organizer", size=256, states={'done': [('readonly', True)]}), # Map with Organizer Attribure of VEvent.
'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}),
'freq': fields.selection([('None', 'No Repeat'), \
('secondly', 'Secondly'), \
@@ -1147,6 +1151,14 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the event alarm information without removing it.")
}
+ def default_organizer(self, cr, uid, context=None):
+ user_pool = self.pool.get('res.users')
+ user = user_pool.browse(cr, uid, uid, context=context)
+ res = user.name
+ if user.user_email:
+ res += " <%s>" %(user.user_email)
+ return res
+
_defaults = {
'state': 'tentative',
'class': 'public',
@@ -1156,7 +1168,7 @@ true, it will allow you to hide the event alarm information without removing it.
'interval': 1,
'active': 1,
'user_id': lambda self, cr, uid, ctx: uid,
- 'organizer_id': lambda self, cr, uid, ctx: uid,
+ 'organizer': default_organizer,
}
def open_event(self, cr, uid, ids, context=None):
@@ -1199,33 +1211,6 @@ true, it will allow you to hide the event alarm information without removing it.
return value
- def modify_this(self, cr, uid, event_id, defaults, real_date, context=None, *args):
- """Modifies only one event record out of virtual recurrent events
- and creates new event as a specific instance of a Recurring Event",
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param event_id: Id of Recurring Event
- @param real_date: Date of event recurrence that is being modified
- @param context: A standard dictionary for contextual values
- @param *args: Get Tupple Value
- """
-
- event_id = base_calendar_id2real_id(event_id)
- datas = self.read(cr, uid, event_id, context=context)
- defaults.update({
- 'recurrent_uid': base_calendar_id2real_id(datas['id']),
- 'recurrent_id': defaults.get('date') or real_date,
- 'rrule_type': 'none',
- 'rrule': ''
- })
- exdate = datas['exdate'] and datas['exdate'].split(',') or []
- if real_date and defaults.get('date'):
- exdate.append(real_date)
- self.write(cr, uid, event_id, {'exdate': ','.join(exdate)}, context=context)
- new_id = self.copy(cr, uid, event_id, default=defaults, context=context)
- return new_id
-
def modify_all(self, cr, uid, event_ids, defaults, context=None, *args):
"""
Modifies the recurring event
@@ -1235,7 +1220,6 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: True
"""
-
for event_id in event_ids:
event_id = base_calendar_id2real_id(event_id)
@@ -1270,9 +1254,10 @@ true, it will allow you to hide the event alarm information without removing it.
else:
ids = select
result = []
+ recur_dict = []
if ids and (base_start_date or base_until_date):
- cr.execute("select m.id, m.rrule, m.date, m.date_deadline, \
- m.exdate, m.exrule from " + self._table + \
+ cr.execute("select m.id, m.rrule, m.date, m.date_deadline, m.duration, \
+ m.exdate, m.exrule, m.recurrent_id, m.recurrent_uid from " + self._table + \
" m where m.id in ("\
+ ','.join(map(lambda x: str(x), ids))+")")
@@ -1293,8 +1278,16 @@ true, it will allow you to hide the event alarm information without removing it.
if until_date and (event_date > until_date):
continue
idval = real_id2base_calendar_id(data['id'], data['date'])
- result.append(idval)
- count += 1
+ if not data['recurrent_id']:
+ result.append(idval)
+ count += 1
+ else:
+ ex_id = real_id2base_calendar_id(data['recurrent_uid'], data['recurrent_id'])
+ ls = base_calendar_id2real_id(ex_id, with_date=data and data.get('duration', 0) or 0)
+ if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
+ if ls[1] == data['recurrent_id']:
+ result.append(idval)
+ recur_dict.append(ex_id)
else:
exdate = data['exdate'] and data['exdate'].split(',') or []
rrule_str = data['rrule']
@@ -1329,7 +1322,7 @@ true, it will allow you to hide the event alarm information without removing it.
result.append(idval)
count += 1
if result:
- ids = result
+ ids = list(set(result)-set(recur_dict))
if isinstance(select, (str, int, long)):
return ids and ids[0] or False
return ids
@@ -1390,7 +1383,6 @@ true, it will allow you to hide the event alarm information without removing it.
return rrule_string
-
def search(self, cr, uid, args, offset=0, limit=100, order=None,
context=None, count=False):
"""
@@ -1424,8 +1416,6 @@ true, it will allow you to hide the event alarm information without removing it.
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
-
-
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
"""
Overrides orm write method.
@@ -1444,22 +1434,27 @@ true, it will allow you to hide the event alarm information without removing it.
else:
select = ids
new_ids = []
+ res = False
for event_id in select:
+ real_event_id = base_calendar_id2real_id(event_id)
if len(str(event_id).split('-')) > 1:
data = self.read(cr, uid, event_id, ['date', 'date_deadline', \
'rrule', 'duration'])
if data.get('rrule'):
- real_date = data.get('date')
- data.update(vals)
- new_id = self.modify_this(cr, uid, event_id, data, \
- real_date, context)
+ vals.update({
+ 'recurrent_uid': real_event_id,
+ 'recurrent_id': data.get('date'),
+ 'rrule_type': 'none',
+ 'rrule': ''
+ })
+ new_id = self.copy(cr, uid, real_event_id, default=vals, context=context)
context.update({'active_id': new_id, 'active_ids': [new_id]})
continue
- event_id = base_calendar_id2real_id(event_id)
- if not event_id in new_ids:
- new_ids.append(event_id)
+ if not real_event_id in new_ids:
+ new_ids.append(real_event_id)
- res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
+ if new_ids:
+ res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
if (vals.has_key('alarm_id') or vals.has_key('base_calendar_alarm_id'))\
or (vals.has_key('date') or vals.has_key('duration') or vals.has_key('date_deadline')):
# change alarm details
@@ -1559,13 +1554,12 @@ true, it will allow you to hide the event alarm information without removing it.
continue
event_id, date_new = event_id.split('-')
event_id = [int(event_id)]
- for record in self.read(cr, uid, event_id, ['date', 'rrule', 'exdate']):
+ for record in self.read(cr, uid, event_id, ['date', 'rrule', 'exdate'], context=context):
if record['rrule']:
# Remove one of the recurrent event
- date_new = time.strftime("%Y-%m-%d %H:%M:%S", \
+ date_new = time.strftime("%Y%m%dT%H%M%S", \
time.strptime(date_new, "%Y%m%d%H%M%S"))
- exdate = (record['exdate'] and (record['exdate'] + ',') or '') + ''.join((re.compile('\d')).findall(date_new)) + 'Z'
- res = self.write(cr, uid, event_id, {'exdate': exdate})
+ res = self.write(cr, uid, event_id, {'exdate': date_new})
else:
res = super(calendar_event, self).unlink(cr, uid, event_id)
self.pool.get('res.alarm').do_alarm_unlink(cr, uid, event_id, self._name)
diff --git a/addons/base_calendar/wizard/base_calendar_invite_attendee_view.xml b/addons/base_calendar/wizard/base_calendar_invite_attendee_view.xml
index bea5ea66a84..494787bbf97 100644
--- a/addons/base_calendar/wizard/base_calendar_invite_attendee_view.xml
+++ b/addons/base_calendar/wizard/base_calendar_invite_attendee_view.xml
@@ -10,6 +10,7 @@
form
+
+
+
+
+
+
+
+
+
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index 04bcd6eaa22..b4f7c03e5aa 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -83,7 +83,61 @@ def openobjectid2uid(cr, uidval, oomodel):
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
return value
-def get_attribute_mapping(cr, uid, calname, context={}):
+def mailto2str(arg):
+ """Take a dict of mail and convert to string.
+ """
+ ret = []
+ if isinstance(arg, dict):
+ args = [arg,]
+ else:
+ args = arg
+
+ for ard in args:
+ rstr = ard.get('name','')
+ if ard.get('company',False):
+ rstr += ' (%s)' % ard.get('company')
+ if ard.get('email'):
+ rstr += ' <%s>' % ard.get('email')
+ ret.append(rstr)
+ return ', '.join(ret)
+
+def str2mailto(emailstr, multi=False):
+ """Split one email string to a dict of name, company, mail parts
+
+ @param multi Return an array, recognize comma-sep
+ """
+ # TODO: move to tools or sth.
+ mege = re.compile(r'([^\(\<]+) *(\((.*?)\))? *(\< ?(.*?) ?\>)? ?(\((.*?)\))? *$')
+
+ mailz= [emailstr,]
+ retz = []
+ if multi:
+ mailz = emailstr.split(',')
+
+ for mas in mailz:
+ m = mege.match(mas.strip())
+ if not m:
+ # one of the rare non-matching strings is "sad" :(
+ # retz.append({ 'name': mas.strip() })
+ # continue
+ raise ValueError("Invalid email address %r" % mas)
+ rd = { 'name': m.group(1).strip(),
+ 'email': m.group(5), }
+ if m.group(2):
+ rd['company'] = m.group(3).strip()
+ elif m.group(6):
+ rd['company'] = m.group(7).strip()
+
+ if rd['name'].startswith('"') and rd['name'].endswith('"'):
+ rd['name'] = rd['name'][1:-1]
+ retz.append(rd)
+
+ if multi:
+ return retz
+ else:
+ return retz[0]
+
+def get_attribute_mapping(cr, uid, calname, context=None):
""" Attribute Mapping with Basic calendar fields and lines
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@@ -220,6 +274,10 @@ class CalDAV(object):
self.__attribute__[name][type] = None
return True
+ def format_date_tz(self, date, tz=None):
+ format = tools.DEFAULT_SERVER_DATETIME_FORMAT
+ return tools.server_to_local_timestamp(date, format, format, tz)
+
def parse_ics(self, cr, uid, child, cal_children=None, context=None):
""" parse calendaring and scheduling information
@param self: The object pointer
@@ -228,9 +286,16 @@ class CalDAV(object):
@param context: A standard dictionary for contextual values """
att_data = []
+ exdates = []
+ _server_tzinfo = pytz.timezone(tools.get_server_timezone())
+
for cal_data in child.getChildren():
if cal_data.name.lower() == 'organizer':
- self.ical_set(cal_data.name.lower(), {'name': cal_data.params.get('CN') and cal_data.params.get('CN')[0]}, 'value')
+ dmail = { 'name': cal_data.params.get('CN', ['',])[0],
+ 'email': cal_data.value.replace('MAILTO:',''),
+ # TODO: company?
+ }
+ self.ical_set(cal_data.name.lower(), mailto2str(dmail), 'value')
continue
if cal_data.name.lower() == 'attendee':
ctx = context.copy()
@@ -249,13 +314,20 @@ class CalDAV(object):
self.ical_set(cal_data.name.lower(), vals, 'value')
continue
if cal_data.name.lower() == 'exdate':
- exval = map(lambda x: str(x), cal_data.value)
- self.ical_set(cal_data.name.lower(), ','.join(exval), 'value')
+ exdates += cal_data.value
+ exvals = []
+ for exdate in exdates:
+ exvals.append(datetime.fromtimestamp(time.mktime(exdate.utctimetuple())).strftime('%Y%m%dT%H%M%S'))
+ self.ical_set(cal_data.name.lower(), ','.join(exvals), 'value')
continue
if cal_data.name.lower() in self.__attribute__:
-
if cal_data.params.get('X-VOBJ-ORIGINAL-TZID'):
- self.ical_set('vtimezone', cal_data.params.get('X-VOBJ-ORIGINAL-TZID'), 'value')
+ # since we do convert, do we also need to save the original tzid?
+ # self.ical_set('vtimezone', cal_data.params.get('X-VOBJ-ORIGINAL-TZID'), 'value')
+
+ date_local = cal_data.value.astimezone(_server_tzinfo)
+ self.ical_set(cal_data.name.lower(), date_local, 'value')
+ continue
self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
vals = map_data(cr, uid, self, context=context)
return vals
@@ -272,6 +344,8 @@ class CalDAV(object):
timezones = []
for data in datas:
tzval = None
+ exfield = None
+ exdates = []
vevent = ical.add(name)
for field in self.__attribute__.keys():
map_field = self.ical_get(field, 'field')
@@ -305,30 +379,53 @@ class CalDAV(object):
alarm_obj = self.pool.get('basic.calendar.alarm')
vevent = alarm_obj.export_cal(cr, uid, model, \
data[map_field][0], vevent, context=ctx)
- elif field == 'vtimezone' and data[map_field] and data[map_field] not in timezones:
+ elif field == 'vtimezone' and data[map_field]:
tzval = data[map_field]
- tz_obj = self.pool.get('basic.calendar.timezone')
- ical = tz_obj.export_cal(cr, uid, None, \
- data[map_field], ical, context=context)
- timezones.append(data[map_field])
+ if tzval not in timezones:
+ tz_obj = self.pool.get('basic.calendar.timezone')
+ ical = tz_obj.export_cal(cr, uid, None, \
+ data[map_field], ical, context=context)
+ timezones.append(data[map_field])
+ if exfield:
+ exfield.params['TZID'] = [tzval.title()]
+ exdates_updated = []
+ for exdate in exdates:
+ date1 = (datetime.strptime(exdate, "%Y%m%dT%H%M%S")).strftime('%Y-%m-%d %H:%M:%S')
+ dest_date = self.format_date_tz(date1, tzval.title())
+ ex_date = (datetime.strptime(dest_date, "%Y-%m-%d %H:%M:%S")).strftime('%Y%m%dT%H%M%S')
+ exdates_updated.append(ex_date)
+ exfield.value = map(parser.parse, exdates_updated)
elif field == 'organizer' and data[map_field]:
+ organizer = str2mailto(data[map_field])
event_org = vevent.add('organizer')
- organizer_id = data[map_field][0]
- user_obj = self.pool.get('res.users')
- organizer = user_obj.browse(cr, uid, organizer_id, context=context)
- event_org.params['CN'] = [organizer.name]
- event_org.value = 'MAILTO:' + (organizer.user_email or organizer.name)
+ event_org.params['CN'] = [organizer['name']]
+ event_org.value = 'MAILTO:' + (organizer.get('email') or '')
+ # TODO: company?
elif data[map_field]:
if map_type in ("char", "text"):
if field in ('exdate'):
- vevent.add(field).value = map(parser.parse, (data[map_field]).split(','))
+ exfield = vevent.add(field)
+ exdates = (data[map_field]).split(',')
+ if tzval:
+ exfield.params['TZID'] = [tzval.title()]
+ exdates_updated = []
+ for exdate in exdates:
+ date1 = (datetime.strptime(exdate, "%Y%m%dT%H%M%S")).strftime('%Y-%m-%d %H:%M:%S')
+ dest_date = self.format_date_tz(date1, tzval.title())
+ ex_date = (datetime.strptime(dest_date, "%Y-%m-%d %H:%M:%S")).strftime('%Y%m%dT%H%M%S')
+ exdates_updated.append(ex_date)
+ exdates = exdates_updated
+ exfield.value = map(parser.parse, exdates)
else:
vevent.add(field).value = tools.ustr(data[map_field])
elif map_type in ('datetime', 'date') and data[map_field]:
dtfield = vevent.add(field)
- dtfield.value = parser.parse(data[map_field])
if tzval:
+ dest_date = self.format_date_tz(data[map_field], tzval.title())
dtfield.params['TZID'] = [tzval.title()]
+ dtfield.value = parser.parse(dest_date)
+ else:
+ dtfield.value = parser.parse(data[map_field])
elif map_type == "timedelta":
vevent.add(field).value = timedelta(hours=data[map_field])
elif map_type == "many2one":
@@ -344,7 +441,7 @@ class CalDAV(object):
vevent.add(field).value = key1
return vevent
- def check_import(self, cr, uid, vals, context={}):
+ def check_import(self, cr, uid, vals, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -352,7 +449,8 @@ class CalDAV(object):
@param vals: Get Values
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
ids = []
model_obj = self.pool.get(context.get('model'))
recur_pool = {}
@@ -379,8 +477,8 @@ class CalDAV(object):
event_id = model_obj.create(cr, uid, val)
recur_pool[u_id] = event_id
ids.append(event_id)
- except Exception, e:
- raise osv.except_osv(('Error !'), (str(e)))
+ except Exception:
+ raise
return ids
def export_cal(self, cr, uid, datas, vobj=None, context=None):
@@ -451,6 +549,7 @@ class Calendar(CalDAV, osv.osv):
'line_ids': fields.one2many('basic.calendar.lines', 'calendar_id', 'Calendar Lines'),
'create_date': fields.datetime('Created Date', readonly=True),
'write_date': fields.datetime('Modifided Date', readonly=True),
+ 'description': fields.text("description"),
}
def get_calendar_objects(self, cr, uid, ids, parent=None, domain=None, context=None):
@@ -467,7 +566,7 @@ class Calendar(CalDAV, osv.osv):
continue
if line.name in ('valarm', 'attendee'):
continue
- line_domain = eval(line.domain)
+ line_domain = eval(line.domain or '[]')
line_domain += domain
if ctx_res_id:
line_domain += [('id','=',ctx_res_id)]
@@ -497,7 +596,7 @@ class Calendar(CalDAV, osv.osv):
continue
if line.name in ('valarm', 'attendee'):
continue
- domain = eval(line.domain)
+ domain = eval(line.domain or '[]')
if ctx_res_id:
domain += [('id','=',ctx_res_id)]
mod_obj = self.pool.get(line.object_id.model)
@@ -580,7 +679,7 @@ class basic_calendar_line(osv.osv):
'domain': lambda *a: '[]',
}
- def create(self, cr, uid, vals, context={}):
+ def create(self, cr, uid, vals, context=None):
""" create calendar's line
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -662,7 +761,7 @@ class basic_calendar_fields(osv.osv):
raise osv.except_osv(_('Warning !'), _('Please provide proper configuration of "%s" in Calendar Lines' % (name)))
return True
- def create(self, cr, uid, vals, context={}):
+ def create(self, cr, uid, vals, context=None):
""" Create Calendar's fields
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -739,7 +838,7 @@ class Event(CalDAV, osv.osv_memory):
'dtend': None, # Use: O-1, Type: DATE-TIME, Specifies the date and time that a calendar component ends.
}
- def export_cal(self, cr, uid, datas, vobj='vevent', context={}):
+ def export_cal(self, cr, uid, datas, vobj='vevent', context=None):
""" Export calendar
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -792,7 +891,7 @@ class ToDo(CalDAV, osv.osv_memory):
'rrule': None,
}
- def export_cal(self, cr, uid, datas, vobj='vevent', context={}):
+ def export_cal(self, cr, uid, datas, vobj='vevent', context=None):
""" Export Calendar
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -842,7 +941,7 @@ class Timezone(CalDAV, osv.osv_memory):
'x-prop': None, # Use: O-n, Type: Text,
}
- def get_name_offset(self, cr, uid, tzid, context={}):
+ def get_name_offset(self, cr, uid, tzid, context=None):
""" Get Name Offset value
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -859,7 +958,7 @@ class Timezone(CalDAV, osv.osv_memory):
realoffset = (val < 0 and ('-' + realoffset) or ('+' + realoffset))
return (mydt.tzname(), realoffset)
- def export_cal(self, cr, uid, model, tzid, ical, context={}):
+ def export_cal(self, cr, uid, model, tzid, ical, context=None):
""" Export Calendar
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -867,7 +966,8 @@ class Timezone(CalDAV, osv.osv_memory):
@param model: Get Model's name
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
ctx = context.copy()
ctx.update({'model': model})
cal_tz = ical.add('vtimezone')
@@ -876,7 +976,8 @@ class Timezone(CalDAV, osv.osv_memory):
tzname, offset = self.get_name_offset(cr, uid, tzid)
tz_std.add("TZOFFSETFROM").value = offset
tz_std.add("TZOFFSETTO").value = offset
- tz_std.add("DTSTART").value = datetime.now() # TODO
+ #TODO: Get start date for timezone
+ tz_std.add("DTSTART").value = datetime.strptime('1970-01-01 00:00:00', '%Y-%m-%d %H:%M:%S')
tz_std.add("TZNAME").value = tzname
return ical
@@ -915,7 +1016,7 @@ class Alarm(CalDAV, osv.osv_memory):
'x-prop': None,
}
- def export_cal(self, cr, uid, model, alarm_id, vevent, context={}):
+ def export_cal(self, cr, uid, model, alarm_id, vevent, context=None):
""" Export Calendar
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -924,7 +1025,8 @@ class Alarm(CalDAV, osv.osv_memory):
@param alarm_id: Get Alarm's Id
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
valarm = vevent.add('valarm')
alarm_object = self.pool.get(model)
alarm_data = alarm_object.read(cr, uid, alarm_id, [])
@@ -1035,7 +1137,7 @@ class Attendee(CalDAV, osv.osv_memory):
vals = map_data(cr, uid, self, context=context)
return vals
- def export_cal(self, cr, uid, model, attendee_ids, vevent, context={}):
+ def export_cal(self, cr, uid, model, attendee_ids, vevent, context=None):
""" Export Calendar
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -1044,7 +1146,8 @@ class Attendee(CalDAV, osv.osv_memory):
@param attendee_ids: Get Attendee's Id
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
attendee_object = self.pool.get(model)
ctx = context.copy()
ctx.update({'model': model})
diff --git a/addons/caldav/wizard/calendar_event_export.py b/addons/caldav/wizard/calendar_event_export.py
index 0be54df9f56..ea90686b347 100644
--- a/addons/caldav/wizard/calendar_event_export.py
+++ b/addons/caldav/wizard/calendar_event_export.py
@@ -33,19 +33,20 @@ class calendar_event_export(osv.osv_memory):
Export Calendar Event.
"""
- def default_get(self, cr, uid, fields, context):
+ def default_get(self, cr, uid, fields, context=None):
"""
Get Default value for Name field.
"""
+ if not context:
+ context = {}
model = context.get('model', 'basic.calendar')
model_obj = self.pool.get(model)
- calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
res = super(calendar_event_export, self).default_get( cr, uid, fields, context=context)
name = 'OpenERP %s.ics' % (model_obj._description)
if 'name' in fields:
res.update({'name': name})
if 'file_path' in fields:
- calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
+ calendar = model_obj.export_cal(cr, uid, context['active_ids'], context=context)
res.update({'file_path': base64.encodestring(calendar)})
return res
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index 3c04006447f..af843666435 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -107,7 +107,7 @@
-
+
diff --git a/addons/crm_caldav/crm_caldav.py b/addons/crm_caldav/crm_caldav.py
index 3c3e8b8ae2e..a9430a47225 100644
--- a/addons/crm_caldav/crm_caldav.py
+++ b/addons/crm_caldav/crm_caldav.py
@@ -27,7 +27,7 @@ from datetime import datetime
class crm_meeting(osv.osv):
_inherit = 'crm.meeting'
- def export_cal(self, cr, uid, ids, context={}):
+ def export_cal(self, cr, uid, ids, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -35,14 +35,16 @@ class crm_meeting(osv.osv):
@param ids: List of CRM Meeting’s IDs
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
ids = map(lambda x: base_calendar.base_calendar_id2real_id(x), ids)
- event_data = self.read(cr, uid, ids)
+ event_data = self.read(cr, uid, ids, context=context)
event_obj = self.pool.get('basic.calendar.event')
- ical = event_obj.export_cal(cr, uid, event_data, context={'model': self._name})
+ context.update({'model': self._name})
+ ical = event_obj.export_cal(cr, uid, event_data, context=context)
return ical.serialize()
- def import_cal(self, cr, uid, data, data_id=None, context={}):
+ def import_cal(self, cr, uid, data, data_id=None, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -51,12 +53,13 @@ class crm_meeting(osv.osv):
@param data_id: calendar's Id
@param context: A standard dictionary for contextual values
"""
-
+ if not context:
+ context = {}
event_obj = self.pool.get('basic.calendar.event')
vals = event_obj.import_cal(cr, uid, data, context=context)
return self.check_import(cr, uid, vals, context=context)
- def check_import(self, cr, uid, vals, context={}):
+ def check_import(self, cr, uid, vals, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -64,6 +67,8 @@ class crm_meeting(osv.osv):
@param vals: Get Values
@param context: A standard dictionary for contextual values
"""
+ if not context:
+ context = {}
ids = []
model_obj = self.pool.get(context.get('model'))
recur_pool = {}
@@ -96,8 +101,8 @@ class crm_meeting(osv.osv):
event_id = model_obj.create(cr, uid, val)
recur_pool[u_id] = event_id
ids.append(event_id)
- except Exception, e:
- raise osv.except_osv(('Error !'), (str(e)))
+ except Exception:
+ raise
return ids
crm_meeting()
diff --git a/addons/crm_caldav/crm_caldav_data.xml b/addons/crm_caldav/crm_caldav_data.xml
index 3b74eef123c..692b7e7389e 100644
--- a/addons/crm_caldav/crm_caldav_data.xml
+++ b/addons/crm_caldav/crm_caldav_data.xml
@@ -32,7 +32,7 @@
-
+
field
diff --git a/addons/document/content_index.py b/addons/document/content_index.py
index d6012e60091..e3b37914f8c 100644
--- a/addons/document/content_index.py
+++ b/addons/document/content_index.py
@@ -98,7 +98,9 @@ class indexer(object):
def _doIndexFile(self,fpath):
raise NhException("Content not handled here")
-
+
+ def __repr__(self):
+ return "" %(self.__module__, self.__class__.__name__)
def mime_match(mime, mdict):
@@ -128,7 +130,7 @@ class contentIndex(object):
f = True
if f:
- self.__logger.debug('Register content indexer: %s', obj)
+ self.__logger.debug('Register content indexer: %r', obj)
if not f:
raise Exception("Your indexer should at least suport a mimetype or extension")
diff --git a/addons/document/directory_content.py b/addons/document/directory_content.py
index bec4f25e45d..685df7910f3 100644
--- a/addons/document/directory_content.py
+++ b/addons/document/directory_content.py
@@ -18,16 +18,13 @@
# along with this program. If not, see .
#
##############################################################################
-import base64
from osv import osv, fields
-from osv.orm import except_orm
-import urlparse
import netsvc
-import os
+# import os
import nodes
-import StringIO
+# import StringIO
class document_directory_content_type(osv.osv):
_name = 'document.directory.content.type'
@@ -83,7 +80,7 @@ class document_directory_content(osv.osv):
tname = ''
if content.include_name:
content_name = node.displayname or ''
- obj = node.context._dirobj.pool.get(model)
+ # obj = node.context._dirobj.pool.get(model)
if content_name:
tname = (content.prefix or '') + content_name + (content.suffix or '') + (content.extension or '')
else:
diff --git a/addons/document/directory_report.py b/addons/document/directory_report.py
index a4cd2f45068..657fd39d9a9 100644
--- a/addons/document/directory_report.py
+++ b/addons/document/directory_report.py
@@ -20,13 +20,7 @@
#
##############################################################################
-import base64
-
from osv import osv, fields
-from osv.orm import except_orm
-import urlparse
-
-import os
class ir_action_report_xml(osv.osv):
_name="ir.actions.report.xml"
diff --git a/addons/document/document.py b/addons/document/document.py
index c62f62da2d9..46cf6d189c1 100644
--- a/addons/document/document.py
+++ b/addons/document/document.py
@@ -22,16 +22,10 @@
import base64
from osv import osv, fields
-import urlparse
import os
-import pooler
-import netsvc
-from osv.orm import except_orm
-#import StringIO
-
-from psycopg2 import Binary
+# from psycopg2 import Binary
#from tools import config
import tools
from tools.translate import _
diff --git a/addons/document/document_directory.py b/addons/document/document_directory.py
index f5b9202fc8e..18544b54eac 100644
--- a/addons/document/document_directory.py
+++ b/addons/document/document_directory.py
@@ -19,11 +19,8 @@
#
##############################################################################
-import base64
from osv import osv, fields
-from osv.orm import except_orm
-import urlparse
import os
import nodes
@@ -141,30 +138,6 @@ class document_directory(osv.osv):
_parent(dir_id, path)
return path
- def ol_get_resource_path(self, cr, uid, dir_id, res_model, res_id):
- # this method will be used in process module
- # to be need test and Improvement if resource dir has parent resource (link resource)
- path=[]
- def _parent(dir_id,path):
- parent=self.browse(cr, uid, dir_id)
- if parent.parent_id and not parent.ressource_parent_type_id:
- _parent(parent.parent_id.id,path)
- path.append(parent.name)
- else:
- path.append(parent.name)
- return path
-
- directory=self.browse(cr,uid,dir_id)
- model_ids=self.pool.get('ir.model').search(cr, uid, [('model','=',res_model)])
- if directory:
- _parent(dir_id,path)
- path.append(self.pool.get(directory.ressource_type_id.model).browse(cr, uid, res_id).name)
- #user=self.pool.get('res.users').browse(cr,uid,uid)
- #return "ftp://%s:%s@localhost:%s/%s/%s"%(user.login,user.password,config.get('ftp_server_port',8021),cr.dbname,'/'.join(path))
- # No way we will return the password!
- return "ftp://user:pass@host:port/test/this"
- return False
-
def _check_recursion(self, cr, uid, ids):
level = 100
while len(ids):
@@ -178,8 +151,9 @@ class document_directory(osv.osv):
_constraints = [
(_check_recursion, 'Error! You can not create recursive Directories.', ['parent_id'])
]
+
def __init__(self, *args, **kwargs):
- res = super(document_directory, self).__init__(*args, **kwargs)
+ super(document_directory, self).__init__(*args, **kwargs)
#self._cache = {}
def onchange_content_id(self, cr, uid, ids, ressource_type_id):
@@ -223,31 +197,8 @@ class document_directory(osv.osv):
""" try to locate the node in uri,
Return a tuple (node_dir, remaining_path)
"""
- return (nodes.node_database(context=ncontext), uri)
+ return (nodes.node_database(context=ncontext), uri)
- def old_code():
- if not uri:
- return node_database(cr, uid, context=context)
- turi = tuple(uri)
- node = node_class(cr, uid, '/', False, context=context, type='database')
- for path in uri[:]:
- if path:
- node = node.child(path)
- if not node:
- return False
- oo = node.object and (node.object._name, node.object.id) or False
- oo2 = node.object2 and (node.object2._name, node.object2.id) or False
- return node
-
- def ol_get_childs(self, cr, uid, uri, context={}):
- node = self.get_object(cr, uid, uri, context)
- if uri:
- children = node.children()
- else:
- children= [node]
- result = map(lambda node: node.path_get(), children)
- return result
-
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default ={}
diff --git a/addons/document/document_storage.py b/addons/document/document_storage.py
index 419d6c03e37..0ecc01941b4 100644
--- a/addons/document/document_storage.py
+++ b/addons/document/document_storage.py
@@ -37,7 +37,6 @@ from osv.orm import except_orm
import random
import string
import pooler
-import netsvc
import nodes
from content_index import cntIndex
@@ -189,7 +188,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
# we now open a *separate* cursor, to update the data.
# FIXME: this may be improved, for concurrency handling
par = self._get_parent()
- uid = par.context.uid
+ # uid = par.context.uid
cr = pooler.get_db(par.context.dbname).cursor()
try:
if self.mode in ('w', 'w+', 'r+'):
@@ -227,7 +226,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
" WHERE id = %s",
(out, len(data), par.file_id))
cr.commit()
- except Exception, e:
+ except Exception:
logging.getLogger('document.storage').exception('Cannot update db file #%d for close:', par.file_id)
raise
finally:
@@ -262,7 +261,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
# we now open a *separate* cursor, to update the data.
# FIXME: this may be improved, for concurrency handling
par = self._get_parent()
- uid = par.context.uid
+ # uid = par.context.uid
cr = pooler.get_db(par.context.dbname).cursor()
try:
if self.mode in ('w', 'w+', 'r+'):
@@ -288,18 +287,18 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
cr.execute('UPDATE ir_attachment SET db_datas = %s::bytea, file_size=%s, ' \
'index_content = %s, file_type = %s ' \
'WHERE id = %s',
- (base64.encodestring(out), len(out), icont_u, mime, par.file_id))
+ (base64.encodestring(data), len(data), icont_u, mime, par.file_id))
elif self.mode == 'a':
- out = self.getvalue()
+ data = self.getvalue()
# Yes, we're obviously using the wrong representation for storing our
# data as base64-in-bytea
cr.execute("UPDATE ir_attachment " \
"SET db_datas = encode( (COALESCE(decode(encode(db_datas,'escape'),'base64'),'') || decode(%s, 'base64')),'base64')::bytea , " \
" file_size = COALESCE(file_size, 0) + %s " \
" WHERE id = %s",
- (base64.encodestring(out), len(out), par.file_id))
+ (base64.encodestring(data), len(data), par.file_id))
cr.commit()
- except Exception, e:
+ except Exception:
logging.getLogger('document.storage').exception('Cannot update db file #%d for close:', par.file_id)
raise
finally:
@@ -500,7 +499,7 @@ class document_storage(osv.osv):
# try to fix their directory.
if ira.file_size:
self._doclog.warning("ir.attachment #%d does not have a filename, trying the name." %ira.id)
- sfname = ira.name
+ # sfname = ira.name
fpath = os.path.join(boo.path,ira.store_fname or ira.name)
if os.path.exists(fpath):
return file(fpath,'rb').read()
@@ -695,7 +694,7 @@ class document_storage(osv.osv):
store_fname = os.path.join(*store_path)
return { 'name': new_name, 'datas_fname': new_name, 'store_fname': store_fname }
else:
- raise TypeError("No %s storage" % boo.type)
+ raise TypeError("No %s storage" % sbro.type)
def simple_move(self, cr, uid, file_node, ndir_bro, context=None):
""" A preparation for a file move.
@@ -734,7 +733,7 @@ class document_storage(osv.osv):
fname = fil_bo.store_fname
if not fname:
return ValueError("Tried to rename a non-stored file")
- path = storage_bo.path
+ path = sbro.path
oldpath = os.path.join(path, fname)
for ch in ('*', '|', "\\", '/', ':', '"', '<', '>', '?', '..'):
@@ -751,7 +750,7 @@ class document_storage(osv.osv):
os.rename(oldpath, newpath)
return { 'name': new_name, 'datas_fname': new_name, 'store_fname': new_name }
else:
- raise TypeError("No %s storage" % boo.type)
+ raise TypeError("No %s storage" % sbro.type)
document_storage()
diff --git a/addons/document/nodes.py b/addons/document/nodes.py
index 228f104574d..cf590dafdad 100644
--- a/addons/document/nodes.py
+++ b/addons/document/nodes.py
@@ -19,17 +19,14 @@
#
##############################################################################
-# import base64
-# import StringIO
-from osv import osv, fields
-from osv.orm import except_orm
# import urlparse
import pooler
from tools.safe_eval import safe_eval
import errno
-import os
+# import os
import time
+import logging
from StringIO import StringIO
@@ -44,6 +41,8 @@ from StringIO import StringIO
# root: if we are at the first directory of a ressource
#
+logger = logging.getLogger('doc2.nodes')
+
def _str2time(cre):
""" Convert a string with time representation (from db) into time (float)
@@ -902,9 +901,8 @@ class node_res_obj(node_class):
def get_dav_eprop(self, cr, ns, prop):
if ns != 'http://groupdav.org/' or prop != 'resourcetype':
- print "Who asked for %s:%s?" % (ns, prop)
+ logger.warning("Who asked for %s:%s?" % (ns, prop))
return None
- res = {}
cntobj = self.context._dirobj.pool.get('document.directory.content')
uid = self.context.uid
ctx = self.context.context.copy()
@@ -1374,11 +1372,11 @@ class nodefd_content(StringIO, node_descriptor):
if self.mode in ('w', 'w+', 'r+'):
data = self.getvalue()
cntobj = par.context._dirobj.pool.get('document.directory.content')
- cntobj.process_write(cr, uid, parent, data, ctx)
+ cntobj.process_write(cr, uid, par, data, par.context.context)
elif self.mode == 'a':
raise NotImplementedError
cr.commit()
- except Exception, e:
+ except Exception:
logging.getLogger('document.content').exception('Cannot update db content #%d for close:', par.cnt_id)
raise
finally:
diff --git a/addons/document/test_cindex.py b/addons/document/test_cindex.py
index 267e0497950..d7ae7c4d160 100644
--- a/addons/document/test_cindex.py
+++ b/addons/document/test_cindex.py
@@ -35,7 +35,7 @@ for fname in args:
for line in res[:5]:
print line
except Exception,e:
- import traceback,sys
+ import traceback
tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py
index 2ddfcc2bb7d..952b75d49e1 100644
--- a/addons/document_ftp/ftpserver/abstracted_fs.py
+++ b/addons/document_ftp/ftpserver/abstracted_fs.py
@@ -1,9 +1,8 @@
# -*- encoding: utf-8 -*-
+
import os
import time
from tarfile import filemode
-import StringIO
-import base64
import logging
import errno
@@ -12,12 +11,11 @@ import fnmatch
import pooler
import netsvc
-import os
+
from service import security
from osv import osv
#from document.nodes import node_res_dir, node_res_obj
from document.nodes import get_node_context
-import stat
def _get_month_name(month):
month=int(month)
@@ -165,7 +163,7 @@ class abstracted_fs(object):
return ret
except EnvironmentError:
raise
- except Exception,e:
+ except Exception:
self._log.exception('Cannot create item %s at node %s', objname, repr(node))
raise OSError(1, 'Operation not permited.')
@@ -177,7 +175,7 @@ class abstracted_fs(object):
try:
res = node.open_data(cr, mode)
cr.commit()
- except TypeError, e:
+ except TypeError:
raise IOError(errno.EINVAL, "No data")
return res
@@ -188,12 +186,11 @@ class abstracted_fs(object):
name. Unlike mkstemp it returns an object with a file-like
interface.
"""
- raise NotImplementedError
+ raise NotImplementedError # TODO
text = not 'b' in mode
# for unique file , maintain version if duplicate file
if dir:
- # TODO
cr = dir.cr
uid = dir.uid
pool = pooler.get_pool(node.context.dbname)
@@ -234,7 +231,7 @@ class abstracted_fs(object):
cdir = node.create_child_collection(cr, basename)
self._log.debug("Created child dir: %r", cdir)
cr.commit()
- except Exception,e:
+ except Exception:
self._log.exception('Cannot create dir "%s" at node %s', basename, repr(node))
raise OSError(1, 'Operation not permited.')
@@ -405,7 +402,7 @@ class abstracted_fs(object):
cr.commit()
except EnvironmentError:
raise
- except Exception, err:
+ except Exception:
self._log.exception('Cannot rename "%s" to "%s" at "%s"', src, datacr[2], datacr[1])
raise OSError(1,'Operation not permited.')
diff --git a/addons/document_ftp/ftpserver/ftpserver.py b/addons/document_ftp/ftpserver/ftpserver.py
index 692abc4aef4..0ca322fca12 100644
--- a/addons/document_ftp/ftpserver/ftpserver.py
+++ b/addons/document_ftp/ftpserver/ftpserver.py
@@ -121,15 +121,9 @@ import tempfile
import warnings
import random
import stat
+from collections import deque
from tarfile import filemode
-try:
- import pwd
- import grp
-except ImportError:
- pwd = grp = None
-
-
LOG_ACTIVE = True
__all__ = ['proto_cmds', 'Error', 'log', 'logline', 'logerror', 'DummyAuthorizer',
@@ -192,24 +186,6 @@ proto_cmds = {
}
-# hack around format_exc function of traceback module to grant
-# backward compatibility with python < 2.4
-if not hasattr(traceback, 'format_exc'):
- try:
- import cStringIO as StringIO
- except ImportError:
- import StringIO
-
- def _format_exc():
- f = StringIO.StringIO()
- traceback.print_exc(file=f)
- data = f.getvalue()
- f.close()
- return data
-
- traceback.format_exc = _format_exc
-
-
def _strerror(err):
"""A wrap around os.strerror() which may be not available on all
platforms (e.g. pythonCE).
@@ -590,16 +566,6 @@ class ActiveDTP(asyncore.dispatcher):
self.cmd_channel.respond("425 Can't connect to specified address.")
self.close()
-
-try:
- from collections import deque
-except ImportError:
- # backward compatibility with Python < 2.4 by replacing deque with a list
- class deque(list):
- def appendleft(self, obj):
- list.insert(self, 0, obj)
-
-
class DTPHandler(asyncore.dispatcher):
"""Class handling server-data-transfer-process (server-DTP, see
RFC-959) managing data-transfer operations involving sending
@@ -1227,21 +1193,9 @@ class AbstractedFS:
if not nlinks: # non-posix system, let's use a bogus value
nlinks = 1
size = st.st_size # file size
- if pwd and grp:
- # get user and group name, else just use the raw uid/gid
- try:
- uname = pwd.getpwuid(st.st_uid).pw_name
- except KeyError:
- uname = st.st_uid
- try:
- gname = grp.getgrgid(st.st_gid).gr_name
- except KeyError:
- gname = st.st_gid
- else:
- # on non-posix systems the only chance we use default
- # bogus values for owner and group
- uname = "owner"
- gname = "group"
+ uname = st.st_uid or "owner"
+ gname = st.st_gid or "group"
+
# stat.st_mtime could fail (-1) if last mtime is too old
# in which case we return the local time as last mtime
try:
@@ -1438,7 +1392,7 @@ class FTPHandler(asynchat.async_chat):
"""
try:
asynchat.async_chat.__init__(self, conn=conn) # python2.5
- except TypeError, e:
+ except TypeError:
asynchat.async_chat.__init__(self, sock=conn) # python2.6
self.server = server
self.remote_ip, self.remote_port = self.socket.getpeername()[:2]
@@ -1469,13 +1423,10 @@ class FTPHandler(asynchat.async_chat):
# mlsx facts attributes
self.current_facts = ['type', 'perm', 'size', 'modify']
- if os.name == 'posix':
- self.current_facts.append('unique')
+ self.current_facts.append('unique')
self.available_facts = self.current_facts[:]
- if pwd and grp:
- self.available_facts += ['unix.mode', 'unix.uid', 'unix.gid']
- if os.name == 'nt':
- self.available_facts.append('create')
+ self.available_facts += ['unix.mode', 'unix.uid', 'unix.gid']
+ self.available_facts.append('create')
# dtp attributes
self.data_server = None
@@ -1866,7 +1817,7 @@ class FTPHandler(asynchat.async_chat):
self.respond('%s %s.' % (str(ret_code), why))
raise FTPExceptionSent(why)
- except Exception, e:
+ except Exception, err:
cmdname = function.__name__
try:
logerror(traceback.format_exc())
@@ -2003,7 +1954,7 @@ class FTPHandler(asynchat.async_chat):
assert len(octs) == 4
for x in octs:
assert 0 <= x <= 255
- except (AssertionError, ValueError, OverflowError), err:
+ except (AssertionError, ValueError, OverflowError):
self.respond("501 Invalid EPRT format.")
else:
self._make_eport(ip, port)
diff --git a/addons/document_ftp/wizard/ftp_browse.py b/addons/document_ftp/wizard/ftp_browse.py
index d033302f22a..37aba5158f1 100644
--- a/addons/document_ftp/wizard/ftp_browse.py
+++ b/addons/document_ftp/wizard/ftp_browse.py
@@ -20,8 +20,9 @@
##############################################################################
from osv import osv, fields
-from tools.translate import _
+# from tools.translate import _
from document_ftp import ftpserver
+
class document_ftp_browse(osv.osv_memory):
_name = 'document.ftp.browse'
_description = 'Document FTP Browse'
@@ -35,8 +36,8 @@ class document_ftp_browse(osv.osv_memory):
if 'url' in fields:
user_pool = self.pool.get('res.users')
current_user = user_pool.browse(cr, uid, uid, context=context)
- dir_pool = self.pool.get('document.directory')
- data_pool = self.pool.get('ir.model.data')
+ # dir_pool = self.pool.get('document.directory')
+ data_pool = self.pool.get('ir.model.data')
aid = data_pool._get_id(cr, uid, 'document_ftp', 'action_document_browse')
aid = data_pool.browse(cr, uid, aid, context=context).res_id
ftp_url = self.pool.get('ir.actions.url').browse(cr, uid, aid, context=context)
@@ -50,12 +51,12 @@ class document_ftp_browse(osv.osv_memory):
def browse_ftp(self, cr, uid, ids, context):
data_id = ids and ids[0] or False
- data = self.browse(cr, uid, data_id, context)
+ data = self.browse(cr, uid, data_id, context)
final_url = data.url
return {
'type': 'ir.actions.act_url',
'url':final_url,
'target': 'new'
}
+
document_ftp_browse()
-
diff --git a/addons/document_ftp/wizard/ftp_configuration.py b/addons/document_ftp/wizard/ftp_configuration.py
index 40926bdf7c9..0522e0348b8 100644
--- a/addons/document_ftp/wizard/ftp_configuration.py
+++ b/addons/document_ftp/wizard/ftp_configuration.py
@@ -19,14 +19,8 @@
#
##############################################################################
-import base64
-
from osv import osv, fields
-from osv.orm import except_orm
from tools import config
-import urlparse
-
-import os
class document_ftp_configuration(osv.osv_memory):
@@ -46,10 +40,10 @@ class document_ftp_configuration(osv.osv_memory):
def execute(self, cr, uid, ids, context=None):
conf = self.browse(cr, uid, ids[0], context)
- dir_pool = self.pool.get('document.directory')
- data_pool = self.pool.get('ir.model.data')
+ data_pool = self.pool.get('ir.model.data')
# Update the action for FTP browse.
aid = data_pool._get_id(cr, uid, 'document_ftp', 'action_document_browse')
aid = data_pool.browse(cr, uid, aid, context=context).res_id
self.pool.get('ir.actions.url').write(cr, uid, [aid], {'url': 'ftp://'+(conf.host or 'localhost:8021')+'/'})
+
document_ftp_configuration()
diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py
index af8738ef0da..5d641cb39c0 100644
--- a/addons/document_webdav/dav_fs.py
+++ b/addons/document_webdav/dav_fs.py
@@ -129,6 +129,7 @@ class openerp_dav_handler(dav_interface):
raise default_exc(err.strerror)
except Exception,e:
import traceback
+ if cr: cr.close()
self.parent.log_error("Cannot %s: %s", opname, str(e))
self.parent.log_message("Exc: %s",traceback.format_exc())
raise default_exc("Operation failed")
@@ -522,7 +523,6 @@ class openerp_dav_handler(dav_interface):
def put(self, uri, data, content_type=None):
""" put the object into the filesystem """
self.parent.log_message('Putting %s (%d), %s'%( misc.ustr(uri), data and len(data) or 0, content_type))
- parent='/'.join(uri.split('/')[:-1])
cr, uid, pool,dbname, uri2 = self.get_cr(uri)
if not dbname:
if cr: cr.close()
@@ -535,20 +535,44 @@ class openerp_dav_handler(dav_interface):
objname = uri2[-1]
ext = objname.find('.') >0 and objname.split('.')[1] or False
+ ret = None
if not node:
dir_node = self.uri2object(cr, uid, pool, uri2[:-1])
if not dir_node:
cr.close()
raise DAV_NotFound('Parent folder not found')
- self._try_function(dir_node.create_child, (cr, objname, data),
+ newchild = self._try_function(dir_node.create_child, (cr, objname, data),
"create %s" % objname, cr=cr)
+ if not newchild:
+ cr.commit()
+ cr.close()
+ raise DAV_Error(400, "Failed to create resource")
+
+ uparts=urlparse.urlparse(uri)
+ fileloc = '/'.join(newchild.full_path())
+ if isinstance(fileloc, unicode):
+ fileloc = fileloc.encode('utf-8')
+ # the uri we get is a mangled one, where the davpath has been removed
+ davpath = self.parent.get_davpath()
+
+ surl = '%s://%s' % (uparts[0], uparts[1])
+ uloc = urllib.quote(fileloc)
+ hurl = False
+ if uri != ('/'+uloc) and uri != (surl + '/' + uloc):
+ hurl = '%s%s/%s/%s' %(surl, davpath, dbname, uloc)
+ etag = False
+ try:
+ etag = str(newchild.get_etag(cr))
+ except Exception, e:
+ self.parent.log_error("Cannot get etag for node: %s" % e)
+ ret = (hurl, etag)
else:
self._try_function(node.set_data, (cr, data), "save %s" % objname, cr=cr)
cr.commit()
cr.close()
- return 201
+ return ret
def rmcol(self,uri):
""" delete a collection """
diff --git a/addons/document_webdav/webdav.py b/addons/document_webdav/webdav.py
index 1fd530cbdca..10a7f9db4e6 100644
--- a/addons/document_webdav/webdav.py
+++ b/addons/document_webdav/webdav.py
@@ -24,8 +24,15 @@ import xml.dom.minidom
domimpl = xml.dom.minidom.getDOMImplementation()
import urlparse
import urllib
-from DAV import utils
-from DAV.propfind import PROPFIND
+from osv import osv
+
+try:
+ from DAV import utils
+ from DAV.propfind import PROPFIND
+except ImportError:
+ raise osv.except_osv('PyWebDAV Import Error!','Please install PyWebDAV \
+from http://code.google.com/p/pywebdav/downloads/detail?name=PyWebDAV-0.9.4.tar.gz&can=2&q=/')
+
import tools
diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py
index 34c255a2b3e..8a83e25456d 100644
--- a/addons/document_webdav/webdav_server.py
+++ b/addons/document_webdav/webdav_server.py
@@ -214,14 +214,21 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
return self.send_status(ec)
headers = {}
+ etag = None
+ if location and isinstance(location, tuple):
+ etag = location[1]
+ location = location[0]
+ # note that we have allowed for > 2 elems
if location:
headers['Location'] = location
-
- try:
- etag = dc.get_prop(location or uri, "DAV:", "getetag")
- headers['ETag'] = etag
- except:
- pass
+ else:
+ try:
+ if not etag:
+ etag = dc.get_prop(location or uri, "DAV:", "getetag")
+ if etag:
+ headers['ETag'] = str(etag)
+ except Exception:
+ pass
self.send_body(None, '201', 'Created', '', headers=headers)
diff --git a/addons/project_caldav/project_caldav.py b/addons/project_caldav/project_caldav.py
index 65e61c6e4cd..ea6c02bc2cb 100644
--- a/addons/project_caldav/project_caldav.py
+++ b/addons/project_caldav/project_caldav.py
@@ -21,13 +21,19 @@
from osv import fields, osv
from caldav import calendar
+from datetime import datetime
+
+from project.project import task as base_project_task
class project_task(osv.osv):
_name = "project.task"
_inherit = ["calendar.todo", "project.task"]
_columns = {
+ # force inherit from project.project_task so that
+ # calendar.todo.active is masked oute
+ 'active': base_project_task._columns['active'],
'write_date': fields.datetime('Write Date'),
- 'create_date': fields.datetime('Create Date'),
+ 'create_date': fields.datetime('Create Date', readonly=True),
'attendee_ids': fields.many2many('calendar.attendee', \
'task_attendee_rel', 'task_id', 'attendee_id', 'Attendees'),
'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True,