diff --git a/debian/control b/debian/control index 91ff36e34c9..7f7786ee98d 100644 --- a/debian/control +++ b/debian/control @@ -35,6 +35,7 @@ Depends: python-pydot, python-pyparsing, python-reportlab, + python-requests, python-simplejson, python-tz, python-unittest2, diff --git a/openerp/addons/base/i18n/ab.po b/openerp/addons/base/i18n/ab.po index 6b28e22586f..86600d7723c 100644 --- a/openerp/addons/base/i18n/ab.po +++ b/openerp/addons/base/i18n/ab.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/af.po b/openerp/addons/base/i18n/af.po index 248585cfa4a..c80488b1b13 100644 --- a/openerp/addons/base/i18n/af.po +++ b/openerp/addons/base/i18n/af.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/am.po b/openerp/addons/base/i18n/am.po index dce06ee8cd5..2801a312ede 100644 --- a/openerp/addons/base/i18n/am.po +++ b/openerp/addons/base/i18n/am.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ar.po b/openerp/addons/base/i18n/ar.po index 15a0ba086b4..e9f68449cd7 100644 --- a/openerp/addons/base/i18n/ar.po +++ b/openerp/addons/base/i18n/ar.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bg.po b/openerp/addons/base/i18n/bg.po index 87b6fde3494..3852489a95e 100644 --- a/openerp/addons/base/i18n/bg.po +++ b/openerp/addons/base/i18n/bg.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bn.po b/openerp/addons/base/i18n/bn.po index 18d9cb25618..7e1c406a26f 100644 --- a/openerp/addons/base/i18n/bn.po +++ b/openerp/addons/base/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bs.po b/openerp/addons/base/i18n/bs.po index 64560df5bfc..9dc651dbaa1 100644 --- a/openerp/addons/base/i18n/bs.po +++ b/openerp/addons/base/i18n/bs.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ca.po b/openerp/addons/base/i18n/ca.po index 5e9a509e2f8..0aa0bdb4b00 100644 --- a/openerp/addons/base/i18n/ca.po +++ b/openerp/addons/base/i18n/ca.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/cs.po b/openerp/addons/base/i18n/cs.po index d5f8a06d703..0cce21599f8 100644 --- a/openerp/addons/base/i18n/cs.po +++ b/openerp/addons/base/i18n/cs.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" "X-Poedit-Language: Czech\n" #. module: base diff --git a/openerp/addons/base/i18n/da.po b/openerp/addons/base/i18n/da.po index 14414eccc68..e18790d9ea7 100644 --- a/openerp/addons/base/i18n/da.po +++ b/openerp/addons/base/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/de.po b/openerp/addons/base/i18n/de.po index 1e0a1c51e4c..18616bdfb59 100644 --- a/openerp/addons/base/i18n/de.po +++ b/openerp/addons/base/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/el.po b/openerp/addons/base/i18n/el.po index 2428ce6643d..8aaa29b1d20 100644 --- a/openerp/addons/base/i18n/el.po +++ b/openerp/addons/base/i18n/el.po @@ -12,8 +12,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" "X-Poedit-Country: GREECE\n" "X-Poedit-Language: Greek\n" "X-Poedit-SourceCharset: utf-8\n" diff --git a/openerp/addons/base/i18n/en_GB.po b/openerp/addons/base/i18n/en_GB.po index 3ac3d49d9ad..c5b27448931 100644 --- a/openerp/addons/base/i18n/en_GB.po +++ b/openerp/addons/base/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:08+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es.po b/openerp/addons/base/i18n/es.po index 3289f1acd3c..1bafe12a2ac 100644 --- a/openerp/addons/base/i18n/es.po +++ b/openerp/addons/base/i18n/es.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_AR.po b/openerp/addons/base/i18n/es_AR.po index ff156da38c1..f9cf96454aa 100644 --- a/openerp/addons/base/i18n/es_AR.po +++ b/openerp/addons/base/i18n/es_AR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:08+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_BO.po b/openerp/addons/base/i18n/es_BO.po index 4d8aa3b9f5e..64115de553f 100644 --- a/openerp/addons/base/i18n/es_BO.po +++ b/openerp/addons/base/i18n/es_BO.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:10+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_CL.po b/openerp/addons/base/i18n/es_CL.po index e5fb10c6ca3..f197496e566 100644 --- a/openerp/addons/base/i18n/es_CL.po +++ b/openerp/addons/base/i18n/es_CL.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:09+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_CR.po b/openerp/addons/base/i18n/es_CR.po index ff0e9053b68..ed96b20642a 100644 --- a/openerp/addons/base/i18n/es_CR.po +++ b/openerp/addons/base/i18n/es_CR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:10+0000\n" +"X-Generator: Launchpad (build 16976)\n" "Language: \n" #. module: base diff --git a/openerp/addons/base/i18n/es_DO.po b/openerp/addons/base/i18n/es_DO.po index c95ba0fcad8..f4cf992b0dc 100644 --- a/openerp/addons/base/i18n/es_DO.po +++ b/openerp/addons/base/i18n/es_DO.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:08+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_EC.po b/openerp/addons/base/i18n/es_EC.po index 6126d7c2a6f..6c9d93d2c5e 100644 --- a/openerp/addons/base/i18n/es_EC.po +++ b/openerp/addons/base/i18n/es_EC.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:12+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_MX.po b/openerp/addons/base/i18n/es_MX.po index 332d7384c82..6d49c4af121 100644 --- a/openerp/addons/base/i18n/es_MX.po +++ b/openerp/addons/base/i18n/es_MX.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:11+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_PE.po b/openerp/addons/base/i18n/es_PE.po index cbdab27c57d..c24a34e899b 100644 --- a/openerp/addons/base/i18n/es_PE.po +++ b/openerp/addons/base/i18n/es_PE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:12+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_VE.po b/openerp/addons/base/i18n/es_VE.po index 15260ad574a..29a5b3730c6 100644 --- a/openerp/addons/base/i18n/es_VE.po +++ b/openerp/addons/base/i18n/es_VE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/et.po b/openerp/addons/base/i18n/et.po index 1192725aac4..d7363e67ba0 100644 --- a/openerp/addons/base/i18n/et.po +++ b/openerp/addons/base/i18n/et.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/eu.po b/openerp/addons/base/i18n/eu.po index 6fabc952d95..af05c90097d 100644 --- a/openerp/addons/base/i18n/eu.po +++ b/openerp/addons/base/i18n/eu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fa.po b/openerp/addons/base/i18n/fa.po index 1b0e025410e..4989167556c 100644 --- a/openerp/addons/base/i18n/fa.po +++ b/openerp/addons/base/i18n/fa.po @@ -9,8 +9,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" "X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n" "X-Poedit-Language: Persian\n" diff --git a/openerp/addons/base/i18n/fa_AF.po b/openerp/addons/base/i18n/fa_AF.po index af0a0e59729..e189962cbd7 100644 --- a/openerp/addons/base/i18n/fa_AF.po +++ b/openerp/addons/base/i18n/fa_AF.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:12+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fi.po b/openerp/addons/base/i18n/fi.po index 5646cffb9c9..ff4918cdeb8 100644 --- a/openerp/addons/base/i18n/fi.po +++ b/openerp/addons/base/i18n/fi.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fr.po b/openerp/addons/base/i18n/fr.po index a7cb0c9fd67..c92aee812f0 100644 --- a/openerp/addons/base/i18n/fr.po +++ b/openerp/addons/base/i18n/fr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing @@ -9951,7 +9951,7 @@ msgid "" msgstr "" "\n" "Le noyau d'OpenERP, nécessaire pour toute installation.\n" -"===================================================\n" +"=======================================================\n" #. module: base #: model:ir.model,name:base.model_ir_server_object_lines diff --git a/openerp/addons/base/i18n/fr_CA.po b/openerp/addons/base/i18n/fr_CA.po index c132e8506f3..48f2b6ec179 100644 --- a/openerp/addons/base/i18n/fr_CA.po +++ b/openerp/addons/base/i18n/fr_CA.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:09+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/gl.po b/openerp/addons/base/i18n/gl.po index 68ab1d36f65..9356943b633 100644 --- a/openerp/addons/base/i18n/gl.po +++ b/openerp/addons/base/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/gu.po b/openerp/addons/base/i18n/gu.po index cf0edaaecf7..3dbee22ae46 100644 --- a/openerp/addons/base/i18n/gu.po +++ b/openerp/addons/base/i18n/gu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/he.po b/openerp/addons/base/i18n/he.po index 70d012d1998..9befcdeacbb 100644 --- a/openerp/addons/base/i18n/he.po +++ b/openerp/addons/base/i18n/he.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/hi.po b/openerp/addons/base/i18n/hi.po index e790f6b39e1..be528252f0f 100644 --- a/openerp/addons/base/i18n/hi.po +++ b/openerp/addons/base/i18n/hi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/hr.po b/openerp/addons/base/i18n/hr.po index 44627278dbc..99319e85877 100644 --- a/openerp/addons/base/i18n/hr.po +++ b/openerp/addons/base/i18n/hr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:03+0000\n" +"X-Generator: Launchpad (build 16976)\n" "Language: hr\n" #. module: base diff --git a/openerp/addons/base/i18n/hu.po b/openerp/addons/base/i18n/hu.po index b812e7ee525..b65e88f7e4e 100644 --- a/openerp/addons/base/i18n/hu.po +++ b/openerp/addons/base/i18n/hu.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/hy.po b/openerp/addons/base/i18n/hy.po index 6275f5896e6..dd77f1732c8 100644 --- a/openerp/addons/base/i18n/hy.po +++ b/openerp/addons/base/i18n/hy.po @@ -9,8 +9,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/id.po b/openerp/addons/base/i18n/id.po index f69a0ae481d..55f984d410c 100644 --- a/openerp/addons/base/i18n/id.po +++ b/openerp/addons/base/i18n/id.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/is.po b/openerp/addons/base/i18n/is.po index ee314bae98b..5cb7d77c323 100644 --- a/openerp/addons/base/i18n/is.po +++ b/openerp/addons/base/i18n/is.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/it.po b/openerp/addons/base/i18n/it.po index d76609aa203..0cb63de9694 100644 --- a/openerp/addons/base/i18n/it.po +++ b/openerp/addons/base/i18n/it.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ja.po b/openerp/addons/base/i18n/ja.po index 03850c59478..c5901311c65 100644 --- a/openerp/addons/base/i18n/ja.po +++ b/openerp/addons/base/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ka.po b/openerp/addons/base/i18n/ka.po index 837f7516cc2..bc03369afe6 100644 --- a/openerp/addons/base/i18n/ka.po +++ b/openerp/addons/base/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/kk.po b/openerp/addons/base/i18n/kk.po index 5592883f098..cb5b5faa652 100644 --- a/openerp/addons/base/i18n/kk.po +++ b/openerp/addons/base/i18n/kk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ko.po b/openerp/addons/base/i18n/ko.po index 50fb6e38537..970efa7c5bb 100644 --- a/openerp/addons/base/i18n/ko.po +++ b/openerp/addons/base/i18n/ko.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/lt.po b/openerp/addons/base/i18n/lt.po index 55518a7b577..1e7063751bc 100644 --- a/openerp/addons/base/i18n/lt.po +++ b/openerp/addons/base/i18n/lt.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/lv.po b/openerp/addons/base/i18n/lv.po index f64156a0738..a907da4ad7e 100644 --- a/openerp/addons/base/i18n/lv.po +++ b/openerp/addons/base/i18n/lv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/mk.po b/openerp/addons/base/i18n/mk.po index 46cfd2f956a..6e4e39603d0 100644 --- a/openerp/addons/base/i18n/mk.po +++ b/openerp/addons/base/i18n/mk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/mn.po b/openerp/addons/base/i18n/mn.po index 1d69c955339..bdc3e7e37b7 100644 --- a/openerp/addons/base/i18n/mn.po +++ b/openerp/addons/base/i18n/mn.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nb.po b/openerp/addons/base/i18n/nb.po index 066dfdb196a..d75034d791d 100644 --- a/openerp/addons/base/i18n/nb.po +++ b/openerp/addons/base/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nl.po b/openerp/addons/base/i18n/nl.po index 9950ea883b2..23c7cf66791 100644 --- a/openerp/addons/base/i18n/nl.po +++ b/openerp/addons/base/i18n/nl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nl_BE.po b/openerp/addons/base/i18n/nl_BE.po index d8e2ab7b023..81590a55d18 100644 --- a/openerp/addons/base/i18n/nl_BE.po +++ b/openerp/addons/base/i18n/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:09+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/pl.po b/openerp/addons/base/i18n/pl.po index bdfe4178bb1..c851223d1b7 100644 --- a/openerp/addons/base/i18n/pl.po +++ b/openerp/addons/base/i18n/pl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/pt.po b/openerp/addons/base/i18n/pt.po index ac1ec23c839..f2ea63aa7f3 100644 --- a/openerp/addons/base/i18n/pt.po +++ b/openerp/addons/base/i18n/pt.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:01+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing @@ -5633,7 +5633,7 @@ msgstr "Falta o valor do campo '%s'." #. module: base #: view:ir.rule:0 msgid "Write Access Right" -msgstr "" +msgstr "Permissões de Escrita" #. module: base #: model:ir.actions.act_window,help:base.action_res_groups diff --git a/openerp/addons/base/i18n/pt_BR.po b/openerp/addons/base/i18n/pt_BR.po index 0d5261a6539..7df1d214e2c 100644 --- a/openerp/addons/base/i18n/pt_BR.po +++ b/openerp/addons/base/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ro.po b/openerp/addons/base/i18n/ro.po index f6afb07778e..28b33255bbc 100644 --- a/openerp/addons/base/i18n/ro.po +++ b/openerp/addons/base/i18n/ro.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:01+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ru.po b/openerp/addons/base/i18n/ru.po index dde0d09a88b..e49768a0f72 100644 --- a/openerp/addons/base/i18n/ru.po +++ b/openerp/addons/base/i18n/ru.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:02+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sk.po b/openerp/addons/base/i18n/sk.po index fa23b9fca86..6075c9ee6d0 100644 --- a/openerp/addons/base/i18n/sk.po +++ b/openerp/addons/base/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:03+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sl.po b/openerp/addons/base/i18n/sl.po index 2ce1102afb6..da1e8f47974 100644 --- a/openerp/addons/base/i18n/sl.po +++ b/openerp/addons/base/i18n/sl.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sq.po b/openerp/addons/base/i18n/sq.po index 75418986b60..e022e19b605 100644 --- a/openerp/addons/base/i18n/sq.po +++ b/openerp/addons/base/i18n/sq.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 05:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sr.po b/openerp/addons/base/i18n/sr.po index 61b34a233f5..bb354004c23 100644 --- a/openerp/addons/base/i18n/sr.po +++ b/openerp/addons/base/i18n/sr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:02+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sr@latin.po b/openerp/addons/base/i18n/sr@latin.po index 8c9348c3094..4e86d70c5bd 100644 --- a/openerp/addons/base/i18n/sr@latin.po +++ b/openerp/addons/base/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:12+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sv.po b/openerp/addons/base/i18n/sv.po index a8e01fb7a5d..08eaa1a49f4 100644 --- a/openerp/addons/base/i18n/sv.po +++ b/openerp/addons/base/i18n/sv.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/th.po b/openerp/addons/base/i18n/th.po index db7e38e2fec..b502e37fdc1 100644 --- a/openerp/addons/base/i18n/th.po +++ b/openerp/addons/base/i18n/th.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/tlh.po b/openerp/addons/base/i18n/tlh.po index afcd43207d9..5ff7e203931 100644 --- a/openerp/addons/base/i18n/tlh.po +++ b/openerp/addons/base/i18n/tlh.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/tr.po b/openerp/addons/base/i18n/tr.po index 2411e610e83..f373aa3c8b4 100644 --- a/openerp/addons/base/i18n/tr.po +++ b/openerp/addons/base/i18n/tr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/uk.po b/openerp/addons/base/i18n/uk.po index 5ec02766e6d..0493f60ddc7 100644 --- a/openerp/addons/base/i18n/uk.po +++ b/openerp/addons/base/i18n/uk.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:06+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ur.po b/openerp/addons/base/i18n/ur.po index d18f9aaea23..75aa8fc4ace 100644 --- a/openerp/addons/base/i18n/ur.po +++ b/openerp/addons/base/i18n/ur.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:06+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/vi.po b/openerp/addons/base/i18n/vi.po index ae1c01cef12..53c94aa43fc 100644 --- a/openerp/addons/base/i18n/vi.po +++ b/openerp/addons/base/i18n/vi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_CN.po b/openerp/addons/base/i18n/zh_CN.po index 6ea18ad57c9..69163ff7b36 100644 --- a/openerp/addons/base/i18n/zh_CN.po +++ b/openerp/addons/base/i18n/zh_CN.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:11+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_HK.po b/openerp/addons/base/i18n/zh_HK.po index 700bf5c84c7..6f21dd44565 100644 --- a/openerp/addons/base/i18n/zh_HK.po +++ b/openerp/addons/base/i18n/zh_HK.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index 1b7ff7144f5..b7e8da5b200 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-09 06:10+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 4cd0492d95c..4e177959792 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -104,7 +104,9 @@ class ir_actions_report_xml(osv.osv): cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,)) r = cr.dictfetchone() if r: - if r['report_rml'] or r['report_rml_content_data']: + if r['report_type'] in ['qweb-pdf', 'qweb-html']: + return r['report_name'] + elif r['report_rml'] or r['report_rml_content_data']: if r['parser']: kwargs = { 'parser': operator.attrgetter(r['parser'])(openerp.addons) } else: @@ -127,7 +129,11 @@ class ir_actions_report_xml(osv.osv): Look up a report definition and render the report for the provided IDs. """ new_report = self._lookup_report(cr, name) - return new_report.create(cr, uid, res_ids, data, context) + # in order to use current yml test files with qweb reports + if isinstance(new_report, (str, unicode)): + return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf' + else: + return new_report.create(cr, uid, res_ids, data, context) _name = 'ir.actions.report.xml' _inherit = 'ir.actions.actions' @@ -944,7 +950,8 @@ class ir_actions_server(osv.osv): 'uid': uid, 'user': user, 'context': context, - 'workflow': workflow + 'workflow': workflow, + 'Warning': openerp.exceptions.Warning, } def run(self, cr, uid, ids, context=None): diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py index 62ecd605223..258d405deb5 100644 --- a/openerp/addons/base/ir/ir_http.py +++ b/openerp/addons/base/ir/ir_http.py @@ -85,8 +85,8 @@ class ir_http(osv.AbstractModel): return auth_method def _handle_exception(self, exception): - # If handle exception return something different than None, it will be used as a response - raise + # If handle_exception returns something different than None, it will be used as a response + return request._handle_exception(exception) def _dispatch(self): # locate the controller method diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index f19a1fa6746..40ed60b05a3 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -241,7 +241,7 @@ class QWeb(orm.AbstractModel): if attribute_name == "groups": cr = qwebcontext.get('request') and qwebcontext['request'].cr or None uid = qwebcontext.get('request') and qwebcontext['request'].uid or None - can_see = self.user_has_groups(cr, uid, groups=attribute_value) + can_see = self.user_has_groups(cr, uid, groups=attribute_value) if cr and uid else False if not can_see: return '' continue @@ -332,7 +332,9 @@ class QWeb(orm.AbstractModel): return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner) def render_tag_esc(self, element, template_attributes, generated_attributes, qwebcontext): - inner = werkzeug.utils.escape(self.eval_str(template_attributes["esc"], qwebcontext)) + options = json.loads(template_attributes.get('esc-options') or '{}') + widget = self.get_widget_for(options.get('widget', '')) + inner = widget.format(template_attributes['esc'], options, qwebcontext) return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner) def render_tag_foreach(self, element, template_attributes, generated_attributes, qwebcontext): @@ -419,6 +421,9 @@ class QWeb(orm.AbstractModel): return self.pool.get('ir.qweb.field.' + field_type, self.pool['ir.qweb.field']) + def get_widget_for(self, widget): + return self.pool.get('ir.qweb.widget.' + widget, self.pool['ir.qweb.widget']) + #-------------------------------------------------------------------- # QWeb Fields converters #-------------------------------------------------------------------- @@ -603,7 +608,7 @@ class DateTimeConverter(osv.AbstractModel): if isinstance(value, basestring): value = datetime.datetime.strptime( value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT) - value = column.context_timestamp( + value = fields.datetime.context_timestamp( cr, uid, timestamp=value, context=context) if options and 'format' in options: @@ -840,6 +845,38 @@ class Contact(orm.AbstractModel): return HTMLSafe(html) +class QwebWidget(osv.AbstractModel): + _name = 'ir.qweb.widget' + + def _format(self, inner, options, qwebcontext): + return self.pool['ir.qweb'].eval_str(inner, qwebcontext) + + def format(self, inner, options, qwebcontext): + return werkzeug.utils.escape(self._format(inner, options, qwebcontext)) + +class QwebWidgetMonetary(osv.AbstractModel): + _name = 'ir.qweb.widget.monetary' + _inherit = 'ir.qweb.widget' + + def _format(self, inner, options, qwebcontext): + inner = self.pool['ir.qweb'].eval(inner, qwebcontext) + display = self.pool['ir.qweb'].eval_object(options['display_currency'], qwebcontext) + precision = int(round(math.log10(display.rounding))) + fmt = "%.{0}f".format(-precision if precision < 0 else 0) + lang_code = qwebcontext.context.get('lang') or 'en_US' + formatted_amount = self.pool['res.lang'].format( + qwebcontext.cr, qwebcontext.uid, [lang_code], fmt, inner, grouping=True, monetary=True + ) + pre = post = u'' + if display.position == 'before': + pre = u'{symbol} ' + else: + post = u' {symbol}' + + return u'{pre}{0}{post}'.format( + formatted_amount, pre=pre, post=post + ).format(symbol=display.symbol,) + class HTMLSafe(object): """ HTMLSafe string wrapper, Werkzeug's escape() has special handling for objects with a ``__html__`` methods but AFAIK does not provide any such diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index 360c5e37b31..7c857e767ba 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -73,12 +73,18 @@ class view_custom(osv.osv): class view(osv.osv): _name = 'ir.ui.view' - def _get_model_data(self, cr, uid, ids, *args, **kwargs): - ir_model_data = self.pool.get('ir.model.data') - data_ids = ir_model_data.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)]) - result = dict(zip(ids, data_ids)) + def _get_model_data(self, cr, uid, ids, fname, args, context=None): + result = dict.fromkeys(ids, False) + IMD = self.pool['ir.model.data'] + data_ids = IMD.search_read(cr, uid, [('res_id', 'in', ids), ('model', '=', 'ir.ui.view')], ['res_id'], context=context) + result.update(map(itemgetter('res_id', 'id'), data_ids)) return result + def _views_from_model_data(self, cr, uid, ids, context=None): + IMD = self.pool['ir.model.data'] + data_ids = IMD.search_read(cr, uid, [('id', 'in', ids), ('model', '=', 'ir.ui.view')], ['res_id'], context=context) + return map(itemgetter('res_id'), data_ids) + _columns = { 'name': fields.char('View Name', required=True), 'model': fields.char('Object', select=True), @@ -97,7 +103,11 @@ class view(osv.osv): 'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade', select=True), 'inherit_children_ids': fields.one2many('ir.ui.view','inherit_id', 'Inherit Views'), 'field_parent': fields.char('Child Field'), - 'model_data_id': fields.function(_get_model_data, type='many2one', relation='ir.model.data', string="Model Data", store=True), + 'model_data_id': fields.function(_get_model_data, type='many2one', relation='ir.model.data', string="Model Data", + store={ + _name: (lambda s, c, u, i, ctx=None: i, None, 10), + 'ir.model.data': (_views_from_model_data, ['model', 'res_id'], 10), + }), 'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID", help="ID of the view defined in xml file"), 'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id', diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 6ad74857f39..b82e6b8242d 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -31,6 +31,7 @@ import shutil import tempfile import urllib import urllib2 +import urlparse import zipfile import zipimport import lxml.html @@ -41,6 +42,7 @@ except ImportError: from StringIO import StringIO # NOQA import openerp +import openerp.exceptions from openerp import modules, tools from openerp.modules.db import create_categories from openerp.modules import get_module_resource @@ -621,40 +623,14 @@ class module(osv.osv): return res def download(self, cr, uid, ids, download=True, context=None): - res = [] - default_version = modules.adapt_version('1.0') - for mod in self.browse(cr, uid, ids, context=context): - if not mod.url: - continue - match = re.search('-([a-zA-Z0-9\._-]+)(\.zip)', mod.url, re.I) - version = default_version - if match: - version = match.group(1) - if parse_version(mod.installed_version) >= parse_version(version): - continue - res.append(mod.url) - if not download: - continue - zip_content = urllib.urlopen(mod.url).read() - fname = modules.get_module_path(str(mod.name) + '.zip', downloaded=True) - try: - with open(fname, 'wb') as fp: - fp.write(zip_content) - except Exception: - _logger.exception('Error when trying to create module ' - 'file %s', fname) - raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,)) - terp = self.get_module_info(mod.name) - self.write(cr, uid, mod.id, self.get_values_from_terp(terp)) - cr.execute('DELETE FROM ir_module_module_dependency WHERE module_id = %s', (mod.id,)) - self._update_dependencies(cr, uid, mod, terp.get('depends', [])) - self._update_category(cr, uid, mod, terp.get('category', 'Uncategorized')) - # Import module - zimp = zipimport.zipimporter(fname) - zimp.load_module(mod.name) - return res + return [] def install_from_urls(self, cr, uid, urls, context=None): + if not self.pool['res.users'].has_group(cr, uid, 'base.group_system'): + raise openerp.exceptions.AccessDenied() + + apps_server = urlparse.urlparse(self.get_apps_server(cr, uid, context=context)) + OPENERP = 'openerp' tmp = tempfile.mkdtemp() _logger.debug('Install from url: %r', urls) @@ -663,6 +639,11 @@ class module(osv.osv): for module_name, url in urls.items(): if not url: continue # nothing to download, local version is already the last one + + up = urlparse.urlparse(url) + if up.scheme != apps_server.scheme or up.netloc != apps_server.netloc: + raise openerp.exceptions.AccessDenied() + try: _logger.info('Downloading module `%s` from OpenERP Apps', module_name) content = urllib2.urlopen(url).read() @@ -727,8 +708,8 @@ class module(osv.osv): finally: shutil.rmtree(tmp) - def install_by_names(self, cr, uid, names, context=None): - raise NotImplementedError('# TODO') + def get_apps_server(self, cr, uid, context=None): + return tools.config.get('apps_server', 'https://apps.openerp.com/apps') def _update_dependencies(self, cr, uid, mod_browse, depends=None): if depends is None: diff --git a/openerp/addons/base/res/res_country.py b/openerp/addons/base/res/res_country.py index df68d211a97..df507dcbac9 100644 --- a/openerp/addons/base/res/res_country.py +++ b/openerp/addons/base/res/res_country.py @@ -56,6 +56,7 @@ addresses belonging to this country.\n\nYou can use the python-style string pate \n%(country_name)s: the name of the country \n%(country_code)s: the code of the country"""), 'currency_id': fields.many2one('res.currency', 'Currency'), + 'image': fields.binary("Image"), } _sql_constraints = [ ('name_uniq', 'unique (name)', diff --git a/openerp/addons/base/res/res_country_data.xml b/openerp/addons/base/res/res_country_data.xml index 13c1025cf6b..eff97fb0aac 100644 --- a/openerp/addons/base/res/res_country_data.xml +++ b/openerp/addons/base/res/res_country_data.xml @@ -5,46 +5,55 @@ United Arab Emirates ae + Afghanistan, Islamic State of af + Antigua and Barbuda ag + Anguilla ai + Albania al + Armenia am + Netherlands Antilles an + Angola ao + @@ -55,103 +64,123 @@ Argentina ar + American Samoa as + Austria at + Australia au + Aruba aw + Åland Islands ax + Azerbaijan az + Bosnia-Herzegovina ba + Barbados bb + Bangladesh bd + Belgium be + Burkina Faso bf + Bulgaria bg + Bahrain bh + Burundi bi + Benin bj + Saint Barthélémy bl + Bermuda bm + Brunei Darussalam bn + Bolivia bo + @@ -162,17 +191,20 @@ Brazil br + Bahamas bs + Bhutan bt + @@ -183,158 +215,189 @@ Botswana bw + Belarus by + Belize bz + Canada ca + Cocos (Keeling) Islands cc + Central African Republic cf + Congo, Democratic Republic of the cd + Congo cg + Switzerland ch + Ivory Coast (Cote D'Ivoire) ci + Cook Islands ck + Chile cl + Cameroon cm + China cn + Colombia co + Costa Rica cr + Cuba cu + Cape Verde cv + Curaçao cw + Christmas Island cx + Cyprus cy + Czech Republic cz + Germany de + Djibouti dj + Denmark dk + Dominica dm + Dominican Republic do + Algeria dz + Ecuador ec + Estonia ee + Egypt eg + @@ -345,63 +408,75 @@ Eritrea er + Spain es + Ethiopia et + Finland fi + Fiji fj + Falkland Islands fk + Micronesia fm + Faroe Islands fo + France fr + Gabon ga + Grenada gd + Georgia ge + @@ -412,31 +487,37 @@ Ghana gh + Gibraltar gi + Guernsey gg + Greenland gl + Gambia gm + Guinea gn + @@ -447,41 +528,49 @@ Equatorial Guinea gq + Greece gr + South Georgia and the South Sandwich Islands gs + Guatemala gt + Guam (USA) gu + Guinea Bissau gw + Guyana gy + Hong Kong hk + @@ -492,222 +581,266 @@ Honduras hn + Croatia hr + Haiti ht + Hungary hu + Indonesia id + Ireland ie + Israel il + Isle of Man im + India in + British Indian Ocean Territory io + Iraq iq + Iran ir + Iceland is + Italy it + Jersey je + Jamaica jm + Jordan jo + Japan jp + Kenya ke + Kyrgyz Republic (Kyrgyzstan) kg + Cambodia, Kingdom of kh + Kiribati ki + Comoros km + Saint Kitts & Nevis Anguilla kn + North Korea kp + South Korea kr + Kuwait kw + Cayman Islands ky + Kazakhstan kz + Laos la + Lebanon lb + Saint Lucia lc + Liechtenstein li + Sri Lanka lk + Liberia lr + Lesotho ls + Lithuania lt + Luxembourg lu + Latvia lv + Libya ly + Morocco ma + Monaco mc + Moldavia md + Montenegro me + @@ -718,142 +851,170 @@ Madagascar mg + Marshall Islands mh + Macedonia, the former Yugoslav Republic of mk + Mali ml + Myanmar mm + Mongolia mn + Macau mo + Northern Mariana Islands mp + Martinique (French) mq + Mauritania mr + Montserrat ms + Malta mt + Mauritius mu + Maldives mv + Malawi mw + Mexico mx + Malaysia my + Mozambique mz + Namibia na + New Caledonia (French) nc + Niger ne + Norfolk Island nf + Nigeria ng + Nicaragua ni + Netherlands nl + Norway no + Nepal np + Nauru nr + @@ -864,66 +1025,79 @@ Niue nu + New Zealand nz + Oman om + Panama pa + Peru pe + Polynesia (French) pf + Papua New Guinea pg + Philippines ph + Pakistan pk + Poland pl + Saint Pierre and Miquelon pm + Pitcairn Island pn + Puerto Rico pr + @@ -934,21 +1108,25 @@ Portugal pt + Palau pw + Paraguay py + Qatar qa + @@ -959,61 +1137,73 @@ Romania ro + Serbia rs + Russian Federation ru + Rwanda rw + Saudi Arabia sa + Solomon Islands sb + Seychelles sc + Sudan sd + Sweden se + Singapore sg + Saint Helena sh + Slovenia si + @@ -1024,131 +1214,157 @@ Slovakia sk + Sierra Leone sl + San Marino sm + Senegal sn + Somalia so + Suriname sr + South Sudan ss + Saint Tome (Sao Tome) and Principe st + El Salvador sv + Sint Maarten (Dutch part) sx + Syria sy + Swaziland sz + Turks and Caicos Islands tc + Chad td + French Southern Territories tf + Togo tg + Thailand th + Tajikistan tj + Tokelau tk + Turkmenistan tm + Tunisia tn + Tonga to + East Timor tp + Turkey tr + Trinidad and Tobago tt + Tuvalu tv + @@ -1159,23 +1375,27 @@ Tanzania tz + Ukraine ua + Uganda ug + United Kingdom gb + @@ -1186,52 +1406,62 @@ United States us + Uruguay uy + Uzbekistan uz + Holy See (Vatican City State) va + Saint Vincent & Grenadines vc + Venezuela ve + Virgin Islands (British) vg + Virgin Islands (USA) vi + Vietnam vn + Vanuatu vu + @@ -1242,11 +1472,13 @@ Samoa ws + Yemen ye + @@ -1262,11 +1494,13 @@ South Africa za + Zambia zm + @@ -1279,6 +1513,7 @@ Zimbabwe zw + diff --git a/openerp/addons/base/res/res_country_view.xml b/openerp/addons/base/res/res_country_view.xml index 8f64d330440..e4784c3d9ca 100644 --- a/openerp/addons/base/res/res_country_view.xml +++ b/openerp/addons/base/res/res_country_view.xml @@ -22,6 +22,7 @@ res.country
+ diff --git a/openerp/addons/base/res/res_font.py b/openerp/addons/base/res/res_font.py index 47e49bf4d39..767fc3754c1 100644 --- a/openerp/addons/base/res/res_font.py +++ b/openerp/addons/base/res/res_font.py @@ -37,6 +37,23 @@ and Ubuntu distros, we have to override the search path, too. """ _logger = logging.getLogger(__name__) +# Alternatives for the [broken] builtin PDF fonts. Default order chosen to match +# the pre-v8 mapping from openerp.report.render.rml2pdf.customfonts.CustomTTFonts. +# Format: [ (BuiltinFontFamily, mode, [AlternativeFontName, ...]), ...] +BUILTIN_ALTERNATIVES = [ + ('Helvetica', "normal", ["DejaVuSans", "LiberationSans"]), + ('Helvetica', "bold", ["DejaVuSans-Bold", "LiberationSans-Bold"]), + ('Helvetica', 'italic', ["DejaVuSans-Oblique", "LiberationSans-Italic"]), + ('Helvetica', 'bolditalic', ["DejaVuSans-BoldOblique", "LiberationSans-BoldItalic"]), + ('Times', 'normal', ["LiberationSerif", "DejaVuSerif"]), + ('Times', 'bold', ["LiberationSerif-Bold", "DejaVuSerif-Bold"]), + ('Times', 'italic', ["LiberationSerif-Italic", "DejaVuSerif-Italic"]), + ('Times', 'bolditalic', ["LiberationSerif-BoldItalic", "DejaVuSerif-BoldItalic"]), + ('Courier', 'normal', ["FreeMono", "DejaVuSansMono"]), + ('Courier', 'bold', ["FreeMonoBold", "DejaVuSansMono-Bold"]), + ('Courier', 'italic', ["FreeMonoOblique", "DejaVuSansMono-Oblique"]), + ('Courier', 'bolditalic', ["FreeMonoBoldOblique", "DejaVuSansMono-BoldOblique"]), +] class res_font(osv.Model): _name = "res.font" @@ -113,9 +130,32 @@ class res_font(osv.Model): def _sync(self, cr, uid, context=None): """Set the customfonts.CustomTTFonts list to the content of the database""" customfonts.CustomTTFonts = [] + local_family_modes = set() + local_font_paths = {} found_fonts_ids = self.search(cr, uid, [('path', '!=', '/dev/null')], context=context) for font in self.browse(cr, uid, found_fonts_ids, context=None): + local_family_modes.add((font.family, font.mode)) + local_font_paths[font.name] = font.path customfonts.CustomTTFonts.append((font.family, font.name, font.path, font.mode)) + + # Attempt to remap the builtin fonts (Helvetica, Times, Courier) to better alternatives + # if available, because they only support a very small subset of unicode + # (missing 'č' for example) + for builtin_font_family, mode, alts in BUILTIN_ALTERNATIVES: + if (builtin_font_family, mode) not in local_family_modes: + # No local font exists with that name, try alternatives + for altern_font in alts: + if local_font_paths.get(altern_font): + altern_def = (builtin_font_family, altern_font, + local_font_paths[altern_font], mode) + customfonts.CustomTTFonts.append(altern_def) + _logger.debug("Builtin remapping %r", altern_def) + break + else: + _logger.warning("No local alternative found for builtin font `%s` (%s mode)." + "Consider installing the DejaVu fonts if you have problems " + "with unicode characters in RML reports", + builtin_font_family, mode) return True def clear_caches(self): diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py index 46f0218e21f..896f455a274 100644 --- a/openerp/addons/base/res/res_partner.py +++ b/openerp/addons/base/res/res_partner.py @@ -28,6 +28,7 @@ import openerp from openerp import SUPERUSER_ID from openerp import tools from openerp.osv import osv, fields +from openerp.osv.expression import get_unaccent_wrapper from openerp.tools.translate import _ class format_address(object): @@ -228,10 +229,10 @@ class res_partner(osv.osv, format_address): _order = "display_name" _columns = { 'name': fields.char('Name', size=128, required=True, select=True), - 'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers), + 'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers, select=True), 'date': fields.date('Date', select=1), 'title': fields.many2one('res.partner.title', 'Title'), - 'parent_id': fields.many2one('res.partner', 'Related Company'), + 'parent_id': fields.many2one('res.partner', 'Related Company', select=True), 'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts', domain=[('active','=',True)]), # force "active_test" domain to bypass _search() override 'ref': fields.char('Reference', size=64, select=1), 'lang': fields.selection(_lang_get, 'Language', @@ -629,10 +630,17 @@ class res_partner(osv.osv, format_address): if operator in ('=ilike', '=like'): operator = operator[1:] - query = ('SELECT id FROM res_partner ' + - where_str + '(email ' + operator + ''' %s - OR display_name ''' + operator + ''' %s) - ORDER BY display_name''') + unaccent = get_unaccent_wrapper(cr) + + query = """SELECT id + FROM res_partner + {where} ({email} {operator} {percent} + OR {display_name} {operator} {percent}) + ORDER BY {display_name} + """.format(where=where_str, operator=operator, + email=unaccent('email'), + display_name=unaccent('display_name'), + percent=unaccent('%s')) where_clause_params += [search_name, search_name] if limit: diff --git a/openerp/addons/base/res/res_partner_demo.xml b/openerp/addons/base/res/res_partner_demo.xml index cffe87b098b..4b8a19a392e 100644 --- a/openerp/addons/base/res/res_partner_demo.xml +++ b/openerp/addons/base/res/res_partner_demo.xml @@ -438,7 +438,7 @@ 89 Dong Lu Road - míng@yourcompany.example.com + ming@yourcompany.example.com +86 215 069 5177 http://www.míng.com diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index b85c49abf15..32e81ee600f 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -388,7 +388,7 @@ class res_users(osv.osv): if not password: return False user_id = False - cr = self.pool.db.cursor() + cr = self.pool.cursor() try: # autocommit: our single update request will be performed atomically. # (In this way, there is no opportunity to have two transactions @@ -439,7 +439,7 @@ class res_users(osv.osv): # Successfully logged in as admin! # Attempt to guess the web base url... if user_agent_env and user_agent_env.get('base_location'): - cr = self.pool.db.cursor() + cr = self.pool.cursor() try: base = user_agent_env['base_location'] ICP = self.pool['ir.config_parameter'] @@ -460,7 +460,7 @@ class res_users(osv.osv): raise openerp.exceptions.AccessDenied() if self._uid_cache.get(db, {}).get(uid) == passwd: return - cr = self.pool.db.cursor() + cr = self.pool.cursor() try: self.check_credentials(cr, uid, passwd) if self._uid_cache.has_key(db): diff --git a/openerp/addons/base/static/img/country_flags/ad.png b/openerp/addons/base/static/img/country_flags/ad.png new file mode 100644 index 00000000000..3806c28c6d8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ad.png differ diff --git a/openerp/addons/base/static/img/country_flags/ae.png b/openerp/addons/base/static/img/country_flags/ae.png new file mode 100644 index 00000000000..4d5c0a3a657 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ae.png differ diff --git a/openerp/addons/base/static/img/country_flags/af.png b/openerp/addons/base/static/img/country_flags/af.png new file mode 100644 index 00000000000..299482a1fad Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/af.png differ diff --git a/openerp/addons/base/static/img/country_flags/ag.png b/openerp/addons/base/static/img/country_flags/ag.png new file mode 100644 index 00000000000..29ec9e8ad1e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ag.png differ diff --git a/openerp/addons/base/static/img/country_flags/ai.png b/openerp/addons/base/static/img/country_flags/ai.png new file mode 100644 index 00000000000..343a6dfc294 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ai.png differ diff --git a/openerp/addons/base/static/img/country_flags/al.png b/openerp/addons/base/static/img/country_flags/al.png new file mode 100644 index 00000000000..0d1b5f87cb3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/al.png differ diff --git a/openerp/addons/base/static/img/country_flags/am.png b/openerp/addons/base/static/img/country_flags/am.png new file mode 100644 index 00000000000..8023ad7a4b2 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/am.png differ diff --git a/openerp/addons/base/static/img/country_flags/an.png b/openerp/addons/base/static/img/country_flags/an.png new file mode 100644 index 00000000000..701d55fbda9 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/an.png differ diff --git a/openerp/addons/base/static/img/country_flags/ao.png b/openerp/addons/base/static/img/country_flags/ao.png new file mode 100644 index 00000000000..b599322efb8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ao.png differ diff --git a/openerp/addons/base/static/img/country_flags/ar.png b/openerp/addons/base/static/img/country_flags/ar.png new file mode 100644 index 00000000000..943ebb2be73 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ar.png differ diff --git a/openerp/addons/base/static/img/country_flags/as.png b/openerp/addons/base/static/img/country_flags/as.png new file mode 100644 index 00000000000..068d34174b6 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/as.png differ diff --git a/openerp/addons/base/static/img/country_flags/at.png b/openerp/addons/base/static/img/country_flags/at.png new file mode 100644 index 00000000000..758147d4bbb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/at.png differ diff --git a/openerp/addons/base/static/img/country_flags/au.png b/openerp/addons/base/static/img/country_flags/au.png new file mode 100644 index 00000000000..6e864267043 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/au.png differ diff --git a/openerp/addons/base/static/img/country_flags/aw.png b/openerp/addons/base/static/img/country_flags/aw.png new file mode 100644 index 00000000000..0f362bbb3fc Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/aw.png differ diff --git a/openerp/addons/base/static/img/country_flags/ax.png b/openerp/addons/base/static/img/country_flags/ax.png new file mode 100644 index 00000000000..e546ec92d5b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ax.png differ diff --git a/openerp/addons/base/static/img/country_flags/az.png b/openerp/addons/base/static/img/country_flags/az.png new file mode 100644 index 00000000000..334567372f2 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/az.png differ diff --git a/openerp/addons/base/static/img/country_flags/ba.png b/openerp/addons/base/static/img/country_flags/ba.png new file mode 100644 index 00000000000..2abf146fc11 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ba.png differ diff --git a/openerp/addons/base/static/img/country_flags/bb.png b/openerp/addons/base/static/img/country_flags/bb.png new file mode 100644 index 00000000000..8fbafd7d12a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bb.png differ diff --git a/openerp/addons/base/static/img/country_flags/bd.png b/openerp/addons/base/static/img/country_flags/bd.png new file mode 100644 index 00000000000..1754328d655 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bd.png differ diff --git a/openerp/addons/base/static/img/country_flags/be.png b/openerp/addons/base/static/img/country_flags/be.png new file mode 100644 index 00000000000..42e4ff638bc Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/be.png differ diff --git a/openerp/addons/base/static/img/country_flags/bf.png b/openerp/addons/base/static/img/country_flags/bf.png new file mode 100644 index 00000000000..bf69a1318e8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bf.png differ diff --git a/openerp/addons/base/static/img/country_flags/bg.png b/openerp/addons/base/static/img/country_flags/bg.png new file mode 100644 index 00000000000..dbe55253e01 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bg.png differ diff --git a/openerp/addons/base/static/img/country_flags/bh.png b/openerp/addons/base/static/img/country_flags/bh.png new file mode 100644 index 00000000000..50944f1ee6f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bh.png differ diff --git a/openerp/addons/base/static/img/country_flags/bi.png b/openerp/addons/base/static/img/country_flags/bi.png new file mode 100644 index 00000000000..6a04c66cdbb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bi.png differ diff --git a/openerp/addons/base/static/img/country_flags/bj.png b/openerp/addons/base/static/img/country_flags/bj.png new file mode 100644 index 00000000000..aac7f881956 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bj.png differ diff --git a/openerp/addons/base/static/img/country_flags/bl.png b/openerp/addons/base/static/img/country_flags/bl.png new file mode 100644 index 00000000000..8fdf4c45717 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bl.png differ diff --git a/openerp/addons/base/static/img/country_flags/bm.png b/openerp/addons/base/static/img/country_flags/bm.png new file mode 100644 index 00000000000..47753a3c677 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bm.png differ diff --git a/openerp/addons/base/static/img/country_flags/bn.png b/openerp/addons/base/static/img/country_flags/bn.png new file mode 100644 index 00000000000..97aa098d88f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bn.png differ diff --git a/openerp/addons/base/static/img/country_flags/bo.png b/openerp/addons/base/static/img/country_flags/bo.png new file mode 100644 index 00000000000..44a066b1601 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bo.png differ diff --git a/openerp/addons/base/static/img/country_flags/br.png b/openerp/addons/base/static/img/country_flags/br.png new file mode 100644 index 00000000000..7231f543ffb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/br.png differ diff --git a/openerp/addons/base/static/img/country_flags/bs.png b/openerp/addons/base/static/img/country_flags/bs.png new file mode 100644 index 00000000000..d7482884694 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bs.png differ diff --git a/openerp/addons/base/static/img/country_flags/bt.png b/openerp/addons/base/static/img/country_flags/bt.png new file mode 100644 index 00000000000..7f889b3c4b7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bt.png differ diff --git a/openerp/addons/base/static/img/country_flags/bw.png b/openerp/addons/base/static/img/country_flags/bw.png new file mode 100644 index 00000000000..f3bcf5663ef Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bw.png differ diff --git a/openerp/addons/base/static/img/country_flags/by.png b/openerp/addons/base/static/img/country_flags/by.png new file mode 100644 index 00000000000..fe37c575ac4 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/by.png differ diff --git a/openerp/addons/base/static/img/country_flags/bz.png b/openerp/addons/base/static/img/country_flags/bz.png new file mode 100644 index 00000000000..bbb9903a237 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/bz.png differ diff --git a/openerp/addons/base/static/img/country_flags/ca.png b/openerp/addons/base/static/img/country_flags/ca.png new file mode 100644 index 00000000000..12807f498ec Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ca.png differ diff --git a/openerp/addons/base/static/img/country_flags/cc.png b/openerp/addons/base/static/img/country_flags/cc.png new file mode 100644 index 00000000000..84ccc4ecaeb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cc.png differ diff --git a/openerp/addons/base/static/img/country_flags/cd.png b/openerp/addons/base/static/img/country_flags/cd.png new file mode 100644 index 00000000000..e96bce99ea7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cd.png differ diff --git a/openerp/addons/base/static/img/country_flags/cf.png b/openerp/addons/base/static/img/country_flags/cf.png new file mode 100644 index 00000000000..366d4cb55e5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cf.png differ diff --git a/openerp/addons/base/static/img/country_flags/cg.png b/openerp/addons/base/static/img/country_flags/cg.png new file mode 100644 index 00000000000..e049d47c408 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cg.png differ diff --git a/openerp/addons/base/static/img/country_flags/ch.png b/openerp/addons/base/static/img/country_flags/ch.png new file mode 100644 index 00000000000..815b6664b49 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ch.png differ diff --git a/openerp/addons/base/static/img/country_flags/ci.png b/openerp/addons/base/static/img/country_flags/ci.png new file mode 100644 index 00000000000..61e92e63a9d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ci.png differ diff --git a/openerp/addons/base/static/img/country_flags/ck.png b/openerp/addons/base/static/img/country_flags/ck.png new file mode 100644 index 00000000000..fb487762817 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ck.png differ diff --git a/openerp/addons/base/static/img/country_flags/cl.png b/openerp/addons/base/static/img/country_flags/cl.png new file mode 100644 index 00000000000..5ad2daaf25c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cl.png differ diff --git a/openerp/addons/base/static/img/country_flags/cm.png b/openerp/addons/base/static/img/country_flags/cm.png new file mode 100644 index 00000000000..80a639ce7dc Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cm.png differ diff --git a/openerp/addons/base/static/img/country_flags/cn.png b/openerp/addons/base/static/img/country_flags/cn.png new file mode 100644 index 00000000000..5b28787b636 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cn.png differ diff --git a/openerp/addons/base/static/img/country_flags/co.png b/openerp/addons/base/static/img/country_flags/co.png new file mode 100644 index 00000000000..53609723452 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/co.png differ diff --git a/openerp/addons/base/static/img/country_flags/cr.png b/openerp/addons/base/static/img/country_flags/cr.png new file mode 100644 index 00000000000..40ee573607b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cr.png differ diff --git a/openerp/addons/base/static/img/country_flags/cu.png b/openerp/addons/base/static/img/country_flags/cu.png new file mode 100644 index 00000000000..31c2bf7dd0c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cu.png differ diff --git a/openerp/addons/base/static/img/country_flags/cv.png b/openerp/addons/base/static/img/country_flags/cv.png new file mode 100644 index 00000000000..d4fd1c54552 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cv.png differ diff --git a/openerp/addons/base/static/img/country_flags/cw.png b/openerp/addons/base/static/img/country_flags/cw.png new file mode 100644 index 00000000000..71fb770b24c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cw.png differ diff --git a/openerp/addons/base/static/img/country_flags/cx.png b/openerp/addons/base/static/img/country_flags/cx.png new file mode 100644 index 00000000000..d093d2e8b3b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cx.png differ diff --git a/openerp/addons/base/static/img/country_flags/cy.png b/openerp/addons/base/static/img/country_flags/cy.png new file mode 100644 index 00000000000..abbf15ce0e3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cy.png differ diff --git a/openerp/addons/base/static/img/country_flags/cz.png b/openerp/addons/base/static/img/country_flags/cz.png new file mode 100644 index 00000000000..bd3cacfe4bb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/cz.png differ diff --git a/openerp/addons/base/static/img/country_flags/de.png b/openerp/addons/base/static/img/country_flags/de.png new file mode 100644 index 00000000000..a479fee6662 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/de.png differ diff --git a/openerp/addons/base/static/img/country_flags/dj.png b/openerp/addons/base/static/img/country_flags/dj.png new file mode 100644 index 00000000000..9ac6493eff3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/dj.png differ diff --git a/openerp/addons/base/static/img/country_flags/dk.png b/openerp/addons/base/static/img/country_flags/dk.png new file mode 100644 index 00000000000..d2882e82a16 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/dk.png differ diff --git a/openerp/addons/base/static/img/country_flags/dm.png b/openerp/addons/base/static/img/country_flags/dm.png new file mode 100644 index 00000000000..f70973854b4 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/dm.png differ diff --git a/openerp/addons/base/static/img/country_flags/do.png b/openerp/addons/base/static/img/country_flags/do.png new file mode 100644 index 00000000000..24614878d56 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/do.png differ diff --git a/openerp/addons/base/static/img/country_flags/dz.png b/openerp/addons/base/static/img/country_flags/dz.png new file mode 100644 index 00000000000..86c293aebef Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/dz.png differ diff --git a/openerp/addons/base/static/img/country_flags/ec.png b/openerp/addons/base/static/img/country_flags/ec.png new file mode 100644 index 00000000000..15ba2c3f2e9 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ec.png differ diff --git a/openerp/addons/base/static/img/country_flags/ee.png b/openerp/addons/base/static/img/country_flags/ee.png new file mode 100644 index 00000000000..fbf210ef42e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ee.png differ diff --git a/openerp/addons/base/static/img/country_flags/eg.png b/openerp/addons/base/static/img/country_flags/eg.png new file mode 100644 index 00000000000..0d8132a03a9 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/eg.png differ diff --git a/openerp/addons/base/static/img/country_flags/er.png b/openerp/addons/base/static/img/country_flags/er.png new file mode 100644 index 00000000000..c89d5a95644 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/er.png differ diff --git a/openerp/addons/base/static/img/country_flags/es.png b/openerp/addons/base/static/img/country_flags/es.png new file mode 100644 index 00000000000..ea384d4d516 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/es.png differ diff --git a/openerp/addons/base/static/img/country_flags/et.png b/openerp/addons/base/static/img/country_flags/et.png new file mode 100644 index 00000000000..d2d1e4255ee Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/et.png differ diff --git a/openerp/addons/base/static/img/country_flags/fi.png b/openerp/addons/base/static/img/country_flags/fi.png new file mode 100644 index 00000000000..195226a5042 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fi.png differ diff --git a/openerp/addons/base/static/img/country_flags/fj.png b/openerp/addons/base/static/img/country_flags/fj.png new file mode 100644 index 00000000000..daee24a3746 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fj.png differ diff --git a/openerp/addons/base/static/img/country_flags/fk.png b/openerp/addons/base/static/img/country_flags/fk.png new file mode 100644 index 00000000000..f202be3118f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fk.png differ diff --git a/openerp/addons/base/static/img/country_flags/fm.png b/openerp/addons/base/static/img/country_flags/fm.png new file mode 100644 index 00000000000..c157b518251 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fm.png differ diff --git a/openerp/addons/base/static/img/country_flags/fo.png b/openerp/addons/base/static/img/country_flags/fo.png new file mode 100644 index 00000000000..eceef2d8d73 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fo.png differ diff --git a/openerp/addons/base/static/img/country_flags/fr.png b/openerp/addons/base/static/img/country_flags/fr.png new file mode 100644 index 00000000000..8fdf4c45717 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/fr.png differ diff --git a/openerp/addons/base/static/img/country_flags/ga.png b/openerp/addons/base/static/img/country_flags/ga.png new file mode 100644 index 00000000000..d4a2b71f2d5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ga.png differ diff --git a/openerp/addons/base/static/img/country_flags/gb.png b/openerp/addons/base/static/img/country_flags/gb.png new file mode 100644 index 00000000000..bf90e9b8b9c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gb.png differ diff --git a/openerp/addons/base/static/img/country_flags/gd.png b/openerp/addons/base/static/img/country_flags/gd.png new file mode 100644 index 00000000000..807755f284f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gd.png differ diff --git a/openerp/addons/base/static/img/country_flags/ge.png b/openerp/addons/base/static/img/country_flags/ge.png new file mode 100644 index 00000000000..6e813b3b310 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ge.png differ diff --git a/openerp/addons/base/static/img/country_flags/gg.png b/openerp/addons/base/static/img/country_flags/gg.png new file mode 100644 index 00000000000..20f3b15c0fd Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gg.png differ diff --git a/openerp/addons/base/static/img/country_flags/gh.png b/openerp/addons/base/static/img/country_flags/gh.png new file mode 100644 index 00000000000..5eb077085c7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gh.png differ diff --git a/openerp/addons/base/static/img/country_flags/gi.png b/openerp/addons/base/static/img/country_flags/gi.png new file mode 100644 index 00000000000..79dbd3333d5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gi.png differ diff --git a/openerp/addons/base/static/img/country_flags/gl.png b/openerp/addons/base/static/img/country_flags/gl.png new file mode 100644 index 00000000000..f7e82893f1a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gl.png differ diff --git a/openerp/addons/base/static/img/country_flags/gm.png b/openerp/addons/base/static/img/country_flags/gm.png new file mode 100644 index 00000000000..8c539e2d23c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gm.png differ diff --git a/openerp/addons/base/static/img/country_flags/gn.png b/openerp/addons/base/static/img/country_flags/gn.png new file mode 100644 index 00000000000..c0d4c72c87a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gn.png differ diff --git a/openerp/addons/base/static/img/country_flags/gq.png b/openerp/addons/base/static/img/country_flags/gq.png new file mode 100644 index 00000000000..375a7b78f62 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gq.png differ diff --git a/openerp/addons/base/static/img/country_flags/gr.png b/openerp/addons/base/static/img/country_flags/gr.png new file mode 100644 index 00000000000..7c4471b86e2 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gr.png differ diff --git a/openerp/addons/base/static/img/country_flags/gs.png b/openerp/addons/base/static/img/country_flags/gs.png new file mode 100644 index 00000000000..b0269d14acf Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gs.png differ diff --git a/openerp/addons/base/static/img/country_flags/gt.png b/openerp/addons/base/static/img/country_flags/gt.png new file mode 100644 index 00000000000..6d6998c4c6c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gt.png differ diff --git a/openerp/addons/base/static/img/country_flags/gu.png b/openerp/addons/base/static/img/country_flags/gu.png new file mode 100644 index 00000000000..847d59520f5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gu.png differ diff --git a/openerp/addons/base/static/img/country_flags/gw.png b/openerp/addons/base/static/img/country_flags/gw.png new file mode 100644 index 00000000000..88ba1d8a531 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gw.png differ diff --git a/openerp/addons/base/static/img/country_flags/gy.png b/openerp/addons/base/static/img/country_flags/gy.png new file mode 100644 index 00000000000..de7bef45285 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/gy.png differ diff --git a/openerp/addons/base/static/img/country_flags/hk.png b/openerp/addons/base/static/img/country_flags/hk.png new file mode 100644 index 00000000000..62f6453b8b7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/hk.png differ diff --git a/openerp/addons/base/static/img/country_flags/hn.png b/openerp/addons/base/static/img/country_flags/hn.png new file mode 100644 index 00000000000..e1201738ca7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/hn.png differ diff --git a/openerp/addons/base/static/img/country_flags/hr.png b/openerp/addons/base/static/img/country_flags/hr.png new file mode 100644 index 00000000000..5e24e9a52d4 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/hr.png differ diff --git a/openerp/addons/base/static/img/country_flags/ht.png b/openerp/addons/base/static/img/country_flags/ht.png new file mode 100644 index 00000000000..58ec58e41be Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ht.png differ diff --git a/openerp/addons/base/static/img/country_flags/hu.png b/openerp/addons/base/static/img/country_flags/hu.png new file mode 100644 index 00000000000..e1f237f802d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/hu.png differ diff --git a/openerp/addons/base/static/img/country_flags/id.png b/openerp/addons/base/static/img/country_flags/id.png new file mode 100644 index 00000000000..1dc8207c288 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/id.png differ diff --git a/openerp/addons/base/static/img/country_flags/ie.png b/openerp/addons/base/static/img/country_flags/ie.png new file mode 100644 index 00000000000..fb8cf9382f1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ie.png differ diff --git a/openerp/addons/base/static/img/country_flags/il.png b/openerp/addons/base/static/img/country_flags/il.png new file mode 100644 index 00000000000..c4c4f21e128 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/il.png differ diff --git a/openerp/addons/base/static/img/country_flags/im.png b/openerp/addons/base/static/img/country_flags/im.png new file mode 100644 index 00000000000..6befe9efe3a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/im.png differ diff --git a/openerp/addons/base/static/img/country_flags/in.png b/openerp/addons/base/static/img/country_flags/in.png new file mode 100644 index 00000000000..a0daccd9397 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/in.png differ diff --git a/openerp/addons/base/static/img/country_flags/io.png b/openerp/addons/base/static/img/country_flags/io.png new file mode 100644 index 00000000000..a112651851b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/io.png differ diff --git a/openerp/addons/base/static/img/country_flags/iq.png b/openerp/addons/base/static/img/country_flags/iq.png new file mode 100644 index 00000000000..1095c9d312a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/iq.png differ diff --git a/openerp/addons/base/static/img/country_flags/ir.png b/openerp/addons/base/static/img/country_flags/ir.png new file mode 100644 index 00000000000..8b9c5fac4d0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ir.png differ diff --git a/openerp/addons/base/static/img/country_flags/iran.png b/openerp/addons/base/static/img/country_flags/iran.png new file mode 100644 index 00000000000..9ca5513ace0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/iran.png differ diff --git a/openerp/addons/base/static/img/country_flags/is.png b/openerp/addons/base/static/img/country_flags/is.png new file mode 100644 index 00000000000..c5d0ffb1ec3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/is.png differ diff --git a/openerp/addons/base/static/img/country_flags/it.png b/openerp/addons/base/static/img/country_flags/it.png new file mode 100644 index 00000000000..1cd74ec0ee0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/it.png differ diff --git a/openerp/addons/base/static/img/country_flags/je.png b/openerp/addons/base/static/img/country_flags/je.png new file mode 100644 index 00000000000..ca62fe471e3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/je.png differ diff --git a/openerp/addons/base/static/img/country_flags/jm.png b/openerp/addons/base/static/img/country_flags/jm.png new file mode 100644 index 00000000000..7458372eea8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/jm.png differ diff --git a/openerp/addons/base/static/img/country_flags/jo.png b/openerp/addons/base/static/img/country_flags/jo.png new file mode 100644 index 00000000000..b5e88a3c251 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/jo.png differ diff --git a/openerp/addons/base/static/img/country_flags/jp.png b/openerp/addons/base/static/img/country_flags/jp.png new file mode 100644 index 00000000000..21f38c35847 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/jp.png differ diff --git a/openerp/addons/base/static/img/country_flags/ke.png b/openerp/addons/base/static/img/country_flags/ke.png new file mode 100644 index 00000000000..57ef9e3f20b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ke.png differ diff --git a/openerp/addons/base/static/img/country_flags/kg.png b/openerp/addons/base/static/img/country_flags/kg.png new file mode 100644 index 00000000000..1b550f6cfaa Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kg.png differ diff --git a/openerp/addons/base/static/img/country_flags/kh.png b/openerp/addons/base/static/img/country_flags/kh.png new file mode 100644 index 00000000000..299ad93e08e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kh.png differ diff --git a/openerp/addons/base/static/img/country_flags/ki.png b/openerp/addons/base/static/img/country_flags/ki.png new file mode 100644 index 00000000000..cf730409013 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ki.png differ diff --git a/openerp/addons/base/static/img/country_flags/km.png b/openerp/addons/base/static/img/country_flags/km.png new file mode 100644 index 00000000000..df5c343fce5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/km.png differ diff --git a/openerp/addons/base/static/img/country_flags/kn.png b/openerp/addons/base/static/img/country_flags/kn.png new file mode 100644 index 00000000000..9ecfa0ab9c4 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kn.png differ diff --git a/openerp/addons/base/static/img/country_flags/kp.png b/openerp/addons/base/static/img/country_flags/kp.png new file mode 100644 index 00000000000..14db96ff065 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kp.png differ diff --git a/openerp/addons/base/static/img/country_flags/kr.png b/openerp/addons/base/static/img/country_flags/kr.png new file mode 100644 index 00000000000..8b66b25f75d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kr.png differ diff --git a/openerp/addons/base/static/img/country_flags/kw.png b/openerp/addons/base/static/img/country_flags/kw.png new file mode 100644 index 00000000000..33c04a64f70 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kw.png differ diff --git a/openerp/addons/base/static/img/country_flags/ky.png b/openerp/addons/base/static/img/country_flags/ky.png new file mode 100644 index 00000000000..84279c83bcf Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ky.png differ diff --git a/openerp/addons/base/static/img/country_flags/kz.png b/openerp/addons/base/static/img/country_flags/kz.png new file mode 100644 index 00000000000..f756682c74f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/kz.png differ diff --git a/openerp/addons/base/static/img/country_flags/la.png b/openerp/addons/base/static/img/country_flags/la.png new file mode 100644 index 00000000000..27d4e2be994 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/la.png differ diff --git a/openerp/addons/base/static/img/country_flags/lb.png b/openerp/addons/base/static/img/country_flags/lb.png new file mode 100644 index 00000000000..8df863b7ca1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lb.png differ diff --git a/openerp/addons/base/static/img/country_flags/lc.png b/openerp/addons/base/static/img/country_flags/lc.png new file mode 100644 index 00000000000..15af8fee7ff Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lc.png differ diff --git a/openerp/addons/base/static/img/country_flags/li.png b/openerp/addons/base/static/img/country_flags/li.png new file mode 100644 index 00000000000..f86197e9af6 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/li.png differ diff --git a/openerp/addons/base/static/img/country_flags/lk.png b/openerp/addons/base/static/img/country_flags/lk.png new file mode 100644 index 00000000000..46bab54aabc Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lk.png differ diff --git a/openerp/addons/base/static/img/country_flags/lr.png b/openerp/addons/base/static/img/country_flags/lr.png new file mode 100644 index 00000000000..3f2cc830120 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lr.png differ diff --git a/openerp/addons/base/static/img/country_flags/ls.png b/openerp/addons/base/static/img/country_flags/ls.png new file mode 100644 index 00000000000..6b6d6b17531 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ls.png differ diff --git a/openerp/addons/base/static/img/country_flags/lt.png b/openerp/addons/base/static/img/country_flags/lt.png new file mode 100644 index 00000000000..a25f6a31aae Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lt.png differ diff --git a/openerp/addons/base/static/img/country_flags/lu.png b/openerp/addons/base/static/img/country_flags/lu.png new file mode 100644 index 00000000000..2899c7bbba1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lu.png differ diff --git a/openerp/addons/base/static/img/country_flags/lv.png b/openerp/addons/base/static/img/country_flags/lv.png new file mode 100644 index 00000000000..674a7c6c9b0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/lv.png differ diff --git a/openerp/addons/base/static/img/country_flags/ly.png b/openerp/addons/base/static/img/country_flags/ly.png new file mode 100644 index 00000000000..0e4eb2a5627 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ly.png differ diff --git a/openerp/addons/base/static/img/country_flags/ma.png b/openerp/addons/base/static/img/country_flags/ma.png new file mode 100644 index 00000000000..b43ea8c8597 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ma.png differ diff --git a/openerp/addons/base/static/img/country_flags/mc.png b/openerp/addons/base/static/img/country_flags/mc.png new file mode 100644 index 00000000000..119460a5e7f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mc.png differ diff --git a/openerp/addons/base/static/img/country_flags/md.png b/openerp/addons/base/static/img/country_flags/md.png new file mode 100644 index 00000000000..a05ba191843 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/md.png differ diff --git a/openerp/addons/base/static/img/country_flags/me.png b/openerp/addons/base/static/img/country_flags/me.png new file mode 100644 index 00000000000..aead438a92f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/me.png differ diff --git a/openerp/addons/base/static/img/country_flags/mg.png b/openerp/addons/base/static/img/country_flags/mg.png new file mode 100644 index 00000000000..75242401c76 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mg.png differ diff --git a/openerp/addons/base/static/img/country_flags/mh.png b/openerp/addons/base/static/img/country_flags/mh.png new file mode 100644 index 00000000000..4cd0d244a49 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mh.png differ diff --git a/openerp/addons/base/static/img/country_flags/mk.png b/openerp/addons/base/static/img/country_flags/mk.png new file mode 100644 index 00000000000..f313b092e4c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mk.png differ diff --git a/openerp/addons/base/static/img/country_flags/ml.png b/openerp/addons/base/static/img/country_flags/ml.png new file mode 100644 index 00000000000..eb5579c08d5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ml.png differ diff --git a/openerp/addons/base/static/img/country_flags/mm.png b/openerp/addons/base/static/img/country_flags/mm.png new file mode 100644 index 00000000000..6723bbb3b03 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mm.png differ diff --git a/openerp/addons/base/static/img/country_flags/mn.png b/openerp/addons/base/static/img/country_flags/mn.png new file mode 100644 index 00000000000..607caac7659 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mn.png differ diff --git a/openerp/addons/base/static/img/country_flags/mo.png b/openerp/addons/base/static/img/country_flags/mo.png new file mode 100644 index 00000000000..f64c674be59 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mo.png differ diff --git a/openerp/addons/base/static/img/country_flags/mp.png b/openerp/addons/base/static/img/country_flags/mp.png new file mode 100644 index 00000000000..3453b270cc0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mp.png differ diff --git a/openerp/addons/base/static/img/country_flags/mq.png b/openerp/addons/base/static/img/country_flags/mq.png new file mode 100644 index 00000000000..54ba3e92b83 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mq.png differ diff --git a/openerp/addons/base/static/img/country_flags/mr.png b/openerp/addons/base/static/img/country_flags/mr.png new file mode 100644 index 00000000000..76b032b47b8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mr.png differ diff --git a/openerp/addons/base/static/img/country_flags/ms.png b/openerp/addons/base/static/img/country_flags/ms.png new file mode 100644 index 00000000000..4f291816856 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ms.png differ diff --git a/openerp/addons/base/static/img/country_flags/mt.png b/openerp/addons/base/static/img/country_flags/mt.png new file mode 100644 index 00000000000..dbdcbf9d503 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mt.png differ diff --git a/openerp/addons/base/static/img/country_flags/mu.png b/openerp/addons/base/static/img/country_flags/mu.png new file mode 100644 index 00000000000..6eae60e796b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mu.png differ diff --git a/openerp/addons/base/static/img/country_flags/mv.png b/openerp/addons/base/static/img/country_flags/mv.png new file mode 100644 index 00000000000..6d2597d66b1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mv.png differ diff --git a/openerp/addons/base/static/img/country_flags/mw.png b/openerp/addons/base/static/img/country_flags/mw.png new file mode 100644 index 00000000000..f2f3454334b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mw.png differ diff --git a/openerp/addons/base/static/img/country_flags/mx.png b/openerp/addons/base/static/img/country_flags/mx.png new file mode 100644 index 00000000000..4c5c32d0589 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mx.png differ diff --git a/openerp/addons/base/static/img/country_flags/my.png b/openerp/addons/base/static/img/country_flags/my.png new file mode 100644 index 00000000000..7ee43cc1925 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/my.png differ diff --git a/openerp/addons/base/static/img/country_flags/mz.png b/openerp/addons/base/static/img/country_flags/mz.png new file mode 100644 index 00000000000..4d47b29b02b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/mz.png differ diff --git a/openerp/addons/base/static/img/country_flags/na.png b/openerp/addons/base/static/img/country_flags/na.png new file mode 100644 index 00000000000..0e09fd2f12a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/na.png differ diff --git a/openerp/addons/base/static/img/country_flags/nc.png b/openerp/addons/base/static/img/country_flags/nc.png new file mode 100644 index 00000000000..5e9b0ca9f73 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nc.png differ diff --git a/openerp/addons/base/static/img/country_flags/ne.png b/openerp/addons/base/static/img/country_flags/ne.png new file mode 100644 index 00000000000..e96acdedbc0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ne.png differ diff --git a/openerp/addons/base/static/img/country_flags/nf.png b/openerp/addons/base/static/img/country_flags/nf.png new file mode 100644 index 00000000000..2bb62238166 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nf.png differ diff --git a/openerp/addons/base/static/img/country_flags/ng.png b/openerp/addons/base/static/img/country_flags/ng.png new file mode 100644 index 00000000000..052ec0e9761 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ng.png differ diff --git a/openerp/addons/base/static/img/country_flags/ni.png b/openerp/addons/base/static/img/country_flags/ni.png new file mode 100644 index 00000000000..4e455f6777e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ni.png differ diff --git a/openerp/addons/base/static/img/country_flags/nl.png b/openerp/addons/base/static/img/country_flags/nl.png new file mode 100644 index 00000000000..1b5938306f5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nl.png differ diff --git a/openerp/addons/base/static/img/country_flags/no.png b/openerp/addons/base/static/img/country_flags/no.png new file mode 100644 index 00000000000..bd2840d96c1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/no.png differ diff --git a/openerp/addons/base/static/img/country_flags/np.png b/openerp/addons/base/static/img/country_flags/np.png new file mode 100644 index 00000000000..4c4beda56fe Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/np.png differ diff --git a/openerp/addons/base/static/img/country_flags/nr.png b/openerp/addons/base/static/img/country_flags/nr.png new file mode 100644 index 00000000000..923bea03faf Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nr.png differ diff --git a/openerp/addons/base/static/img/country_flags/nu.png b/openerp/addons/base/static/img/country_flags/nu.png new file mode 100644 index 00000000000..1f745218efa Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nu.png differ diff --git a/openerp/addons/base/static/img/country_flags/nz.png b/openerp/addons/base/static/img/country_flags/nz.png new file mode 100644 index 00000000000..6d669ae696e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/nz.png differ diff --git a/openerp/addons/base/static/img/country_flags/om.png b/openerp/addons/base/static/img/country_flags/om.png new file mode 100644 index 00000000000..5c61b15a0a5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/om.png differ diff --git a/openerp/addons/base/static/img/country_flags/pa.png b/openerp/addons/base/static/img/country_flags/pa.png new file mode 100644 index 00000000000..b4857d13574 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pa.png differ diff --git a/openerp/addons/base/static/img/country_flags/pe.png b/openerp/addons/base/static/img/country_flags/pe.png new file mode 100644 index 00000000000..14f7e1c86d3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pe.png differ diff --git a/openerp/addons/base/static/img/country_flags/pf.png b/openerp/addons/base/static/img/country_flags/pf.png new file mode 100644 index 00000000000..db134fc81c4 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pf.png differ diff --git a/openerp/addons/base/static/img/country_flags/pg.png b/openerp/addons/base/static/img/country_flags/pg.png new file mode 100644 index 00000000000..56e85161956 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pg.png differ diff --git a/openerp/addons/base/static/img/country_flags/ph.png b/openerp/addons/base/static/img/country_flags/ph.png new file mode 100644 index 00000000000..e74d917eb3d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ph.png differ diff --git a/openerp/addons/base/static/img/country_flags/pk.png b/openerp/addons/base/static/img/country_flags/pk.png new file mode 100644 index 00000000000..adea341ccec Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pk.png differ diff --git a/openerp/addons/base/static/img/country_flags/pl.png b/openerp/addons/base/static/img/country_flags/pl.png new file mode 100644 index 00000000000..4d0f9d19f65 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pl.png differ diff --git a/openerp/addons/base/static/img/country_flags/pm.png b/openerp/addons/base/static/img/country_flags/pm.png new file mode 100644 index 00000000000..b34299ce47b Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pm.png differ diff --git a/openerp/addons/base/static/img/country_flags/pn.png b/openerp/addons/base/static/img/country_flags/pn.png new file mode 100644 index 00000000000..890c9593342 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pn.png differ diff --git a/openerp/addons/base/static/img/country_flags/pr.png b/openerp/addons/base/static/img/country_flags/pr.png new file mode 100644 index 00000000000..5e2c7c6078a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pr.png differ diff --git a/openerp/addons/base/static/img/country_flags/pt.png b/openerp/addons/base/static/img/country_flags/pt.png new file mode 100644 index 00000000000..5fe2ae2cf63 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pt.png differ diff --git a/openerp/addons/base/static/img/country_flags/pw.png b/openerp/addons/base/static/img/country_flags/pw.png new file mode 100644 index 00000000000..fe8ef26d2e6 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/pw.png differ diff --git a/openerp/addons/base/static/img/country_flags/py.png b/openerp/addons/base/static/img/country_flags/py.png new file mode 100644 index 00000000000..0a04748f182 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/py.png differ diff --git a/openerp/addons/base/static/img/country_flags/qa.png b/openerp/addons/base/static/img/country_flags/qa.png new file mode 100644 index 00000000000..35c44fc076d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/qa.png differ diff --git a/openerp/addons/base/static/img/country_flags/ro.png b/openerp/addons/base/static/img/country_flags/ro.png new file mode 100644 index 00000000000..0cb3f29f11d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ro.png differ diff --git a/openerp/addons/base/static/img/country_flags/rs.png b/openerp/addons/base/static/img/country_flags/rs.png new file mode 100644 index 00000000000..6f7d83de2e5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/rs.png differ diff --git a/openerp/addons/base/static/img/country_flags/ru.png b/openerp/addons/base/static/img/country_flags/ru.png new file mode 100644 index 00000000000..1a99c506234 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ru.png differ diff --git a/openerp/addons/base/static/img/country_flags/rw.png b/openerp/addons/base/static/img/country_flags/rw.png new file mode 100644 index 00000000000..2abba014617 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/rw.png differ diff --git a/openerp/addons/base/static/img/country_flags/sa.png b/openerp/addons/base/static/img/country_flags/sa.png new file mode 100644 index 00000000000..6c106a540a1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sa.png differ diff --git a/openerp/addons/base/static/img/country_flags/sb.png b/openerp/addons/base/static/img/country_flags/sb.png new file mode 100644 index 00000000000..a23c5bc58ba Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sb.png differ diff --git a/openerp/addons/base/static/img/country_flags/sc.png b/openerp/addons/base/static/img/country_flags/sc.png new file mode 100644 index 00000000000..d1acc28403e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sc.png differ diff --git a/openerp/addons/base/static/img/country_flags/sd.png b/openerp/addons/base/static/img/country_flags/sd.png new file mode 100644 index 00000000000..e7694590811 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sd.png differ diff --git a/openerp/addons/base/static/img/country_flags/se.png b/openerp/addons/base/static/img/country_flags/se.png new file mode 100644 index 00000000000..a30498df565 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/se.png differ diff --git a/openerp/addons/base/static/img/country_flags/sg.png b/openerp/addons/base/static/img/country_flags/sg.png new file mode 100644 index 00000000000..16bb5445c58 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sg.png differ diff --git a/openerp/addons/base/static/img/country_flags/sh.png b/openerp/addons/base/static/img/country_flags/sh.png new file mode 100644 index 00000000000..cb48a6a2e2f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sh.png differ diff --git a/openerp/addons/base/static/img/country_flags/si.png b/openerp/addons/base/static/img/country_flags/si.png new file mode 100644 index 00000000000..b749349245d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/si.png differ diff --git a/openerp/addons/base/static/img/country_flags/sk.png b/openerp/addons/base/static/img/country_flags/sk.png new file mode 100644 index 00000000000..1609f2c8d9a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sk.png differ diff --git a/openerp/addons/base/static/img/country_flags/sl.png b/openerp/addons/base/static/img/country_flags/sl.png new file mode 100644 index 00000000000..ef67f96c22a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sl.png differ diff --git a/openerp/addons/base/static/img/country_flags/sm.png b/openerp/addons/base/static/img/country_flags/sm.png new file mode 100644 index 00000000000..b515c509030 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sm.png differ diff --git a/openerp/addons/base/static/img/country_flags/sn.png b/openerp/addons/base/static/img/country_flags/sn.png new file mode 100644 index 00000000000..2cb1d0a36c3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sn.png differ diff --git a/openerp/addons/base/static/img/country_flags/so.png b/openerp/addons/base/static/img/country_flags/so.png new file mode 100644 index 00000000000..d6772bdd702 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/so.png differ diff --git a/openerp/addons/base/static/img/country_flags/sr.png b/openerp/addons/base/static/img/country_flags/sr.png new file mode 100644 index 00000000000..9be5dc7b952 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sr.png differ diff --git a/openerp/addons/base/static/img/country_flags/ss.png b/openerp/addons/base/static/img/country_flags/ss.png new file mode 100644 index 00000000000..a07a513e189 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ss.png differ diff --git a/openerp/addons/base/static/img/country_flags/st.png b/openerp/addons/base/static/img/country_flags/st.png new file mode 100644 index 00000000000..b3abd9852f3 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/st.png differ diff --git a/openerp/addons/base/static/img/country_flags/sv.png b/openerp/addons/base/static/img/country_flags/sv.png new file mode 100644 index 00000000000..4685c62e305 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sv.png differ diff --git a/openerp/addons/base/static/img/country_flags/sx.png b/openerp/addons/base/static/img/country_flags/sx.png new file mode 100644 index 00000000000..d8d40f75924 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sx.png differ diff --git a/openerp/addons/base/static/img/country_flags/sy.png b/openerp/addons/base/static/img/country_flags/sy.png new file mode 100644 index 00000000000..a45853957cc Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sy.png differ diff --git a/openerp/addons/base/static/img/country_flags/sz.png b/openerp/addons/base/static/img/country_flags/sz.png new file mode 100644 index 00000000000..49b2a9360c1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/sz.png differ diff --git a/openerp/addons/base/static/img/country_flags/tc.png b/openerp/addons/base/static/img/country_flags/tc.png new file mode 100644 index 00000000000..078b226810d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tc.png differ diff --git a/openerp/addons/base/static/img/country_flags/td.png b/openerp/addons/base/static/img/country_flags/td.png new file mode 100644 index 00000000000..2e8603a6012 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/td.png differ diff --git a/openerp/addons/base/static/img/country_flags/tf.png b/openerp/addons/base/static/img/country_flags/tf.png new file mode 100644 index 00000000000..945c7afb0b1 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tf.png differ diff --git a/openerp/addons/base/static/img/country_flags/tg.png b/openerp/addons/base/static/img/country_flags/tg.png new file mode 100644 index 00000000000..3154c5cb830 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tg.png differ diff --git a/openerp/addons/base/static/img/country_flags/th.png b/openerp/addons/base/static/img/country_flags/th.png new file mode 100644 index 00000000000..f39ce45eeee Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/th.png differ diff --git a/openerp/addons/base/static/img/country_flags/tj.png b/openerp/addons/base/static/img/country_flags/tj.png new file mode 100644 index 00000000000..15d59605186 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tj.png differ diff --git a/openerp/addons/base/static/img/country_flags/tk.png b/openerp/addons/base/static/img/country_flags/tk.png new file mode 100644 index 00000000000..b191458e187 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tk.png differ diff --git a/openerp/addons/base/static/img/country_flags/tl.png b/openerp/addons/base/static/img/country_flags/tl.png new file mode 100644 index 00000000000..0031a4e41f9 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tl.png differ diff --git a/openerp/addons/base/static/img/country_flags/tm.png b/openerp/addons/base/static/img/country_flags/tm.png new file mode 100644 index 00000000000..6699276a8ed Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tm.png differ diff --git a/openerp/addons/base/static/img/country_flags/tn.png b/openerp/addons/base/static/img/country_flags/tn.png new file mode 100644 index 00000000000..04587942bb7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tn.png differ diff --git a/openerp/addons/base/static/img/country_flags/to.png b/openerp/addons/base/static/img/country_flags/to.png new file mode 100644 index 00000000000..51a1556d5e9 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/to.png differ diff --git a/openerp/addons/base/static/img/country_flags/tp.png b/openerp/addons/base/static/img/country_flags/tp.png new file mode 100644 index 00000000000..2ec85c15394 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tp.png differ diff --git a/openerp/addons/base/static/img/country_flags/tr.png b/openerp/addons/base/static/img/country_flags/tr.png new file mode 100644 index 00000000000..ebf2a31e807 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tr.png differ diff --git a/openerp/addons/base/static/img/country_flags/tt.png b/openerp/addons/base/static/img/country_flags/tt.png new file mode 100644 index 00000000000..e49c3682a50 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tt.png differ diff --git a/openerp/addons/base/static/img/country_flags/tv.png b/openerp/addons/base/static/img/country_flags/tv.png new file mode 100644 index 00000000000..ab10c93d5d7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tv.png differ diff --git a/openerp/addons/base/static/img/country_flags/tz.png b/openerp/addons/base/static/img/country_flags/tz.png new file mode 100644 index 00000000000..d4e99a62df7 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/tz.png differ diff --git a/openerp/addons/base/static/img/country_flags/ua.png b/openerp/addons/base/static/img/country_flags/ua.png new file mode 100644 index 00000000000..57cf957010d Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ua.png differ diff --git a/openerp/addons/base/static/img/country_flags/ug.png b/openerp/addons/base/static/img/country_flags/ug.png new file mode 100644 index 00000000000..908784213f0 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ug.png differ diff --git a/openerp/addons/base/static/img/country_flags/us.png b/openerp/addons/base/static/img/country_flags/us.png new file mode 100644 index 00000000000..801ef4e8abb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/us.png differ diff --git a/openerp/addons/base/static/img/country_flags/uy.png b/openerp/addons/base/static/img/country_flags/uy.png new file mode 100644 index 00000000000..7af80710a3f Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/uy.png differ diff --git a/openerp/addons/base/static/img/country_flags/uz.png b/openerp/addons/base/static/img/country_flags/uz.png new file mode 100644 index 00000000000..54840bd935c Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/uz.png differ diff --git a/openerp/addons/base/static/img/country_flags/va.png b/openerp/addons/base/static/img/country_flags/va.png new file mode 100644 index 00000000000..28933fb7e04 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/va.png differ diff --git a/openerp/addons/base/static/img/country_flags/vc.png b/openerp/addons/base/static/img/country_flags/vc.png new file mode 100644 index 00000000000..62b9091dc9a Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/vc.png differ diff --git a/openerp/addons/base/static/img/country_flags/ve.png b/openerp/addons/base/static/img/country_flags/ve.png new file mode 100644 index 00000000000..7ab81205f84 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ve.png differ diff --git a/openerp/addons/base/static/img/country_flags/vg.png b/openerp/addons/base/static/img/country_flags/vg.png new file mode 100644 index 00000000000..9a33f8cf9e6 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/vg.png differ diff --git a/openerp/addons/base/static/img/country_flags/vi.png b/openerp/addons/base/static/img/country_flags/vi.png new file mode 100644 index 00000000000..b6361f49e57 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/vi.png differ diff --git a/openerp/addons/base/static/img/country_flags/vn.png b/openerp/addons/base/static/img/country_flags/vn.png new file mode 100644 index 00000000000..25753977ec5 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/vn.png differ diff --git a/openerp/addons/base/static/img/country_flags/vu.png b/openerp/addons/base/static/img/country_flags/vu.png new file mode 100644 index 00000000000..124c7cf7b56 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/vu.png differ diff --git a/openerp/addons/base/static/img/country_flags/ws.png b/openerp/addons/base/static/img/country_flags/ws.png new file mode 100644 index 00000000000..787354394c8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ws.png differ diff --git a/openerp/addons/base/static/img/country_flags/ye.png b/openerp/addons/base/static/img/country_flags/ye.png new file mode 100644 index 00000000000..07c4c8ef1fb Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/ye.png differ diff --git a/openerp/addons/base/static/img/country_flags/za.png b/openerp/addons/base/static/img/country_flags/za.png new file mode 100644 index 00000000000..dc4fb4df547 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/za.png differ diff --git a/openerp/addons/base/static/img/country_flags/zm.png b/openerp/addons/base/static/img/country_flags/zm.png new file mode 100644 index 00000000000..6275c83148e Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/zm.png differ diff --git a/openerp/addons/base/static/img/country_flags/zw.png b/openerp/addons/base/static/img/country_flags/zw.png new file mode 100644 index 00000000000..de98aa7f4d8 Binary files /dev/null and b/openerp/addons/base/static/img/country_flags/zw.png differ diff --git a/openerp/addons/base/static/src/js/apps.js b/openerp/addons/base/static/src/js/apps.js index e339ed2230e..115d35fcc4f 100644 --- a/openerp/addons/base/static/src/js/apps.js +++ b/openerp/addons/base/static/src/js/apps.js @@ -63,8 +63,8 @@ openerp.base = function(instance) { if (instance.base.apps_client) { return check_client_available(instance.base.apps_client); } else { - var ICP = new instance.web.Model('ir.config_parameter'); - return ICP.call('get_param', ['apps.server', 'https://apps.openerp.com/apps']).then(function(u) { + var Mod = new instance.web.Model('ir.module.module'); + return Mod.call('get_apps_server').then(function(u) { var link = $(_.str.sprintf('', u))[0]; var host = _.str.sprintf('%s//%s', link.protocol, link.host); var dbname = link.pathname; diff --git a/openerp/addons/base/tests/test_db_cursor.py b/openerp/addons/base/tests/test_db_cursor.py index b3ce36467bb..d60f38185b9 100644 --- a/openerp/addons/base/tests/test_db_cursor.py +++ b/openerp/addons/base/tests/test_db_cursor.py @@ -21,7 +21,7 @@ class test_cr_execute(unittest2.TestCase): """ Try to use iterable but non-list or int params in query parameters. """ - with registry().cursor(auto_commit=False) as cr: + with registry().cursor() as cr: with self.assertRaises(ValueError): cr.execute("SELECT id FROM res_users WHERE login=%s", 'admin') with self.assertRaises(ValueError): diff --git a/openerp/addons/base/tests/test_expression.py b/openerp/addons/base/tests/test_expression.py index a05009b0252..de7e0472479 100644 --- a/openerp/addons/base/tests/test_expression.py +++ b/openerp/addons/base/tests/test_expression.py @@ -1,6 +1,7 @@ import unittest2 import openerp +from openerp.osv.expression import get_unaccent_wrapper from openerp.osv.orm import BaseModel import openerp.tests.common as common @@ -124,6 +125,7 @@ class test_expression(common.TransactionCase): def test_20_auto_join(self): registry, cr, uid = self.registry, self.cr, self.uid + unaccent = get_unaccent_wrapper(cr) # Get models partner_obj = registry('res.partner') @@ -180,8 +182,11 @@ class test_expression(common.TransactionCase): sql_query = self.query_list[0].get_sql() self.assertIn('res_partner_bank', sql_query[0], "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect main table") - self.assertIn('"res_partner_bank"."name" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_partner_bank"."name"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect where condition") + self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]), "_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect parameter") sql_query = self.query_list[2].get_sql() @@ -217,8 +222,11 @@ class test_expression(common.TransactionCase): "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect main table") self.assertIn('"res_partner_bank" as "res_partner__bank_ids"', sql_query[0], "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join") - self.assertIn('"res_partner__bank_ids"."name" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_partner__bank_ids"."name"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect where condition") + self.assertIn('"res_partner"."id"="res_partner__bank_ids"."partner_id"', sql_query[1], "_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join condition") self.assertEqual(set(['%' + name_test + '%']), set(sql_query[2]), @@ -296,8 +304,11 @@ class test_expression(common.TransactionCase): sql_query = self.query_list[0].get_sql() self.assertIn('"res_country"', sql_query[0], "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table") - self.assertIn('"res_country"."code" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_country"."code"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition") + self.assertEqual(['%' + name_test + '%'], sql_query[2], "_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect parameter") sql_query = self.query_list[1].get_sql() @@ -327,8 +338,11 @@ class test_expression(common.TransactionCase): "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table") self.assertIn('"res_country" as "res_country_state__country_id"', sql_query[0], "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join") - self.assertIn('"res_country_state__country_id"."code" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_country_state__country_id"."code"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect where condition") + self.assertIn('"res_country_state"."country_id"="res_country_state__country_id"."id"', sql_query[1], "_auto_join on for country_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect join condition") self.assertEqual(['%' + name_test + '%'], sql_query[2], @@ -358,8 +372,11 @@ class test_expression(common.TransactionCase): "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join") self.assertIn('"res_country" as "res_partner__state_id__country_id"', sql_query[0], "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join") - self.assertIn('"res_partner__state_id__country_id"."code" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_partner__state_id__country_id"."code"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect where condition") + self.assertIn('"res_partner"."state_id"="res_partner__state_id"."id"', sql_query[1], "_auto_join on: ('state_id.country_id.code', 'like', '..') query incorrect join condition") self.assertIn('"res_partner__state_id"."country_id"="res_partner__state_id__country_id"."id"', sql_query[1], @@ -385,7 +402,9 @@ class test_expression(common.TransactionCase): "_auto_join on one2many with domains incorrect result") # Test produced queries that domains effectively present sql_query = self.query_list[0].get_sql() - self.assertIn('"res_partner__child_ids__bank_ids"."acc_number" like %s', sql_query[1], + + expected = "%s::text like %s" % (unaccent('"res_partner__child_ids__bank_ids"."acc_number"'), unaccent('%s')) + self.assertIn(expected, sql_query[1], "_auto_join on one2many with domains incorrect result") # TDE TODO: check first domain has a correct table name self.assertIn('"res_partner__child_ids"."name" = %s', sql_query[1], @@ -447,6 +466,19 @@ class test_expression(common.TransactionCase): domain = [('x', 'in', ['y', 'z']), ('a.v', '=', 'e'), '|', '|', ('a', '=', 'b'), '!', ('c', '>', 'd'), ('e', '!=', 'f'), ('g', '=', 'h')] norm_domain = ['&', '&', '&'] + domain assert norm_domain == expression.normalize_domain(domain), "Non-normalized domains should be properly normalized" + + def test_translate_search(self): + Country = self.registry('res.country') + be = self.ref('base.be') + domains = [ + [('name', '=', 'Belgium')], + [('name', 'ilike', 'Belgi')], + [('name', 'in', ['Belgium', 'Care Bears'])], + ] + + for domain in domains: + ids = Country.search(self.cr, self.uid, domain) + self.assertListEqual([be], ids) if __name__ == '__main__': unittest2.main() diff --git a/openerp/addons/base/tests/test_ir_sequence.py b/openerp/addons/base/tests/test_ir_sequence.py index e925fffa3b1..18b56daa58c 100644 --- a/openerp/addons/base/tests/test_ir_sequence.py +++ b/openerp/addons/base/tests/test_ir_sequence.py @@ -21,7 +21,7 @@ def registry(model): return openerp.modules.registry.RegistryManager.get(DB)[model] def cursor(): - return openerp.modules.registry.RegistryManager.get(DB).db.cursor() + return openerp.modules.registry.RegistryManager.get(DB).cursor() def drop_sequence(code): diff --git a/openerp/addons/base/tests/test_orm.py b/openerp/addons/base/tests/test_orm.py index fcd81965b8c..29a5a2880d1 100644 --- a/openerp/addons/base/tests/test_orm.py +++ b/openerp/addons/base/tests/test_orm.py @@ -134,13 +134,17 @@ class TestORM(common.TransactionCase): rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date' + ':' + interval) result = {} for r in rg: - result[r['date']] = set(self.partner.search(self.cr, self.uid, r['__domain'])) + result[r['date:' + interval]] = set(self.partner.search(self.cr, self.uid, r['__domain'])) return result self.assertEqual(len(read_group('day')), len(partners_by_day)) self.assertEqual(len(read_group('month')), len(partners_by_month)) self.assertEqual(len(read_group('year')), len(partners_by_year)) + rg = self.partner.read_group(self.cr, self.uid, [('id', 'in', all_partners)], + ['date'], ['date:month', 'date:day'], lazy=False) + self.assertEqual(len(rg), len(all_partners)) + class TestInherits(common.TransactionCase): """ test the behavior of the orm for models that use _inherits; diff --git a/openerp/addons/base/tests/test_uninstall.py b/openerp/addons/base/tests/test_uninstall.py index 2425249afa4..b5c51c81405 100644 --- a/openerp/addons/base/tests/test_uninstall.py +++ b/openerp/addons/base/tests/test_uninstall.py @@ -13,7 +13,7 @@ def registry(model): return openerp.modules.registry.RegistryManager.get(DB)[model] def cursor(): - return openerp.modules.registry.RegistryManager.get(DB).db.cursor() + return openerp.modules.registry.RegistryManager.get(DB).cursor() def get_module(module_name): registry = openerp.modules.registry.RegistryManager.get(DB) diff --git a/openerp/addons/base/tests/test_views.py b/openerp/addons/base/tests/test_views.py index 06030a84792..f0967836726 100644 --- a/openerp/addons/base/tests/test_views.py +++ b/openerp/addons/base/tests/test_views.py @@ -28,7 +28,7 @@ class ViewCase(common.TransactionCase): self.assertTreesEqual(c1, c2, msg) -class TestNodeLocator(common.BaseCase): +class TestNodeLocator(common.TransactionCase): """ The node locator returns None when it can not find a node, and the first match when it finds something (no jquery-style node sets) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index e7ba695f19c..18ac69c38e2 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -29,6 +29,7 @@ GNU Public Licence. (c) 2003-TODAY, Fabien Pinckaers - OpenERP SA """ +import atexit import logging import os import signal @@ -78,16 +79,23 @@ def report_configuration(): ('database user', config['db_user'])]: _logger.info("%s: %s", name, value) +def rm_pid_file(): + config = openerp.tools.config + if not openerp.evented and os.path.exists(config['pidfile']): + os.unlink(config['pidfile']) + def setup_pid_file(): """ Create a file with the process id written in it. This function assumes the configuration has been initialized. """ config = openerp.tools.config - if config['pidfile']: + if not openerp.evented and config['pidfile']: with open(config['pidfile'], 'w') as fd: pidtext = "%d" % (os.getpid()) fd.write(pidtext) + atexit.register(rm_pid_file) + def export_translation(): config = openerp.tools.config @@ -103,7 +111,7 @@ def export_translation(): fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower() buf = file(config["translate_out"], "w") registry = openerp.modules.registry.RegistryManager.new(dbname) - cr = registry.db.cursor() + cr = registry.cursor() openerp.tools.trans_export(config["language"], config["translate_modules"] or ["all"], buf, fileformat, cr) cr.close() @@ -117,7 +125,7 @@ def import_translation(): dbname = config['db_name'] registry = openerp.modules.registry.RegistryManager.new(dbname) - cr = registry.db.cursor() + cr = registry.cursor() openerp.tools.trans_load( cr, config["translate_in"], config["language"], context=context) cr.commit() @@ -155,8 +163,6 @@ def main(args): setup_pid_file() rc = openerp.service.server.start(preload=preload, stop=stop) - if config['pidfile']: - os.unlink(config['pidfile']) sys.exit(rc) class Server(Command): diff --git a/openerp/http.py b/openerp/http.py index a4fc08bacde..8d7497fc40d 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -235,10 +235,7 @@ class WebRequest(object): """ # some magic to lazy create the cr if not self._cr: - # Test cursors - self._cr = openerp.tests.common.acquire_test_cursor(self.session_id) - if not self._cr: - self._cr = self.registry.db.cursor() + self._cr = self.registry.cursor() return self._cr def __enter__(self): @@ -249,14 +246,9 @@ class WebRequest(object): _request_stack.pop() if self._cr: - # Dont close test cursors - if not openerp.tests.common.release_test_cursor(self._cr): - if exc_type is None and not self._failed: - self._cr.commit() - else: - # just to be explicit - happens at close() anyway - self._cr.rollback() - self._cr.close() + if exc_type is None and not self._failed: + self._cr.commit() + self._cr.close() # just to be sure no one tries to re-use the request self.disable_db = True self.uid = None @@ -270,6 +262,13 @@ class WebRequest(object): self.endpoint = endpoint self.auth_method = auth + + def _handle_exception(self, exception): + """Called within an except block to allow converting exceptions + to abitrary responses. Anything returned (except None) will + be used as response.""" + raise + def _call_function(self, *args, **kwargs): request = self if self.endpoint.routing['type'] != self._request_type: @@ -287,7 +286,7 @@ class WebRequest(object): def checked_call(___dbname, *a, **kw): # The decorator can call us more than once if there is an database error. In this # case, the request cursor is unusable. Rollback transaction to create a new one. - if self._cr and not openerp.tools.config['test_enable']: + if self._cr: self._cr.rollback() return self.endpoint(*a, **kw) @@ -421,39 +420,15 @@ class JsonRequest(WebRequest): self.params = dict(self.jsonrequest.get("params", {})) self.context = self.params.pop('context', dict(self.session.context)) - def dispatch(self): - """ Calls the method asked for by the JSON-RPC2 or JSONP request - """ - if self.jsonp_handler: - return self.jsonp_handler() - response = {"jsonrpc": "2.0" } - error = None - - try: - response['id'] = self.jsonrequest.get('id') - response["result"] = self._call_function(**self.params) - except AuthenticationError, e: - _logger.exception("JSON-RPC AuthenticationError in %s.", self.httprequest.path) - se = serialize_exception(e) - error = { - 'code': 100, - 'message': "OpenERP Session Invalid", - 'data': se - } - self._failed = e # prevent tx commit - except Exception, e: - # Mute test cursor error for runbot - if not (openerp.tools.config['test_enable'] and isinstance(e, psycopg2.OperationalError)): - _logger.exception("JSON-RPC Exception in %s.", self.httprequest.path) - se = serialize_exception(e) - error = { - 'code': 200, - 'message': "OpenERP Server Error", - 'data': se - } - self._failed = e # prevent tx commit - if error: - response["error"] = error + def _json_response(self, result=None, error=None): + response = { + 'jsonrpc': '2.0', + 'id': self.jsonrequest.get('id') + } + if error is not None: + response['error'] = error + if result is not None: + response['result'] = result if self.jsonp: # If we use jsonp, that's mean we are called from another host @@ -466,8 +441,36 @@ class JsonRequest(WebRequest): mime = 'application/json' body = simplejson.dumps(response) - r = Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))]) - return r + return Response( + body, headers=[('Content-Type', mime), + ('Content-Length', len(body))]) + + def _handle_exception(self, exception): + """Called within an except block to allow converting exceptions + to abitrary responses. Anything returned (except None) will + be used as response.""" + _logger.exception("Exception during JSON request handling.") + self._failed = exception # prevent tx commit + error = { + 'code': 200, + 'message': "OpenERP Server Error", + 'data': serialize_exception(exception) + } + if isinstance(exception, AuthenticationError): + error['code'] = 100 + error['message'] = "OpenERP Session Invalid" + return self._json_response(error=error) + + def dispatch(self): + """ Calls the method asked for by the JSON-RPC2 or JSONP request + """ + if self.jsonp_handler: + return self.jsonp_handler() + try: + result = self._call_function(**self.params) + return self._json_response(result) + except Exception, e: + return self._handle_exception(e) def serialize_exception(e): tmp = { @@ -1094,7 +1097,7 @@ class Root(object): return self.dispatch(environ, start_response) def load_addons(self): - """ Load all addons from addons patch containg static files and + """ Load all addons from addons path containing static files and controllers and configure them. """ # TODO should we move this to ir.http so that only configured modules are served ? statics = {} diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 551b7a664b5..82e86e83ce2 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -169,13 +169,15 @@ def get_module_icon(module): return ('/' + module + '/') + '/'.join(iconpath) return '/base/' + '/'.join(iconpath) -def load_information_from_description_file(module): +def load_information_from_description_file(module, mod_path=None): """ :param module: The name of the module (sale, purchase, ...) + :param mod_path: Physical path of module, if not providedThe name of the module (sale, purchase, ...) """ - terp_file = get_module_resource(module, '__openerp__.py') - mod_path = get_module_path(module) + if not mod_path: + mod_path = get_module_path(module) + terp_file = opj(mod_path, '__openerp__.py') if terp_file: info = {} if os.path.isfile(terp_file): diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index 78b7e5caeab..ef6aaf19d5a 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -58,7 +58,10 @@ class Registry(Mapping): self._init_modules = set() self.db_name = db_name - self.db = openerp.sql_db.db_connect(db_name) + self._db = openerp.sql_db.db_connect(db_name) + + # special cursor for test mode; None means "normal" mode + self.test_cr = None # Indicates that the registry is self.ready = False @@ -75,7 +78,7 @@ class Registry(Mapping): # Useful only in a multi-process context. self._any_cache_cleared = False - cr = self.db.cursor() + cr = self.cursor() has_unaccent = openerp.modules.db.has_unaccent(cr) if openerp.tools.config['unaccent'] and not has_unaccent: _logger.warning("The option --unaccent was given but no unaccent() function was found in database.") @@ -102,6 +105,10 @@ class Registry(Mapping): """ Return the model with the given name or raise KeyError if it doesn't exist.""" return self.models[model_name] + def __call__(self, model_name): + """ Same as ``self[model_name]``. """ + return self.models[model_name] + def do_parent_store(self, cr): for o in self._init_parent: self.get(o)._parent_store_compute(cr) @@ -183,27 +190,38 @@ class Registry(Mapping): r, c) return r, c - @contextmanager - def cursor(self, auto_commit=True): - cr = self.db.cursor() - try: - yield cr - if auto_commit: - cr.commit() - finally: - cr.close() + def enter_test_mode(self): + """ Enter the 'test' mode, where one cursor serves several requests. """ + assert self.test_cr is None + self.test_cr = self._db.test_cursor() + RegistryManager.enter_test_mode() -class TestRLock(object): - def __init__(self): - self._lock = threading.RLock() + def leave_test_mode(self): + """ Leave the test mode. """ + assert self.test_cr is not None + self.test_cr.close(force=True) # close the cursor for real + self.test_cr = None + RegistryManager.leave_test_mode() + + def cursor(self): + """ Return a new cursor for the database. The cursor itself may be used + as a context manager to commit/rollback and close automatically. + """ + if self.test_cr is not None: + # While in test mode, we use one special cursor across requests. The + # test cursor uses a reentrant lock to serialize accesses. The lock + # is granted here by cursor(), and automatically released by the + # cursor itself in its method close(). + self.test_cr.acquire() + return self.test_cr + return self._db.cursor() + +class DummyRLock(object): + """ Dummy reentrant lock, to be used while running rpc and js tests """ def acquire(self): - if openerp.tools.config['test_enable']: - return - return self._lock.acquire() + pass def release(self): - if openerp.tools.config['test_enable']: - return - return self._lock.release() + pass def __enter__(self): self.acquire() def __exit__(self, type, value, traceback): @@ -219,12 +237,30 @@ class RegistryManager(object): # Mapping between db name and model registry. # Accessed through the methods below. registries = {} - registries_lock = TestRLock() + _lock = threading.RLock() + _saved_lock = None + + @classmethod + def lock(cls): + """ Return the current registry lock. """ + return cls._lock + + @classmethod + def enter_test_mode(cls): + """ Enter the 'test' mode, where the registry is no longer locked. """ + assert cls._saved_lock is None + cls._lock, cls._saved_lock = DummyRLock(), cls._lock + + @classmethod + def leave_test_mode(cls): + """ Leave the 'test' mode. """ + assert cls._saved_lock is not None + cls._lock, cls._saved_lock = cls._saved_lock, None @classmethod def get(cls, db_name, force_demo=False, status=None, update_module=False): """ Return a registry for a given database name.""" - with cls.registries_lock: + with cls.lock(): try: return cls.registries[db_name] except KeyError: @@ -244,7 +280,7 @@ class RegistryManager(object): """ import openerp.modules - with cls.registries_lock: + with cls.lock(): registry = Registry(db_name) # Initializing a registry will call general code which will in turn @@ -259,7 +295,7 @@ class RegistryManager(object): registry.base_registry_signaling_sequence = seq_registry registry.base_cache_signaling_sequence = seq_cache # This should be a method on Registry - openerp.modules.load_modules(registry.db, force_demo, status, update_module) + openerp.modules.load_modules(registry._db, force_demo, status, update_module) except Exception: del cls.registries[db_name] raise @@ -269,7 +305,7 @@ class RegistryManager(object): # Yeah, crazy. registry = cls.registries[db_name] - cr = registry.db.cursor() + cr = registry.cursor() try: registry.do_parent_store(cr) cr.commit() @@ -286,7 +322,7 @@ class RegistryManager(object): @classmethod def delete(cls, db_name): """Delete the registry linked to a given database. """ - with cls.registries_lock: + with cls.lock(): if db_name in cls.registries: cls.registries[db_name].clear_caches() del cls.registries[db_name] @@ -294,7 +330,7 @@ class RegistryManager(object): @classmethod def delete_all(cls): """Delete all the registries. """ - with cls.registries_lock: + with cls.lock(): for db_name in cls.registries.keys(): cls.delete(db_name) @@ -309,7 +345,7 @@ class RegistryManager(object): This method is given to spare you a ``RegistryManager.get(db_name)`` that would loads the given database if it was not already loaded. """ - with cls.registries_lock: + with cls.lock(): if db_name in cls.registries: cls.registries[db_name].clear_caches() @@ -325,7 +361,7 @@ class RegistryManager(object): changed = False if openerp.multi_process and db_name in cls.registries: registry = cls.get(db_name) - cr = registry.db.cursor() + cr = registry.cursor() try: cr.execute(""" SELECT base_registry_signaling.last_value, @@ -371,7 +407,7 @@ class RegistryManager(object): registry = cls.get(db_name) if registry.any_cache_cleared(): _logger.info("At least one model cache has been cleared, signaling through the database.") - cr = registry.db.cursor() + cr = registry.cursor() r = 1 try: cr.execute("select nextval('base_cache_signaling')") @@ -386,7 +422,7 @@ class RegistryManager(object): if openerp.multi_process and db_name in cls.registries: _logger.info("Registry changed, signaling through the database") registry = cls.get(db_name) - cr = registry.db.cursor() + cr = registry.cursor() r = 1 try: cr.execute("select nextval('base_registry_signaling')") diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index 648a8447292..d3231c54462 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -429,6 +429,10 @@ def select_distinct_from_where_not_null(cr, select_field, from_table): cr.execute('SELECT distinct("%s") FROM "%s" where "%s" is not null' % (select_field, from_table, select_field)) return [r[0] for r in cr.fetchall()] +def get_unaccent_wrapper(cr): + if openerp.modules.registry.RegistryManager.get(cr.dbname).has_unaccent: + return lambda x: "unaccent(%s)" % (x,) + return lambda x: x # -------------------------------------------------- # ExtendedLeaf class for managing leafs and contexts @@ -630,7 +634,7 @@ class expression(object): :attr list expression: the domain expression, that will be normalized and prepared """ - self.has_unaccent = openerp.modules.registry.RegistryManager.get(cr.dbname).has_unaccent + self._unaccent = get_unaccent_wrapper(cr) self.joins = [] self.root_model = table @@ -1012,10 +1016,10 @@ class expression(object): else: if field._type == 'datetime' and right and len(right) == 10: - if operator in ('>', '>=', '='): - right += ' 00:00:00' - elif operator in ('<', '<='): + if operator in ('>', '<='): right += ' 23:59:59' + else: + right += ' 00:00:00' push(create_substitution_leaf(leaf, (left, operator, right), working_model)) elif field.translate and right: @@ -1030,33 +1034,37 @@ class expression(object): sql_operator = sql_operator[4:] if sql_operator[:3] == 'not' else '=' inselect_operator = 'not inselect' - subselect = '( SELECT res_id' \ - ' FROM ir_translation' \ - ' WHERE name = %s' \ - ' AND lang = %s' \ - ' AND type = %s' - instr = ' %s' - #Covering in,not in operators with operands (%s,%s) ,etc. - if sql_operator == 'in': - instr = ','.join(['%s'] * len(right)) - subselect += ' AND value ' + sql_operator + ' ' + " (" + instr + ")" \ - ') UNION (' \ - ' SELECT id' \ - ' FROM "' + working_model._table + '"' \ - ' WHERE "' + left + '" ' + sql_operator + ' ' + " (" + instr + "))" - else: - subselect += ' AND value ' + sql_operator + instr + \ - ') UNION (' \ - ' SELECT id' \ - ' FROM "' + working_model._table + '"' \ - ' WHERE "' + left + '" ' + sql_operator + instr + ")" + unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x - params = [working_model._name + ',' + left, - context.get('lang', False) or 'en_US', - 'model', - right, - right, - ] + trans_left = unaccent('value') + quote_left = unaccent(_quote(left)) + instr = unaccent('%s') + + if sql_operator == 'in': + # params will be flatten by to_sql() => expand the placeholders + instr = '(%s)' % ', '.join(['%s'] * len(right)) + + subselect = """(SELECT res_id + FROM ir_translation + WHERE name = %s + AND lang = %s + AND type = %s + AND {trans_left} {operator} {right} + ) UNION ( + SELECT id + FROM "{table}" + WHERE {left} {operator} {right} + ) + """.format(trans_left=trans_left, operator=sql_operator, + right=instr, table=working_model._table, left=quote_left) + + params = ( + working_model._name + ',' + left, + context.get('lang') or 'en_US', + 'model', + right, + right, + ) push(create_substitution_leaf(leaf, ('id', inselect_operator, (subselect, params)), working_model)) else: @@ -1174,15 +1182,15 @@ class expression(object): else: need_wildcard = operator in ('like', 'ilike', 'not like', 'not ilike') sql_operator = {'=like': 'like', '=ilike': 'ilike'}.get(operator, operator) + cast = '::text' if sql_operator.endswith('like') else '' if left in model._columns: format = need_wildcard and '%s' or model._columns[left]._symbol_set[0] - if self.has_unaccent and sql_operator in ('ilike', 'not ilike'): - query = '(unaccent(%s."%s") %s unaccent(%s))' % (table_alias, left, sql_operator, format) - else: - query = '(%s."%s" %s %s)' % (table_alias, left, sql_operator, format) + unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x + column = '%s.%s' % (table_alias, _quote(left)) + query = '(%s%s %s %s)' % (unaccent(column), cast, sql_operator, unaccent(format)) elif left in MAGIC_COLUMNS: - query = "(%s.\"%s\" %s %%s)" % (table_alias, left, sql_operator) + query = "(%s.\"%s\"%s %s %%s)" % (table_alias, left, cast, sql_operator) params = right else: # Must not happen raise ValueError("Invalid field %r in domain term %r" % (left, leaf)) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index d5d0ee0fa30..f60e83726c4 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -648,7 +648,10 @@ class one2many(_column): else: cr.execute('update '+_table+' set '+self._fields_id+'=null where id=%s', (act[1],)) elif act[0] == 4: - cr.execute("select 1 from {0} where id=%s and {1}=%s".format(_table, self._fields_id), (act[1], id)) + # table of the field (parent_model in case of inherit) + field_model = self._fields_id in obj.pool[self._obj]._columns and self._obj or obj.pool[self._obj]._all_columns[self._fields_id].parent_model + field_table = obj.pool[field_model]._table + cr.execute("select 1 from {0} where id=%s and {1}=%s".format(field_table, self._fields_id), (act[1], id)) if not cr.fetchone(): # Must use write() to recompute parent_store structure if needed and check access rules obj.write(cr, user, [act[1]], {self._fields_id:id}, context=context or {}) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 64fa06783ab..6f3adf66216 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -55,7 +55,7 @@ import traceback import types import babel.dates -import dateutil.parser +import dateutil.relativedelta import psycopg2 from lxml import etree @@ -75,7 +75,7 @@ _schema = logging.getLogger(__name__ + '.schema') # List of etree._Element subclasses that we choose to ignore when parsing XML. from openerp.tools import SKIPPED_ELEMENT_TYPES -regex_order = re.compile('^( *([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I) +regex_order = re.compile('^( *([a-z0-9:_]+|"[a-z0-9:_]+")( *desc| *asc)?( *, *|))+$', re.I) regex_object_name = re.compile(r'^[a-z0-9_.]+$') AUTOINIT_RECALCULATE_STORED_FIELDS = 1000 @@ -469,7 +469,12 @@ class browse_record(object): else: new_data[field_name] = browse_null() elif field_column._type in ('one2many', 'many2many') and len(result_line[field_name]): - new_data[field_name] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool[field_column._obj], self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in result_line[field_name]], self._context) + new_data[field_name] = self._list_class( + (browse_record(self._cr, self._uid, id, self._table.pool.get(field_column._obj), + self._cache, context=self._context, list_class=self._list_class, + fields_process=self._fields_process) + for id in result_line[field_name]), + context=self._context) elif field_column._type == 'reference': if result_line[field_name]: if isinstance(result_line[field_name], browse_record): @@ -1100,7 +1105,7 @@ class BaseModel(object): self._rec_name = 'name' - def __export_row(self, cr, uid, row, fields, context=None): + def __export_row(self, cr, uid, row, fields, raw_data=False, context=None): if context is None: context = {} @@ -1193,8 +1198,7 @@ class BaseModel(object): break for row2 in r: - lines2 = row2._model.__export_row(cr, uid, row2, fields2, - context) + lines2 = row2._model.__export_row(cr, uid, row2, fields2, context=context) if first: for fpos2 in range(len(fields)): if lines2 and lines2[0][fpos2]: @@ -1216,14 +1220,22 @@ class BaseModel(object): lines += lines2 break i += 1 + if i == len(f): if isinstance(r, browse_record): r = self.pool[r._table_name].name_get(cr, uid, [r.id], context=context) r = r and r[0] and r[0][1] or '' - data[fpos] = tools.ustr(r or '') + if raw_data and cols and cols._type in ('integer', 'boolean', 'float'): + data[fpos] = r + elif raw_data and cols and cols._type == 'date': + data[fpos] = datetime.datetime.strptime(r, tools.DEFAULT_SERVER_DATE_FORMAT).date() + elif raw_data and cols and cols._type == 'datetime': + data[fpos] = datetime.datetime.strptime(r, tools.DEFAULT_SERVER_DATETIME_FORMAT) + else: + data[fpos] = tools.ustr(r or '') return [data] + lines - def export_data(self, cr, uid, ids, fields_to_export, context=None): + def export_data(self, cr, uid, ids, fields_to_export, raw_data=False, context=None): """ Export fields for selected objects @@ -1231,6 +1243,7 @@ class BaseModel(object): :param uid: current user id :param ids: list of ids :param fields_to_export: list of fields + :param raw_data: True to return value in fields type, False for string values :param context: context arguments, like lang, time zone :rtype: dictionary with a *datas* matrix @@ -1245,7 +1258,7 @@ class BaseModel(object): fields_to_export = map(fix_import_export_id_paths, fields_to_export) datas = [] for row in self.browse(cr, uid, ids, context): - datas += self.__export_row(cr, uid, row, fields_to_export, context) + datas += self.__export_row(cr, uid, row, fields_to_export, raw_data=raw_data, context=context) return {'datas': datas} def import_data(self, cr, uid, fields, datas, mode='init', current_module='', noupdate=False, context=None, filename=None): @@ -1903,7 +1916,7 @@ class BaseModel(object): return result def _view_look_dom_arch(self, cr, uid, node, view_id, context=None): - return self['ir.ui.view'].postprocess_and_fields( + return self.pool['ir.ui.view'].postprocess_and_fields( cr, uid, self._name, node, view_id, context=context) def search_count(self, cr, user, args, context=None): @@ -2115,7 +2128,7 @@ class BaseModel(object): pass - def _read_group_fill_results(self, cr, uid, domain, groupby, groupby_list, aggregated_fields, + def _read_group_fill_results(self, cr, uid, domain, groupby, remaining_groupbys, aggregated_fields, read_group_result, read_group_order=None, context=None): """Helper method for filling in empty groups for all possible values of the field being grouped by""" @@ -2135,8 +2148,8 @@ class BaseModel(object): result_template = dict.fromkeys(aggregated_fields, False) result_template[groupby + '_count'] = 0 - if groupby_list and len(groupby_list) > 1: - result_template['__context'] = {'group_by': groupby_list[1:]} + if remaining_groupbys: + result_template['__context'] = {'group_by': remaining_groupbys} # Merge the left_side (current results as dicts) with the right_side (all # possible values as m2o pairs). Both lists are supposed to be using the @@ -2185,35 +2198,39 @@ class BaseModel(object): r['__fold'] = folded.get(r[groupby] and r[groupby][0], False) return result - def _read_group_prepare(self, orderby, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type=None): + def _read_group_prepare(self, orderby, aggregated_fields, annotated_groupbys, query): """ Prepares the GROUP BY and ORDER BY terms for the read_group method. Adds the missing JOIN clause to the query if order should be computed against m2o field. :param orderby: the orderby definition in the form "%(field)s %(order)s" :param aggregated_fields: list of aggregated fields in the query - :param groupby: the current groupby field name - :param qualified_groupby_field: the fully qualified SQL name for the grouped field + :param annotated_groupbys: list of dictionaries returned by _read_group_process_groupby + These dictionaries contains the qualified name of each groupby + (fully qualified SQL name for the corresponding field), + and the (non raw) field name. :param osv.Query query: the query under construction - :param groupby_type: the type of the grouped field :return: (groupby_terms, orderby_terms) """ orderby_terms = [] - groupby_terms = [qualified_groupby_field] if groupby else [] + groupby_terms = [gb['qualified_field'] for gb in annotated_groupbys] + groupby_fields = [gb['groupby'] for gb in annotated_groupbys] if not orderby: - return groupby_terms, orderby_terms + return groupby_terms, orderby_terms self._check_qorder(orderby) for order_part in orderby.split(','): order_split = order_part.split() order_field = order_split[0] - if order_field == groupby: - if groupby_type == 'many2one': + if order_field in groupby_fields: + + if self._all_columns[order_field.split(':')[0]].column._type == 'many2one': order_clause = self._generate_order_by(order_part, query).replace('ORDER BY ', '') if order_clause: orderby_terms.append(order_clause) groupby_terms += [order_term.split()[0] for order_term in order_clause.split(',')] else: - orderby_terms.append(order_part) + order = '"%s" %s' % (order_field, '' if len(order_split) == 1 else order_split[1]) + orderby_terms.append(order) elif order_field in aggregated_fields: orderby_terms.append(order_part) else: @@ -2222,7 +2239,100 @@ class BaseModel(object): self._name, order_part) return groupby_terms, orderby_terms - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def _read_group_process_groupby(self, gb, query, context): + """ + Helper method to collect important information about groupbys: raw + field name, type, time informations, qualified name, ... + """ + split = gb.split(':') + field_type = self._all_columns[split[0]].column._type + gb_function = split[1] if len(split) == 2 else None + temporal = field_type in ('date', 'datetime') + tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones + qualified_field = self._inherits_join_calc(split[0], query) + if temporal: + display_formats = { + 'day': 'dd MMM YYYY', + 'week': "'W'w YYYY", + 'month': 'MMMM YYYY', + 'quarter': 'QQQ YYYY', + 'year': 'YYYY' + } + time_intervals = { + 'day': dateutil.relativedelta.relativedelta(days=1), + 'week': datetime.timedelta(days=7), + 'month': dateutil.relativedelta.relativedelta(months=1), + 'quarter': dateutil.relativedelta.relativedelta(months=3), + 'year': dateutil.relativedelta.relativedelta(years=1) + } + if tz_convert: + qualified_field = "timezone('%s', timezone('UTC',%s))" % (context.get('tz', 'UTC'), qualified_field) + qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field) + if field_type == 'boolean': + qualified_field = "coalesce(%s,false)" % qualified_field + return { + 'field': split[0], + 'groupby': gb, + 'type': field_type, + 'display_format': display_formats[gb_function or 'month'] if temporal else None, + 'interval': time_intervals[gb_function or 'month'] if temporal else None, + 'tz_convert': tz_convert, + 'qualified_field': qualified_field + } + + def _read_group_prepare_data(self, key, value, groupby_dict, context): + """ + Helper method to sanitize the data received by read_group. The None + values are converted to False, and the date/datetime are formatted, + and corrected according to the timezones. + """ + value = False if value is None else value + gb = groupby_dict.get(key) + if gb and gb['type'] in ('date', 'datetime') and value: + if isinstance(value, basestring): + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + value = datetime.datetime.strptime(value, dt_format) + if gb['tz_convert']: + value = pytz.timezone(context['tz']).localize(value) + return value + + def _read_group_get_domain(self, groupby, value): + """ + Helper method to construct the domain corresponding to a groupby and + a given value. This is mostly relevant for date/datetime. + """ + if groupby['type'] in ('date', 'datetime') and value: + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + domain_dt_begin = value + domain_dt_end = value + groupby['interval'] + if groupby['tz_convert']: + domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) + domain_dt_end = domain_dt_end.astimezone(pytz.utc) + return [(groupby['field'], '>=', domain_dt_begin.strftime(dt_format)), + (groupby['field'], '<', domain_dt_end.strftime(dt_format))] + if groupby['type'] == 'many2one' and value: + value = value[0] + return [(groupby['field'], '=', value)] + + def _read_group_format_result(self, data, annotated_groupbys, groupby, groupby_dict, domain, context): + """ + Helper method to format the data contained in the dictianary data by + adding the domain corresponding to its values, the groupbys in the + context and by properly formatting the date/datetime values. + """ + domain_group = [dom for gb in annotated_groupbys for dom in self._read_group_get_domain(gb, data[gb['groupby']])] + for k,v in data.iteritems(): + gb = groupby_dict.get(k) + if gb and gb['type'] in ('date', 'datetime') and v: + data[k] = babel.dates.format_date(v, format=gb['display_format'], locale=context.get('lang', 'en_US')) + + data['__domain'] = domain_group + domain + if len(groupby) - len(annotated_groupbys) >= 1: + data['__context'] = { 'group_by': groupby[len(annotated_groupbys):]} + del data['id'] + return data + + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2242,6 +2352,9 @@ class BaseModel(object): overriding the natural sort ordering of the groups, see also :py:meth:`~osv.osv.osv.search` (supported only for many2one fields currently) + :param bool lazy: if true, the results are only grouped by the first groupby and the + remaining groupbys are put in the __context key. If false, all the groupbys are + done in one call. :return: list of dictionaries(one dictionary for each record) containing: * the values of fields grouped by the fields in ``groupby`` argument @@ -2250,100 +2363,56 @@ class BaseModel(object): :rtype: [{'field_name_1': value, ...] :raise AccessError: * if user has no read rights on the requested object * if user tries to bypass access rules for read on the requested object - """ - context = context or {} + if context is None: + context = {} self.check_access_rights(cr, uid, 'read') - if not fields: - fields = self._columns.keys() + query = self._where_calc(cr, uid, domain, context=context) + fields = fields or self._columns.keys() + + groupby = [groupby] if isinstance(groupby, basestring) else groupby + groupby_list = groupby[:1] if lazy else groupby + annotated_groupbys = [self._read_group_process_groupby(gb, query, context) + for gb in groupby_list] + groupby_fields = [g['field'] for g in annotated_groupbys] + order = orderby or ','.join([g for g in groupby_list]) + groupby_dict = {gb['groupby']: gb for gb in annotated_groupbys} - query = self._where_calc(cr, uid, domain, context=context) self._apply_ir_rules(cr, uid, query, 'read', context=context) - - # Take care of adding join(s) if groupby is an '_inherits'ed field - groupby_list = groupby - qualified_groupby_field = groupby - if groupby: - if isinstance(groupby, list): - groupby = groupby[0] - splitted_groupby = groupby.split(':') - if len(splitted_groupby) == 2: - groupby = splitted_groupby[0] - groupby_function = splitted_groupby[1] - else: - groupby_function = False - qualified_groupby_field = self._inherits_join_calc(groupby, query) - - if groupby: - assert not groupby or groupby in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" - groupby_def = self._columns.get(groupby) or (self._inherit_fields.get(groupby) and self._inherit_fields.get(groupby)[2]) + for gb in groupby_fields: + assert gb in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" + groupby_def = self._columns.get(gb) or (self._inherit_fields.get(gb) and self._inherit_fields.get(gb)[2]) assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True" - - # TODO it seems fields_get can be replaced by _all_columns (no need for translation) - fget = self.fields_get(cr, uid, fields) - group_by_params = {} - select_terms = [] - groupby_type = None - if groupby: - if fget.get(groupby): - groupby_type = fget[groupby]['type'] - if groupby_type in ('date', 'datetime'): - if groupby_function: - interval = groupby_function - else: - interval = 'month' - - if interval == 'day': - display_format = 'dd MMM YYYY' - elif interval == 'week': - display_format = "'W'w YYYY" - elif interval == 'month': - display_format = 'MMMM YYYY' - elif interval == 'quarter': - display_format = 'QQQ YYYY' - elif interval == 'year': - display_format = 'YYYY' - - if groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones: - # Convert groupby result to user TZ to avoid confusion! - # PostgreSQL is compatible with all pytz timezone names, so we can use them - # directly for conversion, starting with timestamps stored in UTC. - timezone = context.get('tz', 'UTC') - qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field) - qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field) - elif groupby_type == 'boolean': - qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field - select_terms.append("%s as %s " % (qualified_groupby_field, groupby)) - else: + if not (gb in self._all_columns): # Don't allow arbitrary values, as this would be a SQL injection vector! raise except_orm(_('Invalid group_by'), - _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(groupby,)) + _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(gb,)) aggregated_fields = [ f for f in fields - if f not in ('id', 'sequence', groupby) - if fget[f]['type'] in ('integer', 'float') - if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))] - for f in aggregated_fields: - group_operator = fget[f].get('group_operator', 'sum') - qualified_field = self._inherits_join_calc(f, query) - select_terms.append("%s(%s) AS %s" % (group_operator, qualified_field, f)) + if f not in ('id', 'sequence') + if f not in groupby_fields + if self._all_columns[f].column._type in ('integer', 'float') + if getattr(self._all_columns[f].column, '_classic_write')] - order = orderby or groupby or '' - groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type) + field_formatter = lambda f: (self._all_columns[f].column.group_operator or 'sum', self._inherits_join_calc(f, query), f) + select_terms = ["%s(%s) AS %s" % field_formatter(f) for f in aggregated_fields] + for gb in annotated_groupbys: + select_terms.append('%s as "%s" ' % (gb['qualified_field'], gb['groupby'])) + + groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query) from_clause, where_clause, where_clause_params = query.get_sql() - if len(groupby_list) < 2 and context.get('group_by_no_leaf'): - count_field = '_' + if lazy and (len(groupby_fields) >= 2 or not context.get('group_by_no_leaf')): + count_field = groupby_fields[0] if len(groupby_fields) >= 1 else '_' else: - count_field = groupby + count_field = '_' prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else '' prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else '' query = """ - SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count - %(extra_fields)s + SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count %(extra_fields)s FROM %(from)s %(where)s %(groupby)s @@ -2362,71 +2431,29 @@ class BaseModel(object): 'offset': prefix_term('OFFSET', int(offset) if limit else None), } cr.execute(query, where_clause_params) - alldata = {} fetched_data = cr.dictfetchall() - data_ids = [] - for r in fetched_data: - for fld, val in r.items(): - if val is None: r[fld] = False - alldata[r['id']] = r - data_ids.append(r['id']) - del r['id'] + if not groupby_fields: + return {r.pop('id'): r for r in fetched_data} - if groupby: - data = self.read(cr, uid, data_ids, [groupby], context=context) - # restore order of the search as read() uses the default _order (this is only for groups, so the footprint of data should be small): - data_dict = dict((d['id'], d[groupby] ) for d in data) - result = [{'id': i, groupby: data_dict[i]} for i in data_ids] - else: - result = [{'id': i} for i in data_ids] - - for d in result: - if groupby: - d['__domain'] = [(groupby, '=', alldata[d['id']][groupby] or False)] + domain - if not isinstance(groupby_list, (str, unicode)): - if groupby or not context.get('group_by_no_leaf', False): - d['__context'] = {'group_by': groupby_list[1:]} - if groupby and groupby in fget: - groupby_type = fget[groupby]['type'] - if d[groupby] and groupby_type in ('date', 'datetime'): - groupby_datetime = alldata[d['id']][groupby] - if isinstance(groupby_datetime, basestring): - _default = datetime.datetime(1970, 1, 1) # force starts of month - groupby_datetime = dateutil.parser.parse(groupby_datetime, default=_default) - tz_convert = groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones - if tz_convert: - groupby_datetime = pytz.timezone(context['tz']).localize(groupby_datetime) - d[groupby] = babel.dates.format_date( - groupby_datetime, format=display_format, locale=context.get('lang', 'en_US')) - domain_dt_begin = groupby_datetime - if interval == 'quarter': - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=3) - elif interval == 'month': - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=1) - elif interval == 'week': - domain_dt_end = groupby_datetime + datetime.timedelta(days=7) - elif interval == 'day': - domain_dt_end = groupby_datetime + datetime.timedelta(days=1) - else: - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(years=1) - if tz_convert: - # the time boundaries were all computed in the apparent TZ of the user, - # so we need to convert them to UTC to have proper server-side values. - domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) - domain_dt_end = domain_dt_end.astimezone(pytz.utc) - dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby_type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT - d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime(dt_format)), - (groupby, '<', domain_dt_end.strftime(dt_format))] + domain - del alldata[d['id']][groupby] - d.update(alldata[d['id']]) - del d['id'] - - if groupby and groupby in self._group_by_full: - result = self._read_group_fill_results(cr, uid, domain, groupby, groupby_list, - aggregated_fields, result, read_group_order=order, - context=context) + many2onefields = [gb['field'] for gb in annotated_groupbys if gb['type'] == 'many2one'] + if many2onefields: + data_ids = [r['id'] for r in fetched_data] + many2onefields = list(set(many2onefields)) + data_dict = {d['id']: d for d in self.read(cr, uid, data_ids, many2onefields, context=context)} + for d in fetched_data: + d.update(data_dict[d['id']]) + data = map(lambda r: {k: self._read_group_prepare_data(k,v, groupby_dict, context) for k,v in r.iteritems()}, fetched_data) + result = [self._read_group_format_result(d, annotated_groupbys, groupby, groupby_dict, domain, context) for d in data] + if lazy and groupby_fields[0] in self._group_by_full: + # Right now, read_group only fill results in lazy mode (by default). + # If you need to have the empty groups in 'eager' mode, then the + # method _read_group_fill_results need to be completely reimplemented + # in a sane way + result = self._read_group_fill_results(cr, uid, domain, groupby_fields[0], groupby[len(annotated_groupbys):], + aggregated_fields, result, read_group_order=order, + context=context) return result def _inherits_join_add(self, current_model, parent_model_name, query): @@ -4242,7 +4269,7 @@ class BaseModel(object): if isinstance(select, (int, long)): return browse_record(cr, uid, select, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) elif isinstance(select, list): - return self._list_class([browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select], context=context) + return self._list_class((browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select), context=context) else: return browse_null() diff --git a/openerp/pooler.py b/openerp/pooler.py index 0df6f88c819..5ada4c2a014 100644 --- a/openerp/pooler.py +++ b/openerp/pooler.py @@ -36,7 +36,7 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False) assert openerp.conf.deprecation.openerp_pooler _logger.warning('openerp.pooler.get_db_and_pool() is deprecated.') registry = RegistryManager.get(db_name, force_demo, status, update_module) - return registry.db, registry + return registry._db, registry def restart_pool(db_name, force_demo=False, status=None, update_module=False): @@ -44,7 +44,7 @@ def restart_pool(db_name, force_demo=False, status=None, update_module=False): _logger.warning('openerp.pooler.restart_pool() is deprecated.') assert openerp.conf.deprecation.openerp_pooler registry = RegistryManager.new(db_name, force_demo, status, update_module) - return registry.db, registry + return registry._db, registry def get_db(db_name): """Return a database connection. The corresponding registry is initialized.""" diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index aaed9ddf4c6..6ce69578a8e 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -88,50 +88,30 @@ def _open_image(filename, path=None): class NumberedCanvas(canvas.Canvas): def __init__(self, *args, **kwargs): canvas.Canvas.__init__(self, *args, **kwargs) - self._codes = [] - self._flag=False - self._pageCount=0 - self._currentPage =0 - self._pageCounter=0 - self.pages={} + self._saved_page_states = [] def showPage(self): - self._currentPage +=1 - if not self._flag: - self._pageCount += 1 - else: - self.pages.update({self._currentPage:self._pageCount}) - self._codes.append({'code': self._code, 'stack': self._codeStack}) + self._saved_page_states.append(dict(self.__dict__)) self._startPage() - self._flag=False - def pageCount(self): - if self.pages.get(self._pageCounter,False): - self._pageNumber=0 - self._pageCounter +=1 - key=self._pageCounter - if not self.pages.get(key,False): - while not self.pages.get(key,False): - key += 1 + def save(self): + """add page info to each page (page x of y)""" + for state in self._saved_page_states: + self.__dict__.update(state) + self.draw_page_number() + canvas.Canvas.showPage(self) + canvas.Canvas.save(self) + + def draw_page_number(self): + page_count = len(self._saved_page_states) self.setFont("Helvetica", 8) self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40), " %(this)i / %(total)i" % { 'this': self._pageNumber+1, - 'total': self.pages.get(key,False), + 'total': page_count, } ) - def save(self): - """add page info to each page (page x of y)""" - # reset page counter - self._pageNumber = 0 - for code in self._codes: - self._code = code['code'] - self._codeStack = code['stack'] - self.pageCount() - canvas.Canvas.showPage(self) -# self.restoreState() - self._doc.SaveToFile(self._filename, self) class PageCount(platypus.Flowable): def __init__(self, story_count=0): @@ -303,6 +283,9 @@ class _rml_doc(object): from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont + if mode: + mode = mode.lower() + if fontname not in pdfmetrics._fonts: pdfmetrics.registerFont(TTFont(fontname, filename)) if mode == 'all': @@ -310,14 +293,14 @@ class _rml_doc(object): addMapping(face, 0, 1, fontname) #italic addMapping(face, 1, 0, fontname) #bold addMapping(face, 1, 1, fontname) #italic and bold - elif (mode== 'normal') or (mode == 'regular') or (mode == 'book'): - addMapping(face, 0, 0, fontname) #normal - elif mode == 'italic': + elif mode in ['italic', 'oblique']: addMapping(face, 0, 1, fontname) #italic elif mode == 'bold': addMapping(face, 1, 0, fontname) #bold - elif mode == 'bolditalic': + elif mode in ('bolditalic', 'bold italic','boldoblique', 'bold oblique'): addMapping(face, 1, 1, fontname) #italic and bold + else: + addMapping(face, 0, 0, fontname) #normal def _textual_image(self, node): rc = '' diff --git a/openerp/service/model.py b/openerp/service/model.py index a637e234295..a91baf8ca08 100644 --- a/openerp/service/model.py +++ b/openerp/service/model.py @@ -161,21 +161,10 @@ def execute_cr(cr, uid, obj, method, *args, **kw): def execute_kw(db, uid, obj, method, args, kw=None): return execute(db, uid, obj, method, *args, **kw or {}) -@contextmanager -def closing_cr_and_commit(cr): - try: - yield cr - cr.commit() - except Exception: - cr.rollback() - raise - finally: - cr.close() - @check def execute(db, uid, obj, method, *args, **kw): threading.currentThread().dbname = db - with closing_cr_and_commit(openerp.registry(db).db.cursor()) as cr: + with openerp.registry(db).cursor() as cr: if method.startswith('_'): raise except_orm('Access Denied', 'Private methods (such as %s) cannot be called remotely.' % (method,)) res = execute_cr(cr, uid, obj, method, *args, **kw) @@ -190,7 +179,7 @@ def exec_workflow_cr(cr, uid, obj, signal, *args): @check def exec_workflow(db, uid, obj, signal, *args): - with closing_cr_and_commit(openerp.registry(db).db.cursor()) as cr: + with openerp.registry(db).cursor() as cr: return exec_workflow_cr(cr, uid, obj, signal, *args) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/report.py b/openerp/service/report.py index 370b11fc199..0c2f720f4cb 100644 --- a/openerp/service/report.py +++ b/openerp/service/report.py @@ -49,7 +49,7 @@ def exp_render_report(db, uid, object, ids, datas=None, context=None): self_reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None} - cr = openerp.registry(db).db.cursor() + cr = openerp.registry(db).cursor() try: result, format = openerp.report.render_report(cr, uid, ids, object, datas, context) if not result: @@ -87,7 +87,7 @@ def exp_report(db, uid, object, ids, datas=None, context=None): self_reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None} def go(id, uid, ids, datas, context): - cr = openerp.registry(db).db.cursor() + cr = openerp.registry(db).cursor() try: result, format = openerp.report.render_report(cr, uid, ids, object, datas, context) if not result: diff --git a/openerp/service/server.py b/openerp/service/server.py index f9db66a28ef..76b415eb01e 100644 --- a/openerp/service/server.py +++ b/openerp/service/server.py @@ -62,6 +62,14 @@ class BaseWSGIServerNoBind(werkzeug.serving.BaseWSGIServer): # dont listen as we use PreforkServer#socket pass + +class RequestHandler(werkzeug.serving.WSGIRequestHandler): + def setup(self): + # flag the current thread as handling a http request + super(RequestHandler, self).setup() + me = threading.currentThread() + me.name = 'openerp.service.http.request.%s' % (me.ident,) + # _reexec() should set LISTEN_* to avoid connection refused during reload time. It # should also work with systemd socket activation. This is currently untested # and not yet used. @@ -71,6 +79,10 @@ class ThreadedWSGIServerReloadable(werkzeug.serving.ThreadedWSGIServer): given by the environement, this is used by autoreload to keep the listen socket open when a reload happens. """ + def __init__(self, host, port, app): + super(ThreadedWSGIServerReloadable, self).__init__(host, port, app, + handler=RequestHandler) + def server_bind(self): envfd = os.environ.get('LISTEN_FDS') if envfd and os.environ.get('LISTEN_PID') == str(os.getpid()): @@ -440,7 +452,7 @@ class PreforkServer(CommonServer): sys.exit(0) def long_polling_spawn(self): - nargs = stripped_sys_argv('--pidfile', '--workers') + nargs = stripped_sys_argv() cmd = nargs[0] cmd = os.path.join(os.path.dirname(cmd), "openerp-gevent") nargs[0] = cmd @@ -834,8 +846,13 @@ def _reexec(updated_modules=None): def load_test_file_yml(registry, test_file): with registry.cursor() as cr: - openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True) - cr.rollback() + openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'init') + if config['test_commit']: + _logger.info('test %s has been commited', test_file) + cr.commit() + else: + _logger.info('test %s has been rollbacked', test_file) + cr.rollback() def load_test_file_py(registry, test_file): # Locate python module based on its filename and run the tests @@ -887,10 +904,10 @@ def start(preload=None, stop=False): """ global server load_server_wide_modules() - if config['workers']: - server = PreforkServer(openerp.service.wsgi_server.application) - elif openerp.evented: + if openerp.evented: server = GeventServer(openerp.service.wsgi_server.application) + elif config['workers']: + server = PreforkServer(openerp.service.wsgi_server.application) else: server = ThreadedServer(openerp.service.wsgi_server.application) diff --git a/openerp/sql_db.py b/openerp/sql_db.py index 59841656d8c..fcc60e7b6f3 100644 --- a/openerp/sql_db.py +++ b/openerp/sql_db.py @@ -167,7 +167,7 @@ class Cursor(object): self.sql_log_count = 0 self._closed = True # avoid the call of close() (by __del__) if an exception # is raised by any of the following initialisations - self._pool = pool + self.__pool = pool self.dbname = dbname # Whether to enable snapshot isolation level for this cursor. @@ -313,7 +313,7 @@ class Cursor(object): chosen_template = tools.config['db_template'] templates_list = tuple(set(['template0', 'template1', 'postgres', chosen_template])) keep_in_pool = self.dbname not in templates_list - self._pool.give_back(self._cnx, keep_in_pool=keep_in_pool) + self.__pool.give_back(self._cnx, keep_in_pool=keep_in_pool) @check def autocommit(self, on): @@ -347,6 +347,23 @@ class Cursor(object): """ return self._cnx.rollback() + def __enter__(self): + """ Using the cursor as a contextmanager automatically commits and + closes it:: + + with cr: + cr.execute(...) + + # cr is committed if no failure occurred + # cr is closed in any case + """ + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + self.commit() + self.close() + @contextmanager @check def savepoint(self): @@ -364,6 +381,42 @@ class Cursor(object): def __getattr__(self, name): return getattr(self._obj, name) +class TestCursor(Cursor): + """ A cursor to be used for tests. It keeps the transaction open across + several requests, and simulates committing, rolling back, and closing. + """ + def __init__(self, *args, **kwargs): + super(TestCursor, self).__init__(*args, **kwargs) + # in order to simulate commit and rollback, the cursor maintains a + # savepoint at its last commit + self.execute("SAVEPOINT test_cursor") + # we use a lock to serialize concurrent requests + self._lock = threading.RLock() + + def acquire(self): + self._lock.acquire() + + def release(self): + self._lock.release() + + def close(self, force=False): + if force: + super(TestCursor, self).close() + elif not self._closed: + self.rollback() # for stuff that has not been committed + self.release() + + def autocommit(self, on): + _logger.debug("TestCursor.autocommit(%r) does nothing", on) + + def commit(self): + self.execute("RELEASE SAVEPOINT test_cursor") + self.execute("SAVEPOINT test_cursor") + + def rollback(self): + self.execute("ROLLBACK TO SAVEPOINT test_cursor") + self.execute("SAVEPOINT test_cursor") + class PsycoConnection(psycopg2.extensions.connection): pass @@ -484,12 +537,17 @@ class Connection(object): def __init__(self, pool, dbname): self.dbname = dbname - self._pool = pool + self.__pool = pool def cursor(self, serialized=True): cursor_type = serialized and 'serialized ' or '' _logger.debug('create %scursor to %r', cursor_type, self.dbname) - return Cursor(self._pool, self.dbname, serialized=serialized) + return Cursor(self.__pool, self.dbname, serialized=serialized) + + def test_cursor(self, serialized=True): + cursor_type = serialized and 'serialized ' or '' + _logger.debug('create test %scursor to %r', cursor_type, self.dbname) + return TestCursor(self.__pool, self.dbname, serialized=serialized) # serialized_cursor is deprecated - cursors are serialized by default serialized_cursor = cursor diff --git a/openerp/tests/common.py b/openerp/tests/common.py index a53a8d82240..7cc753e810b 100644 --- a/openerp/tests/common.py +++ b/openerp/tests/common.py @@ -20,6 +20,7 @@ from datetime import datetime, timedelta import werkzeug import openerp +from openerp.modules.registry import RegistryManager _logger = logging.getLogger(__name__) @@ -37,25 +38,6 @@ if not DB and hasattr(threading.current_thread(), 'dbname'): # Useless constant, tests are aware of the content of demo data ADMIN_USER_ID = openerp.SUPERUSER_ID -# Magic session_id, unfortunately we have to serialize access to the cursors to -# serialize requests. We first tried to duplicate the database for each tests -# but this proved too slow. Any idea to improve this is welcome. -HTTP_SESSION = {} - -def acquire_test_cursor(session_id): - if openerp.tools.config['test_enable']: - cr = HTTP_SESSION.get(session_id) - if cr: - cr._test_lock.acquire() - return cr - -def release_test_cursor(cr): - if openerp.tools.config['test_enable']: - if hasattr(cr, '_test_lock'): - cr._test_lock.release() - return True - return False - def at_install(flag): """ Sets the at-install state of a test, the flag is a boolean specifying whether the test should (``True``) or should not (``False``) run during @@ -67,6 +49,7 @@ def at_install(flag): obj.at_install = flag return obj return decorator + def post_install(flag): """ Sets the post-install state of a test. The flag is a boolean specifying whether the test should or should not run after a set of @@ -83,18 +66,13 @@ class BaseCase(unittest2.TestCase): """ Subclass of TestCase for common OpenERP-specific code. - This class is abstract and expects self.cr and self.uid to be initialized by subclasses. + This class is abstract and expects self.registry, self.cr and self.uid to be + initialized by subclasses. """ - @classmethod def cursor(self): - return openerp.modules.registry.RegistryManager.get(DB).db.cursor() + return self.registry.cursor() - @classmethod - def registry(self, model): - return openerp.modules.registry.RegistryManager.get(DB)[model] - - @classmethod def ref(self, xid): """ Returns database ID corresponding to a given identifier. @@ -106,7 +84,6 @@ class BaseCase(unittest2.TestCase): _, id = self.registry('ir.model.data').get_object_reference(self.cr, self.uid, module, xid) return id - @classmethod def browse_ref(self, xid): """ Returns a browsable record for the given identifier. @@ -125,10 +102,9 @@ class TransactionCase(BaseCase): """ def setUp(self): - # Store cr and uid in class variables, to allow ref() and browse_ref to be BaseCase @classmethods - # and still access them - TransactionCase.cr = self.cursor() - TransactionCase.uid = openerp.SUPERUSER_ID + self.registry = RegistryManager.get(DB) + self.cr = self.cursor() + self.uid = openerp.SUPERUSER_ID def tearDown(self): self.cr.rollback() @@ -143,7 +119,8 @@ class SingleTransactionCase(BaseCase): @classmethod def setUpClass(cls): - cls.cr = cls.cursor() + cls.registry = RegistryManager.get(DB) + cls.cr = cls.registry.cursor() cls.uid = openerp.SUPERUSER_ID @classmethod @@ -166,16 +143,15 @@ class HttpCase(TransactionCase): def setUp(self): super(HttpCase, self).setUp() + self.registry.enter_test_mode() # setup a magic session_id that will be rollbacked self.session = openerp.http.root.session_store.new() self.session_id = self.session.sid self.session.db = DB openerp.http.root.session_store.save(self.session) - self.cr._test_lock = threading.RLock() - HTTP_SESSION[self.session_id] = self.cr def tearDown(self): - del HTTP_SESSION[self.session_id] + self.registry.leave_test_mode() super(HttpCase, self).tearDown() def url_open(self, url, data=None, timeout=10): @@ -253,9 +229,19 @@ class HttpCase(TransactionCase): # kill phantomjs if phantom.exit() wasn't called in the test if phantom.poll() is None: phantom.terminate() + self._wait_remaining_requests() _logger.info("phantom_run execution finished") - def phantom_jsfile(self, jsfile, timeout=30, **kw): + def _wait_remaining_requests(self): + for thread in threading.enumerate(): + if thread.name.startswith('openerp.service.http.request.'): + while thread.isAlive(): + # Need a busyloop here as thread.join() masks signals + # and would prevent the forced shutdown. + thread.join(0.05) + time.sleep(0.05) + + def phantom_jsfile(self, jsfile, timeout=60, **kw): options = { 'timeout' : timeout, 'port': PORT, @@ -269,7 +255,7 @@ class HttpCase(TransactionCase): cmd = ['phantomjs', jsfile, phantomtest, json.dumps(options)] self.phantom_run(cmd, timeout) - def phantom_js(self, url_path, code, ready="window", login=None, timeout=30, **kw): + def phantom_js(self, url_path, code, ready="window", login=None, timeout=60, **kw): """ Test js code running in the browser - optionnally log as 'login' - load page given by url_path diff --git a/openerp/tools/convert.py b/openerp/tools/convert.py index 43ee96660bd..a4231529b8f 100644 --- a/openerp/tools/convert.py +++ b/openerp/tools/convert.py @@ -857,12 +857,12 @@ form: module.record_id""" % (xml_id,) def _tag_template(self, cr, el, data_node=None): # This helper transforms a