Esempio n. 1
0
        def inner(auth,
                  cache,
                  update,
                  version_check,
                  hasher,
                  read_path,
                  write_path=None,
                  cache_on_write=False,
                  *args,
                  **kwargs):

            with data_file.get_local_path(auth, cache, update, version_check,
                                          hasher, read_path, write_path,
                                          cache_on_write) as fp:

                assert isinstance(fp, string_types)

                with open(fp, *args, **kwargs) as f:
                    yield f
Esempio n. 2
0
    def get_local_path(
            self,
            version=None,
            bumpversion=None,
            prerelease=None,
            dependencies=None,
            metadata=None):
        '''
        Returns a local path for read/write

        Parameters
        ----------
        version : str
            Version number of the file to retrieve (default latest)

        bumpversion : str
            Version component to update on write if archive is versioned. Valid
            bumpversion values are 'major', 'minor', and 'patch', representing
            the three components of the strict version numbering system (e.g.
            "1.2.3"). If bumpversion is None the version number is not updated
            on write. Either bumpversion or prerelease (or both) must be a
            non-None value. If the archive is not versioned, bumpversion is
            ignored.

        prerelease : str
            Prerelease component of archive version to update on write if
            archive is versioned. Valid prerelease values are 'alpha' and
            'beta'. Either bumpversion or prerelease (or both) must be a
            non-None value. If the archive is not versioned, prerelease is
            ignored.

        metadata : dict
            Updates to archive metadata. Pass {key: None} to remove a key from
            the archive's metadata.

        '''

        if metadata is None:
            metadata = {}

        latest_version = self.get_latest_version()
        version = _process_version(self, version)

        version_hash = self.get_version_hash(version)

        if self.versioned:

            if latest_version is None:
                latest_version = BumpableVersion()

            next_version = latest_version.bump(
                kind=bumpversion,
                prerelease=prerelease,
                inplace=False)

            msg = "Version must be bumped on write. " \
                "Provide bumpversion and/or prerelease."

            assert next_version > latest_version, msg

            read_path = self.get_version_path(version)
            write_path = self.get_version_path(next_version)

        else:
            read_path = self.archive_path
            write_path = self.archive_path
            next_version = None

        # version_check returns true if fp's hash is current as of read
        def version_check(chk):
            return chk['checksum'] == version_hash

        # Updater updates the manager with the latest version number
        def updater(checksum, algorithm):
            self._update_manager(
                archive_metadata=metadata,
                version_metadata=dict(
                    version=next_version,
                    dependencies=dependencies,
                    checksum=checksum,
                    algorithm=algorithm))
        path = data_file.get_local_path(
            self.authority,
            self.api.cache,
            updater,
            version_check,
            self.api.hash_file,
            read_path,
            write_path)

        with path as fp:
            yield fp
Esempio n. 3
0
def test_delete_handling(local_auth, cache):

    a1 = DataService(local_auth)
    csh = DataService(cache)

    # "touch" the csh file
    csh.fs.makedir(fs.path.dirname(p), recursive=True, allow_recreate=True)
    with open(csh.fs.getsyspath(p), 'w+') as f:
        f.write('')

    with data_file.get_local_path(a1, csh, updater, get_checker(a1, p), hasher,
                                  p) as fp:

        with open(fp, 'w+') as f:
            f.write(u('test data 1'))

    assert a1.fs.isfile(p)

    # We expect authority to contain the new data
    with open(a1.fs.getsyspath(p), 'r') as f:
        assert u('test data 1') == f.read()

    # We expect csh to contain the new data
    with open(csh.fs.getsyspath(p), 'r') as f:
        assert u('test data 1') == f.read()

    # Test error handling of file deletion within a
    # get_local_path context manager

    with pytest.raises(OSError) as excinfo:

        with data_file.get_local_path(a1, csh, updater, get_checker(a1, p),
                                      hasher, p) as fp:

            with open(fp, 'r') as f:
                assert u('test data 1') == f.read()

            with open(fp, 'w+') as f:
                f.write(u('test data 2'))

            with open(fp, 'r') as f:
                assert u('test data 2') == f.read()

            os.remove(fp)

    assert "removed during execution" in str(excinfo.value)

    # We expect authority to be unchanged
    with open(a1.fs.getsyspath(p), 'r') as f:
        assert u('test data 1') == f.read()

    # Unexpected things may have happened to the csh. But we expect it to be
    # back to normal after another read:
    with data_file.open_file(a1,
                             csh,
                             updater,
                             get_checker(a1, p),
                             hasher,
                             p,
                             mode='r') as f:

        assert u('test data 1') == f.read()

    with open(a1.fs.getsyspath(p), 'r') as f:
        assert u('test data 1') == f.read()

    with open(csh.fs.getsyspath(p), 'r') as f:
        assert u('test data 1') == f.read()