Products.validation/master: Python 3 compatibilty

Tom Gross <jenkins-z4DKO/[email protected]> Tue, 01 Aug 2017 02:10:55 -0700 (PDT)
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: Products.validation
Branch: refs/heads/master
Date: 2017-07-30T21:37:26Z
Author: Tom Gross (tomgross) <[email protected]>
Commit: https://github.com/plone/Products.validation/commit/6035de491b1bcd84bcbe540d96fa2d7418f50f4c

Python 3 compatibilty

Files changed:
M CHANGES.txt
M Products/validation/__init__.py
M Products/validation/chain.py
M Products/validation/i18n.py
M Products/validation/interfaces/__init__.py
M Products/validation/service.py
M Products/validation/tests/test_validation.py
M Products/validation/validators/BaseValidators.py
M Products/validation/validators/ExpressionValidator.py
M Products/validation/validators/IdValidator.py
M Products/validation/validators/RegexValidator.py
M Products/validation/validators/__init__.py
M setup.py

diff --git a/CHANGES.txt b/CHANGES.txt
index 4b0f3f8..4055927 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,7 +10,8 @@ Breaking changes:
 
 New features:
 
-- *add item here*
+- Python 3 compatibility
+  [tomgross]
 
 Bug fixes:
 
diff --git a/Products/validation/__init__.py b/Products/validation/__init__.py
index eb584bb..f32bf23 100644
--- a/Products/validation/__init__.py
+++ b/Products/validation/__init__.py
@@ -1,3 +1,7 @@
-from config import validation
-from chain import ValidationChain, V_REQUIRED, V_SUFFICIENT
-from exceptions import UnknowValidatorError, FalseValidatorError, AlreadyRegisteredValidatorError
+from Products.validation.config import validation
+from Products.validation.chain import ValidationChain
+from Products.validation.chain import V_REQUIRED
+from Products.validation.chain import V_SUFFICIENT
+from Products.validation.exceptions import UnknowValidatorError
+from Products.validation.exceptions import FalseValidatorError
+from Products.validation.exceptions import AlreadyRegisteredValidatorError
diff --git a/Products/validation/chain.py b/Products/validation/chain.py
index 966359a..6319feb 100644
--- a/Products/validation/chain.py
+++ b/Products/validation/chain.py
@@ -1,12 +1,13 @@
+from Products.validation.config import validation as validationService
+from Products.validation.exceptions import ValidatorError
 from Products.validation.interfaces.IValidator import IValidationChain
 from zope.interface import implementer
 
-from types import TupleType, ListType
-from config import validation as validationService
-from exceptions import ValidatorError
 
 V_REQUIRED   = 1
 V_SUFFICIENT = 2
+TupleType = type((0,1))
+ListType = type([])
 
 
 @implementer(IValidationChain)
@@ -140,7 +141,7 @@ def __call__(self, value, *args, **kwargs):
                 elif mode == V_REQUIRED:
                     continue    # go on
                 else:
-                    raise ValidatorError, 'Unknown mode %s' % mode
+                    raise ValidatorError('Unknown mode {0}'.format(mode))
             else:
                 if mode == V_SUFFICIENT:
                     if isinstance(result, basestring):
@@ -154,7 +155,7 @@ def __call__(self, value, *args, **kwargs):
                     failed = True
                     break    # fatal error, stop and fail
                 else:
-                    raise ValidatorError, 'Unknown mode %s' % mode
+                    raise ValidatorError('Unknown mode {0}'.format(mode))
 
         if failed:
             return '\n'.join([
diff --git a/Products/validation/i18n.py b/Products/validation/i18n.py
index 6c931d6..f01953c 100644
--- a/Products/validation/i18n.py
+++ b/Products/validation/i18n.py
@@ -2,18 +2,24 @@
 from zope.i18n import translate
 from zope.i18nmessageid import Message
 
+import six
+
 
 PloneMessageFactory = MessageFactory('plone')
 
-def safe_unicode(value):
-    if isinstance(value, unicode):
+if six.PY2:
+    def safe_unicode(value):
+        if isinstance(value, unicode):
+            return value
+        elif isinstance(value, str):
+            try:
+                return unicode(value, 'utf-8')
+            except UnicodeDecodeError:
+                return unicode(value, 'utf-8', 'ignore')
+        return str(value)
+else:
+    def safe_unicode(value):
         return value
-    elif isinstance(value, str):
-        try:
-            return unicode(value, 'utf-8')
-        except UnicodeDecodeError:
-            return unicode(value, 'utf-8', 'ignore')
-    return str(value)
 
 
 def recursiveTranslate(message, **kwargs):
diff --git a/Products/validation/interfaces/__init__.py b/Products/validation/interfaces/__init__.py
index 47a8423..28454b5 100644
--- a/Products/validation/interfaces/__init__.py
+++ b/Products/validation/interfaces/__init__.py
@@ -1,3 +1,3 @@
 # backward compatibility
-from IValidator import IValidator as ivalidator
-from IValidationService import IValidationService as ivalidationService
+from Products.validation.interfaces.IValidator import IValidator as ivalidator
+from Products.validation.interfaces.IValidationService import IValidationService as ivalidationService
diff --git a/Products/validation/service.py b/Products/validation/service.py
index eb86f18..898fdd6 100644
--- a/Products/validation/service.py
+++ b/Products/validation/service.py
@@ -1,9 +1,12 @@
+from Products.validation.exceptions import FalseValidatorError
+from Products.validation.exceptions import UnknowValidatorError
+from Products.validation.exceptions import AlreadyRegisteredValidatorError
 from Products.validation.interfaces.IValidationService import IValidationService
 from Products.validation.interfaces.IValidator import IValidator
 from zope.interface import implementer
 
-from exceptions import UnknowValidatorError, FalseValidatorError, AlreadyRegisteredValidatorError
-from types import StringType, StringTypes
+import six
+
 
 @implementer(IValidationService)
 class Service:
@@ -18,19 +21,19 @@ def validate(self, name_or_validator, value, *args, **kwargs):
     __call__ = validate
 
     def validatorFor(self, name_or_validator):
-        if type(name_or_validator) in StringTypes:
+        if isinstance(name_or_validator, str):
             try:
                 return self._validator[name_or_validator]
             except KeyError:
-                raise UnknowValidatorError, name_or_validator
+                raise UnknowValidatorError(name_or_validator)
         elif IValidator.providedBy(name_or_validator):
             return name_or_validator
         else:
-            raise FalseValidatorError, name_or_validator
+            raise FalseValidatorError(name_or_validator)
 
     def register(self, validator): #XXX
         if not IValidator.providedBy(validator):
-            raise FalseValidatorError, validator
+            raise FalseValidatorError(validator)
         name = validator.name
         # The following code prevents refreshing
         ##if self._validator.has_key(name):
@@ -47,7 +50,7 @@ def values(self):
         return [v for k, v in self.items()]
 
     def unregister(self, name_or_validator):
-        if type(name_or_validator) is StringType:
+        if isinstance(name_or_validator, str):
             name = name_or_validator
         elif IValidator.implementedBy(name_or_validator):
             name = name_or_validator.name
diff --git a/Products/validation/tests/test_validation.py b/Products/validation/tests/test_validation.py
index 5c67230..245e924 100644
--- a/Products/validation/tests/test_validation.py
+++ b/Products/validation/tests/test_validation.py
@@ -1,7 +1,10 @@
-import unittest
+# -*- coding: utf-8 -*-
+from Products.validation import validation
+
 import doctest
+import six
+import unittest
 
-from Products.validation import validation
 
 class TestValidation(unittest.TestCase):
 
@@ -20,8 +23,18 @@ def test_isDecimal(self):
     def test_isPrintable(self):
         v = validation.validatorFor('isPrintable')
         self.assertEqual(v('text'), 1)
-        self.assertEqual(v('\u203'), u"Validation failed(isPrintable): '\\u203' contains unprintable characters")
-        self.assertEqual(v(10), u"Validation failed(isPrintable): 10 of type <type 'int'>, expected 'string'")
+        self.assertEqual(
+            v('\\u203'),
+            u"Validation failed(isPrintable): '\\u203' contains unprintable characters"
+        )
+        if six.PY3:
+            int_type = "<class 'int'>"
+        else:
+            int_type = "<type 'int'>"
+        self.assertEqual(
+            v(10),
+            u"Validation failed(isPrintable): 10 of type {0}, expected 'string'".format(int_type)
+        )
 
     def test_isSSN(self):
         v = validation.validatorFor('isSSN')
@@ -67,7 +80,7 @@ def test_isMailto(self):
     def test_isUnixLikeName(self):
         v = validation.validatorFor('isUnixLikeName')
         self.assertEqual(v('abcd'), 1)
-        self.failUnless(v('a_123456'), 1)
+        self.assertTrue(v('a_123456'), 1)
         self.assertNotEqual(v('123'), 1)
         self.assertNotEqual(v('ab.c'), 1)
         self.assertEqual(v('ab,c'), u"Validation failed(isUnixLikeName): 'ab,c' this name is not a valid identifier")
diff --git a/Products/validation/validators/BaseValidators.py b/Products/validation/validators/BaseValidators.py
index 5fbd093..c956e0c 100644
--- a/Products/validation/validators/BaseValidators.py
+++ b/Products/validation/validators/BaseValidators.py
@@ -1,5 +1,5 @@
-from RegexValidator import RegexValidator
-from RangeValidator import RangeValidator
+from Products.validation.validators.RegexValidator import RegexValidator
+from Products.validation.validators.RangeValidator import RangeValidator
 from Products.validation.i18n import PloneMessageFactory as _
 
 # protocols for isURL validator, the secure (*s) variants are automagically
diff --git a/Products/validation/validators/ExpressionValidator.py b/Products/validation/validators/ExpressionValidator.py
index ccf1d92..b92a595 100644
--- a/Products/validation/validators/ExpressionValidator.py
+++ b/Products/validation/validators/ExpressionValidator.py
@@ -45,8 +45,8 @@ class ExpressionValidator:
     True
 
     now lets fail a test
-    >>> val(4,c)
-    u'validation failed, expr was:python: int(value) == 5'
+    >>> str(val(4,c))
+    'validation failed, expr was:python: int(value) == 5'
 
     It is also possible to specify the error string
 
diff --git a/Products/validation/validators/IdValidator.py b/Products/validation/validators/IdValidator.py
index f98181d..0fb1f75 100644
--- a/Products/validation/validators/IdValidator.py
+++ b/Products/validation/validators/IdValidator.py
@@ -40,11 +40,11 @@ def __call__(self, id, instance, *args, **kwargs):
                         mapping = {'id': safe_unicode(id)})
                 return recursiveTranslate(msg, **kwargs)
 
-            # objet manager test
+            # object manager test
             # XXX: This is f***ed
             try:
                 ObjectManager.checkValidId(self, id, allow_dup=1)
-            except BadRequest, m:
+            except BadRequest as m:
                 return str(m)
             return 1
 
diff --git a/Products/validation/validators/RegexValidator.py b/Products/validation/validators/RegexValidator.py
index 148e6f7..62923b3 100644
--- a/Products/validation/validators/RegexValidator.py
+++ b/Products/validation/validators/RegexValidator.py
@@ -1,15 +1,18 @@
 from Products.validation.interfaces.IValidator import IValidator
-from zope.interface import implementer
 from Products.validation.i18n import PloneMessageFactory as _
 from Products.validation.i18n import recursiveTranslate
 from Products.validation.i18n import safe_unicode
+from zope.interface import implementer
+
 import re
-from types import StringType
+import six
+
 
 def ignoreRE(value, expression):
     ignore = re.compile(expression)
     return ignore.sub('', value)
 
+
 @implementer(IValidator)
 class RegexValidator:
 
@@ -40,7 +43,7 @@ def __setstate__(self, dict):
         self.compileRegex()
 
     def __call__(self, value, *args, **kwargs):
-        if type(value) != StringType:
+        if not isinstance(value, str):
             msg =  _(u"Validation failed($name): $value of type $type, expected 'string'",
                      mapping = {
                         'name' : safe_unicode(self.name),
diff --git a/Products/validation/validators/__init__.py b/Products/validation/validators/__init__.py
index f9e3033..f6abbfa 100644
--- a/Products/validation/validators/__init__.py
+++ b/Products/validation/validators/__init__.py
@@ -1,19 +1,19 @@
-from RegexValidator import RegexValidator
-from RangeValidator import RangeValidator
-from ExpressionValidator import ExpressionValidator
+from Products.validation.validators.RegexValidator import RegexValidator
+from Products.validation.validators.RangeValidator import RangeValidator
+from Products.validation.validators.ExpressionValidator import ExpressionValidator
 
 validators = []
 
-from BaseValidators import baseValidators
+from Products.validation.validators.BaseValidators import baseValidators
 validators.extend(baseValidators)
 
-from EmptyValidator import validatorList
+from Products.validation.validators.EmptyValidator import validatorList
 validators.extend(validatorList)
 
-from SupplValidators import validatorList
+from Products.validation.validators.SupplValidators import validatorList
 validators.extend(validatorList)
 
-from IdValidator import validatorList
+from Products.validation.validators.IdValidator import validatorList
 validators.extend(validatorList)
 
 
diff --git a/setup.py b/setup.py
index 17434c0..ae81845 100644
--- a/setup.py
+++ b/setup.py
@@ -1,24 +1,26 @@
 from setuptools import setup, find_packages
 
-version = '2.0.3.dev0'
+version = '2.1.dev0'
 
 setup(
     name='Products.validation',
     version=version,
-    description="Data validation package for Archetypes",
+    description="Data validation package for Zope",
     long_description=(open("README.txt").read() + "\n" +
                       open("CHANGES.txt").read()),
     classifiers=[
         "Framework :: Zope2",
         "Operating System :: OS Independent",
+        "Framework :: Plone",
         "Framework :: Plone :: 4.3",
         "Framework :: Plone :: 5.0",
         "Framework :: Plone :: 5.1",
         "Programming Language :: Python",
         "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3.5",
     ],
-    keywords='Zope catalog index',
+    keywords='Zope validation regex email',
     author='Benjamin Saller',
     author_email='plone-developers-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org',
     url='https://pypi.python.org/pypi/Products.validation',
@@ -30,6 +32,7 @@
     extras_require={},
     install_requires=[
         'setuptools',
+        'six',
         'zope.i18n',
         'zope.i18nmessageid',
         'zope.interface',



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot