[MERGE] Forward-port latest saas-3 bugfixes, up to 30f43da
authorOlivier Dony <odo@openerp.com>
Tue, 27 May 2014 15:18:43 +0000 (17:18 +0200)
committerOlivier Dony <odo@openerp.com>
Tue, 27 May 2014 15:18:43 +0000 (17:18 +0200)
20 files changed:
addons/account/account_invoice_view.xml
addons/account/report/account_aged_partner_balance.py
addons/account_analytic_analysis/account_analytic_analysis.py
addons/account_analytic_analysis/account_analytic_analysis_view.xml
addons/account_budget/account_budget.py
addons/delivery/delivery.py
addons/hr/static/src/img/default_image.png [new file with mode: 0644]
addons/hr_recruitment/hr_recruitment.py
addons/mail/static/src/js/mail.js
addons/mail/static/src/xml/mail.xml
addons/pad/static/src/img/pad_link_companies.jpeg [new file with mode: 0644]
addons/purchase/edi/purchase_order_action_data.xml
addons/purchase/purchase.py
addons/report_webkit/webkit_report.py
addons/web/static/src/js/view_form.js
addons/website/models/ir_http.py
addons/website_sale/controllers/main.py
addons/website_sale/models/product.py
openerp/http.py
openerp/report/render/rml2pdf/trml2pdf.py

index 61c3973..fe701a8 100644 (file)
@@ -60,7 +60,7 @@
                         </group>
                         <group>
                             <field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)" groups="account.group_account_user"/>
-                            <field name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
+                            <field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
                             <field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
                             <field name="company_id" groups="base.group_multi_company" readonly="1"/>
                         </group>
index 3fd83c1..2e3c9b7 100644 (file)
@@ -161,7 +161,7 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
                 dates_query += ' < %s)'
                 args_list += (form[str(i)]['stop'],)
             args_list += (self.date_from,)
-            self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit)
+            self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit), l.reconcile_partial_id
                     FROM account_move_line AS l, account_account, account_move am 
                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)
                         AND (am.state IN %s)
@@ -173,12 +173,24 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header):
                         AND account_account.active
                         AND ''' + dates_query + '''
                     AND (l.date <= %s)
-                    GROUP BY l.partner_id''', args_list)
-            t = self.cr.fetchall()
-            d = {}
-            for i in t:
-                d[i[0]] = i[1]
-            history.append(d)
+                    GROUP BY l.partner_id, l.reconcile_partial_id''', args_list)
+            partners_partial = self.cr.fetchall()
+            partners_amount = dict((i[0],0) for i in partners_partial)
+            for partner_info in partners_partial:
+                if partner_info[2]:
+                    # in case of partial reconciliation, we want to keep the left amount in the oldest period
+                    self.cr.execute('''SELECT MIN(COALESCE(date_maturity,date)) FROM account_move_line WHERE reconcile_partial_id = %s''', (partner_info[2],))
+                    date = self.cr.fetchall()
+                    if date and args_list[-3] <= date[0][0] <= args_list[-2]:
+                        # partial reconcilation
+                        self.cr.execute('''SELECT SUM(l.debit-l.credit)
+                                           FROM account_move_line AS l
+                                           WHERE l.reconcile_partial_id = %s''', (partner_info[2],))
+                        unreconciled_amount = self.cr.fetchall()
+                        partners_amount[partner_info[0]] += unreconciled_amount[0][0]
+                else:
+                    partners_amount[partner_info[0]] += partner_info[1]
+            history.append(partners_amount)
 
         for partner in partners:
             values = {}
index 36b829e..3192703 100644 (file)
@@ -82,7 +82,7 @@ class account_analytic_invoice_line(osv.osv):
         if not name:
             name = self.pool.get('product.product').name_get(cr, uid, [res.id], context=local_context)[0][1]
             if res.description_sale:
-                result['name'] += '\n'+res.description_sale
+                name += '\n'+res.description_sale
 
         result.update({'name': name or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price})
 
@@ -756,6 +756,8 @@ class account_analytic_account(osv.osv):
                     new_date = next_date+relativedelta(days=+interval)
                 elif contract.recurring_rule_type == 'weekly':
                     new_date = next_date+relativedelta(weeks=+interval)
