diff --git a/openerp/addons/base/i18n/ab.po b/openerp/addons/base/i18n/ab.po
index 43085686f85df..86600d7723c4c 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-28 05:26+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 8b72134a932c6..c80488b1b138a 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-28 05:26+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 8da3ddda48b0d..2801a312ede10 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-28 05:27+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 bfec4b6175c28..e9f68449cd712 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-28 05:27+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 8ef295ab11035..3852489a95ea2 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-28 05:28+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 31ddf58c50353..7e1c406a26f27 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-28 05:27+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 0260f5f17216e..9dc651dbaa1bd 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-28 05:28+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 d3ee26f8aaad2..0aa0bdb4b0030 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-28 05:28+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 6f5180c287d96..0cce21599f8f6 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-28 05:28+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 09df3428d98a0..e18790d9ea70a 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-28 05:28+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 e5bd8df5beeb8..18616bdfb59b2 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-28 05:30+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 e3519923b062d..8aaa29b1d20b1 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-28 05:30+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 8f9c671d7fd50..c5b274489312d 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-28 05:39+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 71e1a37e6cb24..1bafe12a2ac29 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-28 05:36+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 b9fc7e6a6ae98..f9cf96454aa37 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-28 05:38+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 8fbeef6945cd3..64115de553f28 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-28 05:39+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 ee7a13a95cef3..f197496e56642 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-28 05:39+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 adc1071c93fe6..ed96b20642a80 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-28 05:40+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 38db01a388e8e..f4cf992b0dcd8 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-28 05:39+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 7254e6a5ff54f..6c9d93d2c5e66 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-28 05:41+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 c3eb28cb10eb1..6d49c4af1215e 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-28 05:40+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 0e551a5aa642e..c24a34e899b21 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-28 05:41+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 4ef9287878835..29a5b3730c654 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-28 05:38+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 c517ae44f2c56..d7363e67ba045 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-28 05:29+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 d16bce3efdeb9..af05c90097d77 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-28 05:27+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 0bfe683b7148f..4989167556c8a 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-28 05:34+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 e1d9cdb945a87..e189962cbd756 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-28 05:41+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 723867d301de8..ff4918cdeb8b1 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-28 05:29+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 9e75eb74b8780..c92aee812f0a9 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-28 05:29+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_CA.po b/openerp/addons/base/i18n/fr_CA.po
index 4a6a61ac48f78..48f2b6ec17985 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-28 05:39+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 48abd8027ae6f..9356943b63313 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-28 05:30+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 7022005574f1a..3dbee22ae468a 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-28 05:30+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 86276f6bc259b..9befcdeacbb82 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-28 05:31+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 96d55ee9b36ac..be528252f0fb8 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-28 05:31+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 62ce7012da74e..99319e8587701 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-28 05:35+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 043900400b47e..b65e88f7e4e16 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-28 05:31+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 b168e30f2d6d8..dd77f1732c864 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-28 05:27+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 8f0474dbcb3ab..55f984d410cc7 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-28 05:31+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 3752f2c679f84..5cb7d77c32377 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-28 05:31+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 f7a1bfdb4b04f..0cb63de96942f 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-28 05:32+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 63d0e0638f325..c5901311c657c 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-28 05:32+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 e227a1eeb17d1..bc03369afe623 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-28 05:29+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 559d5404844de..cb5b5faa6525f 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-28 05:32+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 144f0c8791875..970efa7c5bbe3 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-28 05:33+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 4ee73e3cb1c2f..1e7063751bc96 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-28 05:33+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 c607e7da1ee7b..a907da4ad7e36 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-28 05:33+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 7c4972a5415fe..6e4e39603d067 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-28 05:33+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 cee07a00d7d10..bdc3e7e37b7bb 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-28 05:34+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 1bdb6a4586b2d..d75034d791da9 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-28 05:34+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 1d54d67f3860d..23c7cf6679131 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-28 05:28+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 947ba509118b7..81590a55d185a 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-28 05:39+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 8f0f667841038..c851223d1b772 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-28 05:34+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 d6556d54c4e1e..f2ea63aa7f3f5 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-28 05:34+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/pt_BR.po b/openerp/addons/base/i18n/pt_BR.po
index 77821aaaefa69..7df1d214e2ce6 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-28 05:38+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 2cca4a60e1476..28b33255bbcb4 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-28 05:35+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 2146841182c5a..e49768a0f728e 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-28 05:35+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 ee5c82b00fd9b..6075c9ee6d024 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-28 05:36+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 55c241f346204..da1e8f4797447 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-28 05:36+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 8814da0bc607b..e022e19b6054d 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-28 05:27+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 014ca56f8fb48..bb354004c232c 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-28 05:35+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 86a4bacf873d6..4e86d70c5bd9a 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-28 05:41+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 bb452c8ce3510..08eaa1a49f4a0 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-28 05:36+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 2b1b772b9649c..b502e37fdc1ae 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-28 05:37+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 8d8ffb0464352..5ff7e20393192 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-28 05:37+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 6021dafeb01ad..f373aa3c8b446 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-28 05:37+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 12baea4370c18..0493f60ddc722 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-28 05:37+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 a616ae2d4345e..75aa8fc4ace42 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-28 05:37+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 5f82fc7f1a05c..53c94aa43fcf6 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-28 05:37+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 a192a6a169e3a..69163ff7b360b 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-28 05:40+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 f3bc1c1923e82..6f21dd4456568 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-28 05:38+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 c57c69227a25e..b7e8da5b200ca 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-28 05:40+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 966489b4be22b..4e17795979251 100644
--- a/openerp/addons/base/ir/ir_actions.py
+++ b/openerp/addons/base/ir/ir_actions.py
@@ -104,7 +104,9 @@ def _lookup_report(self, cr, name):
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 @@ def render_report(self, cr, uid, res_ids, name, data, context=None):
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'
diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py
index 3c195c93c6c91..40ed60b05a3d3 100644
--- a/openerp/addons/base/ir/ir_qweb.py
+++ b/openerp/addons/base/ir/ir_qweb.py
@@ -241,7 +241,7 @@ def render_node(self, element, qwebcontext):
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 @@ def render_tag_raw(self, element, template_attributes, generated_attributes, qwe
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 @@ def get_converter_for(self, field_type):
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
#--------------------------------------------------------------------
@@ -840,6 +845,38 @@ def record_to_html(self, cr, uid, field_name, record, column, options=None, cont
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/module/module.py b/openerp/addons/base/module/module.py
index 6ad74857f39b6..b82e6b8242dea 100644
--- a/openerp/addons/base/module/module.py
+++ b/openerp/addons/base/module/module.py
@@ -31,6 +31,7 @@
import tempfile
import urllib
import urllib2
+import urlparse
import zipfile
import zipimport
import lxml.html
@@ -41,6 +42,7 @@
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 @@ def update_list(self, cr, uid, context=None):
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 @@ def install_from_urls(self, cr, uid, urls, context=None):
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 @@ def install_from_urls(self, cr, uid, urls, context=None):
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_users.py b/openerp/addons/base/res/res_users.py
index 772f7f7290bf3..32e81ee600f1b 100644
--- a/openerp/addons/base/res/res_users.py
+++ b/openerp/addons/base/res/res_users.py
@@ -388,14 +388,13 @@ def login(self, db, login, password):
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
# interleaving their cr.execute()..cr.commit() calls and have one
# of them rolled back due to a concurrent access.)
- if not openerp.tools.config['test_enable']:
- cr.autocommit(True)
+ cr.autocommit(True)
# check if user exists
res = self.search(cr, SUPERUSER_ID, [('login','=',login)])
if res:
@@ -440,7 +439,7 @@ def authenticate(self, db, login, password, user_agent_env):
# 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']
@@ -461,7 +460,7 @@ def check(self, db, uid, passwd):
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/src/js/apps.js b/openerp/addons/base/static/src/js/apps.js
index e339ed2230e9f..115d35fcc4f1e 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 b3ce36467bbf4..d60f38185b944 100644
--- a/openerp/addons/base/tests/test_db_cursor.py
+++ b/openerp/addons/base/tests/test_db_cursor.py
@@ -21,7 +21,7 @@ def test_execute_bad_params(self):
"""
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 f12b7216b77ee..de7e04724795b 100644
--- a/openerp/addons/base/tests/test_expression.py
+++ b/openerp/addons/base/tests/test_expression.py
@@ -183,7 +183,7 @@ def test_20_auto_join(self):
self.assertIn('res_partner_bank', sql_query[0],
"_auto_join off: ('bank_ids.name', 'like', '..') first query incorrect main table")
- expected = "%s like %s" % (unaccent('"res_partner_bank"."name"'), unaccent('%s'))
+ 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")
@@ -223,7 +223,7 @@ def test_20_auto_join(self):
self.assertIn('"res_partner_bank" as "res_partner__bank_ids"', sql_query[0],
"_auto_join on: ('bank_ids.name', 'like', '..') query incorrect join")
- expected = "%s like %s" % (unaccent('"res_partner__bank_ids"."name"'), unaccent('%s'))
+ 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")
@@ -305,7 +305,7 @@ def test_20_auto_join(self):
self.assertIn('"res_country"', sql_query[0],
"_auto_join on for state_id: ('state_id.country_id.code', 'like', '..') query 1 incorrect main table")
- expected = "%s like %s" % (unaccent('"res_country"."code"'), unaccent('%s'))
+ 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")
@@ -339,7 +339,7 @@ def test_20_auto_join(self):
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")
- expected = "%s like %s" % (unaccent('"res_country_state__country_id"."code"'), unaccent('%s'))
+ 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")
@@ -373,7 +373,7 @@ def test_20_auto_join(self):
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")
- expected = "%s like %s" % (unaccent('"res_partner__state_id__country_id"."code"'), unaccent('%s'))
+ 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")
@@ -403,7 +403,7 @@ def test_20_auto_join(self):
# Test produced queries that domains effectively present
sql_query = self.query_list[0].get_sql()
- expected = "%s like %s" % (unaccent('"res_partner__child_ids__bank_ids"."acc_number"'), unaccent('%s'))
+ 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
diff --git a/openerp/addons/base/tests/test_ir_sequence.py b/openerp/addons/base/tests/test_ir_sequence.py
index e925fffa3b119..18b56daa58cff 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_uninstall.py b/openerp/addons/base/tests/test_uninstall.py
index 2425249afa4bc..b5c51c814059f 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 06030a84792d2..f096783672692 100644
--- a/openerp/addons/base/tests/test_views.py
+++ b/openerp/addons/base/tests/test_views.py
@@ -28,7 +28,7 @@ def assertTreesEqual(self, n1, n2, msg=None):
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 561b9a19879c7..18ac69c38e204 100644
--- a/openerp/cli/server.py
+++ b/openerp/cli/server.py
@@ -111,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()
@@ -125,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()
diff --git a/openerp/http.py b/openerp/http.py
index 2e21d27528a73..8d7497fc40d02 100644
--- a/openerp/http.py
+++ b/openerp/http.py
@@ -235,10 +235,7 @@ def cr(self):
"""
# 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 @@ def __exit__(self, exc_type, exc_value, traceback):
_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
@@ -294,7 +286,7 @@ def _call_function(self, *args, **kwargs):
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)
diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py
index 78b7e5caeab42..ef6aaf19d5abc 100644
--- a/openerp/modules/registry.py
+++ b/openerp/modules/registry.py
@@ -58,7 +58,10 @@ def __init__(self, db_name):
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 @@ def __init__(self, db_name):
# 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 @@ def __getitem__(self, model_name):
""" 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 @@ def setup_multi_process_signaling(cls, cr):
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()
-
-class TestRLock(object):
- def __init__(self):
- self._lock = threading.RLock()
+ 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()
+
+ 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 @@ def new(cls, db_name, force_demo=False, status=None,
"""
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 @@ def new(cls, db_name, force_demo=False, status=None,
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 @@ def new(cls, db_name, force_demo=False, status=None,
# 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 @@ def new(cls, db_name, force_demo=False, status=None,
@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 @@ def delete(cls, db_name):
@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 @@ def clear_caches(cls, db_name):
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 @@ def check_registry_signaling(cls, db_name):
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 @@ def signal_caches_change(cls, db_name):
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 @@ def signal_registry_change(cls, db_name):
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 52dc4a265ba50..d3231c54462bd 100644
--- a/openerp/osv/expression.py
+++ b/openerp/osv/expression.py
@@ -1182,14 +1182,15 @@ def __leaf_to_sql(self, eleaf):
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]
unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x
column = '%s.%s' % (table_alias, _quote(left))
- query = '(%s %s %s)' % (unaccent(column), sql_operator, unaccent(format))
+ 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/pooler.py b/openerp/pooler.py
index 0df6f88c819d0..5ada4c2a01423 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/service/model.py b/openerp/service/model.py
index a637e234295d0..a91baf8ca08c0 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 370b11fc19966..0c2f720f4cbea 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/sql_db.py b/openerp/sql_db.py
index 59841656d8ca3..fcc60e7b6f32e 100644
--- a/openerp/sql_db.py
+++ b/openerp/sql_db.py
@@ -167,7 +167,7 @@ def __init__(self, pool, dbname, serialized=True):
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 @@ def _close(self, leak=False):
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 @@ def rollback(self):
"""
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 @@ def savepoint(self):
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 c1f7cf88ed135..9f3684fa6df47 100644
--- a/openerp/tests/common.py
+++ b/openerp/tests/common.py
@@ -20,6 +20,7 @@
import werkzeug
import openerp
+from openerp.modules.registry import RegistryManager
_logger = logging.getLogger(__name__)
@@ -37,25 +38,6 @@
# 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 decorator(obj):
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 @@ def ref(self, xid):
_, 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 @@ def __init__(self, methodName='runTest'):
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):
diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py
index 85dcfd368fefa..de6cd1735219d 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 508a072a3b2ed..2f28068535082 100644
--- a/openerp/tools/safe_eval.py
+++ b/openerp/tools/safe_eval.py
@@ -71,7 +71,8 @@
'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 874a8cced6152..c008c20ae2988 100644
--- a/openerp/tools/test_reports.py
+++ b/openerp/tools/test_reports.py
@@ -38,7 +38,7 @@
_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 _exec_action(action, datas, context):
# 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 _exec_action(action, datas, context):
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 _exec_action(action, datas, context):
return True
-#eof
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/openerpcommand/module.py b/openerpcommand/module.py
index 550e0a2be2821..284c0186785ad 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 5b68fb26ef097..61c051178756a 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 27e4e04002ac0..244b0575e53d3 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 214002d6f44e2..21a6e6ad0897c 100644
--- a/setup.py
+++ b/setup.py
@@ -150,7 +150,7 @@ def py2exe_options():
#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',
@@ -171,7 +171,7 @@ def py2exe_options():
'python-openid',
'pytz',
'pyusb >= 1.0.0b1',
- 'pywebdav',
+ 'pywebdav <= 0.9.4',
'pyyaml',
'qrcode',
'reportlab', # windows binary pypi.python.org/pypi/reportlab