[MERGE] sync with trunk
authorOlivier Dony <odo@openerp.com>
Thu, 22 Dec 2011 10:25:55 +0000 (11:25 +0100)
committerOlivier Dony <odo@openerp.com>
Thu, 22 Dec 2011 10:25:55 +0000 (11:25 +0100)
bzr revid: odo@openerp.com-20111222102555-bydsozbdu6urkj31

1  2 
openerp/addons/base/base.sql
openerp/addons/base/ir/ir.xml
openerp/addons/base/ir/ir_model.py
openerp/osv/fields.py
openerp/osv/orm.py
setup.py

Simple merge
Simple merge
Simple merge
@@@ -1177,96 -1177,9 +1178,97 @@@ class related(function)
              })
              if f.get('relation',False):
                  obj_name = f['relation']
-                 self._relations[-1]['relation'] = f['relation']
+                 result[-1]['relation'] = f['relation']
+         self._relations = result
  
 +
 +class sparse(function):   
 +
 +    def convert_value(self, obj, cr, uid, record, value, read_value, context=None):        
 +        """
 +            + For a many2many field, a list of tuples is expected.
 +              Here is the list of tuple that are accepted, with the corresponding semantics ::
 +
 +                 (0, 0,  { values })    link to a new record that needs to be created with the given values dictionary
 +                 (1, ID, { values })    update the linked record with id = ID (write *values* on it)
 +                 (2, ID)                remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
 +                 (3, ID)                cut the link to the linked record with id = ID (delete the relationship between the two objects but does not delete the target object itself)
 +                 (4, ID)                link to existing record with id = ID (adds a relationship)
 +                 (5)                    unlink all (like using (3,ID) for all linked records)
 +                 (6, 0, [IDs])          replace the list of linked IDs (like using (5) then (4,ID) for each ID in the list of IDs)
 +
 +                 Example:
 +                    [(6, 0, [8, 5, 6, 4])] sets the many2many to ids [8, 5, 6, 4]
 +
 +            + For a one2many field, a lits of tuples is expected.
 +              Here is the list of tuple that are accepted, with the corresponding semantics ::
 +
 +                 (0, 0,  { values })    link to a new record that needs to be created with the given values dictionary
 +                 (1, ID, { values })    update the linked record with id = ID (write *values* on it)
 +                 (2, ID)                remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
 +
 +                 Example:
 +                    [(0, 0, {'field_name':field_value_record1, ...}), (0, 0, {'field_name':field_value_record2, ...})]
 +        """
 +
 +        if self._type == 'many2many':
 +            assert value[0][0] == 6, 'Unsupported m2m value for sparse field: %s' % value
 +            return value[0][2]
 +
 +        elif self._type == 'one2many':
 +            if not read_value:
 +                read_value = []
 +            relation_obj = obj.pool.get(self.relation)
 +            for vals in value:
 +                assert vals[0] in (0,1,2), 'Unsupported o2m value for sparse field: %s' % vals
 +                if vals[0] == 0:
 +                    read_value.append(relation_obj.create(cr, uid, vals[2], context=context))
 +                elif vals[0] == 1:
 +                    relation_obj.write(cr, uid, vals[1], vals[2], context=context)
 +                elif vals[0] == 2:
 +                    relation_obj.unlink(cr, uid, vals[1], context=context)
 +                    read_value.remove(vals[1])
 +            return read_value
 +        return value
 +
 +
 +    def _fnct_write(self,obj,cr, uid, ids, field_name, value, args, context=None):
 +        if not type(ids) == list:
 +            ids = [ids]
 +        records = obj.browse(cr, uid, ids, context=context)
 +        for record in records:
 +            # grab serialized value as object - already deserialized
 +            serialized = getattr(record, self.serialization_field)
 +            if value is None:
 +                # simply delete the key to unset it.
 +                serialized.pop(field_name, None)
 +            else: 
 +                serialized[field_name] = self.convert_value(obj, cr, uid, record, value, serialized.get(field_name), context=context)
 +            obj.write(cr, uid, ids, {self.serialization_field: serialized}, context=context)
 +        return True
 +
 +    def _fnct_read(self, obj, cr, uid, ids, field_names, args, context=None):
 +        results = {}
 +        records = obj.browse(cr, uid, ids, context=context)
 +        for record in records:
 +            # grab serialized value as object - already deserialized
 +            serialized = getattr(record, self.serialization_field)
 +            results[record.id] = {}
 +            for field_name in field_names:
 +                if obj._columns[field_name]._type in ['one2many']:
 +                    value = serialized.get(field_name, [])
 +                else:
 +                    results[record.id].update(field_name=value)
 +        return results
 +
 +    def __init__(self, serialization_field, **kwargs):
 +        self.serialization_field = serialization_field
 +        return super(sparse, self).__init__(self._fnct_read, fnct_inv=self._fnct_write, multi='__sparse_multi', method=True, **kwargs)
 +     
 +
 +
 +
 +
  # ---------------------------------------------------------
  # Dummy fields
  # ---------------------------------------------------------
Simple merge
diff --cc setup.py
index 3f10868,a239b6f..10c98d7
mode 100644,100644..100755
+++ b/setup.py
++#!/usr/bin/env python
++# -*- coding: utf-8 -*-
++##############################################################################
++#
++#    OpenERP, Open Source Management Solution
++#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
++#
++#    This program is free software: you can redistribute it and/or modify
++#    it under the terms of the GNU Affero 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 Affero General Public License for more details.
++#
++#    You should have received a copy of the GNU Affero General Public License
++#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
++#
++##############################################################################
  
--import os
--import re
--import sys
--from setuptools import setup, find_packages
++import glob, os, re, setuptools, sys
++from os.path import join, isfile
  