+                elif contract.recurring_rule_type == 'yearly':
+                    new_date = next_date+relativedelta(years=+interval)
                 else:
                     new_date = next_date+relativedelta(months=+interval)
                 self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context)
index a6fe828..af4caae 100644 (file)
                     <div attrs="{'invisible': [('recurring_invoices','=',False)]}">
                         <field name="recurring_invoice_line_ids">
                             <tree string="Account Analytic Lines" editable="bottom">
-                                <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, name, parent.partner_id, price_unit, parent.pricelist_id, parent.company_id)"/>
+                                <field name="product_id" on_change="product_id_change(product_id, uom_id, quantity, False, parent.partner_id, False, parent.pricelist_id, parent.company_id)"/>
                                 <field name="name"/>
                                 <field name="quantity"/>
                                 <field name="uom_id"/>
index 753a5df..78e8571 100644 (file)
@@ -22,6 +22,7 @@
 import datetime
 
 from openerp.osv import fields, osv
+from openerp.tools import ustr
 from openerp.tools.translate import _
 
 import openerp.addons.decimal_precision as dp
@@ -114,7 +115,7 @@ class crossovered_budget_lines(osv.osv):
         for line in self.browse(cr, uid, ids, context=context):
             acc_ids = [x.id for x in line.general_budget_id.account_ids]
             if not acc_ids:
-                raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % str(line.general_budget_id.name))
+                raise osv.except_osv(_('Error!'),_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name))
             date_to = line.date_to
             date_from = line.date_from
             if context.has_key('wizard_date_from'):
index 3827baa..59542ee 100644 (file)
@@ -191,14 +191,15 @@ class delivery_grid(osv.osv):
         total = 0
         weight = 0
         volume = 0
+        product_uom_obj = self.pool.get('product.uom')
         for line in order.order_line:
             if not line.product_id or line.is_delivery:
                 continue
-            weight += (line.product_id.weight or 0.0) * line.product_uom_qty
-            volume += (line.product_id.volume or 0.0) * line.product_uom_qty
+            q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uos_qty, line.product_id.uom_id.id)
+            weight += (line.product_id.weight or 0.0) * q
+            volume += (line.product_id.volume or 0.0) * q
         total = order.amount_total or 0.0
 
-
         return self.get_price_from_picking(cr, uid, id, total,weight, volume, context=context)
 
     def get_price_from_picking(self, cr, uid, id, total, weight, volume, context=None):
diff --git a/addons/hr/static/src/img/default_image.png b/addons/hr/static/src/img/default_image.png
new file mode 100644 (file)
index 0000000..87fdbc5
Binary files /dev/null and b/addons/hr/static/src/img/default_image.png differ
index fa51f58..0d27418 100644 (file)
@@ -115,6 +115,15 @@ class hr_applicant(osv.Model):
                 return int(department_ids[0][0])
         return None
 
+    def _get_default_company_id(self, cr, uid, department_id=None, context=None):
+        company_id = False
+        if department_id:
+            department = self.pool['hr.department'].browse(cr,  uid, department_id, context=context)
+            company_id = department.company_id.id if department and department.company_id else False
+        if not company_id:
+            company_id = self.pool['res.company']._company_default_get(cr, uid, 'hr.applicant', context=context)
+        return company_id            
+
     def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
         access_rights_uid = access_rights_uid or uid
         stage_obj = self.pool.get('hr.recruitment.stage')
@@ -232,7 +241,7 @@ class hr_applicant(osv.Model):
         'user_id': lambda s, cr, uid, c: uid,
         'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
         'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
-        'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'hr.applicant', context=c),
+        'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, s._get_default_department_id(cr, uid, c), c),
         'color': 0,
         'date_last_stage_update': fields.datetime.now,
     }
index 99a7751..e5eca72 100644 (file)
@@ -919,15 +919,45 @@ openerp.mail = function (session) {
             this.$('.oe_mail_expand').on('click', this.on_expand);
             this.$('.oe_mail_reduce').on('click', this.on_expand);
             this.$('.oe_mail_action_model').on('click', this.on_record_clicked);
+            this.$('.oe_mail_action_author').on('click', this.on_record_author_clicked);
         },
 
         on_record_clicked: function  (event) {
+            event.preventDefault();
+            var self = this;
             var state = {
                 'model': this.model,
                 'id': this.res_id,
                 'title': this.record_name
             };
             session.webclient.action_manager.do_push_state(state);
+            this.context.params = {
+                model: this.model,
+                res_id: this.res_id,
+            };
+            this.thread.ds_thread.call("message_redirect_action", {context: this.context}).then(function(action){
+                self.do_action(action); 
+            });
+        },
+
+        on_record_author_clicked: function  (event) {
+            event.preventDefault();
+            var partner_id = $(event.target).data('partner');
+            var state = {
+                'model': 'res.partner',
+                'id': partner_id,
+                'title': this.record_name
+            };
+            session.webclient.action_manager.do_push_state(state);
+            var action = {
+                type:'ir.actions.act_window',
+                view_type: 'form',
+                view_mode: 'form',
+                res_model: 'res.partner',
+                views: [[false, 'form']],
+                res_id: partner_id,
+            }
+            this.do_action(action);
         },
 
         /* Call the on_compose_message on the thread of this message. */
index 28cbbca..2a4ac8d 100644 (file)
                     <t t-if="widget.attachment_ids.length > 0">
                         <div class="oe_msg_attachment_list"></div>
                     </t>
-                    <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-esc="widget.author_id[2]"/></a>
+                    <a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}" t-att-data-partner="widget.author_id[0]" class="oe_mail_action_author"><t t-esc="widget.author_id[2]"/></a>
                     <span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-esc="widget.author_id[2]"/></span>
                     <t t-if="widget.type == 'notification'">
                         updated document
                     <t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
                             t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
                         <span t-attf-class="oe_partner_follower">
-                        <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-esc="partner[1]"/></a>
+                        <a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}" t-att-data-partner="partner[0]" class="oe_mail_action_author"><t t-esc="partner[1]"/></a>
                         <t t-if="!widget.options.show_link" t-esc="partner[1]"/>
                         </span>
                         <t t-if="!partner_last">,</t>
diff --git a/addons/pad/static/src/img/pad_link_companies.jpeg b/addons/pad/static/src/img/pad_link_companies.jpeg
new file mode 100644 (file)
index 0000000..1bce3a5
Binary files /dev/null and b/addons/pad/static/src/img/pad_link_companies.jpeg differ
index 5bb56e8..51d075b 100644 (file)
@@ -37,7 +37,7 @@
     <p style="border-left: 1px solid #8e0000; margin-left: 30px;">
        &nbsp;&nbsp;<strong>REFERENCES</strong><br />
        &nbsp;&nbsp;Order number: <strong>${object.name}</strong><br />
-       &nbsp;&nbsp;Order total: <strong>${object.amount_total} ${object.pricelist_id.currency_id.name}</strong><br />
+       &nbsp;&nbsp;Order total: <strong>${object.amount_total} ${object.currency_id.name}</strong><br />
        &nbsp;&nbsp;Order date: ${object.date_order}<br />
        % if object.origin:
        &nbsp;&nbsp;Order reference: ${object.origin}<br />
index e7b83b4..fa074bb 100644 (file)
@@ -192,7 +192,7 @@ class purchase_order(osv.osv):
         'picking_ids': fields.one2many('stock.picking.in', 'purchase_id', 'Picking List', readonly=True, help="This is the list of incoming shipments that have been generated for this purchase order."),
         'shipped':fields.boolean('Received', readonly=True, select=True, help="It indicates that a picking has been done"),
         'shipped_rate': fields.function(_shipped_rate, string='Received Ratio', type='float'),
-        'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been paid"),
+        'invoiced': fields.function(_invoiced, string='Invoice Received', type='boolean', help="It indicates that an invoice has been validated"),
         'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'),
         'invoice_method': fields.selection([('manual','Based on Purchase Order lines'),('order','Based on generated draft invoice'),('picking','Based on incoming shipments')], 'Invoicing Control', required=True,
             readonly=True, states={'draft':[('readonly',False)], 'sent':[('readonly',False)]},
index 60fb536..c442ea3 100644 (file)
@@ -156,8 +156,8 @@ class WebKitParser(report_sxw):
         """Call webkit in order to generate pdf"""
         if not webkit_header:
             webkit_header = report_xml.webkit_header
-        tmp_dir = tempfile.gettempdir()
-        out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.")
+        fd, out_filename = tempfile.mkstemp(suffix=".pdf",
+                                            prefix="webkit.tmp.")
         file_to_del = [out_filename]
         if comm_path:
             command = [comm_path]
@@ -168,25 +168,15 @@ class WebKitParser(report_sxw):
         # default to UTF-8 encoding.  Use <meta charset="latin-1"> to override.
         command.extend(['--encoding', 'utf-8'])
         if header :
-            head_file = file( os.path.join(
-                                  tmp_dir,
-                                  str(time.time()) + '.head.html'
-                                 ),
-                                'w'
-                            )
-            head_file.write(self._sanitize_html(header.encode('utf-8')))
-            head_file.close()
+            with tempfile.NamedTemporaryFile(suffix=".head.html",
+                                             delete=False) as head_file:
+                head_file.write(self._sanitize_html(header.encode('utf-8')))
             file_to_del.append(head_file.name)
             command.extend(['--header-html', head_file.name])
         if footer :
-            foot_file = file(  os.path.join(
-                                  tmp_dir,
-                                  str(time.time()) + '.foot.html'
-                                 ),
-                                'w'
-                            )
-            foot_file.write(self._sanitize_html(footer.encode('utf-8')))
-            foot_file.close()
+            with tempfile.NamedTemporaryFile(suffix=".foot.html",
+                                             delete=False) as foot_file:
+                foot_file.write(self._sanitize_html(footer.encode('utf-8')))
             file_to_del.append(foot_file.name)
             command.extend(['--footer-html', foot_file.name])
 
@@ -204,10 +194,10 @@ class WebKitParser(report_sxw):
             command.extend(['--page-size', str(webkit_header.format).replace(',', '.')])
         count = 0
         for html in html_list :
-            html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w')
-            count += 1
-            html_file.write(self._sanitize_html(html.encode('utf-8')))
-            html_file.close()
+            with tempfile.NamedTemporaryFile(suffix="%d.body.html" %count,
+                                             delete=False) as html_file:
+                count += 1
+                html_file.write(self._sanitize_html(html.encode('utf-8')))
             file_to_del.append(html_file.name)
             command.append(html_file.name)
         command.append(out_filename)
@@ -227,9 +217,9 @@ class WebKitParser(report_sxw):
             if status :
                 raise except_osv(_('Webkit error' ),
                                  _("The command 'wkhtmltopdf' failed with error code = %s. Message: %s") % (status, error_message))
-            pdf_file = open(out_filename, 'rb')
-            pdf = pdf_file.read()
-            pdf_file.close()
+            with open(out_filename, 'rb') as pdf_file:
+                pdf = pdf_file.read()
+            os.close(fd)
         finally:
             if stderr_fd is not None:
                 os.close(stderr_fd)
index 7a869d7..dee6856 100644 (file)
@@ -4337,7 +4337,11 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
             else
                 return $.when();
         }).done(function () {
-            if (!self.o2m.options.reload_on_button) {
+            var ds = self.o2m.dataset;
+            var cached_records = _.any([ds.to_create, ds.to_delete, ds.to_write], function(value) {
+                return value.length;
+            });
+            if (!self.o2m.options.reload_on_button && !cached_records) {
                 self.handle_button(name, id, callback);
             }else {
                 self.handle_button(name, id, function(){
index 62b6fa3..d348d17 100644 (file)
@@ -126,50 +126,50 @@ class ir_http(orm.AbstractModel):
             return response
 
     def _handle_exception(self, exception=None, code=500):
-        res = super(ir_http, self)._handle_exception(exception)
-        if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response:
-            return exception.response
+        try:
+            return super(ir_http, self)._handle_exception(exception)
+        except Exception:
 
         attach = self._serve_attachment()
         if attach:
             return attach
 
-        if getattr(request, 'website_enabled', False) and request.website:
-            values = dict(
-                exception=exception,
-                traceback=traceback.format_exc(exception),
-            )
-            if exception:
-                code = getattr(exception, 'code', code)
-                if isinstance(exception, ir_qweb.QWebException):
-                    values.update(qweb_exception=exception)
-                    if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
-                        code = 403
-            if code == 500:
-                logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
-                if 'qweb_exception' in values:
-                    view = request.registry.get("ir.ui.view")
-                    views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
-                    to_reset = [v for v in views if v.model_data_id.noupdate is True]
-                    values['views'] = to_reset
-            elif code == 403:
-                logger.warn("403 Forbidden:\n\n%s", values['traceback'])
-
-            values.update(
-                status_message=werkzeug.http.HTTP_STATUS_CODES[code],
-                status_code=code,
-            )
-
-            if not request.uid:
-                self._auth_method_public()
-
-            try:
-                html = request.website._render('website.%s' % code, values)
-            except Exception:
-                html = request.website._render('website.http_error', values)
-            return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
-
-        return res
+            if getattr(request, 'website_enabled', False) and request.website:
+                values = dict(
+                    exception=exception,
+                    traceback=traceback.format_exc(exception),
+                )
+                if exception:
+                    code = getattr(exception, 'code', code)
+                    if isinstance(exception, ir_qweb.QWebException):
+                        values.update(qweb_exception=exception)
+                        if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
+                            code = 403
+                if code == 500:
+                    logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
+                    if 'qweb_exception' in values:
+                        view = request.registry.get("ir.ui.view")
+                        views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
+                        to_reset = [v for v in views if v.model_data_id.noupdate is True]
+                        values['views'] = to_reset
+                elif code == 403:
+                    logger.warn("403 Forbidden:\n\n%s", values['traceback'])
+
+                values.update(
+                    status_message=werkzeug.http.HTTP_STATUS_CODES[code],
+                    status_code=code,
+                )
+
+                if not request.uid:
+                    self._auth_method_public()
+
+                try:
+                    html = request.website._render('website.%s' % code, values)
+                except Exception:
+                    html = request.website._render('website.http_error', values)
+                return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
+
+            raise
 
 class ModelConverter(ir.ir_http.ModelConverter):
     def __init__(self, url_map, model=False, domain='[]'):
index e49ed5f..89eae9f 100644 (file)
@@ -78,8 +78,8 @@ class table_compute(object):
         index = 0
         maxy = 0
         for p in products:
-            x = p.website_size_x
-            y = p.website_size_y
+            x = min(max(p.website_size_x, 1), PPR)
+            y = min(max(p.website_size_y, 1), PPR)
             if index>PPG:
                 x = y = 1
 
index bfb3c14..3f71340 100644 (file)
@@ -33,6 +33,7 @@ class product_template(osv.Model):
     _inherit = ["product.template", "website.seo.metadata"]
     _order = 'website_published desc, website_sequence desc, name'
     _name = 'product.template'
+    _mail_post_access = 'read'
 
     def _website_url(self, cr, uid, ids, field_name, arg, context=None):
         res = dict.fromkeys(ids, '')
index c5924b5..45a09f9 100644 (file)
@@ -268,6 +268,9 @@ class WebRequest(object):
            to abitrary responses. Anything returned (except None) will
            be used as response.""" 
         self._failed = exception # prevent tx commit
+        if isinstance(exception, werkzeug.exceptions.HTTPException):
+            return exception
+        raise
 
     def _call_function(self, *args, **kwargs):
         request = self
@@ -448,18 +451,20 @@ class JsonRequest(WebRequest):
     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.""" 
-        super(JsonRequest, self)._handle_exception(exception)
-        _logger.exception("Exception during JSON request handling.")
-        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)
+           be used as response."""
+        try:
+            return super(JsonRequest, self)._handle_exception(exception)
+        except Exception:
+            _logger.exception("Exception during JSON request handling.")
+            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
index 8d6edb8..af04683 100644 (file)
@@ -1007,6 +1007,8 @@ class _rml_template(object):
             if story_cnt > 0:
                 fis.append(platypus.PageBreak())
             fis += r.render(node_story)
+            # Reset Page Number with new story tag
+            fis.append(PageReset())
             story_cnt += 1
         try:
             if self.localcontext and self.localcontext.get('internal_header',False):