Commit 0cfb1586 authored by Jérome Perrin's avatar Jérome Perrin

More python3 support

See merge request nexedi/erp5!1863
parents 2e8ef0bb 7fc1e3b0
Pipeline #32189 failed with stage
"""Resets grouping reference on this line and all related lines.
This runs by default asynchronously, but can be call with `async=False` to
run synchronously and returns the list of ungrouped lines. With `async=True`,
This runs by default asynchronoushronously, but can be call with `asynchronous=False` to
run synchronously and returns the list of ungrouped lines. With `asynchronous=True`,
the returned list is always empty.
"""
......@@ -13,7 +13,7 @@ if not context.getGroupingReference():
portal = context.getPortalObject()
resetGroupingReference = portal.ERP5Site_resetAccountingTransactionLineGroupingReference
if async:
if asynchronous:
resetGroupingReference = portal.portal_simulation.activate(
activity='SQLQueue',
after_tag='accounting_grouping_reference'
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>async=True</string> </value>
<value> <string>asynchronous=True</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -121,7 +121,7 @@ else:
if line.getGroupingReference():
# Call AccountingTransactionLine_resetGroupingReference synchronously
# to know the number of ungrouped lines.
ungrouped_line_list.extend(line.AccountingTransactionLine_resetGroupingReference(async=False))
ungrouped_line_list.extend(line.AccountingTransactionLine_resetGroupingReference(asynchronous=False))
portal_status_message = Base_translateString('${ungrouped_line_count} lines ungrouped.',
mapping=dict(ungrouped_line_count=len(ungrouped_line_list)))
......
......@@ -3907,7 +3907,7 @@ class TestTransactions(AccountingTestCase):
# reset from the payment line, the invoice line from the same group will be
# ungrouped
payment_line.AccountingTransactionLine_resetGroupingReference(async=False)
payment_line.AccountingTransactionLine_resetGroupingReference(asynchronous=False)
self.assertFalse(payment_line.getGroupingReference())
self.assertFalse(payment_line.getGroupingDate())
self.assertFalse(invoice_line.getGroupingReference())
......
......@@ -27,6 +27,10 @@ from mimetools import choose_boundary
from Products.CMFCore.utils import _setCacheHeaders, _ViewEmulator
from DateTime import DateTime
import re
import six
if six.PY3:
long = int # pylint:disable=redefined-builtin
class BigFile(File):
"""
......
......@@ -33,6 +33,7 @@ from random import randint
import sys
import threading
import traceback
import unittest
import six
from AccessControl import getSecurityManager
from AccessControl.SecurityManagement import newSecurityManager
......@@ -48,6 +49,9 @@ from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery, SimpleQuery
from Testing import ZopeTestCase
from zLOG import LOG
if six.PY3:
long = int # pylint:disable=redefined-builtin
def format_stack(thread=None):
frame_dict = sys._current_frames()
if thread is not None:
......@@ -588,7 +592,7 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor):
uid_dict = {}
for _ in xrange(UID_BUFFER_SIZE * 3):
uid = portal_catalog.newUid()
self.assertTrue(isinstance(uid, long))
self.assertIsInstance(uid, long)
self.assertNotIn(uid, uid_dict)
uid_dict[uid] = None
......@@ -1647,6 +1651,9 @@ class TestERP5Catalog(ERP5TypeTestCase, LogInterceptor):
portal_type='Organisation',**catalog_kw)])
def test_54_FixIntUid(self):
if six.PY3:
return unittest.skipTest(
"Python3 does not have different types for int and long")
portal = self.getPortal()
module = portal.getDefaultModule('Organisation')
......
......@@ -34,7 +34,7 @@ import unittest
def get_Z2_log_last_line():
z2_log_path = os.path.join(log_directory, 'Z2.log')
f = open(z2_log_path, 'rb')
f = open(z2_log_path, 'r')
try:
f.seek(-256, os.SEEK_END) # Assumes last line is not longer than 256 chars (it should be about 130)
except IOError: # too short
......
......@@ -34,7 +34,7 @@ import unittest
from AccessControl.SecurityManagement import newSecurityManager
from Testing import ZopeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from DocumentTemplate.DT_Util import html_quote
from DocumentTemplate.html_quote import html_quote
class TestEditorField(ERP5TypeTestCase, ZopeTestCase.Functional):
"""
......
# export_only : allow to disable the uid column and the id of columns
import six
result = ''
request = context.REQUEST
......@@ -9,7 +10,7 @@ listboxline_list = context.get_value('default', render_format='list', REQUEST=re
def encode(value):
if isinstance(value, bool):
return '"%s"' % value
if isinstance(value, (int, long, float)):
if isinstance(value, six.integer_types + (float,)):
return str(value)
else:
if isinstance(value, str):
......
......@@ -238,7 +238,7 @@
error python: value[2]"
class="DataA" align="left"
tal:attributes="class python: error and (css + 'Error') or css;
align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'">
align python: isinstance(original_value, modules['six'].integer_types + (float,)) and 'right' or 'left'">
<input tal:condition="not: repeat/value/index"
type="hidden" value="1" name="listbox_uid:list"
tal:attributes="value python: line.getUid() or '';
......@@ -268,7 +268,7 @@
<tal:block tal:repeat="value here/getStatValueList">
<td class="Data" align="left"
tal:define="original_value python: value[0]; processed_value python: value[1]"
tal:attributes="align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'"
tal:attributes="align python: isinstance(original_value, modules['six'].integer_types + (float,)) and 'right' or 'left'"
tal:content="structure processed_value" />
</tal:block>
</tr>
......
......@@ -15,16 +15,17 @@ There are runtime values hidden in every dialog form (injected by getHateoas Scr
from erp5.component.module.Log import log, WARNING
from Products.Formulator.Errors import FormValidationError
import json
import six
# http://stackoverflow.com/a/13105359
def byteify(value):
if isinstance(value, dict):
return {byteify(key): byteify(value) for key, value in value.iteritems()}
return {byteify(key): byteify(value) for key, value in six.iteritems(value)}
elif isinstance(value, list):
return [byteify(element) for element in value]
elif isinstance(value, tuple):
return tuple(byteify(element) for element in value)
elif isinstance(value, unicode):
elif six.PY2 and isinstance(value, six.text_type):
return value.encode('utf-8')
else:
return value
......
......@@ -6,8 +6,9 @@ Return JSON with message to be displayed and set according HTTP STATUS for messa
"""
import json
from erp5.component.module.Log import WARNING, ERROR
import six
if isinstance(level, (str, unicode)):
if isinstance(level, (str, six.text_type)):
if level.lower() == "error":
response_code = 500
elif level.lower().startswith("warn"):
......
......@@ -3,6 +3,7 @@ from Products.Formulator.Errors import FormValidationError
from Products.ERP5Type.Core.Workflow import ValidationFailed
from Products.ERP5Type.Message import translateString
from erp5.component.module.Log import WARNING
import six
portal = context.getPortalObject()
request = REQUEST or context.REQUEST
......@@ -43,7 +44,7 @@ for f in form.get_fields():
listbox = request.get('listbox') # XXX: hardcoded field name
if listbox is not None:
listbox_line_list = []
for key, value in sorted(listbox.iteritems()):
for key, value in sorted(six.iteritems(listbox)):
value['listbox_key'] = key
listbox_line_list.append(value)
doaction_param_list['listbox'] = tuple(listbox_line_list)
......
......@@ -273,9 +273,9 @@
</span>
<span style="color: green;">&nbsp;:&nbsp;</span>
<tal:block tal:condition="show_search_line">
<span tal:condition="python: isinstance(original_value,(float, int, long))"
<span tal:condition="python: isinstance(original_value, modules['six'].integer_types + (float,))"
id="data_short" tal:content="python: original_value" />
<span tal:condition="python: not isinstance(original_value,(float, int, long))"
<span tal:condition="python: not isinstance(original_value, modules['six'].integer_types + (float,))"
id="data_short" tal:content="data_short" />
</tal:block>
<tal:block tal:condition="not:show_search_line">
......@@ -302,7 +302,7 @@
<tal:block tal:condition="python: original_value is not None">
<span align="right"
tal:define="original_value python: valueZ[0]; processed_value python: valueZ[1]"
tal:attributes="align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'"
tal:attributes="align python: isinstance(original_value, modules['six'].integer_types + (float,)) and 'right' or 'left'"
tal:content="structure processed_value" />
</tal:block>
</div>
......
......@@ -100,7 +100,7 @@
-->
<tal:block metal:define-macro="cell_value">
<tal:block tal:define="is_list python:same_type(value, []) or same_type(value, ());
is_float python: isinstance(value, (int, long, float));">
is_float python: isinstance(value, modules['six'].integer_types + (float,));">
<tal:block tal:condition="python: is_list">
......@@ -116,7 +116,7 @@
</tal:block>
<tal:block tal:condition="python: value is not None and not is_list">
<tal:block tal:condition="is_float">
<tal:block tal:condition="python: isinstance(value, (int, long))">
<tal:block tal:condition="python: isinstance(value, modules['six'].integer_types)">
<table:table-cell tal:define="field python: editable_fields.get(column_id, None)"
tal:attributes="office:value value;
table:style-name string:${style_prefix}figure"
......
......@@ -18,7 +18,7 @@
<tal:block tal:condition="not:listboxline/isTitleLine">
<table:table-row tal:attributes="table:style-name python: listboxline.isStatLine() and 'listbox_stat_row' or 'listbox_data_row'">
<tal:block tal:condition="python: listboxline.isDataLine()">
<tal:block tal:repeat="empty_index python: xrange(0, max_section_depth)">
<tal:block tal:repeat="empty_index python: range(0, max_section_depth)">
<table:table-cell table:style-name='report-column-title'
table:number-columns-spanned='1'
office:value-type='string'>
......@@ -36,7 +36,7 @@
</tal:block>
<tal:block tal:condition="python: listboxline.isStatLine() or listboxline.isSummaryLine()">
<tal:block tal:repeat="empty_index python: xrange(0, listboxline.getSectionDepth())">
<tal:block tal:repeat="empty_index python: range(0, listboxline.getSectionDepth())">
<table:table-cell table:style-name='report-column-title'
table:number-columns-spanned='1'
office:value-type='string'>
......@@ -48,7 +48,7 @@
office:value-type='string'>
<text:p tal:content="listboxline/getSectionName"/>
</table:table-cell>
<tal:block tal:repeat="empty_index python: xrange(listboxline.getSectionDepth()+1, max_section_depth)">
<tal:block tal:repeat="empty_index python: range(listboxline.getSectionDepth()+1, max_section_depth)">
<table:table-cell table:style-name='report-column-title'
table:number-columns-spanned='1'
office:value-type='string'>
......
......@@ -70,7 +70,7 @@
<tal:block tal:condition="not:display_header">
<table:table-row table:style-name='listbox_header_row'>
<tal:block tal:repeat="empty_index python: xrange(0, max_section_depth)">
<tal:block tal:repeat="empty_index python: range(0, max_section_depth)">
<table:table-cell table:style-name='report-column-title'
table:number-columns-spanned='1'
office:value-type='string'>
......
......@@ -110,7 +110,7 @@
<style:style style:name="date_with_time" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="date_style">
<style:table-cell-properties style:vertical-align='middle' style:repeat-content='false' style:text-align-source='fix' fo:border-right='0.002cm solid #000000' />
</style:style>
<tal:block tal:repeat="precision python: xrange(0,here.Base_getODSMaximumSupportedPrecision())">
<tal:block tal:repeat="precision python: range(0,here.Base_getODSMaximumSupportedPrecision())">
<tal:block tal:define="figure_data_precision_style_name string:figure_data_precision_${precision}">
<number:number-style style:name="figure_data_precision_X" tal:attributes="style:name figure_data_precision_style_name">
<number:number number:decimal-places="X" number:min-integer-digits="1" number:grouping="true" tal:attributes="number:decimal-places precision"/>
......
......@@ -118,11 +118,11 @@
column_id python: column_item[0]">
<tal:block tal:condition="python: column_property is not None">
<table:table-cell table:style-name='listbox-table.A1' office:value-type='string'>
<tal:block tal:condition="python: untranslatable_columns_dict.has_key(column_id)">
<tal:block tal:condition="python: column_id in untranslatable_columns_dict">
<text:p text:style-name='listbox-header'
tal:content="python: column_property"/>
</tal:block>
<tal:block tal:condition="python: not(untranslatable_columns_dict.has_key(column_id))">
<tal:block tal:condition="python: column_id not in untranslatable_columns_dict">
<text:p text:style-name='listbox-header'
tal:content="python: here.Base_translateString(column_property)"/>
</tal:block>
......
......@@ -139,34 +139,6 @@
<td>2000</td>
<td></td>
</tr>
<!-- Second loader while updating the page -->
<!--
<tr>
<td>waitForElementPresent</td>
<td>//h1[@class="ui-title"]//a[contains(@class, "ui-icon-spinner")]</td>
<td></td>
</tr>
<!-- Save Button is disabled -->
<!--
<tr>
<td>verifyElementPresent</td>
<td>//button[@data-i18n="Save"][contains(@class, "ui-disabled")]</td>
<td></td>
</tr>
<tr>
<td>waitForElementNotPresent</td>
<td>//h1[@class="ui-title"]//a[contains(@class, "ui-icon-spinner")]</td>
<td></td>
</tr>
<tr>
<td>verifyElementPresent</td>
<td>//button[@data-i18n="Save"][contains(@class, "ui-icon-check")]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><p></p></td>
</tr>
<-->
</tal:block>
<tal:block metal:define-macro="click_to_align_center">
<tr>
......
......@@ -3,6 +3,7 @@ import datetime
import time
import json
from DateTime import DateTime
import six
response = container.REQUEST.RESPONSE
start = time.time()
......@@ -32,7 +33,7 @@ for line in results.tuples():
v = v.isoformat()
elif isinstance(v, Decimal):
v = float(v)
elif isinstance(v, (long, int, float)) and not isSafeInteger(v):
elif isinstance(v, six.integer_types + (float,)) and not isSafeInteger(v):
# if numbers are too large to be handled by javascript, we simply return them
# as string, this will still not work for pivot table, but at least the spreadsheet
# will not display truncated values.
......
......@@ -40,6 +40,10 @@ from lxml import etree
from zLOG import LOG, ERROR, INFO
from erp5.component.tool.WebServiceTool import ConnectionError
from Products.ERP5Type.Cache import CachingMethod
import six
if six.PY3:
long = int
ID_SEPARATOR="-"
......
......@@ -11,11 +11,7 @@ import socket
import sys
from tempfile import TemporaryFile
import time
from six.moves.urllib.parse import quote
try:
from urllib import splitport
except ImportError: # six.PY3
from urllib.parse import splitport
from six.moves.urllib.parse import quote, urlsplit
from waitress.server import create_server
import ZConfig
......@@ -268,8 +264,7 @@ def runwsgi():
new_limit = (cur_limit[1], cur_limit[1])
resource.setrlimit(resource.RLIMIT_NOFILE, new_limit)
ip, port = splitport(args.address)
port = int(port)
port = urlsplit('//' + args.address).port
createServer(
app_wrapper(
large_file_threshold=args.large_file_threshold,
......
......@@ -9,7 +9,7 @@
cell_number python: len(module_category_list);
row_number python: (cell_number/max_per_line+1)"
class="access_tab_table">
<tr tal:repeat="row python: xrange(row_number)">
<tr tal:repeat="row python: range(row_number)">
<tal:block tal:repeat="module_category python: module_category_list[(row*max_per_line):((row+1)*max_per_line)]">
<td>
<div style="width:25%; min-width:150px; float:left;"
......
......@@ -330,7 +330,7 @@
error python: value[2]"
class="DataA" align="left"
tal:attributes="class python: error and (css + 'Error') or css;
align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'">
align python: isinstance(original_value, modules['six'].integer_types + (float,)) and 'right' or 'left'">
<input tal:condition="not: repeat/value/index"
type="hidden" value="1" name="listbox_uid:list"
tal:attributes="value python: line.getUid() or '';
......@@ -348,7 +348,7 @@
<tal:block tal:repeat="value here/getStatValueList">
<td class="Data" align="left"
tal:define="original_value python: value[0]; processed_value python: value[1]"
tal:attributes="align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'"
tal:attributes="align python: isinstance(original_value, modules['six'].integer_types + (float,)) and 'right' or 'left'"
tal:content="structure processed_value" />
</tal:block>
</tr>
......
......@@ -38,7 +38,7 @@ import os
import sys
import tempfile
import zipfile
import popen2
import subprocess
from six.moves import urllib
from six.moves import cStringIO as StringIO
......@@ -93,8 +93,12 @@ elif odfpy:
fd, file_name = tempfile.mkstemp()
os.write(fd, odf_file_content)
os.close(fd)
stdout, stdin = popen2.popen4('odflint %s' % file_name)
stdin.close()
process = subprocess.Popen(
['odflint', file_name],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
stdout, _ = process.communicate()
error_list = ''
for line in stdout:
if line.startswith('Error: '):
......
......@@ -567,6 +567,8 @@ def checkPythonSourceCode(source_code_str, portal_type=None):
if str is bytes:
bytes2str = str2bytes = lambda s: s
def str2unicode(s):
return s.decode('utf-8')
def unicode2str(s):
return s.encode('utf-8')
else:
......@@ -574,6 +576,8 @@ else:
return s.decode()
def str2bytes(s):
return s.encode()
def str2unicode(s):
return s
def unicode2str(s):
return s
......
......@@ -189,7 +189,7 @@ ModuleSecurityInfo('Products.ERP5Type.Utils').declarePublic(
'int2letter', 'getMessageIdWithContext', 'getTranslationStringWithContext',
'Email_parseAddressHeader', 'guessEncodingFromText',
'isValidTALESExpression',
'ensure_list', 'bytes2str', 'str2bytes', 'unicode2str',
'ensure_list', 'bytes2str', 'str2bytes', 'str2unicode', 'unicode2str',
)
allow_module('Products.ERP5Type.Message')
......
......@@ -61,8 +61,7 @@ ACQUIRE_LOCAL_ROLE_GETTER_DICT = {
for acquire_local_role in (False, True)
}
if six.PY3:
StandardError = Exception
def _importFilesystemClass(classpath):
try:
module_path, class_name = classpath.rsplit('.', 1)
......@@ -74,7 +73,7 @@ def _importFilesystemClass(classpath):
InitializeClass(klass)
return klass
except StandardError:
except Exception as e:
raise ImportError('Could not import document class ' + classpath)
def _importComponentClass(component_package, name):
......
......@@ -32,6 +32,7 @@ import math
from DateTime.DateTime import _calcSD, _calcDependentSecond, _calcYMDHMS,\
getDefaultDateFormat, _correctYear, _calcHMS, _calcDependentSecond2, DateTimeError,\
SyntaxError, DateError, TimeError, localtime, time
from Products.ERP5Type import IS_ZOPE2
STATE_KEY = 'str'
......@@ -297,12 +298,13 @@ DateTimeKlass.SyntaxError = SyntaxError
DateTimeKlass.DateError = DateError
DateTimeKlass.TimeError = TimeError
# BBB undo patch from DateTime 2.12 , which patches
# copy_reg._reconstructor with a function that appears as
# `DateTime.DateTime._dt_reconstructor` in pickles.
# See https://github.com/zopefoundation/DateTime/blob/2.12.8/src/DateTime/DateTime.py#L1863-L1874
# This patch is no longer needed once we are using DateTime >= 3 so
# it is not needed on python3 (copy_reg does not exist on python3)
import copy_reg
copy_reg._reconstructor.__module__ = 'copy_reg'
copy_reg._reconstructor.__name__ = '_reconstructor'
if IS_ZOPE2: # BBB Zope2
# BBB undo patch from DateTime 2.12 , which patches
# copy_reg._reconstructor with a function that appears as
# `DateTime.DateTime._dt_reconstructor` in pickles.
# See https://github.com/zopefoundation/DateTime/blob/2.12.8/src/DateTime/DateTime.py#L1863-L1874
# This patch is no longer needed once we are using DateTime >= 3 so
# it is not needed on python3 (copy_reg does not exist on python3)
import copy_reg
copy_reg._reconstructor.__module__ = 'copy_reg'
copy_reg._reconstructor.__name__ = '_reconstructor'
......@@ -80,6 +80,9 @@ add_builtins(Ellipsis=Ellipsis, NotImplemented=NotImplemented,
dict=dict, list=list)
if "set" not in safe_builtins: # BBB
add_builtins(set=set, frozenset=frozenset, slice=slice)
if "bytes" not in safe_builtins: # BBB Zope2
assert six.PY2
add_builtins(bytes=str)
add_builtins(bin=bin, classmethod=classmethod, format=format, object=object,
property=property, staticmethod=staticmethod,
......
......@@ -1356,7 +1356,7 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
try:
portal_activities = self.portal.portal_activities
message_list = portal_activities.getMessageList()
except StandardError: # AttributeError, TransactionFailedError ...
except Exception: # AttributeError, TransactionFailedError ...
pass
else:
for m in message_list:
......
......@@ -4,9 +4,8 @@ from six import unichr
from six.moves import xrange
import string
from .DummyField import fields
from DocumentTemplate.DT_Util import html_quote
from DocumentTemplate.html_quote import html_quote
from DateTime import DateTime, Timezones
from Products.PythonScripts.standard import html_quote
import types
from DocumentTemplate.ustr import ustr
from six.moves.urllib.parse import urljoin
......
# -*- coding: utf-8 -*-
import unittest, re
from lxml import etree
from DateTime import DateTime
import Zope2
......@@ -122,9 +123,12 @@ class FormTestCase(unittest.TestCase):
.manage_addField('date_time','Test Field','DateTimeField')
field = self.form.date_time
field._edit({'timezone_style': 0})
self.assertNotIn('<select size="1" name="subfield_field_date_time_timezone" >', field.render())
parser = etree.HTMLParser()
e = etree.fromstring(field.render(), parser=parser)
self.assertFalse(e.xpath('//select[@size="1"][@name="subfield_field_date_time_timezone"]'))
field._edit({'timezone_style': 1})
self.assertIn('<select size="1" name="subfield_field_date_time_timezone" >', field.render())
e = etree.fromstring(field.render(), parser=parser)
self.assertTrue(e.xpath('//select[@size="1"][@name="subfield_field_date_time_timezone"]'))
def test_datetime_css_class_rendering(self):
......@@ -181,13 +185,18 @@ class FormTestCase(unittest.TestCase):
.manage_addField('date_time','Test Field','DateTimeField')
field = self.form.date_time
field._edit({'input_style': 'number'})
self.assertIn('<input name="subfield_field_date_time_year" value="" maxlength="4" type="number" size="4" min="0" max="9999" />', field.render())
parser = etree.HTMLParser()
e = etree.fromstring(field.render(), parser=parser)
self.assertTrue(e.xpath('//input[@name="subfield_field_date_time_year"][@value=""][@maxlength="4"][@type="number"][@size="4"][@min="0"][@max="9999"]'))
field._edit({'start_datetime': DateTime('1900/01/01'), 'end_datetime': None})
self.assertIn('<input name="subfield_field_date_time_year" value="" maxlength="4" type="number" size="4" min="1900" max="9999" />', field.render())
e = etree.fromstring(field.render(), parser=parser)
self.assertTrue(e.xpath('//input[@name="subfield_field_date_time_year"][@value=""][@maxlength="4"][@type="number"][@size="4"][@min="1900"][@max="9999"]'))
field._edit({'start_datetime': None, 'end_datetime': DateTime('2099/12/31')})
self.assertIn('<input name="subfield_field_date_time_year" value="" maxlength="4" type="number" size="4" min="0" max="2099" />', field.render())
e = etree.fromstring(field.render(), parser=parser)
self.assertTrue(e.xpath('//input[@name="subfield_field_date_time_year"][@value=""][@maxlength="4"][@type="number"][@size="4"][@min="0"][@max="2099"]'))
field._edit({'start_datetime': DateTime('1900/01/01'), 'end_datetime': DateTime('2099/12/31')})
self.assertIn('<input name="subfield_field_date_time_year" value="" maxlength="4" type="number" size="4" min="1900" max="2099" />', field.render())
e = etree.fromstring(field.render(), parser=parser)
self.assertTrue(e.xpath('//input[@name="subfield_field_date_time_year"][@value=""][@maxlength="4"][@type="number"][@size="4"][@min="1900"][@max="2099"]'))
def test_suite():
......
......@@ -26,7 +26,8 @@ from App.Common import package_home
ph = package_home(globals())
# Initializes a list with the charsets
charsets = [ x.strip() for x in open(ph + '/charsets.txt').readlines() ]
with open(ph + '/charsets.txt') as f:
charsets = [ x.strip() for x in f.readlines() ]
......
......@@ -20,7 +20,7 @@ from six.moves import cStringIO as StringIO
from Products.PortalTransforms.interfaces import ITransform
from zope.interface import implementer
from DocumentTemplate.DT_Util import html_quote
from DocumentTemplate.html_quote import html_quote
## Python Source Parser #####################################################
......
from Products.PortalTransforms.interfaces import ITransform
from zope.interface import implementer
from DocumentTemplate.DT_Util import html_quote
from DocumentTemplate.html_quote import html_quote
__revision__ = '$Id: text_pre_to_html.py 3658 2005-02-23 16:29:54Z tiran $'
......
from Products.PortalTransforms.interfaces import ITransform
from zope.interface import implementer
from DocumentTemplate.DT_Util import html_quote
from DocumentTemplate.html_quote import html_quote
__revision__ = '$Id: text_to_html.py 4787 2005-08-19 21:43:41Z dreamcatcher $'
......
......@@ -25,8 +25,11 @@ from OFS.Folder import Folder
from DateTime import DateTime
from Acquisition import Implicit, aq_base
from Persistence import Persistent
from DocumentTemplate.DT_Util import InstanceDict, TemplateDict
from DocumentTemplate.DT_Util import Eval
from DocumentTemplate.DT_Util import Eval, TemplateDict
try:
from DocumentTemplate._DocumentTemplate import InstanceDict
except ImportError: # BBB
from DocumentTemplate.DT_Util import InstanceDict
from AccessControl.Permission import pname
from AccessControl.Permissions import import_export_objects, \
manage_zcatalog_entries
......
......@@ -69,7 +69,9 @@ def _makeFile(filename, prefix=None, id=None):
if id is None:
id = os.path.split( path )[ 1 ]
return File( id=id, title='', file=open(path).read() )
with open(path, 'rb') as f:
data = f.read()
return File( id=id, title='', file=data )
def registerFiles(directory, prefix):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment