Products.validation/master: Merge pull request #3 from plone/no_at

GitHub <jenkins-z4DKO/[email protected]> Tue, 01 Aug 2017 02:11:01 -0700 (PDT)
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: Products.validation
Branch: refs/heads/master
Date: 2017-08-01T11:10:30+02:00
Author: Gil Forcada Codinachs (gforcada) <[email protected]>
Commit: https://github.com/plone/Products.validation/commit/953887bae0bafcfe2dbeec1962e2494c260e495e

Merge pull request #3 from plone/no_at

Remove AT dependency and PY3 compatibility

Files changed:
A README.rst
A requirements.txt
M .gitignore
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 buildout.cfg
M setup.py
D README.txt
D setup.cfg

diff --git a/.gitignore b/.gitignore
index e60fdd3..1a4e837 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,9 @@
 bin/
-lib/
+lib*
 include/
 *.egg-info
 .installed.cfg
 bootstrap.py
 develop-eggs/
-*.pyc
-*.pyo
+*.py[co]
+pip-selfcheck.json
diff --git a/CHANGES.txt b/CHANGES.txt
index 48258e6..4055927 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,11 +10,13 @@ Breaking changes:
 
 New features:
 
-- *add item here*
+- Python 3 compatibility
+  [tomgross]
 
 Bug fixes:
 
-- *add item here*
+- Remove unnecessary test dependencies
+  [tomgross]
 
 
 2.0.2 (2016-08-08)
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 61d18cc..245e924 100644
--- a/Products/validation/tests/test_validation.py
+++ b/Products/validation/tests/test_validation.py
@@ -1,84 +1,94 @@
+# -*- coding: utf-8 -*-
+from Products.validation import validation
 
-from Testing import ZopeTestCase
-from Products.Archetypes.tests.atsitetestcase import ATSiteTestCase
-from Testing.ZopeTestCase import doctest
+import doctest
+import six
+import unittest
 
-from Products.validation import validation
 
-class TestValidation(ATSiteTestCase):
+class TestValidation(unittest.TestCase):
 
     def test_inNumericRange(self):
         v = validation.validatorFor('inNumericRange')
-        self.failUnlessEqual(v(10, 1, 20), 1)
-        self.failUnlessEqual(v('10', 1, 20), 1)
-        self.failUnlessEqual(v(0, 4, 5), u"Validation failed(inNumericRange): '0' out of range(4, 5)")
+        self.assertEqual(v(10, 1, 20), 1)
+        self.assertEqual(v('10', 1, 20), 1)
+        self.assertEqual(v(0, 4, 5), u"Validation failed(inNumericRange): '0' out of range(4, 5)")
 
     def test_isDecimal(self):
         v = validation.validatorFor('isDecimal')
-        self.failUnlessEqual(v('1.5'), 1)
-        self.failUnlessEqual(v('1,5'), 1)
-        self.failUnlessEqual(v('NaN'), u"Validation failed(isDecimal): 'NaN' is not a decimal number.")
+        self.assertEqual(v('1.5'), 1)
+        self.assertEqual(v('1,5'), 1)
+        self.assertEqual(v('NaN'), u"Validation failed(isDecimal): 'NaN' is not a decimal number.")
 
     def test_isPrintable(self):
         v = validation.validatorFor('isPrintable')
-        self.failUnlessEqual(v('text'), 1)
-        self.failUnlessEqual(v('\u203'), u"Validation failed(isPrintable): '\\u203' contains unprintable characters")
-        self.failUnlessEqual(v(10), u"Validation failed(isPrintable): 10 of type <type 'int'>, expected 'string'")
+        self.assertEqual(v('text'), 1)
+        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')
-        self.failUnlessEqual(v('111223333'), 1)
-        self.failUnlessEqual(v('111-22-3333', ignore=r'-'), 1)
+        self.assertEqual(v('111223333'), 1)
+        self.assertEqual(v('111-22-3333', ignore=r'-'), 1)
 
     def test_isUSPhoneNumber(self):
         v = validation.validatorFor('isUSPhoneNumber')
