diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..010ea080 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,12 @@ +[run] +branch = True +source = stor, stor_dx, stor_s3, stor_swift +omit = stor/stor/tests/test_posix_path_compat.py,stor/stor/tests/test_integration.py,stor/stor/third_party/backoff.py,stor_dx/stor_dx/tests/test_integration_dx.py,stor_s3/stor_s3/tests/test_integration_s3.py,stor_swift/stor_swift/tests/test_integration_swift.py + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + raise NotImplementedError +show_missing=1 +fail_under=100 diff --git a/.gitignore b/.gitignore index 5cb9b068..1b978a61 100644 --- a/.gitignore +++ b/.gitignore @@ -6,12 +6,17 @@ *.orig *.DS_Store .tox +stor*/*.egg-info/* +stor*/.eggs/ +.*cache/ +stor*/.*cache/ *.egg/* .eggs/ *.egg-info/* +stor*/build/* build/* docs/_build/* -dist/* +stor*/dist/* *.log nosetests*.xml diff --git a/AUTHORS b/AUTHORS index a3534f6d..19fc25af 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,3 +3,4 @@ Jeff Tratner @jtratner Stephanie Huang @phanieste Kyle Beauchamp @kyleabeauchamp Piotr Kaleta @pkaleta +Anuj Kumar @anujkumar93 diff --git a/Makefile b/Makefile index f773055e..21656773 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Makefile utilities for running tests and publishing the package -PACKAGE_NAME=stor +PACKAGE_NAMES:=stor/ stor_dx/ stor_swift/ stor_s3/ TEST_OUTPUT?=nosetests.xml PIP_INDEX_URL=https://pypi.python.org/simple/ PYTHON?=$(shell which python) @@ -13,7 +13,7 @@ endif .PHONY: default default: - python setup.py check build + cd stor; python setup.py check build; cd .. VENV_DIR?=.venv VENV_ACTIVATE=$(VENV_DIR)/bin/activate @@ -23,42 +23,42 @@ WITH_PBR=$(WITH_VENV) PBR_REQUIREMENTS_FILES=requirements-pbr.txt .PHONY: venv venv: $(VENV_ACTIVATE) -$(VENV_ACTIVATE): requirements*.txt +$(VENV_ACTIVATE): stor*/requirements*.txt test -f $@ || virtualenv --python=$(PYTHON) $(VENV_DIR) $(WITH_VENV) echo "Within venv, running $$(python --version)" - $(WITH_VENV) pip install -r requirements-setup.txt --index-url=${PIP_INDEX_URL} - $(WITH_VENV) pip install -e . --index-url=${PIP_INDEX_URL} - $(WITH_VENV) pip install -r requirements-dev.txt --index-url=${PIP_INDEX_URL} - $(WITH_VENV) pip install -r requirements-docs.txt --index-url=${PIP_INDEX_URL} + $(WITH_VENV) pip install -r stor/requirements-setup.txt --index-url=${PIP_INDEX_URL} + $(WITH_VENV) ./run_all.sh 'pip install -e . --index-url=${PIP_INDEX_URL}' $(PACKAGE_NAMES) + $(WITH_VENV) pip install -r stor/requirements-dev.txt --index-url=${PIP_INDEX_URL} + $(WITH_VENV) pip install -r stor/requirements-docs.txt --index-url=${PIP_INDEX_URL} touch $@ develop: venv - $(WITH_VENV) python setup.py develop + $(WITH_VENV) ./run_all.sh 'python setup.py develop' $(PACKAGE_NAMES) .PHONY: docs docs: venv clean-docs $(WITH_VENV) cd docs && make html - .PHONY: setup setup: ##[setup] Run an arbitrary setup.py command setup: venv ifdef ARGS - $(WITH_PBR) python setup.py ${ARGS} + $(WITH_PBR) ./run_all.sh 'python setup.py ${ARGS}' $(PACKAGE_NAMES) else @echo "Won't run 'python setup.py ${ARGS}' without ARGS set." endif .PHONY: clean clean: - $(PYTHON) setup.py clean - rm -rf build/ - rm -rf dist/ - rm -rf *.egg*/ - rm -rf __pycache__/ + ./run_all.sh '$(PYTHON) setup.py clean' $(PACKAGE_NAMES) + ./run_all.sh 'rm -rf *.egg*/' $(PACKAGE_NAMES) . + ./run_all.sh 'rm -rf dist/' $(PACKAGE_NAMES) + ./run_all.sh 'rm -rf build/' $(PACKAGE_NAMES) + ./run_all.sh 'rm -rf __pycache__/' $(PACKAGE_NAMES) . + ./run_all.sh 'rm -rf .*cache/' $(PACKAGE_NAMES) . rm -f MANIFEST rm -f $(TEST_OUTPUT) - find $(PACKAGE_NAME) -type f -name '*.pyc' -delete + ./run_all.sh 'find . -type f -name '*.pyc' -delete' $(PACKAGE_NAMES) . rm -rf nosetests* "${TEST_OUTPUT}" coverage .coverage @@ -73,7 +73,7 @@ teardown: .PHONY: lint lint: venv - $(WITH_VENV) flake8 $(PACKAGE_NAME)/ + $(WITH_VENV) ./run_all.sh 'flake8 .' $(PACKAGE_NAMES) .PHONY: unit-test unit-test: venv @@ -99,14 +99,15 @@ endif .PHONY: travis-test travis-test: venv $(WITH_VENV) \ - coverage erase; \ - coverage run setup.py test; \ + ./run_all.sh 'coverage erase' $(PACKAGE_NAMES) .; \ + ./run_all.sh 'coverage run setup.py test' $(PACKAGE_NAMES); \ + coverage combine stor*/.coverage; \ status=$$?; \ coverage report && exit $$status; # Distribution -VERSION=$(shell $(WITH_PBR) python setup.py --version | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\).*$$/\1/') +VERSION=$(shell $(WITH_PBR) cd stor; python setup.py --version | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\).*$$/\1/'; cd ..) .PHONY: tag tag: ##[distribution] Tag the release. @@ -117,7 +118,7 @@ tag: venv .PHONY: dist dist: venv fullname - $(WITH_VENV) python setup.py sdist + $(WITH_VENV) ./run_all.sh 'python setup.py sdist' $(PACKAGE_NAMES) .PHONY: publish-docs publish-docs: @@ -133,4 +134,4 @@ version: .PHONY: fullname fullname: - $(PYTHON) setup.py --fullname + ./run_all.sh '$(PYTHON) setup.py --fullname' $(PACKAGE_NAMES) diff --git a/docs/package_split.rst b/docs/package_split.rst new file mode 100644 index 00000000..bf9483fa --- /dev/null +++ b/docs/package_split.rst @@ -0,0 +1,45 @@ +Stor Modularization +=================== + +The legacy version of stor has been split into 4 packages: ``stor``, ``stor_dx``, ``stor_swift``, and +``stor_s3``. ``stor_swift``, ``stor_dx``, ``stor_s3`` are modular packages implemented to be used with +the core package ``stor`` directly. The core package ``stor`` now only supports Posix and Windows +filesystems, apart from supporting extra plugins. + + +Implementation +-------------- + +Each of the modular packages work by registering themselves onto pkg_resources with an entry_point +``stor.providers``. This entry point should be a function which takes in a prefix and a path, and +returns the cls that the path should be instantiated to, as well as the path that should be initialized. +Typically, this function is called ``class_for_path`` in ``stor_dx``, ``stor_s3``, and ``stor_swift``. +Each plugin module currently raise an error if the prefix passed is not the prefix it supports. For +example, ``stor_dx.class_for_path`` errors if the prefix is not ``dx``. ``get_class_for_path`` in each +plugin module may assume that the prefix is the true prefix to the path argument as this is guaranteed +by the core ``stor`` package. + + +Code Changes +------------ + +`stor.copy`, `stor.copytree` and ``stor.open`` which were earlier present in the core ``stor.utils`` and +``stor.obs`` have been split according to their individual functionalities into the three packages. +These functions in the core package now only deal with posix/windows paths while the three plugins +implement the finer aspects of the logic individual to each platform. The only external effect of +these changes is that `stor.copy` and `stor.copytree` now don't support a ``source`` kwarg, instead +expect the first argument to be a ``Path | str``, which is then taken to be the source to be copied from. + +``is_swift_path`` has been removed from the core `stor` package. Thus, using ``stor.is_swift_path`` will +fail. This is because the plugins determine the prefix they support and the core package cannot know in +advance if ``swift://`` is a supported path. In cases where ``stor.is_swift_path`` was being used, +``stor.is_obs_path`` is a possible substitution. Thus, each individual plugin ``stor_dx``, ``stor_s3`` and +``stor_swift`` is now responsible for supporting ``is_dx_path``, ``is_s3_path`` and ``is_swift_path`` resp. + + +Versioning +---------- +Since the core stor package and the plugins live on the same github repo, and PBR is used for semantic +versioning, they will have the same published version at any given time. However, it is possible to +install an older version of ``stor`` with a newer version of the plugins ``stor_dx``, etc. The behavior is +undefined in this case. The core ``stor`` package has been implemented to require the extra plugins for now. diff --git a/docs/release_notes.rst b/docs/release_notes.rst index 40957bf0..125dd050 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -1,6 +1,27 @@ Release Notes ============= +v4.0.0 +------ + +Package Split +^^^^^^^^^^^^^ + +* To ease the installation of dependencies, stor is broken down into 4 packages: ``stor``, ``stor_dx``, + ``stor_swift``, and ``stor_s3``. +* ``stor_dx``, ``stor_s3``, and ``stor_swift`` are meant to be plugins to stor. The core stor package, + responsible for posix and windows paths, is still required to be able to use stor. +* ``stor_dx``, ``stor_s3``, and ``stor_swift`` are responsible for manipulating resources on the DNAnexus, + Amazon S3 and Swift cloud platforms respectively. + +API Breaks +^^^^^^^^^^ +* The function signature of ``stor.copy`` has changed slightly, from ``stor.copy(source='some/source', + dest='some/dest')`` to ``stor.copy('some/source', dest='some/dest')``. ``stor.copy`` needs a ``Path|str`` + as its first argument (which is taken to be the source). The source kwarg is no longer supported. +* ``is_swift_path`` has been removed from the core ``stor`` package. Hence, ``stor.is_swift_path`` is no + longer supported. Can use `stor.is_obs_path` in such cases after consideration. + v3.0.0 ------ diff --git a/docs/settings.rst b/docs/settings.rst index 793a4e34..f9554cb7 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -47,7 +47,7 @@ Settings can be configured in the following ways in order of precedence: Default Settings ---------------- -.. literalinclude:: ../stor/default.cfg +.. literalinclude:: ../stor/stor/default.cfg Settings API ------------ diff --git a/docs/toc.rst b/docs/toc.rst index 755b30eb..303058d1 100644 --- a/docs/toc.rst +++ b/docs/toc.rst @@ -18,5 +18,6 @@ Table of Contents settings extensions contributing + package_split roadmap release_notes diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4f88e4f6..00000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# have to explicitly ban certain requests versions to match keystoneauth1 package -requests!=2.12.2,!=2.13.0,>=2.10.0 -boto3>=1.4.0 -cached-property -contextlib2 -dxpy>=0.265.0; python_version <= '2.7' -dxpy3; python_version > '3.0' -python-keystoneclient>=1.8.1 -python-swiftclient -six diff --git a/run_all.sh b/run_all.sh new file mode 100755 index 00000000..72154362 --- /dev/null +++ b/run_all.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +CMD=$1 +shift +DIRS=$* +for directory in $DIRS; do + cd $directory; ${CMD}; cd .. +done \ No newline at end of file diff --git a/setup.py b/setup.py index e74f898b..e69de29b 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +0,0 @@ -from setuptools import setup - -setup( - pbr=True, - setup_requires=['pbr'], -) diff --git a/README.rst b/stor/README.rst similarity index 100% rename from README.rst rename to stor/README.rst diff --git a/requirements-dev.txt b/stor/requirements-dev.txt similarity index 100% rename from requirements-dev.txt rename to stor/requirements-dev.txt diff --git a/requirements-docs.txt b/stor/requirements-docs.txt similarity index 100% rename from requirements-docs.txt rename to stor/requirements-docs.txt diff --git a/requirements-setup.txt b/stor/requirements-setup.txt similarity index 100% rename from requirements-setup.txt rename to stor/requirements-setup.txt diff --git a/stor/requirements.txt b/stor/requirements.txt new file mode 100644 index 00000000..77d9f404 --- /dev/null +++ b/stor/requirements.txt @@ -0,0 +1,4 @@ +# have to explicitly ban certain requests versions to match keystoneauth1 package for swift +requests!=2.12.2,!=2.13.0,>=2.10.0 +six +python-swiftclient \ No newline at end of file diff --git a/setup.cfg b/stor/setup.cfg similarity index 84% rename from setup.cfg rename to stor/setup.cfg index 61ae4470..d803c37a 100644 --- a/setup.cfg +++ b/stor/setup.cfg @@ -23,7 +23,7 @@ classifier = [coverage:run] branch = True source = stor -omit = stor/tests/test_posix_path_compat.py,stor_swift/tests/test_integration_swift.py,stor_s3/tests/test_integration_s3.py,stor/tests/test_integration.py,stor/third_party/backoff.py,stor_dx/tests/test_integration_dx.py +omit = stor/tests/test_posix_path_compat.py,stor/tests/test_integration.py,stor/third_party/backoff.py [coverage:report] exclude_lines = diff --git a/stor/setup.py b/stor/setup.py new file mode 100644 index 00000000..e74f898b --- /dev/null +++ b/stor/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup( + pbr=True, + setup_requires=['pbr'], +) diff --git a/stor/__init__.py b/stor/stor/__init__.py similarity index 100% rename from stor/__init__.py rename to stor/stor/__init__.py diff --git a/stor/base.py b/stor/stor/base.py similarity index 94% rename from stor/base.py rename to stor/stor/base.py index b9e394d3..d3a1c613 100644 --- a/stor/base.py +++ b/stor/stor/base.py @@ -1,8 +1,10 @@ import errno import fnmatch import glob -import os +import logging import ntpath +import os +import pkg_resources import posixpath import shutil import sys @@ -16,6 +18,30 @@ from stor import utils +logger = logging.getLogger(__name__) + + +def get_modules(): + modules = {} + for entry_point in pkg_resources.iter_entry_points('stor.providers'): + try: + modules.update({entry_point.name: entry_point.load()}) + except pkg_resources.DistributionNotFound as e: # pragma: no cover + warnings.warn('Ignoring {entry_point} module as the requirement(s) ' + 'for the module are not installed. Exception : {exception}' + .format(entry_point=entry_point.name, exception=e)) + pass + return modules + + +def get_class_for_path(path): + module_map = get_modules() + for k, v in module_map.items(): + if path.startswith(k + '://'): + return v(k, path) + return None, None + + class TreeWalkWarning(Warning): pass @@ -41,32 +67,23 @@ class Path(text_type): """ def __new__(cls, path): - from stor_swift import utils as swift_utils - from stor_s3 import utils as s3_utils - from stor_dx import utils as dx_utils if cls is Path: if not hasattr(path, 'startswith'): raise TypeError('must be a string like') - if dx_utils.is_dx_path(path): - cls = dx_utils.find_dx_class(path) - elif swift_utils.is_swift_path(path): - from stor_swift.swift import SwiftPath - - cls = SwiftPath - elif s3_utils.is_s3_path(path): - from stor_s3.s3 import S3Path - - cls = S3Path - elif os.path == ntpath: - from stor.windows import WindowsPath - - cls = WindowsPath - elif os.path == posixpath: - from stor.posix import PosixPath - - cls = PosixPath - else: # pragma: no cover - assert False, 'path is not compatible with stor' + cls, obs_p = get_class_for_path(path) + if cls is None: + if os.path == ntpath: + from stor.windows import WindowsPath + + cls = WindowsPath + elif os.path == posixpath: + from stor.posix import PosixPath + + cls = PosixPath + else: # pragma: no cover + assert False, 'path is not compatible with stor' + else: + path = obs_p return text_type.__new__(cls, path) def __init__(self, path): diff --git a/stor/cli.py b/stor/stor/cli.py similarity index 97% rename from stor/cli.py rename to stor/stor/cli.py index 672570b1..200ebd46 100644 --- a/stor/cli.py +++ b/stor/stor/cli.py @@ -118,7 +118,10 @@ def force_exit(signum, frame): # pragma: no cover class TempPath(Path): """Persist stdin to a temporary file for CLI operations with OBS.""" - def __del__(self): + + # manually checked that TempPath is deleted at the end. Different python versions + # delete it at different times in their stack though, so not easy to test + def __del__(self): # pragma: no cover os.remove(str(self)) @@ -279,8 +282,8 @@ def _wrapped_list(path, **kwargs): """Use iterative walkfiles for DX paths, rather than trying to generate full list first""" func = stor.list try: - from stor_dx import utils as dx_utils - if dx_utils.is_dx_path(path): + import stor_dx + if stor_dx.is_dx_path(path): func = stor.walkfiles except ImportError: # pragma: no cover pass @@ -295,18 +298,18 @@ def _to_url(path): def _convert_swiftstack(path, bucket=None): try: - from stor_swift import utils as swift_utils - from stor_s3 import utils as s3_utils + import stor_swift + import stor_s3 except ImportError: # pragma: no cover raise ImportError( 'stor-swift and stor-s3 must be installed to use convert-swiftstack command') path = stor.Path(path) - if swift_utils.is_swift_path(path): + if stor_swift.is_swift_path(path): if not bucket: # TODO (jtratner): print help here raise ValueError('--bucket is required for swift paths') return swiftstack.swift_to_s3(path, bucket=bucket) - elif s3_utils.is_s3_path(path): + elif stor_s3.is_s3_path(path): return swiftstack.s3_to_swift(path) raise ValueError("invalid path for conversion: '%s'" % path) diff --git a/stor/default.cfg b/stor/stor/default.cfg similarity index 100% rename from stor/default.cfg rename to stor/stor/default.cfg diff --git a/stor/default.env b/stor/stor/default.env similarity index 100% rename from stor/default.env rename to stor/stor/default.env diff --git a/stor/exceptions.py b/stor/stor/exceptions.py similarity index 100% rename from stor/exceptions.py rename to stor/stor/exceptions.py diff --git a/stor/extensions/__init__.py b/stor/stor/extensions/__init__.py similarity index 100% rename from stor/extensions/__init__.py rename to stor/stor/extensions/__init__.py diff --git a/stor/extensions/swiftstack.py b/stor/stor/extensions/swiftstack.py similarity index 100% rename from stor/extensions/swiftstack.py rename to stor/stor/extensions/swiftstack.py diff --git a/stor/obs.py b/stor/stor/obs.py similarity index 99% rename from stor/obs.py rename to stor/stor/obs.py index aefbde24..dca174c9 100644 --- a/stor/obs.py +++ b/stor/stor/obs.py @@ -67,9 +67,9 @@ def __init__(self, pth): can be any of s3 or swift. The ``(drive)://`` prefix is required in the path. """ - if not hasattr(pth, 'startswith') or not pth.startswith(self.drive): - raise ValueError('path must have %s (got %r)' % (self.drive, pth)) - return super(OBSPath, self).__init__(pth) + if not hasattr(self, 'startswith') or not self.startswith(self.drive): + raise ValueError('path must have %s (got %r)' % (self.drive, self)) + return super(OBSPath, self).__init__(self) def copy(self, dest, **swift_retry_options): """Copies a source file to a destination file. diff --git a/stor/posix.py b/stor/stor/posix.py similarity index 100% rename from stor/posix.py rename to stor/stor/posix.py diff --git a/stor/settings.py b/stor/stor/settings.py similarity index 100% rename from stor/settings.py rename to stor/stor/settings.py diff --git a/stor/stor-completion.bash b/stor/stor/stor-completion.bash similarity index 100% rename from stor/stor-completion.bash rename to stor/stor/stor-completion.bash diff --git a/stor/tests/__init__.py b/stor/stor/tests/__init__.py similarity index 100% rename from stor/tests/__init__.py rename to stor/stor/tests/__init__.py diff --git a/stor/tests/file_data/s_3_2126.bcl.gz b/stor/stor/tests/file_data/s_3_2126.bcl.gz similarity index 100% rename from stor/tests/file_data/s_3_2126.bcl.gz rename to stor/stor/tests/file_data/s_3_2126.bcl.gz diff --git a/stor/tests/file_data/test.cfg b/stor/stor/tests/file_data/test.cfg similarity index 100% rename from stor/tests/file_data/test.cfg rename to stor/stor/tests/file_data/test.cfg diff --git a/stor/tests/shared.py b/stor/stor/tests/shared.py similarity index 100% rename from stor/tests/shared.py rename to stor/stor/tests/shared.py diff --git a/stor/tests/shared_obs.py b/stor/stor/tests/shared_obs.py similarity index 100% rename from stor/tests/shared_obs.py rename to stor/stor/tests/shared_obs.py diff --git a/stor/tests/swift_upload/data_dir/file2 b/stor/stor/tests/swift_upload/data_dir/file2 similarity index 100% rename from stor/tests/swift_upload/data_dir/file2 rename to stor/stor/tests/swift_upload/data_dir/file2 diff --git a/stor/tests/swift_upload/file1 b/stor/stor/tests/swift_upload/file1 similarity index 100% rename from stor/tests/swift_upload/file1 rename to stor/stor/tests/swift_upload/file1 diff --git a/stor/tests/test_cli.py b/stor/stor/tests/test_cli.py similarity index 100% rename from stor/tests/test_cli.py rename to stor/stor/tests/test_cli.py diff --git a/stor/tests/test_extensions_swiftstack.py b/stor/stor/tests/test_extensions_swiftstack.py similarity index 100% rename from stor/tests/test_extensions_swiftstack.py rename to stor/stor/tests/test_extensions_swiftstack.py diff --git a/stor/tests/test_integration.py b/stor/stor/tests/test_integration.py similarity index 100% rename from stor/tests/test_integration.py rename to stor/stor/tests/test_integration.py diff --git a/stor/tests/test_integration_posix.py b/stor/stor/tests/test_integration_posix.py similarity index 100% rename from stor/tests/test_integration_posix.py rename to stor/stor/tests/test_integration_posix.py diff --git a/stor/tests/test_posix.py b/stor/stor/tests/test_posix.py similarity index 96% rename from stor/tests/test_posix.py rename to stor/stor/tests/test_posix.py index d62c6cb8..a62a6670 100644 --- a/stor/tests/test_posix.py +++ b/stor/stor/tests/test_posix.py @@ -7,6 +7,14 @@ from stor import Path from stor import posix from stor import windows +from stor.base import get_class_for_path + + +class TestInit(unittest.TestCase): + def test_swift_init(self): + cls, path = get_class_for_path('some/posix/path') + self.assertEqual(cls, None) + self.assertEqual(path, None) class TestDiv(unittest.TestCase): diff --git a/stor/tests/test_posix_path_compat.py b/stor/stor/tests/test_posix_path_compat.py similarity index 100% rename from stor/tests/test_posix_path_compat.py rename to stor/stor/tests/test_posix_path_compat.py diff --git a/stor/tests/test_settings.py b/stor/stor/tests/test_settings.py similarity index 100% rename from stor/tests/test_settings.py rename to stor/stor/tests/test_settings.py diff --git a/stor/tests/test_utils.py b/stor/stor/tests/test_utils.py similarity index 100% rename from stor/tests/test_utils.py rename to stor/stor/tests/test_utils.py diff --git a/stor/tests/test_windows.py b/stor/stor/tests/test_windows.py similarity index 100% rename from stor/tests/test_windows.py rename to stor/stor/tests/test_windows.py diff --git a/stor/third_party/__init__.py b/stor/stor/third_party/__init__.py similarity index 100% rename from stor/third_party/__init__.py rename to stor/stor/third_party/__init__.py diff --git a/stor/third_party/backoff.py b/stor/stor/third_party/backoff.py similarity index 100% rename from stor/third_party/backoff.py rename to stor/stor/third_party/backoff.py diff --git a/stor/utils.py b/stor/stor/utils.py similarity index 97% rename from stor/utils.py rename to stor/stor/utils.py index be7d1cbb..068d8384 100644 --- a/stor/utils.py +++ b/stor/stor/utils.py @@ -6,6 +6,7 @@ import tempfile from stor import exceptions +import stor logger = logging.getLogger(__name__) @@ -144,7 +145,6 @@ def generate_and_save_data_manifest(manifest_dir, data_manifest_contents): data_manifest_contents (List[str]): The list of all objects that will be part of the manifest. """ - import stor from stor import Path manifest_file_name = Path(manifest_dir) / DATA_MANIFEST_FILE_NAME @@ -155,7 +155,6 @@ def generate_and_save_data_manifest(manifest_dir, data_manifest_contents): def get_data_manifest_contents(manifest_dir): """Reads the manifest file and returns a set of expected files""" - import stor manifest = manifest_dir / DATA_MANIFEST_FILE_NAME with stor.open(manifest, 'r') as manifest_file: @@ -182,10 +181,11 @@ def is_filesystem_path(p): Returns: bool: True if p is a Windows path, False otherwise. """ - from stor_swift.utils import is_swift_path - from stor_s3.utils import is_s3_path - from stor_dx.utils import is_dx_path - return not (is_swift_path(p) or is_s3_path(p) or is_dx_path(p)) + module_map = stor.base.get_modules() + for k, v in module_map.items(): + if p.startswith(k + '://'): + return False + return True def is_obs_path(p): @@ -248,8 +248,8 @@ def is_writeable(path, swift_retry_options=None): container_path = None container_existed = None try: - from stor_swift.swift import SwiftPath - from stor_swift.utils import is_swift_path + from stor_swift import SwiftPath + from stor_swift import is_swift_path if is_swift_path(path): # We want this function to behave as a no-op with regards to the underlying diff --git a/stor/windows.py b/stor/stor/windows.py similarity index 100% rename from stor/windows.py rename to stor/stor/windows.py diff --git a/stor_dx/requirements.txt b/stor_dx/requirements.txt new file mode 100644 index 00000000..6f228e4e --- /dev/null +++ b/stor_dx/requirements.txt @@ -0,0 +1,4 @@ +cached-property +contextlib2 +dxpy>=0.265.0; python_version <= '2.7' +dxpy3; python_version > '3.0' diff --git a/stor_dx/setup.cfg b/stor_dx/setup.cfg new file mode 100644 index 00000000..2d076df8 --- /dev/null +++ b/stor_dx/setup.cfg @@ -0,0 +1,52 @@ +[metadata] +name = stor_dx +author = Counsyl Inc. +author-email = opensource@counsyl.com +summary = Add-on package to stor for accessing DX storage systems +home-page = https://github.com/counsyl/stor +requires-python = >=2.7 +license = MIT +classifier = + Topic :: Internet :: WWW/HTTP :: Dynamic Content + Intended Audience :: Developers + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Development Status :: 5 - Production/Stable + Operating System :: OS Independent + +[coverage:run] +branch = True +source = stor_dx, ../stor/stor +omit = stor_dx/tests/test_integration_dx.py + +[coverage:report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + raise NotImplementedError +fail_under = 100 +show_missing = 1 + +[files] +packages = stor_dx + +[entry_points] +stor.providers = + dx = stor_dx:class_for_path + +[flake8] +max-complexity=10 +max-line-length=99 +exclude = stor_dx/__init__.py + +[pbr] +skip_authors = true +skip_changelog = true + +[bdist_wheel] +universal = 1 diff --git a/stor_dx/setup.py b/stor_dx/setup.py new file mode 100644 index 00000000..e74f898b --- /dev/null +++ b/stor_dx/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup( + pbr=True, + setup_requires=['pbr'], +) diff --git a/stor_dx/stor_dx/__init__.py b/stor_dx/stor_dx/__init__.py new file mode 100644 index 00000000..97167e39 --- /dev/null +++ b/stor_dx/stor_dx/__init__.py @@ -0,0 +1,13 @@ +from stor_dx.utils import is_dx_path +from stor_dx.dx import DXPath +from stor_dx import utils + + +drive = DXPath.drive + + +def class_for_path(prefix, path): + if prefix+'://' != drive: + raise ValueError('Invalid prefix to initialize DXPaths: {}'.format(prefix)) + cls = utils.find_dx_class(path) + return cls, path diff --git a/stor_dx/dx.py b/stor_dx/stor_dx/dx.py similarity index 99% rename from stor_dx/dx.py rename to stor_dx/stor_dx/dx.py index 06b5a796..7cb9b36b 100644 --- a/stor_dx/dx.py +++ b/stor_dx/stor_dx/dx.py @@ -493,7 +493,7 @@ def copy(self, dest, raise_if_same_project=False, **kwargs): raise stor_exceptions.NotFoundError( 'No data object was found for the given path on DNAnexus') else: - # for other filesystems, delegate to stor.obs.OBSPath.copy + # for other filesystems, delegate to stor.base.Path.copy super(DXPath, self).copy(dest, **kwargs) def copytree(self, dest, raise_if_same_project=False, **kwargs): @@ -564,7 +564,7 @@ def copytree(self, dest, raise_if_same_project=False, **kwargs): raise stor_exceptions.NotFoundError( 'No project or directory was found at path ({})'.format(self)) else: - # for other filesystems, delegate to stor.obs.OBSPath.copytree + # for other filesystems, delegate to stor.base.Path.copytree super(DXPath, self).copytree(dest, **kwargs) def _prep_for_copytree(self, dest): diff --git a/stor_dx/test.py b/stor_dx/stor_dx/test.py similarity index 100% rename from stor_dx/test.py rename to stor_dx/stor_dx/test.py diff --git a/stor_dx/__init__.py b/stor_dx/stor_dx/tests/__init__.py similarity index 100% rename from stor_dx/__init__.py rename to stor_dx/stor_dx/tests/__init__.py diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path_on_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path_on_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path_on_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_canonical_path_on_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_duplicate_projects.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_duplicate_projects.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalProject/test_duplicate_projects.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_duplicate_projects.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_no_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_no_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalProject/test_no_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_no_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_unique_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_unique_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalProject/test_unique_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalProject/test_unique_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_duplicate_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_duplicate_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalResource/test_duplicate_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_duplicate_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_no_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_no_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalResource/test_no_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_no_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalResource/test_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_unique_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_unique_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalResource/test_unique_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_unique_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_virtual_on_virtual.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_virtual_on_virtual.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCanonicalResource/test_virtual_on_virtual.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCanonicalResource/test_virtual_on_virtual.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_clone_move_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_clone_move_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_clone_move_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_clone_move_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_clone_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_clone_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_clone_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_clone_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_canonical_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_canonical_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_canonical_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_canonical_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_dir_to_posix_error.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_dir_to_posix_error.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_dir_to_posix_error.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_dir_to_posix_error.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_dx_within_project_pass.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_other_obs.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_other_obs.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_other_obs.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_other_obs.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_posix_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_same_dx_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_same_dx_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_same_dx_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_dx_to_same_dx_pass.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_move_diff_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_move_diff_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_move_diff_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_move_diff_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_other_obs_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_other_obs_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_other_obs_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_other_obs_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_dx_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_existing_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_existing_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_existing_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopy/test_posix_to_existing_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_clonetree_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_clonetree_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_clonetree_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_clonetree_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_posix.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_posix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_posix.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_dir_to_posix.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_file_to_posix.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_file_to_posix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_file_to_posix.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_file_to_posix.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_root.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_root.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_root.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_dx_root.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_other_obs.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_other_obs.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_other_obs.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_other_obs.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_same_dx_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_same_dx_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_same_dx_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_dx_to_same_dx_pass.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_diff_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_diff_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_move_diff_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_diff_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_root_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_root_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_move_root_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_move_root_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_nonexistent_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_nonexistent_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_nonexistent_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_nonexistent_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_other_obs_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_other_obs_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_other_obs_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_other_obs_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_existing.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_existing.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_existing.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_existing.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_nested.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_nested.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_nested.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_dir_to_dx_nested.yaml diff --git a/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_file_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_file_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_file_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestCopyTree/test_posix_file_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_absolute_paths.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_absolute_paths.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestDownloadObjects/test_absolute_paths.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_absolute_paths.yaml diff --git a/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_local_paths.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_local_paths.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestDownloadObjects/test_local_paths.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestDownloadObjects/test_local_paths.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_false_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_false_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_false_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_false_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_false_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_false_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_false_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_false_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_project_does_not_exist.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_project_does_not_exist.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_project_does_not_exist.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_project_does_not_exist.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_true_dir_with_object.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_dir_with_object.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_true_dir_with_object.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_dir_with_object.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_true_empty_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_empty_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_true_empty_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_empty_dir.yaml diff --git a/stor_dx/tests/cassettes_py2/TestExists/test_true_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestExists/test_true_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestExists/test_true_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGetSize/test_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGetSize/test_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGetSize/test_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGetSize/test_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGetSize/test_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGetSize/test_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGetSize/test_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_cond_no_met.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_cond_no_met.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_cond_no_met.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_cond_no_met.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_glob_cond_met.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_glob_cond_met.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_glob_cond_met.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_glob_cond_met.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_pattern_no_file_match.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_pattern_no_file_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_pattern_no_file_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_pattern_no_file_match.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_prefix_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_prefix_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_prefix_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_prefix_pattern.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_suffix_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_suffix_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_suffix_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_suffix_pattern.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern.yaml diff --git a/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern_wo_wildcard.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern_wo_wildcard.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern_wo_wildcard.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestGlob/test_valid_pattern_wo_wildcard.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_absent_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_absent_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_absent_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_absent_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_canonical.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_empty_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_empty_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_empty_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_empty_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_fail_w_condition.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_fail_w_condition.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_fail_w_condition.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_fail_w_condition.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_folder_share_filename.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_folder_share_filename.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_folder_share_filename.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_folder_share_filename.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_folder_w_files.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_folder_w_files.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_folder_w_files.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_folder_w_files.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_iter_canon_on_canon.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_iter_canon_on_canon.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_iter_canon_on_canon.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_iter_canon_on_canon.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_iter_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_iter_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_iter_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_iter_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_limit.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_limit.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_limit.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_limit.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_on_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_starts_with.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_starts_with.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_starts_with.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_starts_with.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_w_category.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_w_category.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_w_category.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_w_category.yaml diff --git a/stor_dx/tests/cassettes_py2/TestList/test_list_w_condition.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_w_condition.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestList/test_list_w_condition.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestList/test_list_w_condition.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_absent_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_absent_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_absent_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_absent_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_canonical.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_empty_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_empty_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_empty_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_empty_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_share_filename.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_share_filename.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_share_filename.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_share_filename.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_w_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_w_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_w_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_folder_w_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_canon_on_canon.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_canon_on_canon.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_canon_on_canon.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_canon_on_canon.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_iter_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_on_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestListDir/test_listdir_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestListDir/test_listdir_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestLoginAuth/test_login_auth.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestLoginAuth/test_login_auth.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestLoginAuth/test_login_auth.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestLoginAuth/test_login_auth.yaml diff --git a/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder_exists.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder_exists.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder_exists.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_folder_exists.yaml diff --git a/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_nested_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_nested_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_nested_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_nested_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project_exists.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project_exists.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project_exists.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestMakedirsP/test_makedirs_p_project_exists.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_append_mode_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_append_mode_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_append_mode_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_append_mode_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_read_dir_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_dir_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_read_dir_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_dir_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_read_fail_on_closed_buffer.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_fail_on_closed_buffer.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_read_fail_on_closed_buffer.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_fail_on_closed_buffer.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_buffer.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_buffer.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_buffer.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_buffer.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_read_on_open_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_flush_multiple_upload.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_flush_multiple_upload.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_flush_multiple_upload.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_flush_multiple_upload.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_wo_context_manager.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_wo_context_manager.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_wo_context_manager.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_multiple_wo_context_manager.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_read_over_files.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_read_over_files.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_read_over_files.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_read_over_files.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_to_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_to_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_to_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_to_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_big_timeout.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_big_timeout.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_big_timeout.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_big_timeout.yaml diff --git a/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_no_timeout.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_no_timeout.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_no_timeout.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestOpen/test_write_w_settings_no_timeout.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_nonexistent_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_remove_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_fail_rmtree_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_rmtree_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_fail_rmtree_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_fail_rmtree_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_remove_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_remove_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_remove_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_remove_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRemove/test_rmtree_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRename/test_rename_file_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_file_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRename/test_rename_file_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_file_pass.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRename/test_rename_folder_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_folder_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRename/test_rename_folder_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_folder_fail.yaml diff --git a/stor_dx/tests/cassettes_py2/TestRename/test_rename_to_self.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_to_self.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestRename/test_rename_to_self.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestRename/test_rename_to_self.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_project_error.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_project_error.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_project_error.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_project_error.yaml diff --git a/stor_dx/tests/cassettes_py2/TestStat/test_stat_virtual_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_virtual_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestStat/test_stat_virtual_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestStat/test_stat_virtual_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_folder.yaml diff --git a/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_project.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_fail_on_project.yaml diff --git a/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file.yaml diff --git a/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_canonical.yaml diff --git a/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_named_timed.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_named_timed.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_named_timed.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestTempUrl/test_on_file_named_timed.yaml diff --git a/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_no_match.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_no_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_no_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_no_match.yaml diff --git a/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_share_folder_match.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_share_folder_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_share_folder_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_share_folder_match.yaml diff --git a/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix.yaml diff --git a/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix_suffix.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix_suffix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix_suffix.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_prefix_suffix.yaml diff --git a/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_suffix.yaml b/stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_suffix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_suffix.yaml rename to stor_dx/stor_dx/tests/cassettes_py2/TestWalkFiles/test_pattern_w_suffix.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path_on_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path_on_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path_on_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_canonical_path_on_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_duplicate_projects.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_duplicate_projects.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalProject/test_duplicate_projects.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_duplicate_projects.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_no_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_no_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalProject/test_no_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_no_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_unique_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_unique_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalProject/test_unique_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalProject/test_unique_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_duplicate_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_duplicate_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalResource/test_duplicate_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_duplicate_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_no_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_no_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalResource/test_no_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_no_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalResource/test_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_unique_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_unique_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalResource/test_unique_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_unique_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_virtual_on_virtual.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_virtual_on_virtual.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCanonicalResource/test_virtual_on_virtual.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCanonicalResource/test_virtual_on_virtual.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_clone_move_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_clone_move_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_clone_move_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_clone_move_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_clone_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_clone_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_clone_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_clone_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_canonical_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_canonical_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_canonical_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_canonical_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_dir_to_posix_error.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_dir_to_posix_error.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_dir_to_posix_error.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_dir_to_posix_error.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_diff_project_exist_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_same_project_exist_dest.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_dx_within_project_pass.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_other_obs.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_other_obs.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_other_obs.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_other_obs.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_posix_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_same_dx_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_same_dx_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_same_dx_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_dx_to_same_dx_pass.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_move_diff_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_move_diff_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_move_diff_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_move_diff_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_other_obs_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_other_obs_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_other_obs_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_other_obs_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_file_folder_no_ext.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_dx_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_existing_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_existing_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_existing_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopy/test_posix_to_existing_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_clonetree_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_clonetree_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_clonetree_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_clonetree_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_same_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_dir_w_slash.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_existing_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_dx_root_same_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_posix.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_posix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_posix.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_dir_to_posix.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_file_to_posix.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_file_to_posix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_file_to_posix.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_file_to_posix.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_same_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_dir_w_slash.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_root.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_root.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_root.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_dx_root.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_root_to_existing_dx_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_existing_dx_dest_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_other_obs.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_other_obs.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_other_obs.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_other_obs.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_same_dx_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_same_dx_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_same_dx_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_dx_to_same_dx_pass.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_diff_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_diff_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_move_diff_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_diff_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_root_within_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_root_within_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_move_root_within_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_move_root_within_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_nonexistent_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_nonexistent_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_nonexistent_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_nonexistent_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_other_obs_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_other_obs_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_other_obs_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_other_obs_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_existing.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_existing.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_existing.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_existing.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_nested.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_nested.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_nested.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_dir_to_dx_nested.yaml diff --git a/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_file_to_dx.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_file_to_dx.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_file_to_dx.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestCopyTree/test_posix_file_to_dx.yaml diff --git a/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_absolute_paths.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_absolute_paths.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestDownloadObjects/test_absolute_paths.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_absolute_paths.yaml diff --git a/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_local_paths.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_local_paths.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestDownloadObjects/test_local_paths.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestDownloadObjects/test_local_paths.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_false_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_false_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_false_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_false_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_false_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_false_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_false_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_false_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_project_does_not_exist.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_project_does_not_exist.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_project_does_not_exist.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_project_does_not_exist.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_true_dir_with_object.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_dir_with_object.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_true_dir_with_object.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_dir_with_object.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_true_empty_dir.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_empty_dir.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_true_empty_dir.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_empty_dir.yaml diff --git a/stor_dx/tests/cassettes_py3/TestExists/test_true_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestExists/test_true_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestExists/test_true_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGetSize/test_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGetSize/test_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGetSize/test_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGetSize/test_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGetSize/test_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGetSize/test_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGetSize/test_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_cond_no_met.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_cond_no_met.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_cond_no_met.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_cond_no_met.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_glob_cond_met.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_glob_cond_met.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_glob_cond_met.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_glob_cond_met.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_pattern_no_file_match.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_pattern_no_file_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_pattern_no_file_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_pattern_no_file_match.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_prefix_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_prefix_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_prefix_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_prefix_pattern.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_suffix_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_suffix_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_suffix_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_suffix_pattern.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern.yaml diff --git a/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern_wo_wildcard.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern_wo_wildcard.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern_wo_wildcard.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestGlob/test_valid_pattern_wo_wildcard.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_absent_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_absent_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_absent_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_absent_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_canonical.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_empty_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_empty_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_empty_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_empty_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_fail_w_condition.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_fail_w_condition.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_fail_w_condition.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_fail_w_condition.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_folder_share_filename.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_folder_share_filename.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_folder_share_filename.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_folder_share_filename.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_folder_w_files.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_folder_w_files.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_folder_w_files.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_folder_w_files.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_iter_canon_on_canon.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_iter_canon_on_canon.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_iter_canon_on_canon.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_iter_canon_on_canon.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_iter_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_iter_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_iter_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_iter_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_limit.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_limit.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_limit.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_limit.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_on_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_starts_with.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_starts_with.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_starts_with.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_starts_with.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_w_category.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_w_category.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_w_category.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_w_category.yaml diff --git a/stor_dx/tests/cassettes_py3/TestList/test_list_w_condition.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_w_condition.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestList/test_list_w_condition.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestList/test_list_w_condition.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_absent_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_absent_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_absent_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_absent_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_canonical.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_empty_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_empty_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_empty_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_empty_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_share_filename.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_share_filename.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_share_filename.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_share_filename.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_w_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_w_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_w_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_folder_w_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_canon_on_canon.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_canon_on_canon.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_canon_on_canon.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_canon_on_canon.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_iter_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_on_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestListDir/test_listdir_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestListDir/test_listdir_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestLoginAuth/test_login_auth.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestLoginAuth/test_login_auth.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestLoginAuth/test_login_auth.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestLoginAuth/test_login_auth.yaml diff --git a/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder_exists.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder_exists.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder_exists.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_folder_exists.yaml diff --git a/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_nested_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_nested_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_nested_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_nested_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project_exists.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project_exists.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project_exists.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestMakedirsP/test_makedirs_p_project_exists.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_append_mode_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_append_mode_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_append_mode_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_append_mode_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_read_dir_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_dir_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_read_dir_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_dir_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_read_fail_on_closed_buffer.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_fail_on_closed_buffer.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_read_fail_on_closed_buffer.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_fail_on_closed_buffer.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_buffer.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_buffer.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_buffer.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_buffer.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_dx_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_dx_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_dx_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_read_on_open_dx_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_flush_multiple_upload.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_flush_multiple_upload.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_flush_multiple_upload.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_flush_multiple_upload.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_wo_context_manager.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_wo_context_manager.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_wo_context_manager.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_multiple_wo_context_manager.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_read_over_files.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_read_over_files.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_read_over_files.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_read_over_files.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_to_project_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_to_project_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_to_project_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_to_project_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_big_timeout.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_big_timeout.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_big_timeout.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_big_timeout.yaml diff --git a/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_no_timeout.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_no_timeout.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_no_timeout.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestOpen/test_write_w_settings_no_timeout.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_nonexistent_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_remove_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_fail_rmtree_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_rmtree_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_fail_rmtree_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_fail_rmtree_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_remove_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_remove_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_remove_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_remove_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRemove/test_rmtree_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRename/test_rename_file_pass.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_file_pass.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRename/test_rename_file_pass.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_file_pass.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRename/test_rename_folder_fail.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_folder_fail.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRename/test_rename_folder_fail.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_folder_fail.yaml diff --git a/stor_dx/tests/cassettes_py3/TestRename/test_rename_to_self.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_to_self.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestRename/test_rename_to_self.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestRename/test_rename_to_self.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_resource.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_resource.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_resource.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_canonical_resource.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_project_error.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_project_error.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_project_error.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_project_error.yaml diff --git a/stor_dx/tests/cassettes_py3/TestStat/test_stat_virtual_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_virtual_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestStat/test_stat_virtual_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestStat/test_stat_virtual_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_folder.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_folder.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_folder.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_folder.yaml diff --git a/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_project.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_project.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_project.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_fail_on_project.yaml diff --git a/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file.yaml diff --git a/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_canonical.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_canonical.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_canonical.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_canonical.yaml diff --git a/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_named_timed.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_named_timed.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_named_timed.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestTempUrl/test_on_file_named_timed.yaml diff --git a/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_no_match.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_no_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_no_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_no_match.yaml diff --git a/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_share_folder_match.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_share_folder_match.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_share_folder_match.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_share_folder_match.yaml diff --git a/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix.yaml diff --git a/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix_suffix.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix_suffix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix_suffix.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_prefix_suffix.yaml diff --git a/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_suffix.yaml b/stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_suffix.yaml similarity index 100% rename from stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_suffix.yaml rename to stor_dx/stor_dx/tests/cassettes_py3/TestWalkFiles/test_pattern_w_suffix.yaml diff --git a/stor_dx/stor_dx/tests/file_data/s_3_2126.bcl.gz b/stor_dx/stor_dx/tests/file_data/s_3_2126.bcl.gz new file mode 100644 index 00000000..c98d2ee1 Binary files /dev/null and b/stor_dx/stor_dx/tests/file_data/s_3_2126.bcl.gz differ diff --git a/stor_dx/tests/test_cli_dx.py b/stor_dx/stor_dx/tests/test_cli_dx.py similarity index 97% rename from stor_dx/tests/test_cli_dx.py rename to stor_dx/stor_dx/tests/test_cli_dx.py index bddc6d14..c4c5a90f 100644 --- a/stor_dx/tests/test_cli_dx.py +++ b/stor_dx/stor_dx/tests/test_cli_dx.py @@ -5,8 +5,8 @@ import six -from stor_dx.dx import DXPath from stor import cli +from stor_dx import DXPath from stor_dx import test diff --git a/stor_dx/tests/test_dx.py b/stor_dx/stor_dx/tests/test_dx.py similarity index 99% rename from stor_dx/tests/test_dx.py rename to stor_dx/stor_dx/tests/test_dx.py index 895c1814..4272e826 100644 --- a/stor_dx/tests/test_dx.py +++ b/stor_dx/stor_dx/tests/test_dx.py @@ -11,11 +11,23 @@ from stor import exceptions from stor import Path from stor.tests.shared_obs import SharedOBSFileCases +from stor_dx import DXPath from stor_dx import utils -from stor_dx.dx import DXPath from stor_dx.test import DXTestCase import stor import stor_dx.dx as dx +import stor_dx + + +class TestInit(unittest.TestCase): + def test_dx_init(self): + cls, path = stor_dx.class_for_path('dx', 'dx://temp:') + self.assertEqual(cls, dx.DXVirtualPath) + self.assertEqual(path, 'dx://temp:') + + def test_other_obs_init(self): + with pytest.raises(ValueError, match='Invalid prefix'): + stor_dx.class_for_path('swift', 'swift://tenant/container') class TestBasicPathMethods(unittest.TestCase): diff --git a/stor_dx/tests/test_dx_path_compat.py b/stor_dx/stor_dx/tests/test_dx_path_compat.py similarity index 100% rename from stor_dx/tests/test_dx_path_compat.py rename to stor_dx/stor_dx/tests/test_dx_path_compat.py diff --git a/stor_dx/tests/test_integration_dx.py b/stor_dx/stor_dx/tests/test_integration_dx.py similarity index 99% rename from stor_dx/tests/test_integration_dx.py rename to stor_dx/stor_dx/tests/test_integration_dx.py index 593c0d2f..6b704b25 100644 --- a/stor_dx/tests/test_integration_dx.py +++ b/stor_dx/stor_dx/tests/test_integration_dx.py @@ -11,7 +11,7 @@ from stor import Path from stor.tests.shared import assert_same_data from stor.tests.test_integration import BaseIntegrationTest -from stor_dx.dx import DXPath +from stor_dx import DXPath from stor_dx.test import DXTestCase import stor import stor.tests.test_integration as test_integration diff --git a/stor_dx/utils.py b/stor_dx/stor_dx/utils.py similarity index 98% rename from stor_dx/utils.py rename to stor_dx/stor_dx/utils.py index f3178ada..cba9e22a 100644 --- a/stor_dx/utils.py +++ b/stor_dx/stor_dx/utils.py @@ -13,7 +13,7 @@ def is_dx_path(p): Returns bool: True if p is a DX path, False otherwise. """ - from stor_dx.dx import DXPath + from stor_dx import DXPath return p.startswith(DXPath.drive) diff --git a/stor_s3/requirements.txt b/stor_s3/requirements.txt new file mode 100644 index 00000000..6679508f --- /dev/null +++ b/stor_s3/requirements.txt @@ -0,0 +1 @@ +boto3>=1.4.0 diff --git a/stor_s3/setup.cfg b/stor_s3/setup.cfg new file mode 100644 index 00000000..686d7fa3 --- /dev/null +++ b/stor_s3/setup.cfg @@ -0,0 +1,52 @@ +[metadata] +name = stor_s3 +author = Counsyl Inc. +author-email = opensource@counsyl.com +summary = Add-on package to stor for accessing S3 storage systems +home-page = https://github.com/counsyl/stor +requires-python = >=2.7 +license = MIT +classifier = + Topic :: Internet :: WWW/HTTP :: Dynamic Content + Intended Audience :: Developers + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Development Status :: 5 - Production/Stable + Operating System :: OS Independent + +[coverage:run] +branch = True +source = stor_s3, ../stor/stor +omit = stor_s3/tests/test_integration_s3.py + +[coverage:report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + raise NotImplementedError +fail_under = 100 +show_missing = 1 + +[files] +packages = stor_s3 + +[entry_points] +stor.providers = + s3 = stor_s3:class_for_path + +[flake8] +max-complexity=10 +max-line-length=99 +exclude = stor_s3/__init__.py + +[pbr] +skip_authors = true +skip_changelog = true + +[bdist_wheel] +universal = 1 diff --git a/stor_s3/setup.py b/stor_s3/setup.py new file mode 100644 index 00000000..e74f898b --- /dev/null +++ b/stor_s3/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup( + pbr=True, + setup_requires=['pbr'], +) diff --git a/stor_s3/stor_s3/__init__.py b/stor_s3/stor_s3/__init__.py new file mode 100644 index 00000000..fb041981 --- /dev/null +++ b/stor_s3/stor_s3/__init__.py @@ -0,0 +1,12 @@ +from stor_s3.utils import is_s3_path +from stor_s3.s3 import S3Path + + +drive = S3Path.drive + + +def class_for_path(prefix, path): + if prefix+'://' != drive: + raise ValueError('Invalid prefix to initialize S3Paths: {}'.format(prefix)) + cls = S3Path + return cls, path diff --git a/stor_s3/s3.py b/stor_s3/stor_s3/s3.py similarity index 99% rename from stor_s3/s3.py rename to stor_s3/stor_s3/s3.py index 1c872a15..7b2edda8 100644 --- a/stor_s3/s3.py +++ b/stor_s3/stor_s3/s3.py @@ -648,7 +648,8 @@ def _upload_object(self, upload_obj, config=None): def _copy_upload(self, source, **kwargs): """Wrapper function on upload for transformations when copying. - Due to the legacy nature of upload being used in write_object/copy/copytree, + + Due to the legacy nature of upload being used in write_object/copy/copytree, we cannot call upload directly from stor.copy, we need to perform checks here. """ if self.is_ambiguous(): @@ -658,7 +659,8 @@ def _copy_upload(self, source, **kwargs): def _copytree_upload(self, source, **kwargs): """Wrapper function on upload for transformations when copying. - Due to the legacy nature of upload being used in write_object/copy/copytree, + + Due to the legacy nature of upload being used in write_object/copy/copytree, we cannot call upload directly from stor.copytree, we need to perform checks here. """ with source: diff --git a/stor_s3/test.py b/stor_s3/stor_s3/test.py similarity index 99% rename from stor_s3/test.py rename to stor_s3/stor_s3/test.py index 0c6546bb..68ab2dd6 100644 --- a/stor_s3/test.py +++ b/stor_s3/stor_s3/test.py @@ -2,7 +2,7 @@ import unittest from stor_s3 import s3 -from stor_s3.s3 import S3Path +from stor_s3 import S3Path class S3TestMixin(object): diff --git a/stor_dx/tests/__init__.py b/stor_s3/stor_s3/tests/__init__.py similarity index 100% rename from stor_dx/tests/__init__.py rename to stor_s3/stor_s3/tests/__init__.py diff --git a/stor_s3/tests/test_cli_s3.py b/stor_s3/stor_s3/tests/test_cli_s3.py similarity index 99% rename from stor_s3/tests/test_cli_s3.py rename to stor_s3/stor_s3/tests/test_cli_s3.py index b0c6bb95..75310688 100644 --- a/stor_s3/tests/test_cli_s3.py +++ b/stor_s3/stor_s3/tests/test_cli_s3.py @@ -10,8 +10,8 @@ from stor import cli from stor import exceptions +from stor_s3 import S3Path from stor_s3 import test -from stor_s3.s3 import S3Path class BaseCliTest(test.S3TestCase): @@ -340,4 +340,4 @@ def test_pwd_swift(self): def test_pwd_error(self): with self.assertOutputMatches(exit_status=1, stderr='invalid service'): - self.parse_args('stor pwd service') \ No newline at end of file + self.parse_args('stor pwd service') diff --git a/stor_s3/tests/test_integration_s3.py b/stor_s3/stor_s3/tests/test_integration_s3.py similarity index 100% rename from stor_s3/tests/test_integration_s3.py rename to stor_s3/stor_s3/tests/test_integration_s3.py diff --git a/stor_s3/tests/test_posix_s3.py b/stor_s3/stor_s3/tests/test_posix_s3.py similarity index 100% rename from stor_s3/tests/test_posix_s3.py rename to stor_s3/stor_s3/tests/test_posix_s3.py diff --git a/stor_s3/tests/test_s3.py b/stor_s3/stor_s3/tests/test_s3.py similarity index 99% rename from stor_s3/tests/test_s3.py rename to stor_s3/stor_s3/tests/test_s3.py index 24c98d0a..0e39231f 100644 --- a/stor_s3/tests/test_s3.py +++ b/stor_s3/stor_s3/tests/test_s3.py @@ -18,9 +18,21 @@ from stor.obs import OBSUploadObject from stor.tests.shared_obs import SharedOBSFileCases from stor_s3 import s3 -from stor_s3.s3 import S3Path +from stor_s3 import S3Path from stor_s3.test import S3TestCase import stor +import stor_s3 + + +class TestInit(unittest.TestCase): + def test_s3_init(self): + cls, path = stor_s3.class_for_path('s3', 's3://random/path') + self.assertEqual(cls, S3Path) + self.assertEqual(path, 's3://random/path') + + def test_other_obs_init(self): + with self.assertRaisesRegexp(ValueError, 'Invalid prefix'): + stor_s3.class_for_path('dx', 'dx://tenant:/container') class TestBasicPathMethods(unittest.TestCase): diff --git a/stor_s3/tests/test_s3_path_compat.py b/stor_s3/stor_s3/tests/test_s3_path_compat.py similarity index 98% rename from stor_s3/tests/test_s3_path_compat.py rename to stor_s3/stor_s3/tests/test_s3_path_compat.py index ad6eda1a..25b4fe97 100644 --- a/stor_s3/tests/test_s3_path_compat.py +++ b/stor_s3/stor_s3/tests/test_s3_path_compat.py @@ -1,6 +1,6 @@ import unittest -from stor_s3.s3 import S3Path +from stor_s3 import S3Path class TestBasics(unittest.TestCase): diff --git a/stor_s3/tests/test_utils_s3.py b/stor_s3/stor_s3/tests/test_utils_s3.py similarity index 89% rename from stor_s3/tests/test_utils_s3.py rename to stor_s3/stor_s3/tests/test_utils_s3.py index 30877418..669fd5c1 100644 --- a/stor_s3/tests/test_utils_s3.py +++ b/stor_s3/stor_s3/tests/test_utils_s3.py @@ -2,9 +2,9 @@ import unittest from stor import Path -from stor_s3 import utils -from stor_s3.s3 import S3Path +from stor_s3 import S3Path import stor +import stor_s3 class TestPath(unittest.TestCase): @@ -15,10 +15,10 @@ def test_s3_returned(self): class TestIsS3Path(unittest.TestCase): def test_true(self): - self.assertTrue(utils.is_s3_path('s3://my/s3/path')) + self.assertTrue(stor_s3.is_s3_path('s3://my/s3/path')) def test_false(self): - self.assertFalse(utils.is_s3_path('my/posix/path')) + self.assertFalse(stor_s3.is_s3_path('my/posix/path')) class TestIsWriteableS3(unittest.TestCase): diff --git a/stor_s3/tests/test_windows_s3.py b/stor_s3/stor_s3/tests/test_windows_s3.py similarity index 100% rename from stor_s3/tests/test_windows_s3.py rename to stor_s3/stor_s3/tests/test_windows_s3.py diff --git a/stor_s3/utils.py b/stor_s3/stor_s3/utils.py similarity index 75% rename from stor_s3/utils.py rename to stor_s3/stor_s3/utils.py index 88ea7598..ccf22192 100644 --- a/stor_s3/utils.py +++ b/stor_s3/stor_s3/utils.py @@ -1,8 +1,3 @@ -import tempfile - -import stor.utils as stor_utils - - def is_s3_path(p): """Determines if the path is a S3 path. @@ -14,5 +9,5 @@ def is_s3_path(p): Returns bool: True if p is a S3 path, False otherwise. """ - from stor_s3.s3 import S3Path + from stor_s3 import S3Path return p.startswith(S3Path.drive) diff --git a/stor_s3/tests/__init__.py b/stor_s3/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/stor_swift/__init__.py b/stor_swift/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/stor_swift/requirements.txt b/stor_swift/requirements.txt new file mode 100644 index 00000000..9d44a4e6 --- /dev/null +++ b/stor_swift/requirements.txt @@ -0,0 +1 @@ +python-keystoneclient>=1.8.1 \ No newline at end of file diff --git a/stor_swift/setup.cfg b/stor_swift/setup.cfg new file mode 100644 index 00000000..8d2a7fa7 --- /dev/null +++ b/stor_swift/setup.cfg @@ -0,0 +1,52 @@ +[metadata] +name = stor_swift +author = Counsyl Inc. +author-email = opensource@counsyl.com +summary = Add-on package to stor for accessing Swift storage systems +home-page = https://github.com/counsyl/stor +requires-python = >=2.7 +license = MIT +classifier = + Topic :: Internet :: WWW/HTTP :: Dynamic Content + Intended Audience :: Developers + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.4 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Development Status :: 5 - Production/Stable + Operating System :: OS Independent + +[coverage:run] +branch = True +source = stor_swift, ../stor/stor +omit = stor_swift/tests/test_integration_swift.py + +[coverage:report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + raise NotImplementedError +fail_under = 100 +show_missing = 1 + +[files] +packages = stor_swift + +[entry_points] +stor.providers = + swift = stor_swift:class_for_path + +[flake8] +max-complexity=10 +max-line-length=99 +exclude = stor_swift/__init__.py + +[pbr] +skip_authors = true +skip_changelog = true + +[bdist_wheel] +universal = 1 diff --git a/stor_swift/setup.py b/stor_swift/setup.py new file mode 100644 index 00000000..e74f898b --- /dev/null +++ b/stor_swift/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup + +setup( + pbr=True, + setup_requires=['pbr'], +) diff --git a/stor_swift/stor_swift/__init__.py b/stor_swift/stor_swift/__init__.py new file mode 100644 index 00000000..7f3446d8 --- /dev/null +++ b/stor_swift/stor_swift/__init__.py @@ -0,0 +1,13 @@ +from stor_swift.utils import is_swift_path +from stor_swift.swift import SwiftPath + + + +drive = SwiftPath.drive + + +def class_for_path(prefix, path): + if prefix+'://' != drive: + raise ValueError('Invalid prefix to initialize SwiftPaths: {}'.format(prefix)) + cls = SwiftPath + return cls, path diff --git a/stor_swift/swift.py b/stor_swift/stor_swift/swift.py similarity index 99% rename from stor_swift/swift.py rename to stor_swift/stor_swift/swift.py index 0bcee451..558bed7d 100644 --- a/stor_swift/swift.py +++ b/stor_swift/stor_swift/swift.py @@ -57,7 +57,7 @@ from stor.obs import OBSUploadObject from stor.posix import PosixPath from stor.third_party.backoff import with_backoff -from stor_swift.utils import is_swift_path +from stor_swift import is_swift_path logger = logging.getLogger(__name__) @@ -1018,7 +1018,8 @@ def download(self, def _copy_upload(self, source, **kwargs): """Wrapper function on upload for transformations when copying. - Due to the legacy nature of upload being used in write_object/copy/copytree, + + Due to the legacy nature of upload being used in write_object/copy/copytree, we cannot call upload directly from stor.copy, we need to perform checks here. """ if self.is_ambiguous(): @@ -1034,7 +1035,8 @@ def _copy_upload(self, source, **kwargs): def _copytree_upload(self, source, **kwargs): """Wrapper function on upload for transformations when copying. - Due to the legacy nature of upload being used in write_object/copy/copytree, + + Due to the legacy nature of upload being used in write_object/copy/copytree, we cannot call upload directly from stor.copytree, we need to perform checks here. """ with source: diff --git a/stor_swift/test.py b/stor_swift/stor_swift/test.py similarity index 99% rename from stor_swift/test.py rename to stor_swift/stor_swift/test.py index 51a5886d..14c44515 100644 --- a/stor_swift/test.py +++ b/stor_swift/stor_swift/test.py @@ -2,7 +2,7 @@ import unittest from stor import settings -from stor_swift.swift import SwiftPath +from stor_swift import SwiftPath class SwiftTestMixin(object): diff --git a/stor_s3/__init__.py b/stor_swift/stor_swift/tests/__init__.py similarity index 100% rename from stor_s3/__init__.py rename to stor_swift/stor_swift/tests/__init__.py diff --git a/stor_swift/tests/test_cli_swift.py b/stor_swift/stor_swift/tests/test_cli_swift.py similarity index 99% rename from stor_swift/tests/test_cli_swift.py rename to stor_swift/stor_swift/tests/test_cli_swift.py index ac595683..7f69b0a3 100644 --- a/stor_swift/tests/test_cli_swift.py +++ b/stor_swift/stor_swift/tests/test_cli_swift.py @@ -9,7 +9,7 @@ import six from stor import cli -from stor_swift.swift import SwiftPath +from stor_swift import SwiftPath from stor_swift import test diff --git a/stor_swift/tests/test_integration_swift.py b/stor_swift/stor_swift/tests/test_integration_swift.py similarity index 100% rename from stor_swift/tests/test_integration_swift.py rename to stor_swift/stor_swift/tests/test_integration_swift.py diff --git a/stor_swift/tests/test_posix_swift.py b/stor_swift/stor_swift/tests/test_posix_swift.py similarity index 100% rename from stor_swift/tests/test_posix_swift.py rename to stor_swift/stor_swift/tests/test_posix_swift.py diff --git a/stor_swift/tests/test_swift.py b/stor_swift/stor_swift/tests/test_swift.py similarity index 99% rename from stor_swift/tests/test_swift.py rename to stor_swift/stor_swift/tests/test_swift.py index 3bdf4ae8..233ae424 100644 --- a/stor_swift/tests/test_swift.py +++ b/stor_swift/stor_swift/tests/test_swift.py @@ -18,9 +18,10 @@ from stor import utils from stor.tests.shared_obs import SharedOBSFileCases from stor_swift import swift -from stor_swift.swift import SwiftPath +from stor_swift import SwiftPath from stor_swift.test import SwiftTestCase import stor +import stor_swift def _service_404_exception(): @@ -45,6 +46,17 @@ def _make_stat_response(stat_response=None): return [defaults] +class TestInit(unittest.TestCase): + def test_swift_init(self): + cls, path = stor_swift.class_for_path('swift', 'swift://tenant/') + self.assertEqual(cls, SwiftPath) + self.assertEqual(path, 'swift://tenant/') + + def test_other_obs_init(self): + with self.assertRaisesRegexp(ValueError, 'Invalid prefix'): + stor_swift.class_for_path('dx', 'swift://tenant/container') + + class TestPatchedGetAuthKeystone(unittest.TestCase): @mock.patch('stor_swift.swift.real_get_auth_keystone', autospec=True) def test_patched_get_auth_keystone(self, mock_get_real_auth_keystone): diff --git a/stor_swift/tests/test_swift_path_compat.py b/stor_swift/stor_swift/tests/test_swift_path_compat.py similarity index 97% rename from stor_swift/tests/test_swift_path_compat.py rename to stor_swift/stor_swift/tests/test_swift_path_compat.py index 546de56b..34afb009 100644 --- a/stor_swift/tests/test_swift_path_compat.py +++ b/stor_swift/stor_swift/tests/test_swift_path_compat.py @@ -1,6 +1,6 @@ import unittest -from stor_swift.swift import SwiftPath +from stor_swift import SwiftPath class TestBasics(unittest.TestCase): diff --git a/stor_swift/tests/test_utils_swift.py b/stor_swift/stor_swift/tests/test_utils_swift.py similarity index 95% rename from stor_swift/tests/test_utils_swift.py rename to stor_swift/stor_swift/tests/test_utils_swift.py index 9110c995..08777d17 100644 --- a/stor_swift/tests/test_utils_swift.py +++ b/stor_swift/stor_swift/tests/test_utils_swift.py @@ -3,8 +3,7 @@ from stor import Path from stor import utils as stor_utils -from stor_swift import utils -from stor_swift.swift import SwiftPath +from stor_swift import SwiftPath import stor_swift @@ -16,10 +15,10 @@ def test_swift_returned(self): class TestIsSwiftPath(unittest.TestCase): def test_true(self): - self.assertTrue(utils.is_swift_path('swift://my/swift/path')) + self.assertTrue(stor_swift.is_swift_path('swift://my/swift/path')) def test_false(self): - self.assertFalse(utils.is_swift_path('my/posix/path')) + self.assertFalse(stor_swift.is_swift_path('my/posix/path')) class TestIsWriteableSwift(unittest.TestCase): diff --git a/stor_swift/tests/test_windows_swift.py b/stor_swift/stor_swift/tests/test_windows_swift.py similarity index 100% rename from stor_swift/tests/test_windows_swift.py rename to stor_swift/stor_swift/tests/test_windows_swift.py diff --git a/stor_swift/utils.py b/stor_swift/stor_swift/utils.py similarity index 69% rename from stor_swift/utils.py rename to stor_swift/stor_swift/utils.py index b293d81b..72c2122b 100644 --- a/stor_swift/utils.py +++ b/stor_swift/stor_swift/utils.py @@ -1,9 +1,3 @@ -import tempfile - -from stor import exceptions -import stor.utils as stor_utils - - def is_swift_path(p): """Determines if the path is a Swift path. @@ -15,5 +9,5 @@ def is_swift_path(p): Returns: bool: True if p is a Swift path, False otherwise. """ - from stor_swift.swift import SwiftPath + from stor_swift import SwiftPath return p.startswith(SwiftPath.drive) diff --git a/stor_swift/tests/__init__.py b/stor_swift/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tox.ini b/tox.ini index 3f9bd6f6..107b72c1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,4 +1,5 @@ [tox] +skipsdist=True install_command = pip install {opts} {packages} indexserver = default = https://pypi.python.org/simple/ @@ -10,10 +11,12 @@ setenv = XUNIT_FILE=nosetests-{envname}.xml commands = rm -f .coverage - py.test -v -rsx --cov=stor --cov=stor_swift --cov=stor_dx \ - --cov=stor_s3 {posargs: stor/tests} {posargs: stor_dx/tests} {posargs: stor_swift/tests} {posargs: stor_s3/tests} + ./run_all.sh 'pip install -e .' stor/ stor_dx/ stor_swift/ stor_s3/ + py.test -v -rsx --cov-config .coveragerc --cov=stor/stor --cov=stor_swift/stor_swift --cov=stor_dx/stor_dx \ + --cov=stor_s3/stor_s3 {posargs: stor/stor/tests} {posargs: stor_dx/stor_dx/tests} {posargs: stor_swift/stor_swift/tests} {posargs: stor_s3/stor_s3/tests} + deps = - -r{toxinidir}/requirements-dev.txt + -r{toxinidir}/stor/requirements-dev.txt whitelist_externals = make bash nosetests