Commit 3f7bfa1e authored by Tres Seaver's avatar Tres Seaver

Support Python 3.2 / 3.3, and test them w/ tox.

parent 4c700b17
......@@ -4,6 +4,8 @@
Unreleased
----------
- Added support for Python 3.2 / 3.3.
- Added ``setup.py docs`` alias (runs ``setup.py develop`` and installs
documentation dependencies).
......
......@@ -29,8 +29,12 @@ setup(name='zodburi',
classifiers=[
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"License :: Repoze Public License",
],
keywords='zodb zodbconn',
......
[tox]
envlist =
py26,py27,cover,docs
py26,py27,py32,py33,cover,docs
[testenv]
commands =
python setup.py test -q
[py3]
deps =
# Py3k compatible ZODB not yet released
git+https://github.com/zopefoundation/ZODB.git@py3#egg=ZODB
git+https://github.com/zopefoundation/ZEO.git@py3#egg=ZEO
[testenv:py32]
commands =
python setup.py test -q
deps = {[py3]deps}
[testenv:py33]
commands =
python setup.py test -q
deps = {[py3]deps}
[testenv:cover]
basepython =
python2.6
......
try:
from urllib.parse import parse_qsl
except ImportError: #pragma NO COVER
from cgi import parse_qsl
try:
from urllib.parse import quote
except ImportError: #pragma NO COVER
from urllib import quote
try:
from urllib.parse import urlsplit
except ImportError: #pragma NO COVER
from urlparse import urlsplit
import cgi
from cStringIO import StringIO
from io import BytesIO
import os
import sys
import urlparse
from ZODB.config import ZODBDatabase
from ZConfig import loadConfig
from ZConfig import loadSchemaFile
from ZEO.ClientStorage import ClientStorage
from ZODB.FileStorage.FileStorage import FileStorage
from ZODB.blob import BlobStorage
from ZODB.config import ZODBDatabase
from ZODB.DemoStorage import DemoStorage
from ZODB.FileStorage.FileStorage import FileStorage
from ZODB.MappingStorage import MappingStorage
from ZODB.blob import BlobStorage
import ZConfig
from zodburi.datatypes import convert_bytesize
from zodburi.datatypes import convert_int
from zodburi.datatypes import convert_tuple
from zodburi._compat import parse_qsl
from zodburi._compat import urlsplit
class Resolver(object):
......@@ -55,7 +56,7 @@ class MappingStorageURIResolver(Resolver):
query = ''
else:
name, query = result
kw = dict(cgi.parse_qsl(query))
kw = dict(parse_qsl(query))
kw, unused = self.interpret_kwargs(kw)
args = (name,)
def factory():
......@@ -70,7 +71,7 @@ class FileStorageURIResolver(Resolver):
_bytesize_args = ('quota',)
def __call__(self, uri):
# we can't use urlparse.urlsplit here due to Windows filenames
# we can't use urlsplit here due to Windows filenames
prefix, rest = uri.split('file://', 1)
result = rest.split('?', 1)
if len(result) == 1:
......@@ -80,7 +81,7 @@ class FileStorageURIResolver(Resolver):
path, query = result
path = os.path.normpath(path)
args = (path,)
kw = dict(cgi.parse_qsl(query))
kw = dict(parse_qsl(query))
kw, unused = self.interpret_kwargs(kw)
demostorage = False
......@@ -127,10 +128,10 @@ class ClientStorageURIResolver(Resolver):
_bytesize_args = ('cache_size', )
def __call__(self, uri):
# urlparse doesnt understand zeo URLs so force to something that
# urlsplit doesnt understand zeo URLs so force to something that
# doesn't break
uri = uri.replace('zeo://', 'http://', 1)
(scheme, netloc, path, query, frag) = urlparse.urlsplit(uri)
(scheme, netloc, path, query, frag) = urlsplit(uri)
if netloc:
# TCP URL
if ':' in netloc:
......@@ -144,7 +145,7 @@ class ClientStorageURIResolver(Resolver):
# Unix domain socket URL
path = os.path.normpath(path)
args = (path,)
kw = dict(cgi.parse_qsl(query))
kw = dict(parse_qsl(query))
kw, unused = self.interpret_kwargs(kw)
if 'demostorage' in kw:
kw.pop('demostorage')
......@@ -158,7 +159,7 @@ class ClientStorageURIResolver(Resolver):
class ZConfigURIResolver(object):
schema_xml_template = """
schema_xml_template = b"""
<schema>
<import package="ZODB"/>
<multisection type="ZODB.storage" attribute="storages" />
......@@ -167,16 +168,16 @@ class ZConfigURIResolver(object):
"""
def __call__(self, uri):
(scheme, netloc, path, query, frag) = urlparse.urlsplit(uri)
(scheme, netloc, path, query, frag) = urlsplit(uri)
if sys.version_info[:3] < (2, 7, 4): #pragma NO COVER
# urlparse used not to allow fragments in non-standard schemes,
# urlsplit used not to allow fragments in non-standard schemes,
# stuffed everything into 'path'
(scheme, netloc, path, query, frag
) = urlparse.urlsplit('http:' + path)
) = urlsplit('http:' + path)
path = os.path.normpath(path)
schema_xml = self.schema_xml_template
schema = ZConfig.loadSchemaFile(StringIO(schema_xml))
config, handler = ZConfig.loadConfig(schema, path)
schema = loadSchemaFile(BytesIO(schema_xml))
config, handler = loadConfig(schema, path)
for config_item in config.databases + config.storages:
if not frag:
# use the first defined in the file
......@@ -198,7 +199,7 @@ class ZConfigURIResolver(object):
dbkw['database_name'] = config.database_name
else:
factory = config_item
dbkw = dict(cgi.parse_qsl(query))
dbkw = dict(parse_qsl(query))
return factory.open, dbkw
......
......@@ -27,8 +27,7 @@ class Base:
for name in names:
kwargs[name] = '10'
args = resolver.interpret_kwargs(kwargs)[0]
keys = args.keys()
keys.sort()
keys = sorted(args.keys())
self.assertEqual(sorted(keys), sorted(names))
for name, value in args.items():
self.assertEqual(value, 10)
......@@ -160,8 +159,8 @@ class TestFileStorageURIResolver(Base, unittest.TestCase):
def test_invoke_factory_blobstorage(self):
import os
from urllib import quote as q
from ZODB.blob import BlobStorage
from .._compat import quote as q
DB_FILE = os.path.join(self.tmpdir, 'db.db')
BLOB_DIR = os.path.join(self.tmpdir, 'blob')
self.assertFalse(os.path.exists(DB_FILE))
......@@ -177,8 +176,8 @@ class TestFileStorageURIResolver(Base, unittest.TestCase):
def test_invoke_factory_blobstorage_and_demostorage(self):
import os
from urllib import quote as q
from ZODB.DemoStorage import DemoStorage
from .._compat import quote as q
DB_FILE = os.path.join(self.tmpdir, 'db.db')
BLOB_DIR = os.path.join(self.tmpdir, 'blob')
self.assertFalse(os.path.exists(DB_FILE))
......@@ -290,7 +289,7 @@ class TestZConfigURIResolver(unittest.TestCase):
self.tmp.close()
def test_named_storage(self):
self.tmp.write("""
self.tmp.write(b"""
<demostorage foo>
</demostorage>
......@@ -305,7 +304,7 @@ class TestZConfigURIResolver(unittest.TestCase):
self.assertTrue(isinstance(storage, MappingStorage), storage)
def test_anonymous_storage(self):
self.tmp.write("""
self.tmp.write(b"""
<mappingstorage>
</mappingstorage>
......@@ -321,7 +320,7 @@ class TestZConfigURIResolver(unittest.TestCase):
self.assertEqual(dbkw, {})
def test_query_string_args(self):
self.tmp.write("""
self.tmp.write(b"""
<mappingstorage>
</mappingstorage>
......@@ -334,7 +333,7 @@ class TestZConfigURIResolver(unittest.TestCase):
self.assertEqual(dbkw, {'foo': 'bar'})
def test_storage_not_found(self):
self.tmp.write("""
self.tmp.write(b"""
<mappingstorage x>
</mappingstorage>
""")
......@@ -343,7 +342,7 @@ class TestZConfigURIResolver(unittest.TestCase):
self.assertRaises(KeyError, resolver, 'zconfig://%s#y' % self.tmp.name)
def test_anonymous_database(self):
self.tmp.write("""
self.tmp.write(b"""
<zodb>
<mappingstorage>
</mappingstorage>
......@@ -360,7 +359,7 @@ class TestZConfigURIResolver(unittest.TestCase):
'connection_pool_size': 7})
def test_named_database(self):
self.tmp.write("""
self.tmp.write(b"""
<zodb x>
<mappingstorage>
</mappingstorage>
......
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