-        self.failUnlessEqual(v('(212) 555-1212',
+        self.assertEqual(v('(212) 555-1212',
                                ignore=r'[\s\(\)\-]'), 1)
-        self.failUnlessEqual(v('2125551212',
+        self.assertEqual(v('2125551212',
                                ignore=r'[\s\(\)\-]'), 1)
 
-        self.failUnlessEqual(v('(212) 555-1212'), 1)
+        self.assertEqual(v('(212) 555-1212'), 1)
 
     def test_isURL(self):
         v = validation.validatorFor('isURL')
-        self.failUnlessEqual(v('http://foo.bar:8080/manage'), 1)
-        self.failUnlessEqual(v('https://foo.bar:8080/manage'), 1)
-        self.failUnlessEqual(v('https://be.brussels:8080/manage'), 1)
-        self.failUnlessEqual(v('irc://[email protected]:6667/#plone'), 1)
-        self.failUnlessEqual(v('fish://tiran:password@myserver/~/'), 1)
-        self.failUnlessEqual(v('http://\n'), u"Validation failed(isURL): 'http://\n' is not a valid url.")
-        self.failIfEqual(v('../foo/bar'), 1)
+        self.assertEqual(v('http://foo.bar:8080/manage'), 1)
+        self.assertEqual(v('https://foo.bar:8080/manage'), 1)
+        self.assertEqual(v('https://be.brussels:8080/manage'), 1)
+        self.assertEqual(v('irc://[email protected]:6667/#plone'), 1)
+        self.assertEqual(v('fish://tiran:password@myserver/~/'), 1)
+        self.assertEqual(v('http://\n'), u"Validation failed(isURL): 'http://\n' is not a valid url.")
+        self.assertNotEqual(v('../foo/bar'), 1)
 
     def test_isEmail(self):
         v = validation.validatorFor('isEmail')
-        self.failUnlessEqual(v('[email protected]'), 1)
-        self.failUnlessEqual(v('[email protected]'), 1)
-        self.failIfEqual(v('@foo.bar'), 1)
-        self.failUnlessEqual(v('me'), u"Validation failed(isEmail): 'me' is not a valid email address.")
+        self.assertEqual(v('[email protected]'), 1)
+        self.assertEqual(v('[email protected]'), 1)
+        self.assertNotEqual(v('@foo.bar'), 1)
+        self.assertEqual(v('me'), u"Validation failed(isEmail): 'me' is not a valid email address.")
 
     def test_isMailto(self):
         v = validation.validatorFor('isMailto')
-        self.failUnlessEqual(v('mailto:[email protected]'), 1)
-        self.failUnlessEqual(v('mailto:[email protected]'), 1)
-        self.failIfEqual(v('[email protected]'), 1)
-        self.failIfEqual(v('mailto:@foo.bar'), 1)
-        self.failIfEqual(v('@foo.bar'), 1)
-        self.failIfEqual(v('mailto:'), 1)
-        self.failUnlessEqual(v('me'), u"Validation failed(isMailto): 'me' is not a valid email address.")
+        self.assertEqual(v('mailto:[email protected]'), 1)
+        self.assertEqual(v('mailto:[email protected]'), 1)
+        self.assertNotEqual(v('[email protected]'), 1)
+        self.assertNotEqual(v('mailto:@foo.bar'), 1)
+        self.assertNotEqual(v('@foo.bar'), 1)
+        self.assertNotEqual(v('mailto:'), 1)
+        self.assertEqual(v('me'), u"Validation failed(isMailto): 'me' is not a valid email address.")
 
     def test_isUnixLikeName(self):
         v = validation.validatorFor('isUnixLikeName')
-        self.failUnlessEqual(v('abcd'), 1)
-        self.failUnless(v('a_123456'), 1)
-        self.failIfEqual(v('123'), 1)
-        self.failIfEqual(v('ab.c'), 1)
-        self.failUnlessEqual(v('ab,c'), u"Validation failed(isUnixLikeName): 'ab,c' this name is not a valid identifier")
-        self.failIfEqual(v('aaaaaaaab'), 1) # too long
+        self.assertEqual(v('abcd'), 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")
+        self.assertNotEqual(v('aaaaaaaab'), 1) # too long
 
     def test_isValidId(self):
         v = validation.validatorFor("isValidId")
-        self.failUnlessEqual(v("a b", object()), u"Spaces are not allowed in ids")
-        # TODO: more tests require a site
+        self.assertEqual(v("a b", object()), u"Spaces are not allowed in ids")
 
 
 def test_suite():
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 ad45b45..b92a595 100644
--- a/Products/validation/validators/ExpressionValidator.py
+++ b/Products/validation/validators/ExpressionValidator.py
@@ -19,7 +19,6 @@
 #
 ##############################################################################
 """
-$Id: __init__.py,v 1.2 2005/02/26 17:56:10 sidnei Exp $
 """
 
 from Products.validation.interfaces.IValidator import IValidator
@@ -46,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/README.rst b/README.rst
new file mode 100644
index 0000000..e5a792b
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,4 @@
+Introduction
+============
+
+Data validation package for Zope.
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 218c730..0000000
--- a/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Introduction
-============
-
-Data validation package for Archetypes.
diff --git a/buildout.cfg b/buildout.cfg
index eb5b38d..17e7299 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -1,8 +1,8 @@
 [buildout]
-extends = https://raw.githubusercontent.com/collective/buildout.plonetest/master/test-4.3.x.cfg
-package-name = Products.validation
-package-extras = [test]
+parts = test
+extends = https://raw.githubusercontent.com/zopefoundation/Zope/4.0a6/versions.cfg
 develop = .
 
-[versions]
-Products.validation = 
+[test]
+recipe = zc.recipe.testrunner
+eggs = Products.validation
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..244887f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+setuptools==33.1.1
+zc.buildout==2.8.0
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index e116e38..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-[check-manifest]
-ignore = bootstrap.py
-         .installed.cfg
diff --git a/setup.py b/setup.py
index f6acbd7..20341d7 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",
-    long_description=(open("README.txt").read() + "\n" +
+    description="Data validation package for Zope",
+    long_description=(open("README.rst").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',
@@ -27,13 +29,10 @@
     namespace_packages=['Products'],
     include_package_data=True,
     zip_safe=False,
-    extras_require=dict(
-        test=[
-            'Products.Archetypes[test]',
-        ]
-    ),
+    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