summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.functests2
-rw-r--r--.stestr.conf2
-rwxr-xr-x.unittests2
-rw-r--r--.zuul.yaml4
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog15
-rw-r--r--doc/source/conf.py4
-rw-r--r--lower-constraints.txt1
-rw-r--r--releasenotes/notes/3_8_1_release-cb5648c3ae69bde1.yaml14
-rw-r--r--releasenotes/source/index.rst1
-rw-r--r--releasenotes/source/train.rst6
-rw-r--r--setup.cfg1
-rw-r--r--swiftclient/authv1.py12
-rw-r--r--swiftclient/multithreading.py6
-rwxr-xr-xswiftclient/shell.py6
-rw-r--r--test-requirements.txt1
-rw-r--r--test/__init__.py (renamed from tests/__init__.py)0
-rw-r--r--test/functional/__init__.py93
-rw-r--r--test/functional/test_openstacksdk.py92
-rw-r--r--test/functional/test_swiftclient.py (renamed from tests/functional/test_swiftclient.py)85
-rw-r--r--test/sample.conf (renamed from tests/sample.conf)0
-rw-r--r--test/unit/__init__.py (renamed from tests/functional/__init__.py)0
-rw-r--r--test/unit/test_authv1.py (renamed from tests/unit/test_authv1.py)0
-rw-r--r--test/unit/test_command_helpers.py (renamed from tests/unit/test_command_helpers.py)0
-rw-r--r--test/unit/test_multithreading.py (renamed from tests/unit/test_multithreading.py)0
-rw-r--r--test/unit/test_service.py (renamed from tests/unit/test_service.py)8
-rw-r--r--test/unit/test_shell.py (renamed from tests/unit/test_shell.py)0
-rw-r--r--test/unit/test_swiftclient.py (renamed from tests/unit/test_swiftclient.py)0
-rw-r--r--test/unit/test_utils.py (renamed from tests/unit/test_utils.py)0
-rw-r--r--test/unit/utils.py (renamed from tests/unit/utils.py)0
-rw-r--r--tests/unit/__init__.py0
-rw-r--r--tox.ini15
32 files changed, 289 insertions, 82 deletions
diff --git a/.functests b/.functests
index d199ec8..288c9e6 100755
--- a/.functests
+++ b/.functests
@@ -1,7 +1,7 @@
#!/bin/bash
set -e
-export OS_TEST_PATH='tests.functional'
+export OS_TEST_PATH='test.functional'
export PYTHON='coverage run --source swiftclient --parallel-mode'
stestr run --concurrency=1
diff --git a/.stestr.conf b/.stestr.conf
index 5228f20..90f5b81 100644
--- a/.stestr.conf
+++ b/.stestr.conf
@@ -1,4 +1,4 @@
[DEFAULT]
-test_path=${OS_TEST_PATH:-./tests/unit}
+test_path=${OS_TEST_PATH:-./test/unit}
top_dir=./
diff --git a/.unittests b/.unittests
index 5d935b1..3a7ffe9 100755
--- a/.unittests
+++ b/.unittests
@@ -1,7 +1,7 @@
#!/bin/bash
set -e
-python setup.py testr --coverage --testr-args="tests.unit"
+python setup.py testr --coverage --testr-args="test.unit"
RET=$?
coverage report -m
rm -f .coverage
diff --git a/.zuul.yaml b/.zuul.yaml
index ac1d966..4f288d7 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -39,9 +39,7 @@
- openstack-lower-constraints-jobs
- openstack-pypy-jobs-nonvoting
- openstack-python-jobs
- - openstack-python35-jobs
- - openstack-python36-jobs
- - openstack-python37-jobs
+ - openstack-python3-ussuri-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
diff --git a/AUTHORS b/AUTHORS
index 16dfcf9..da8e44b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,6 +24,7 @@ Clark Boylan (clark.boylan@gmail.com)
Claudiu Belu (cbelu@cloudbasesolutions.com)
Clay Gerrard (clay.gerrard@gmail.com)
Clint Byrum (clint@fewbar.com)
+Corey Bryant (corey.bryant@canonical.com)
Dan Prince (dprince@redhat.com)
Daniel Wakefield (daniel.wakefield@hp.com)
Darrell Bishop (darrell@swiftstack.com)
diff --git a/ChangeLog b/ChangeLog
index 253a3cc..501491b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+3.8.1
+-----
+
+* Deleting or overwriting a symlink to an SLO or DLO will no longer attempt
+ to clean up the large object's segments.
+
+* Fixed an issue sending non-ASCII metadata keys on Python 3.
+ Note that receiving such metadata on py3 is still broken;
+ see https://bugs.python.org/issue37093
+
+* Documentation can now be rendered as a PDF.
+
+* Dropped Python 3.5 testing.
+
+
3.8.0
-----
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 85dd81e..a8ad3ad 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -181,7 +181,7 @@ htmlhelp_basename = 'SwiftClientwebdoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual])
latex_documents = [
- ('index', 'SwiftClient.tex', u'SwiftClient Documentation',
+ ('index', 'doc-python-swiftclient.tex', u'SwiftClient Documentation',
u'OpenStack, LLC.', 'manual'),
]
@@ -201,3 +201,5 @@ latex_documents = [
# If false, no module index is generated.
# latex_use_modindex = True
+
+latex_use_xindy = False
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 88d2865..ead0279 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -21,6 +21,7 @@ mccabe==0.2.1
mock==1.2.0
netaddr==0.7.10
openstackdocstheme==1.20.0
+openstacksdk==0.11.0
oslo.config==1.2.0
pbr==2.0.0
pep8==1.5.7
diff --git a/releasenotes/notes/3_8_1_release-cb5648c3ae69bde1.yaml b/releasenotes/notes/3_8_1_release-cb5648c3ae69bde1.yaml
new file mode 100644
index 0000000..7985d37
--- /dev/null
+++ b/releasenotes/notes/3_8_1_release-cb5648c3ae69bde1.yaml
@@ -0,0 +1,14 @@
+---
+fixes:
+ - |
+ Deleting or overwriting a symlink to an SLO or DLO will no longer attempt
+ to clean up the large object's segments.
+ - |
+ Fixed an issue sending non-ASCII metadata keys on Python 3.
+ Note that *receiving* such metadata on py3 is `still broken
+ <https://bugs.python.org/issue37093>`__.
+other:
+ - |
+ Documentation can now be rendered as a PDF.
+ - |
+ Dropped Python 3.5 testing.
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 27f675e..662c6f6 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
current
+ train
stein
rocky
queens
diff --git a/releasenotes/source/train.rst b/releasenotes/source/train.rst
new file mode 100644
index 0000000..5839003
--- /dev/null
+++ b/releasenotes/source/train.rst
@@ -0,0 +1,6 @@
+==========================
+Train Series Release Notes
+==========================
+
+.. release-notes::
+ :branch: stable/train
diff --git a/setup.cfg b/setup.cfg
index d3b13a6..5653bf3 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -17,7 +17,6 @@ classifier =
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
diff --git a/swiftclient/authv1.py b/swiftclient/authv1.py
index 55469ac..d70acac 100644
--- a/swiftclient/authv1.py
+++ b/swiftclient/authv1.py
@@ -45,6 +45,7 @@ from six.moves.urllib.parse import urljoin
# Note that while we import keystoneauth1 here, we *don't* need to add it to
# requirements.txt -- this entire module only makes sense (and should only be
# loaded) if keystoneauth is already installed.
+from keystoneauth1 import discover
from keystoneauth1 import plugin
from keystoneauth1 import exceptions
from keystoneauth1 import loading
@@ -110,11 +111,20 @@ class ServiceCatalogV1(object):
]
def url_for(self, **kwargs):
+ return self.endpoint_data_for(**kwargs).url
+
+ def endpoint_data_for(self, **kwargs):
kwargs.setdefault('interface', 'public')
kwargs.setdefault('service_type', None)
if kwargs['service_type'] == 'object-store':
- return self.storage_url
+ return discover.EndpointData(
+ service_type='object-store',
+ service_name='swift',
+ interface=kwargs['interface'],
+ region_name='default',
+ catalog_url=self.storage_url,
+ )
# Although our "catalog" includes an identity entry, nothing that uses
# url_for() (including `openstack endpoint list`) will know what to do
diff --git a/swiftclient/multithreading.py b/swiftclient/multithreading.py
index fcf0ed9..f128790 100644
--- a/swiftclient/multithreading.py
+++ b/swiftclient/multithreading.py
@@ -168,6 +168,12 @@ class ConnectionThreadPoolExecutor(ThreadPoolExecutor):
We will only create as many connections as are required concurrently.
"""
def __init__(self, create_connection, max_workers):
+ """
+ Initializes a new ThreadPoolExecutor instance.
+
+ :param create_connection: callable to use to create new connections
+ :param max_workers: the maximum number of threads that can be used
+ """
self._connections = PriorityQueue()
self._create_connection = create_connection
for p in range(0, max_workers):
diff --git a/swiftclient/shell.py b/swiftclient/shell.py
index cc4f325..5e23bc4 100755
--- a/swiftclient/shell.py
+++ b/swiftclient/shell.py
@@ -169,7 +169,8 @@ def st_delete(parser, args, output_manager, return_parser=False):
for r in del_iter:
c = r.get('container', '')
o = r.get('object', '')
- a = r.get('attempts')
+ a = (' [after {0} attempts]'.format(r.get('attempts'))
+ if r.get('attempts') > 1 else '')
if r['action'] == 'bulk_delete':
if r['success']:
@@ -202,9 +203,6 @@ def st_delete(parser, args, output_manager, return_parser=False):
else:
if r['success']:
if options['verbose']:
- a = (' [after {0} attempts]'.format(a)
- if a > 1 else '')
-
if r['action'] == 'delete_object':
if options['yes_all']:
p = '{0}/{1}'.format(c, o)
diff --git a/test-requirements.txt b/test-requirements.txt
index b3ca5f8..1373253 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -4,3 +4,4 @@ coverage!=4.4,>=4.0 # Apache-2.0
keystoneauth1>=3.4.0 # Apache-2.0
mock>=1.2.0 # BSD
stestr>=2.0.0 # Apache-2.0
+openstacksdk>=0.11.0 # Apache-2.0
diff --git a/tests/__init__.py b/test/__init__.py
index e69de29..e69de29 100644
--- a/tests/__init__.py
+++ b/test/__init__.py
diff --git a/test/functional/__init__.py b/test/functional/__init__.py
new file mode 100644
index 0000000..248875a
--- /dev/null
+++ b/test/functional/__init__.py
@@ -0,0 +1,93 @@
+# Copyright (c) 2014 Christian Schwede <christian.schwede@enovance.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+from six.moves import configparser
+
+TEST_CONFIG = None
+
+
+def _load_config(force_reload=False):
+ global TEST_CONFIG
+ if not force_reload and TEST_CONFIG is not None:
+ return TEST_CONFIG
+
+ config_file = os.environ.get('SWIFT_TEST_CONFIG_FILE',
+ '/etc/swift/test.conf')
+ parser = configparser.ConfigParser({'auth_version': '1'})
+ parser.read(config_file)
+ conf = {}
+ if parser.has_section('func_test'):
+ if parser.has_option('func_test', 'auth_uri'):
+ conf['auth_url'] = parser.get('func_test', 'auth_uri')
+ try:
+ conf['auth_version'] = parser.get('func_test', 'auth_version')
+ except configparser.NoOptionError:
+ last_piece = conf['auth_url'].rstrip('/').rsplit('/', 1)[1]
+ if last_piece.endswith('.0'):
+ last_piece = last_piece[:-2]
+ if last_piece in ('1', '2', '3'):
+ conf['auth_version'] = last_piece
+ else:
+ raise
+ else:
+ auth_host = parser.get('func_test', 'auth_host')
+ auth_port = parser.getint('func_test', 'auth_port')
+ auth_ssl = parser.getboolean('func_test', 'auth_ssl')
+ auth_prefix = parser.get('func_test', 'auth_prefix')
+ conf['auth_version'] = parser.get('func_test', 'auth_version')
+ if auth_ssl:
+ auth_url = "https://"
+ else:
+ auth_url = "http://"
+ auth_url += "%s:%s%s" % (auth_host, auth_port, auth_prefix)
+ if conf['auth_version'] == "1":
+ auth_url += 'v1.0'
+ conf['auth_url'] = auth_url
+
+ try:
+ conf['account_username'] = parser.get('func_test',
+ 'account_username')
+ except configparser.NoOptionError:
+ conf['account'] = parser.get('func_test', 'account')
+ conf['username'] = parser.get('func_test', 'username')
+ conf['account_username'] = "%s:%s" % (conf['account'],
+ conf['username'])
+ else:
+ # Still try to get separate account/usernames for keystone tests
+ try:
+ conf['account'] = parser.get('func_test', 'account')
+ conf['username'] = parser.get('func_test', 'username')
+ except configparser.NoOptionError:
+ pass
+
+ conf['password'] = parser.get('func_test', 'password')
+
+ # For keystone v3
+ try:
+ conf['account4'] = parser.get('func_test', 'account4')
+ conf['username4'] = parser.get('func_test', 'username4')
+ conf['domain4'] = parser.get('func_test', 'domain4')
+ conf['password4'] = parser.get('func_test', 'password4')
+ except configparser.NoOptionError:
+ pass
+
+ TEST_CONFIG = conf
+
+
+try:
+ _load_config()
+except configparser.NoOptionError:
+ TEST_CONFIG = None # sentinel used in test setup
diff --git a/test/functional/test_openstacksdk.py b/test/functional/test_openstacksdk.py
new file mode 100644
index 0000000..cee7f4e
--- /dev/null
+++ b/test/functional/test_openstacksdk.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2019 Tim Burke <tim@swiftstack.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import uuid
+
+import openstack
+
+from . import TEST_CONFIG
+
+PREFIX = 'test-swiftclient-'
+
+
+class TestOpenStackSDK(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # NB: Only runs for v1 auth, to exercise our keystoneauth plugin
+ cls.skip_tests = (TEST_CONFIG is None or
+ TEST_CONFIG['auth_version'] != '1')
+ if not cls.skip_tests:
+ cls.conn = openstack.connect(
+ auth_type='v1password',
+ auth_url=TEST_CONFIG['auth_url'],
+ username=TEST_CONFIG['account_username'],
+ password=TEST_CONFIG['password'],
+ )
+ cls.object_store = cls.conn.object_store
+
+ def setUp(self):
+ if self.skip_tests:
+ raise unittest.SkipTest('SKIPPING V1-AUTH TESTS')
+
+ def tearDown(self):
+ if self.skip_tests:
+ return
+ for c in self.object_store.containers():
+ if c.name.startswith(PREFIX):
+ for o in self.object_store.objects(c.name):
+ self.object_store.delete_object(
+ o.name, container=c.name)
+ self.object_store.delete_container(c.name)
+
+ def test_containers(self):
+ meta = self.object_store.get_account_metadata()
+ count_before = meta.account_container_count
+ containers = sorted(PREFIX + str(uuid.uuid4())
+ for _ in range(10))
+ for c in containers:
+ self.object_store.create_container(c)
+ self.assertEqual([
+ c.name for c in self.object_store.containers()
+ if c.name.startswith(PREFIX)
+ ], containers)
+ meta = self.object_store.get_account_metadata()
+ self.assertEqual(count_before + len(containers),
+ meta.account_container_count)
+
+ def test_objects(self):
+ container = PREFIX + str(uuid.uuid4())
+ self.object_store.create_container(container)
+ objects = sorted(str(uuid.uuid4()) for _ in range(10))
+ for o in objects:
+ self.object_store.create_object(container, o, data=b'x')
+ self.assertEqual([
+ o.name for o in self.object_store.objects(container)
+ ], objects)
+ meta = self.object_store.get_container_metadata(container)
+ self.assertEqual(len(objects), meta.object_count)
+
+ def test_object_metadata(self):
+ container = PREFIX + str(uuid.uuid4())
+ self.object_store.create_container(container)
+ obj = str(uuid.uuid4())
+ obj_meta = {str(uuid.uuid4()): str(uuid.uuid4()) for _ in range(10)}
+ # NB: as of 0.36.0, create_object() doesn't play well with passing
+ # both data and metadata, so we do a PUT then POST
+ self.object_store.create_object(container, obj, data=b'x')
+ self.object_store.set_object_metadata(obj, container, **obj_meta)
+ meta = self.object_store.get_object_metadata(obj, container)
+ self.assertEqual(obj_meta, meta.metadata)
diff --git a/tests/functional/test_swiftclient.py b/test/functional/test_swiftclient.py
index 9a74c63..54c514d 100644
--- a/tests/functional/test_swiftclient.py
+++ b/test/functional/test_swiftclient.py
@@ -13,23 +13,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import os
import unittest
import time
from io import BytesIO
import six
-from six.moves import configparser
import swiftclient
+from . import TEST_CONFIG
class TestFunctional(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestFunctional, self).__init__(*args, **kwargs)
- self.skip_tests = False
- self._get_config()
+ self.skip_tests = (TEST_CONFIG is None)
+ if not self.skip_tests:
+ self._get_config()
self.test_data = b'42' * 10
self.etag = '2704306ec982238d85d4b235c925d58e'
@@ -41,50 +41,10 @@ class TestFunctional(unittest.TestCase):
self.objectname_2 = self.objectname + '_second'
def _get_config(self):
- config_file = os.environ.get('SWIFT_TEST_CONFIG_FILE',
- '/etc/swift/test.conf')
- config = configparser.ConfigParser({'auth_version': '1'})
- config.read(config_file)
- self.config = config
- if config.has_section('func_test'):
- if config.has_option('func_test', 'auth_uri'):
- self.auth_url = config.get('func_test', 'auth_uri')
- try:
- self.auth_version = config.get('func_test', 'auth_version')
- except configparser.NoOptionError:
- last_piece = self.auth_url.rstrip('/').rsplit('/', 1)[1]
- if last_piece.endswith('.0'):
- last_piece = last_piece[:-2]
- if last_piece in ('1', '2', '3'):
- self.auth_version = last_piece
- else:
- raise
- else:
- auth_host = config.get('func_test', 'auth_host')
- auth_port = config.getint('func_test', 'auth_port')
- auth_ssl = config.getboolean('func_test', 'auth_ssl')
- auth_prefix = config.get('func_test', 'auth_prefix')
- self.auth_version = config.get('func_test', 'auth_version')
- self.auth_url = ""
- if auth_ssl:
- self.auth_url += "https://"
- else:
- self.auth_url += "http://"
- self.auth_url += "%s:%s%s" % (
- auth_host, auth_port, auth_prefix)
- if self.auth_version == "1":
- self.auth_url += 'v1.0'
-
- try:
- self.account_username = config.get('func_test',
- 'account_username')
- except configparser.NoOptionError:
- account = config.get('func_test', 'account')
- username = config.get('func_test', 'username')
- self.account_username = "%s:%s" % (account, username)
- self.password = config.get('func_test', 'password')
- else:
- self.skip_tests = True
+ self.auth_url = TEST_CONFIG['auth_url']
+ self.auth_version = TEST_CONFIG['auth_version']
+ self.account_username = TEST_CONFIG['account_username']
+ self.password = TEST_CONFIG['password']
def _get_connection(self):
"""
@@ -514,20 +474,20 @@ class TestUsingKeystone(TestFunctional):
"""
def _get_connection(self):
- account = username = password = None
+ account = username = None
if self.auth_version not in ('2', '3'):
self.skipTest('SKIPPING KEYSTONE-SPECIFIC FUNCTIONAL TESTS')
try:
- account = self.config.get('func_test', 'account')
- username = self.config.get('func_test', 'username')
- password = self.config.get('func_test', 'password')
- except Exception:
+ account = TEST_CONFIG['account']
+ username = TEST_CONFIG['username']
+ except KeyError:
self.skipTest('SKIPPING KEYSTONE-SPECIFIC FUNCTIONAL TESTS' +
' - NO CONFIG')
- os_options = {'tenant_name': account}
+
return swiftclient.Connection(
- self.auth_url, username, password, auth_version=self.auth_version,
- os_options=os_options)
+ self.auth_url, username, self.password,
+ auth_version=self.auth_version,
+ os_options={'tenant_name': account})
class TestUsingKeystoneV3(TestFunctional):
@@ -539,13 +499,14 @@ class TestUsingKeystoneV3(TestFunctional):
account = username = password = project_domain = user_domain = None
if self.auth_version != '3':
self.skipTest('SKIPPING KEYSTONE-V3-SPECIFIC FUNCTIONAL TESTS')
+
try:
- account = self.config.get('func_test', 'account4')
- username = self.config.get('func_test', 'username4')
- user_domain = self.config.get('func_test', 'domain4')
- project_domain = self.config.get('func_test', 'domain4')
- password = self.config.get('func_test', 'password4')
- except Exception:
+ account = TEST_CONFIG['account4']
+ username = TEST_CONFIG['username4']
+ user_domain = TEST_CONFIG['domain4']
+ project_domain = TEST_CONFIG['domain4']
+ password = TEST_CONFIG['password4']
+ except KeyError:
self.skipTest('SKIPPING KEYSTONE-V3-SPECIFIC FUNCTIONAL TESTS' +
' - NO CONFIG')
diff --git a/tests/sample.conf b/test/sample.conf
index 95c1a47..95c1a47 100644
--- a/tests/sample.conf
+++ b/test/sample.conf
diff --git a/tests/functional/__init__.py b/test/unit/__init__.py
index e69de29..e69de29 100644
--- a/tests/functional/__init__.py
+++ b/test/unit/__init__.py
diff --git a/tests/unit/test_authv1.py b/test/unit/test_authv1.py
index 2ddf24b..2ddf24b 100644
--- a/tests/unit/test_authv1.py
+++ b/test/unit/test_authv1.py
diff --git a/tests/unit/test_command_helpers.py b/test/unit/test_command_helpers.py
index 24684ae..24684ae 100644
--- a/tests/unit/test_command_helpers.py
+++ b/test/unit/test_command_helpers.py
diff --git a/tests/unit/test_multithreading.py b/test/unit/test_multithreading.py
index 8944d48..8944d48 100644
--- a/tests/unit/test_multithreading.py
+++ b/test/unit/test_multithreading.py
diff --git a/tests/unit/test_service.py b/test/unit/test_service.py
index b760352..ed3a2d6 100644
--- a/tests/unit/test_service.py
+++ b/test/unit/test_service.py
@@ -36,7 +36,7 @@ from swiftclient.service import (
SwiftService, SwiftError, SwiftUploadObject
)
-from tests.unit import utils as test_utils
+from test.unit import utils as test_utils
clean_os_environ = {}
@@ -1060,11 +1060,11 @@ class TestService(unittest.TestCase):
@mock.patch('swiftclient.service.getsize', return_value=4)
def test_upload_with_relative_path(self, *args, **kwargs):
service = SwiftService({})
- objects = [{'path': "./test",
+ objects = [{'path': "./testobj",
'strt_indx': 2},
- {'path': os.path.join(os.getcwd(), "test"),
+ {'path': os.path.join(os.getcwd(), "testobj"),
'strt_indx': 1},
- {'path': ".\\test",
+ {'path': ".\\testobj",
'strt_indx': 2}]
for obj in objects:
with mock.patch('swiftclient.service.Connection') as mock_conn, \
diff --git a/tests/unit/test_shell.py b/test/unit/test_shell.py
index c972281..c972281 100644
--- a/tests/unit/test_shell.py
+++ b/test/unit/test_shell.py
diff --git a/tests/unit/test_swiftclient.py b/test/unit/test_swiftclient.py
index 2d45deb..2d45deb 100644
--- a/tests/unit/test_swiftclient.py
+++ b/test/unit/test_swiftclient.py
diff --git a/tests/unit/test_utils.py b/test/unit/test_utils.py
index 97abc44..97abc44 100644
--- a/tests/unit/test_utils.py
+++ b/test/unit/test_utils.py
diff --git a/tests/unit/utils.py b/test/unit/utils.py
index 025a234..025a234 100644
--- a/tests/unit/utils.py
+++ b/test/unit/utils.py
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/unit/__init__.py
+++ /dev/null
diff --git a/tox.ini b/tox.ini
index e029efd..002d24c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py37,py36,py35,py27,pypy,pep8
+envlist = py27,py37,pypy,pep8
minversion = 2.0
skipsdist = True
@@ -24,7 +24,7 @@ passenv = SWIFT_* *_proxy
[testenv:pep8]
basepython = python3
commands =
- python -m flake8 swiftclient tests
+ python -m flake8 swiftclient test
[testenv:venv]
basepython = python3
@@ -44,7 +44,7 @@ commands =
[testenv:func]
basepython = python3
setenv =
- OS_TEST_PATH=tests.functional
+ OS_TEST_PATH=test.functional
PYTHON=coverage run --source swiftclient --parallel-mode
whitelist_externals =
coverage
@@ -109,3 +109,12 @@ deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt
.[keystone]
+
+[testenv:pdf-docs]
+basepython = python3
+deps = {[testenv:docs]deps}
+whitelist_externals =
+ make
+commands =
+ sphinx-build -W -b latex doc/source doc/build/pdf
+ make -C doc/build/pdf