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