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 @@
Andorra, Principality of
ad
+
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_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 element into a and forwards it
tpl_id = el.get('id', el.get('t-name', '')).encode('ascii')
- module = self.module
- if '.' in tpl_id:
- module, tpl_id = tpl_id.split('.', 1)
+ full_tpl_id = tpl_id
+ if '.' not in full_tpl_id:
+ full_tpl_id = '%s.%s' % (self.module, tpl_id)
# set the full template name for qweb .
if not (el.get('inherit_id') or el.get('inherit_option_id')):
- el.set('t-name', '%s.%s' % (module, tpl_id))
+ el.set('t-name', full_tpl_id)
el.tag = 't'
else:
el.tag = 'data'
@@ -952,8 +952,9 @@ form: module.record_id""" % (xml_id,)
'url': self._tag_url
}
-def convert_file(cr, module, filename, idref, mode='update', noupdate=False, kind=None, report=None):
- pathname = os.path.join(module, filename)
+def convert_file(cr, module, filename, idref, mode='update', noupdate=False, kind=None, report=None, pathname=None):
+ if pathname is None:
+ pathname = os.path.join(module, filename)
fp = misc.file_open(pathname)
ext = os.path.splitext(filename)[1].lower()
try:
diff --git a/openerp/tools/image.py b/openerp/tools/image.py
index 08c2fd91f21..93458fb9408 100644
--- a/openerp/tools/image.py
+++ b/openerp/tools/image.py
@@ -70,7 +70,11 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
image_stream = StringIO.StringIO(base64_source.decode(encoding))
image = Image.open(image_stream)
# store filetype here, as Image.new below will lose image.format
- filetype = filetype or image.format
+ filetype = (filetype or image.format).upper()
+
+ filetype = {
+ 'BMP': 'PNG',
+ }.get(filetype, filetype)
asked_width, asked_height = size
if asked_width is None:
diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py
index 85dcfd368fe..de6cd173521 100644
--- a/openerp/tools/mail.py
+++ b/openerp/tools/mail.py
@@ -625,7 +625,7 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non
if not cr:
db_name = getattr(threading.currentThread(), 'dbname', None)
if db_name:
- local_cr = cr = openerp.registry(db_name).db.cursor()
+ local_cr = cr = openerp.registry(db_name).cursor()
else:
raise Exception("No database cursor found, please pass one explicitly")
diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py
index 508a072a3b2..2f280685350 100644
--- a/openerp/tools/safe_eval.py
+++ b/openerp/tools/safe_eval.py
@@ -71,7 +71,8 @@ _SAFE_OPCODES = _EXPR_OPCODES.union(set(opmap[x] for x in [
'CONTINUE_LOOP', 'RAISE_VARARGS',
# New in Python 2.7 - http://bugs.python.org/issue4715 :
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE',
- 'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY'
+ 'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY', 'LOAD_FAST',
+ 'LOAD_GLOBAL', # Only allows access to restricted globals
] if x in opmap))
_logger = logging.getLogger(__name__)
@@ -86,16 +87,65 @@ def _get_opcodes(codeobj):
[100, 100, 23, 100, 100, 102, 103, 83]
"""
i = 0
- opcodes = []
byte_codes = codeobj.co_code
while i < len(byte_codes):
code = ord(byte_codes[i])
- opcodes.append(code)
+ yield code
+
if code >= HAVE_ARGUMENT:
i += 3
else:
i += 1
- return opcodes
+
+def assert_no_dunder_name(code_obj, expr):
+ """ assert_no_dunder_name(code_obj, expr) -> None
+
+ Asserts that the code object does not refer to any "dunder name"
+ (__$name__), so that safe_eval prevents access to any internal-ish Python
+ attribute or method (both are loaded via LOAD_ATTR which uses a name, not a
+ const or a var).
+
+ Checks that no such name exists in the provided code object (co_names).
+
+ :param code_obj: code object to name-validate
+ :type code_obj: CodeType
+ :param str expr: expression corresponding to the code object, for debugging
+ purposes
+ :raises NameError: in case a forbidden name (containing two underscores)
+ is found in ``code_obj``
+
+ .. note:: actually forbids every name containing 2 underscores
+ """
+ for name in code_obj.co_names:
+ if "__" in name:
+ raise NameError('Access to forbidden name %r (%r)' % (name, expr))
+
+def assert_valid_codeobj(allowed_codes, code_obj, expr):
+ """ Asserts that the provided code object validates against the bytecode
+ and name constraints.
+
+ Recursively validates the code objects stored in its co_consts in case
+ lambdas are being created/used (lambdas generate their own separated code
+ objects and don't live in the root one)
+
+ :param allowed_codes: list of permissible bytecode instructions
+ :type allowed_codes: set(int)
+ :param code_obj: code object to name-validate
+ :type code_obj: CodeType
+ :param str expr: expression corresponding to the code object, for debugging
+ purposes
+ :raises ValueError: in case of forbidden bytecode in ``code_obj``
+ :raises NameError: in case a forbidden name (containing two underscores)
+ is found in ``code_obj``
+ """
+ assert_no_dunder_name(code_obj, expr)
+ for opcode in _get_opcodes(code_obj):
+ if opcode not in allowed_codes:
+ raise ValueError(
+ "opcode %s not allowed (%r)" % (opname[opcode], expr))
+ for const in code_obj.co_consts:
+ if isinstance(const, CodeType):
+ assert_valid_codeobj(allowed_codes, const, 'lambda')
def test_expr(expr, allowed_codes, mode="eval"):
"""test_expr(expression, allowed_codes[, mode]) -> code_object
@@ -110,15 +160,13 @@ def test_expr(expr, allowed_codes, mode="eval"):
# eval() does not like leading/trailing whitespace
expr = expr.strip()
code_obj = compile(expr, "", mode)
- except (SyntaxError, TypeError):
+ except (SyntaxError, TypeError, ValueError):
raise
except Exception, e:
import sys
exc_info = sys.exc_info()
raise ValueError, '"%s" while compiling\n%r' % (ustr(e), expr), exc_info[2]
- for code in _get_opcodes(code_obj):
- if code not in allowed_codes:
- raise ValueError("opcode %s not allowed (%r)" % (opname[code], expr))
+ assert_valid_codeobj(allowed_codes, code_obj, expr)
return code_obj
@@ -187,19 +235,13 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal
This can be used to e.g. evaluate
an OpenERP domain expression from an untrusted source.
- Throws TypeError, SyntaxError or ValueError (not allowed) accordingly.
-
- >>> safe_eval("__import__('sys').modules")
- Traceback (most recent call last):
- ...
- ValueError: opcode LOAD_NAME not allowed
-
+ :throws TypeError: If the expression provided is a code object
+ :throws SyntaxError: If the expression provided is not valid Python
+ :throws NameError: If the expression provided accesses forbidden names
+ :throws ValueError: If the expression provided uses forbidden bytecode
"""
if isinstance(expr, CodeType):
- raise ValueError("safe_eval does not allow direct evaluation of code objects.")
-
- if '__subclasses__' in expr:
- raise ValueError('expression not allowed (__subclasses__)')
+ raise TypeError("safe_eval does not allow direct evaluation of code objects.")
if globals_dict is None:
globals_dict = {}
diff --git a/openerp/tools/test_reports.py b/openerp/tools/test_reports.py
index 874a8cced61..c008c20ae29 100644
--- a/openerp/tools/test_reports.py
+++ b/openerp/tools/test_reports.py
@@ -38,7 +38,7 @@ _logger = logging.getLogger(__name__)
_test_logger = logging.getLogger('openerp.tests')
-def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None):
+def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None, report_type=None):
""" Try to render a report with contents of ids
This function should also check for common pitfalls of reports.
@@ -114,7 +114,6 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None,
Eg. 'OK' or 'gtk-print'
:param our_module: the name of the calling module (string), like 'account'
"""
-
if not our_module and isinstance(action_id, basestring):
if '.' in action_id:
our_module = action_id.split('.', 1)[0]
@@ -161,7 +160,10 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None,
# Updating the context : Adding the context of action in order to use it on Views called from buttons
if datas.get('id',False):
context.update( {'active_id': datas.get('id',False), 'active_ids': datas.get('ids',[]), 'active_model': datas.get('model',False)})
- context.update(safe_eval(action.get('context','{}'), context.copy()))
+ context1 = action.get('context', {})
+ if isinstance(context1, basestring):
+ context1 = safe_eval(context1, context.copy())
+ context.update(context1)
if action['type'] in ['ir.actions.act_window', 'ir.actions.submenu']:
for key in ('res_id', 'res_model', 'view_type', 'view_mode',
'limit', 'auto_refresh', 'search_view', 'auto_search', 'search_view_id'):
@@ -272,7 +274,9 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None,
if 'window' in datas:
del datas['window']
if not datas:
- datas = action.get('datas',{})
+ datas = action.get('datas')
+ if not datas:
+ datas = action.get('data')
datas = datas.copy()
ids = datas.get('ids')
if 'ids' in datas:
@@ -303,6 +307,4 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None,
return True
-#eof
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerpcommand/module.py b/openerpcommand/module.py
index 550e0a2be28..284c0186785 100644
--- a/openerpcommand/module.py
+++ b/openerpcommand/module.py
@@ -33,12 +33,9 @@ def run(args):
xs = []
ir_module_module = registry.get('ir.module.module')
- cr = registry.db.cursor() # TODO context manager
- try:
+ with registry.cursor() as cr:
ids = ir_module_module.search(cr, openerp.SUPERUSER_ID, [], {})
xs = ir_module_module.read(cr, openerp.SUPERUSER_ID, ids, [], {})
- finally:
- cr.close()
if xs:
print "Modules (database `%s`):" % (args.database,)
diff --git a/openerpcommand/read.py b/openerpcommand/read.py
index 5b68fb26ef0..61c05117875 100644
--- a/openerpcommand/read.py
+++ b/openerpcommand/read.py
@@ -20,15 +20,12 @@ def run(args):
registry = openerp.modules.registry.RegistryManager.get(
args.database, update_module=False)
model = registry[args.model]
- cr = registry.db.cursor() # TODO context manager
field_names = [args.field] if args.field else []
if args.short:
# ignore --field
field_names = ['name']
- try:
+ with registry.cursor() as cr:
xs = model.read(cr, 1, args.id, field_names, {})
- finally:
- cr.close()
if xs:
print "Records (model `%s`, database `%s`):" % (args.model, args.database)
diff --git a/openerpcommand/uninstall.py b/openerpcommand/uninstall.py
index 27e4e04002a..244b0575e53 100644
--- a/openerpcommand/uninstall.py
+++ b/openerpcommand/uninstall.py
@@ -43,15 +43,12 @@ def run(args):
args.database, update_module=False)
ir_module_module = registry.get('ir.module.module')
- cr = registry.db.cursor() # TODO context manager
- try:
+ with registry.cursor() as cr:
ids = ir_module_module.search(cr, openerp.SUPERUSER_ID, [('name', 'in', args.module), ('state', '=', 'installed')], {})
if len(ids) == len(args.module):
ir_module_module.button_immediate_uninstall(cr, openerp.SUPERUSER_ID, ids, {})
else:
print "At least one module not found (database `%s`)." % (args.database,)
- finally:
- cr.close()
def add_parser(subparsers):
parser = subparsers.add_parser('uninstall',
diff --git a/setup.py b/setup.py
index a44e26fd36f..21a6e6ad089 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@ def data():
# but this will work fine (especially since we don't use the ZIP file
# approach).
r["babel/localedata"] = glob.glob(os.path.join(os.path.dirname(babel.__file__), "localedata", '*'))
- others = ['global.dat', 'numbers.py', 'support.py']
+ others = ['global.dat', 'numbers.py', 'support.py', 'plural.py']
r["babel"] = map(lambda f: os.path.join(os.path.dirname(babel.__file__), f), others)
others = ['frontend.py', 'mofile.py']
r["babel/messages"] = map(lambda f: os.path.join(os.path.dirname(babel.__file__), "messages", f), others)
@@ -75,7 +75,42 @@ def py2exe_options():
"skip_archive": 1,
"optimize": 0, # keep the assert running, because the integrated tests rely on them.
"dist_dir": 'dist',
- "packages": ["HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "jinja2", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "pytz", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
+ "packages": [
+ "HTMLParser",
+ "PIL",
+ "asynchat", "asyncore",
+ "commands",
+ "dateutil",
+ "decimal",
+ "docutils",
+ "email",
+ "encodings",
+ "imaplib",
+ "jinja2",
+ "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify",
+ "mako",
+ "markupsafe", # dependence of jinja2 and mako
+ "mock",
+ "openerp",
+ "poplib",
+ "psutil",
+ "pychart",
+ "pydot",
+ "pyparsing",
+ "pytz",
+ "reportlab",
+ "requests",
+ "select",
+ "simplejson",
+ "smtplib",
+ "uuid",
+ "vatnumber",
+ "vobject",
+ "win32service", "win32serviceutil",
+ "xlwt",
+ "xml", "xml.dom",
+ "yaml",
+ ],
"excludes" : ["Tkconstants","Tkinter","tcl"],
}
}
@@ -115,7 +150,7 @@ setuptools.setup(
#include_package_data = True,
install_requires = [
'pychart', # not on pypi, use: pip install http://download.gna.org/pychart/PyChart-1.39.tar.gz
- 'babel',
+ 'babel >= 1.0',
'docutils',
'feedparser',
'gdata',
@@ -136,10 +171,11 @@ setuptools.setup(
'python-openid',
'pytz',
'pyusb >= 1.0.0b1',
- 'pywebdav',
+ 'pywebdav <= 0.9.4',
'pyyaml',
'qrcode',
'reportlab', # windows binary pypi.python.org/pypi/reportlab
+ 'requests',
'simplejson',
'unittest2',
'vatnumber',
@@ -150,7 +186,7 @@ setuptools.setup(
extras_require = {
'SSL' : ['pyopenssl'],
},
- tests_require = ['unittest2'],
+ tests_require = ['unittest2', 'mock'],
**py2exe_options()
)