--execfile('addons/web/common/release.py')
++# List all data files
++def data():
++    files = []
++    for root, dirnames, filenames in os.walk('openerp'):
++        for filename in filenames:
++            if not re.match(r'.*(\.pyc|\.pyo|\~)$',filename):
++                files.append(os.path.join(root, filename))
++    d = {}
++    for v in files:
++        k=os.path.dirname(v)
++        if k in d:
++            d[k].append(v)
++        else:
++            d[k]=[v]
++    r = d.items()
++    if os.name == 'nt':
++        r.append(("Microsoft.VC90.CRT", glob.glob('C:\Microsoft.VC90.CRT\*.*')))
++    return r
  
--version_dash_incompatible = False
--if 'bdist_rpm' in sys.argv:
--    version_dash_incompatible = True
--try:
--    import py2exe
--    from py2exe_utils import opts
--    version_dash_incompatible = True
--except ImportError:
--    opts = {}
--if version_dash_incompatible:
--    version = version.split('-')[0]
++def gen_manifest():
++    file_list="\n".join(data())
++    open('MANIFEST','w').write(file_list)
  
--FILE_PATTERNS = \
--    r'.+\.(py|cfg|po|pot|mo|txt|rst|gif|png|jpg|ico|mako|html|js|css|htc|swf)$'
--def find_data_files(source, patterns=FILE_PATTERNS):
--    file_matcher = re.compile(patterns, re.I)
--    out = []
--    for base, _, files in os.walk(source):
--        cur_files = []
--        for f in files:
--            if file_matcher.match(f):
--                cur_files.append(os.path.join(base, f))
--        if cur_files:
--            out.append(
--                (base, cur_files))
++if os.name == 'nt':
++    sys.path.append("C:\Microsoft.VC90.CRT")
  
--    return out
++def py2exe_options():
++    if os.name == 'nt':
++        import py2exe
++        return {
++            "console" : [ { "script": "openerp-server", "icon_resources": [(1, join("install","openerp-icon.ico"))], }],
++            'options' : {
++                "py2exe": {
++                    "skip_archive": 1,
++                    "optimize": 2,
++                    "dist_dir": 'dist',
++                    "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "email", "encodings", "imaplib", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
++                    "excludes" : ["Tkconstants","Tkinter","tcl"],
++                }
++            }
++        }
++    else:
++        return {}
  
--setup(
--    name=name,
--    version=version,
--    description=description,
--    long_description=long_description,
--    author=author,
--    author_email=author_email,
--    url=url,
--    download_url=download_url,
--    license=license,
--    install_requires=[
--        "Babel >= 0.9.6",
--        "simplejson >= 2.0.9",
-         "python-dateutil >= 1.4.1",
-         "pytz",
-         "werkzeug == 0.7",
-     ],
-     tests_require=[
-         'unittest2',
-         'mock',
-     ],
-     test_suite = 'unittest2.collector',
-     zip_safe=False,
-     packages=find_packages(),
-     classifiers=[
-         'Development Status :: 6 - Production/Stable',
-         'Operating System :: OS Independent',
-         'Programming Language :: Python',
-         'Environment :: Web Environment',
-         'Topic :: Office/Business :: Financial',
-         ],
-     scripts=['openerp-web'],
-     data_files=(find_data_files('addons')
-               + opts.pop('data_files', [])
-     ),
-     **opts
 -        "python-dateutil >= 1.4.1, < 2",
 -        "pytz",
 -        "werkzeug == 0.7",
 -    ],
 -    tests_require=[
 -        'unittest2',
 -        'mock',
 -    ],
 -    test_suite = 'unittest2.collector',
 -    zip_safe=False,
 -    packages=find_packages(),
 -    classifiers=[
 -        'Development Status :: 6 - Production/Stable',
 -        'Operating System :: OS Independent',
 -        'Programming Language :: Python',
 -        'Environment :: Web Environment',
 -        'Topic :: Office/Business :: Financial',
 -        ],
 -    scripts=['openerp-web'],
 -    data_files=(find_data_files('addons')
 -              + opts.pop('data_files', [])
 -    ),
 -    **opts
++execfile(join(os.path.dirname(__file__), 'openerp', 'release.py'))
++
++setuptools.setup(
++      name             = 'openerp',
++      version          = version,
++      description      = description,
++      long_description = long_desc,
++      url              = url,
++      author           = author,
++      author_email     = author_email,
++      classifiers      = filter(None, classifiers.split("\n")),
++      license          = license,
++      scripts          = ['openerp-server'],
++      data_files       = data(),
++      packages         = setuptools.find_packages(),
++      #include_package_data = True,
++      install_requires = [
++        # TODO the pychart package we include in openerp corresponds to PyChart 1.37.
++        # It seems there is a single difference, which is a spurious print in generate_docs.py.
++        # It is probably safe to move to PyChart 1.39 (the latest one).
++        # (Let setup.py choose the latest one, and we should check we can remove pychart from
++        # our tree.) http://download.gna.org/pychart/
++        # TODO  'pychart',
++          'babel',
++          'feedparser',
++          'gdata',
++          'lxml',
++          'mako',
++          'psycopg2',
++          'pydot',
++          'python-dateutil < 2',
++          'python-ldap',
++          'python-openid',
++          'pytz',
++          'pywebdav',
++          'pyyaml',
++          'reportlab',
++          'simplejson',
++          'vatnumber',
++          'vobject',
++          'werkzeug',
++          'zsi',
++      ],
++      extras_require = {
++          'SSL' : ['pyopenssl'],
++      },
++      **py2exe_options()
  )
++
++
++# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: