Esempio n. 1
0
def check_compress_file(ext, annex, path=None, name=None):
    # we base the archive name on the filename, in order to also
    # be able to properly test compressors where the corresponding
    # archive format has no capability of storing a filename
    # (i.e. where the archive name itself determines the filename
    # of the decompressed file, like .xz)
    archive = op.join(name, _filename + ext)
    compress_files([_filename], archive, path=path)
    assert_true(op.exists(archive))
    if annex:
        # It should work even when file is annexed and is a symlink to the
        # key
        from datalad.support.annexrepo import AnnexRepo
        repo = AnnexRepo(path, init=True)
        repo.add(_filename)
        repo.commit(files=[_filename], msg="commit")

    dir_extracted = name + "_extracted"
    try:
        decompress_file(archive, dir_extracted)
    except MissingExternalDependency as exc:
        raise SkipTest() from exc
    _filepath = op.join(dir_extracted, _filename)

    ok_file_has_content(_filepath, 'content')
Esempio n. 2
0
def test_timeout_nothing():
    # Expect timeout protocol calls for the process on long running processes,
    # if the specified timeout is short enough.
    class TestProtocol(NoCapture):
        def __init__(self,
                     timeout_queue: List):
            NoCapture.__init__(self)
            self.timeout_queue = timeout_queue
            self.counter = count()

        def timeout(self, fd: Optional[int]) -> bool:
            self.timeout_queue.append(fd)
            return False

    stdin_queue = queue.Queue()
    for i in range(12):
        stdin_queue.put(b"\x00" * 1024)
    stdin_queue.put(None)

    timeout_queue = []
    run_command(
        py2cmd("import time; time.sleep(.4)\n"),
        stdin=stdin_queue,
        protocol=TestProtocol,
        timeout=.1,
        protocol_kwargs=dict(timeout_queue=timeout_queue)
    )
    # Ensure that we have only process timeouts and at least one
    assert_true(all(map(lambda e: e is None, timeout_queue)))
    assert_true(len(timeout_queue) > 0)
Esempio n. 3
0
def test_exit_4():
    rt = ThreadedRunner(cmd=["sleep", "4"],
                        stdin=None,
                        protocol_class=GenNothing,
                        timeout=.5)
    tuple(rt.run())
    assert_true(rt.process.poll() is not None)
Esempio n. 4
0
def test_timeout_process():
    # Expect timeouts on stdin, stdout, stderr, and the process
    class TestProtocol(StdOutErrCapture):
        def __init__(self,
                     timeout_queue: List):
            StdOutErrCapture.__init__(self)
            self.timeout_queue = timeout_queue
            self.counter = count()

        def timeout(self, fd: Optional[int]) -> bool:
            self.timeout_queue.append((self.counter.__next__(), fd))
            return False

    stdin_queue = queue.Queue()
    for i in range(12):
        stdin_queue.put(b"\x00" * 1024)
    stdin_queue.put(None)

    timeout_queue = []
    run_command(
        py2cmd("import time;time.sleep(.5)\n"),
        stdin=stdin_queue,
        protocol=TestProtocol,
        timeout=.1,
        protocol_kwargs=dict(timeout_queue=timeout_queue)
    )

    # Expect at least one timeout for stdout and stderr.
    # there might be more.
    sources = (1, 2)
    assert_true(len(timeout_queue) >= len(sources))
    for source in sources:
        assert_true(any(filter(lambda t: t[1] == source, timeout_queue)))
Esempio n. 5
0
    def test_path_and_url(path, url):
        def _urlopen(url, auth=None):
            req = Request(url)
            if auth:
                req.add_header(
                    "Authorization", b"Basic " + base64.standard_b64encode(
                        '{0}:{1}'.format(*auth).encode('utf-8')))
            return urlopen(req)

        # @serve_ should remove http_proxy from the os.environ if was present
        if not on_windows:
            assert_false('http_proxy' in os.environ)
        # get the "dir-view"
        dirurl = url + test_fpath.parent.as_posix()
        u = _urlopen(dirurl, auth)
        assert_true(u.getcode() == 200)
        html = u.read()
        # get the actual content
        file_html = _urlopen(url + url_quote(test_fpath.as_posix()),
                             auth).read().decode()
        # verify we got the right one
        eq_(file_html, test_fpath_full.read_text())

        if bs4 is None:
            return

        # MIH is not sure what this part below is supposed to do
        # possibly some kind of internal consistency test
        soup = bs4.BeautifulSoup(html, "html.parser")
        href_links = [txt.get('href') for txt in soup.find_all('a')]
        assert_true(len(href_links) == 1)
        parsed_url = f"{dirurl}/{href_links[0]}"
        u = _urlopen(parsed_url, auth)
        html = u.read().decode()
        eq_(html, file_html)
 def decorated_test1(url):
     # we expect a file-scheme url to a cached version of `ds_url`
     expect_origin_path = cache_dir / name_in_cache
     assert_equal(expect_origin_path.as_uri(), url)
     origin = Dataset(expect_origin_path)
     assert_true(origin.is_installed())
     assert_false(origin.repo.file_has_content(str(annexed_file)))
Esempio n. 7
0
def test_ExtractedArchive(path=None):
    archive = op.join(path, fn_archive_obscure_ext)
    earchive = ExtractedArchive(archive)
    assert_false(op.exists(earchive.path))
    # no longer the case -- just using hash for now
    # assert_in(os.path.basename(archive), earchive.path)

    fpath = op.join(
        fn_archive_obscure,  # lead directory
        fn_in_archive_obscure)
    extracted = earchive.get_extracted_filename(fpath)
    eq_(extracted, op.join(earchive.path, fpath))
    assert_false(op.exists(extracted))  # not yet

    extracted_ = earchive.get_extracted_file(fpath)
    eq_(extracted, extracted_)
    assert_true(op.exists(extracted))  # now it should

    extracted_files = earchive.get_extracted_files()
    ok_generator(extracted_files)
    eq_(
        sorted(extracted_files),
        sorted([
            # ['bbc/3.txt', 'bbc/abc']
            op.join(fn_archive_obscure, fn_in_archive_obscure),
            op.join(fn_archive_obscure, '3.txt')
        ]))

    earchive.clean()
    if not dl_cfg.get('datalad.tests.temp.keep'):
        assert_false(op.exists(earchive.path))
Esempio n. 8
0
def test_ignore_nondatasets(path=None):
    # we want to ignore the version/commits for this test
    def _kill_time(meta):
        for m in meta:
            for k in ('version', 'shasum'):
                if k in m:
                    del m[k]
        return meta

    ds = Dataset(path).create()
    meta = _kill_time(ds.metadata(reporton='datasets', on_failure='ignore'))
    n_subm = 0
    # placing another repo in the dataset has no effect on metadata
    for cls, subpath in ((GitRepo, 'subm'), (AnnexRepo, 'annex_subm')):
        subm_path = opj(ds.path, subpath)
        r = cls(subm_path, create=True)
        with open(opj(subm_path, 'test'), 'w') as f:
            f.write('test')
        r.add('test')
        r.commit('some')
        assert_true(Dataset(subm_path).is_installed())
        assert_equal(meta, _kill_time(ds.metadata(reporton='datasets', on_failure='ignore')))
        # making it a submodule has no effect either
        ds.save(subpath)
        assert_equal(len(ds.subdatasets()), n_subm + 1)
        assert_equal(meta, _kill_time(ds.metadata(reporton='datasets', on_failure='ignore')))
        n_subm += 1
Esempio n. 9
0
def test_configs(path=None):

    # set up dataset with registered procedure (c&p from test_basics):
    ds = Dataset(path).create(force=True)
    ds.run_procedure('cfg_yoda')
    # configure dataset to look for procedures in its code folder
    ds.config.add('datalad.locations.dataset-procedures',
                  'code',
                  scope='branch')

    # 1. run procedure based on execution guessing by run_procedure:
    ds.run_procedure(spec=['datalad_test_proc', 'some_arg'])
    # look for traces
    ok_file_has_content(op.join(ds.path, 'fromproc.txt'), 'some_arg\n')

    # 2. now configure specific call format including usage of substitution config
    # for run:
    ds.config.add('datalad.procedures.datalad_test_proc.call-format',
                  u'%s {script} {ds} {{mysub}} {args}' %
                  quote_cmdlinearg(sys.executable),
                  scope='branch')
    ds.config.add('datalad.run.substitutions.mysub',
                  'dataset-call-config',
                  scope='branch')
    # TODO: Should we allow for --inputs/--outputs arguments for run_procedure
    #       (to be passed into run)?
    ds.unlock("fromproc.txt")
    # run again:
    ds.run_procedure(spec=['datalad_test_proc', 'some_arg'])
    # look for traces
    ok_file_has_content(op.join(ds.path, 'fromproc.txt'),
                        'dataset-call-config\n')

    # 3. have a conflicting config at user-level, which should override the
    # config on dataset level:
    ds.config.add('datalad.procedures.datalad_test_proc.call-format',
                  u'%s {script} {ds} local {args}' %
                  quote_cmdlinearg(sys.executable),
                  scope='local')
    ds.unlock("fromproc.txt")
    # run again:
    ds.run_procedure(spec=['datalad_test_proc', 'some_arg'])
    # look for traces
    ok_file_has_content(op.join(ds.path, 'fromproc.txt'), 'local\n')

    # 4. get configured help message:
    r = ds.run_procedure('datalad_test_proc',
                         help_proc=True,
                         on_failure='ignore')
    assert_true(len(r) == 1)
    assert_in_results(r, status="impossible")

    ds.config.add('datalad.procedures.datalad_test_proc.help',
                  "This is a help message",
                  scope='branch')

    r = ds.run_procedure('datalad_test_proc', help_proc=True)
    assert_true(len(r) == 1)
    assert_in_results(r, message="This is a help message", status='ok')
Esempio n. 10
0
def test_noannex_fail_if_has_annexed(path=None):
    ds = Dataset(path).create(force=True)
    ds.save()
    assert_true(isinstance(ds.repo, AnnexRepo))
    # internally procedure raises RuntimeError, but since we run it via runner, we
    # get CommandError here
    with assert_raises(CommandError):
        ds.run_procedure('cfg_noannex')  # we are killing annex while ds.repo
Esempio n. 11
0
def test_exit_3():
    # Expect the process to be closed after
    # the generator exits.
    rt = ThreadedRunner(cmd=["sleep", "4"],
                        stdin=None,
                        protocol_class=GenStdoutStderr,
                        timeout=.5,
                        exception_on_error=False)
    tuple(rt.run())
    assert_true(rt.process.poll() is not None)
Esempio n. 12
0
def test_external_versions_popular_packages():
    ev = ExternalVersions()

    for modname in ('scipy', 'numpy', 'mvpa2', 'sklearn', 'statsmodels',
                    'pandas', 'matplotlib', 'psychopy', 'github'):
        _test_external(ev, modname)

    # more of a smoke test
    assert_false(linesep in ev.dumps())
    assert_true(ev.dumps(indent=True).endswith(linesep))
Esempio n. 13
0
def test_external_versions_rogue_module(topd=None):
    ev = ExternalVersions()
    # if module throws some other non-ImportError exception upon import
    # we must not crash, but issue a warning
    modname = 'verycustomrogue__'
    create_tree(topd, {modname + '.py': 'raise Exception("pickaboo")'})
    with patch('sys.path', [topd]), \
        swallow_logs(new_level=logging.WARNING) as cml:
        assert ev[modname] is None
        assert_true(ev.dumps(indent=True).endswith(linesep))
        assert_in('pickaboo', cml.out)
Esempio n. 14
0
def test_bare(src=None, path=None):
    # create a proper datalad dataset with all bells and whistles
    ds = Dataset(src).create()
    dlconfig_sha = ds.repo.call_git(['rev-parse', 'HEAD:.datalad/config'])
    # can we handle a bare repo version of it?
    gr = AnnexRepo.clone(src,
                         path,
                         clone_options=['--bare', '-b', DEFAULT_BRANCH])
    # we had to specifically checkout the standard branch, because on crippled
    # FS, HEAD will point to an adjusted branch by default, and the test logic
    # below does not account for this case.
    # this should just make sure the bare repo has the expected setup,
    # but it should still be bare. Let's check that to be sure
    assert_true(gr.bare)
    # do we read the correct local config?
    assert_in(gr.pathobj / 'config', gr.config._stores['git']['files'])
    # do we pick up the default branch config too?
    assert_in('blob:HEAD:.datalad/config',
              gr.config._stores['branch']['files'])
    # and track its reload stamp via its file shasum
    assert_equal(
        dlconfig_sha,
        gr.config._stores['branch']['stats']['blob:HEAD:.datalad/config'])
    # check that we can pick up the dsid from the commit branch config
    assert_equal(ds.id, gr.config.get('datalad.dataset.id'))
    # and it is coming from the correct source
    assert_equal(ds.id,
                 gr.config.get_from_source('branch', 'datalad.dataset.id'))
    assert_equal(None, gr.config.get_from_source('local',
                                                 'datalad.dataset.id'))
    # any sensible (and also our CI) test environment(s) should have this
    assert_in('user.name', gr.config)
    # not set something that wasn't there
    obscure_key = 'sec.reallyobscurename!@@.key'
    assert_not_in(obscure_key, gr.config)
    # to the local config, which is easily accessible
    gr.config.set(obscure_key, 'myvalue', scope='local')
    assert_equal(gr.config.get(obscure_key), 'myvalue')
    # now make sure the config is where we think it is
    assert_in(obscure_key.split('.')[1], (gr.pathobj / 'config').read_text())
    # update committed config and check update
    old_id = ds.id
    ds.config.set('datalad.dataset.id', 'surprise!', scope='branch')
    ds.save()
    # fetch into default branch (like `update`, but for bare-repos)
    gr.call_git(
        ['fetch', f'{DEFAULT_REMOTE}', f'{DEFAULT_BRANCH}:{DEFAULT_BRANCH}'])
    # without a reload, no state change, like with non-bare repos
    assert_equal(old_id,
                 gr.config.get_from_source('branch', 'datalad.dataset.id'))
    # a non-forced reload() must be enough, because state change
    # detection kicks in
    gr.config.reload()
    assert_equal('surprise!', gr.config.get('datalad.dataset.id'))
Esempio n. 15
0
def test_batched_close_ok():
    # Expect a long wait and no timeout if the process runs longer than timeout
    # seconds and the config for "datalad.runtime.stalled-external" has its
    # default value.
    bc = BatchedCommand(cmd=[sys.executable, "-i", "-u", "-q", "-"], timeout=2)
    # Send at least one instruction to start the subprocess
    response = bc("import time; print('a')")
    assert_equal(response, "a")
    bc.stdin_queue.put("time.sleep(.5); exit(3)\n".encode())
    bc.close(return_stderr=False)
    assert_true(bc.wait_timed_out is False)
    assert_equal(bc.return_code, 3)
Esempio n. 16
0
def test_ephemeral(ds_path=None, store_path=None, clone_path=None):

    dspath = Path(ds_path)
    store = Path(store_path)
    file_test = Path('file1.txt')
    file_testsub = Path('sub') / 'other.txt'

    # create the original dataset
    ds = Dataset(dspath)
    ds.create(force=True)
    ds.save()

    # put into store:
    ds.create_sibling_ria("ria+{}".format(store.as_uri()),
                          "riastore",
                          new_store_ok=True)
    ds.push(to="riastore", data="anything")

    # now, get an ephemeral clone from the RIA store:
    eph_clone = clone('ria+{}#{}'.format(store.as_uri(), ds.id),
                      clone_path,
                      reckless="ephemeral")

    # ephemeral clone was properly linked (store has bare repos!):
    clone_annex = (eph_clone.repo.dot_git / 'annex')
    assert_true(clone_annex.is_symlink())
    assert_true(clone_annex.resolve().samefile(store / ds.id[:3] / ds.id[3:] /
                                               'annex'))
    if not eph_clone.repo.is_managed_branch():
        # TODO: We can't properly handle adjusted branch yet
        # we don't need to get files in order to access them:
        assert_equal((eph_clone.pathobj / file_test).read_text(), "some")
        assert_equal((eph_clone.pathobj / file_testsub).read_text(), "other")

        # can we unlock those files?
        eph_clone.unlock(file_test)
        # change content
        (eph_clone.pathobj / file_test).write_text("new content")
        eph_clone.save()

        # new content should already be in store
        # (except the store doesn't know yet)
        res = eph_clone.repo.fsck(remote="riastore-storage", fast=True)
        assert_equal(len(res), 2)
        assert_result_count(res, 1, success=True, file=file_test.as_posix())
        assert_result_count(res, 1, success=True, file=file_testsub.as_posix())

        # push back git history
        eph_clone.push(to=DEFAULT_REMOTE, data="nothing")

        # get an update in origin
        ds.update(merge=True, reobtain_data=True)
        assert_equal((ds.pathobj / file_test).read_text(), "new content")
Esempio n. 17
0
def test_batched_close_abandon():
    # Expect a timeout if the process runs longer than timeout and the config
    # for "datalad.runtime.stalled-external" is "abandon".
    bc = BatchedCommand(cmd=[sys.executable, "-i", "-u", "-q", "-"],
                        timeout=.1)
    # Send at least one instruction to start the subprocess
    response = bc("import time; print('a')")
    assert_equal(response, "a")
    bc.stdin_queue.put("time.sleep(2); exit(1)\n".encode())
    with unittest.mock.patch("datalad.cfg") as cfg_mock:
        cfg_mock.configure_mock(**{"obtain.return_value": "abandon"})
        bc.close(return_stderr=False)
        assert_true(bc.wait_timed_out is True)
        assert_is_none(bc.return_code)
Esempio n. 18
0
def test_zip_archive(path=None):
    ds = Dataset(opj(path, 'ds')).create(force=True, annex=False)
    ds.save()
    with chpwd(path):
        ds.export_archive(filename='my', archivetype='zip')
        assert_true(os.path.exists('my.zip'))
        custom1_md5 = md5sum('my.zip')
        time.sleep(1.1)
        ds.export_archive(filename='my', archivetype='zip')
        assert_equal(md5sum('my.zip'), custom1_md5)

    # should be able to export without us cd'ing to that ds directory
    ds.export_archive(filename=ds.path, archivetype='zip')
    default_name = 'datalad_{}.zip'.format(ds.id)
    assert_true(os.path.exists(os.path.join(ds.path, default_name)))
Esempio n. 19
0
def test_repo_cache(path=None):
    ds = Dataset(path)
    # none by default
    eq_(ds.repo, None)
    # make Git repo manually
    git = GitRepo(path=path, create=True)
    repo = ds.repo
    # got one
    assert_false(repo is None)
    # stays that one
    assert_true(ds.repo is repo)
    # now turn into an annex
    annex = AnnexRepo(path=path, create=True)
    # repo instance must change
    assert_false(ds.repo is repo)
    assert_true(isinstance(ds.repo, AnnexRepo))
Esempio n. 20
0
def test_text2git(path=None):
    # Test if files being correctly annexed in a ds configured with text2git.
    TEXT_FILES = ('JSON', 'YAML', 'MARKDOWN', 'empty')
    BINARY_FILES = ('0blob', 'emptyline')

    ds = Dataset(path).create(force=True)
    ds.run_procedure('cfg_text2git')
    ds.save(path=TEXT_FILES + BINARY_FILES, message="added all files")
    assert_repo_status(ds.path)

    # check that text files are not annexed
    for f in TEXT_FILES:
        assert_false(ds.repo.is_under_annex(f))
    # and trivial binaries - annexed
    for f in BINARY_FILES:
        assert_true(ds.repo.is_under_annex(f))
Esempio n. 21
0
def test_basic_setup():
    # the import alone will verify that all default values match their
    # constraints
    from datalad import api

    # random pick of something that should be there
    assert_true(hasattr(api, 'install'))
    assert_true(hasattr(api, 'create'))
    # make sure all helper utilities do not pollute the namespace
    # and we end up only with __...__ attributes
    assert_false(
        list(
            filter(lambda s: s.startswith('_') and not re.match('__.*__', s),
                   dir(api))))

    assert_in('Parameters', api.Dataset.install.__doc__)
    assert_in('Parameters', api.Dataset.create.__doc__)
Esempio n. 22
0
def test_dataset_id(path=None):

    ds = Dataset(path)
    assert_equal(ds.id, None)
    ds.create()
    dsorigid = ds.id
    # ID is always a UUID
    assert_equal(ds.id.count('-'), 4)
    assert_equal(len(ds.id), 36)

    # Ben: The following part of the test is concerned with creating new objects
    #      and therefore used to reset the flyweight dict while keeping a ref to
    #      the old object for comparison etc. This is ugly and in parts
    #      retesting what is already tested in `test_Dataset_flyweight`. No need
    #      for that. If we del the last ref to an instance and gc.collect(),
    #      then we get a new instance on next request. This test should trust
    #      the result of `test_Dataset_flyweight`.

    # creating a new object for the same path
    # yields the same ID
    del ds
    newds = Dataset(path)
    assert_equal(dsorigid, newds.id)

    # recreating the dataset does NOT change the id
    del newds

    ds = Dataset(path)
    ds.create(annex=False, force=True)
    assert_equal(ds.id, dsorigid)

    # even adding an annex doesn't
    del ds
    ds = Dataset(path)
    ds.create(force=True)
    assert_equal(ds.id, dsorigid)

    # dataset ID and annex UUID have nothing to do with each other
    # if an ID was already generated
    assert_true(ds.repo.uuid != ds.id)

    # even if we generate a dataset from scratch with an annex UUID right away,
    # this is also not the ID
    annexds = Dataset(opj(path, 'scratch')).create()
    assert_true(annexds.id != annexds.repo.uuid)
Esempio n. 23
0
    def test_add_delete_after_and_drop_subdir(self=None):
        os.mkdir(opj(self.annex.path, 'subdir'))
        mv_out = self.annex.call_git(['mv', '1.tar', 'subdir'])
        self.annex.commit("moved into subdir")
        with chpwd(self.annex.path):
            # was failing since deleting without considering if tarball
            # was extracted in that tarball directory
            commits_prior_master = list(self.annex.get_branch_commits_())
            commits_prior = list(self.annex.get_branch_commits_('git-annex'))
            add_out = self.ds.add_archive_content(opj('subdir', '1.tar'),
                                                  delete_after=True,
                                                  drop_after=True)
            assert_repo_status(self.annex.path)
            if not self.annex.is_managed_branch():
                # whole counting logic here is ignorant of adjusted branches
                commits_after_master = list(self.annex.get_branch_commits_())
                commits_after = list(
                    self.annex.get_branch_commits_('git-annex'))
                # There should be a single commit for all additions +1 to
                # initiate datalad-archives gh-1258.  If faking dates,
                # there should be another +1 because annex.alwayscommit
                # isn't set to false.
                assert_equal(
                    len(commits_after),
                    len(commits_prior) + 2 + self.annex.fake_dates_enabled)
                assert_equal(len(commits_after_master),
                             len(commits_prior_master))
            # there should be no .datalad temporary files hanging around
            self.assert_no_trash_left_behind()

            # and if we add some untracked file, redo, there should be no changes
            # to master and file should remain not committed
            create_tree(self.annex.path, {'dummy.txt': '123'})
            assert_true(self.annex.dirty)  # untracked file
            add_out = add_archive_content(opj('subdir', '1.tar'),
                                          delete_after=True,
                                          drop_after=True,
                                          allow_dirty=True)
            assert_repo_status(self.annex.path, untracked=['dummy.txt'])
            assert_equal(len(list(self.annex.get_branch_commits_())),
                         len(commits_prior_master))

            # there should be no .datalad temporary files hanging around
            self.assert_no_trash_left_behind()
Esempio n. 24
0
def test_interactive_communication():

    class BidirectionalProtocol(Protocol):

        proc_out = True
        proc_err = True

        def __init__(self, result_pool: dict):
            super().__init__()
            self.state = 0
            self.result_pool = result_pool

        def connection_made(self, process):
            super().connection_made(process)
            os.write(self.process.stdin.fileno(), b"1 + 1\n")

        def connection_lost(self, exc):
            self.result_pool["connection_lost_called"] = True

        def process_exited(self):
            self.result_pool["process_exited_called"] = True

        def pipe_data_received(self, fd, data):
            super().pipe_data_received(fd, data)
            if self.state == 0:
                self.state += 1
                os.write(self.process.stdin.fileno(), b"2 ** 3\n")
            if self.state == 1:
                self.state += 1
                os.write(self.process.stdin.fileno(), b"exit(0)\n")

    result_pool = dict()
    result = run_command([sys.executable, "-i"],
                         BidirectionalProtocol,
                         stdin=subprocess.PIPE,
                         protocol_kwargs={
                            "result_pool": result_pool
                         })

    lines = [line.strip() for line in result["stdout"].splitlines()]
    eq_(lines, ["2", "8"])
    assert_true(result_pool["connection_lost_called"], True)
    assert_true(result_pool["process_exited_called"], True)
Esempio n. 25
0
def test_property_reevaluation(repo1=None):
    ds = Dataset(repo1)
    assert_is_none(ds.repo)
    assert_is_not_none(ds.config)
    first_config = ds.config
    assert_false(ds._cfg_bound)
    assert_is_none(ds.id)

    ds.create()
    assert_repo_status(repo1)
    # after creation, we have `repo`, and `config` was reevaluated to point
    # to the repo's config:
    assert_is_not_none(ds.repo)
    assert_is_not_none(ds.config)
    second_config = ds.config
    assert_true(ds._cfg_bound)
    assert_is(ds.config, ds.repo.config)
    assert_is_not(first_config, second_config)
    assert_is_not_none(ds.id)
    first_id = ds.id

    ds.drop(what='all', reckless='kill', recursive=True)
    # repo is gone, and config is again reevaluated to only provide user/system
    # level config:
    assert_false(lexists(ds.path))
    assert_is_none(ds.repo)
    assert_is_not_none(ds.config)
    third_config = ds.config
    assert_false(ds._cfg_bound)
    assert_is_not(second_config, third_config)
    assert_is_none(ds.id)

    ds.create()
    assert_repo_status(repo1)
    # after recreation everything is sane again:
    assert_is_not_none(ds.repo)
    assert_is_not_none(ds.config)
    assert_is(ds.config, ds.repo.config)
    forth_config = ds.config
    assert_true(ds._cfg_bound)
    assert_is_not(third_config, forth_config)
    assert_is_not_none(ds.id)
    assert_not_equal(ds.id, first_id)
Esempio n. 26
0
def test_param():
    # having a parameter with no information is fine
    # it doesn't need a name, because it comes from the signature
    # of the actual implementation that is described
    p = Parameter()
    pname = 'testname'
    # minimal docstring
    assert_equal(pname, p.get_autodoc('testname'))
    doc = 'somedoc'
    p = Parameter(doc=doc)
    assert_equal('%s\n  %s.' % (pname, doc), p.get_autodoc('testname'))
    # constraints
    p = Parameter(doc=doc, constraints=cnstr.EnsureInt() | cnstr.EnsureStr())
    autodoc = p.get_autodoc('testname')
    assert_true('int or str' in autodoc)

    with assert_raises(ValueError) as cmr:
        Parameter(unknown_arg=123)
    assert_in('Detected unknown argument(s) for the Parameter: unknown_arg',
              str(cmr.value))
Esempio n. 27
0
def test_subprocess_return_code_capture():

    class KillProtocol(Protocol):

        proc_out = True
        proc_err = True

        def __init__(self, signal_to_send: int, result_pool: dict):
            super().__init__()
            self.signal_to_send = signal_to_send
            self.result_pool = result_pool

        def connection_made(self, process):
            super().connection_made(process)
            process.send_signal(self.signal_to_send)

        def connection_lost(self, exc):
            self.result_pool["connection_lost_called"] = (True, exc)

        def process_exited(self):
            self.result_pool["process_exited_called"] = True

    # windows doesn't support SIGINT but would need a Ctrl-C
    signal_to_send = signal.SIGTERM if on_windows else signal.SIGINT
    result_pool = dict()
    result = run_command(["waitfor", "/T", "10000", "TheComputerTurnsIntoATulip"]
                         if on_windows
                         else ["sleep", "10000"],
                         KillProtocol,
                         None,
                         {
                             "signal_to_send": signal_to_send,
                             "result_pool": result_pool
                         },
                         exception_on_error=False)
    if not on_windows:
        # this one specifically tests the SIGINT case, which is not supported
        # on windows
        eq_(result["code"], -signal_to_send)
    assert_true(result_pool["connection_lost_called"][0])
    assert_true(result_pool["process_exited_called"])
Esempio n. 28
0
def test_symlinked_dataset_properties(repo1=None,
                                      repo2=None,
                                      repo3=None,
                                      non_repo=None,
                                      symlink=None):

    ds = Dataset(repo1).create()

    # now, let ds be a symlink and change that symlink to point to different
    # things:
    ar2 = AnnexRepo(repo2)
    ar3 = AnnexRepo(repo3)
    assert_true(os.path.isabs(non_repo))

    os.symlink(repo1, symlink)
    ds_link = Dataset(symlink)
    assert_is(ds_link.repo, ds.repo)  # same Repo instance
    assert_is_not(ds_link, ds)  # but not the same Dataset instance
    assert_is(ds_link.config, ds.repo.config)
    assert_true(ds_link._cfg_bound)
    assert_is_not_none(ds_link.id)
    # same id, although different Dataset instance:
    assert_equal(ds_link.id, ds.id)

    os.unlink(symlink)
    os.symlink(repo2, symlink)

    assert_is(ds_link.repo, ar2)  # same Repo instance
    assert_is(ds_link.config, ar2.config)
    assert_true(ds_link._cfg_bound)
    # id is None again, since this repository is an annex but there was no
    # Dataset.create() called yet.
    assert_is_none(ds_link.id)

    os.unlink(symlink)
    os.symlink(repo3, symlink)

    assert_is(ds_link.repo, ar3)  # same Repo instance
    assert_is(ds_link.config, ar3.config)
    assert_true(ds_link._cfg_bound)
    # id is None again, since this repository is an annex but there was no
    # Dataset.create() called yet.
    assert_is_none(ds_link.id)

    os.unlink(symlink)
    os.symlink(non_repo, symlink)

    assert_is_none(ds_link.repo)
    assert_is_not(ds_link.config, ar3.config)
    assert_false(ds_link._cfg_bound)
    assert_is_none(ds_link.id)
Esempio n. 29
0
def test_external_versions_basic():
    ev = ExternalVersions()
    our_module = 'datalad'
    assert_equal(ev.versions, {})
    assert_equal(ev[our_module], __version__)
    # and it could be compared
    assert_greater_equal(ev[our_module], __version__)
    # We got some odd failure in this test not long are after switching to versionner
    # https://github.com/datalad/datalad/issues/5785.  Verify that we do get expected
    # data types
    our_version = ev[our_module].version
    assert isinstance(
        our_version,
        (str, list)), f"Got {our_version!r} of type {type(our_version)}"
    assert_greater(ev[our_module], '0.1')
    assert_equal(list(ev.keys()), [our_module])
    assert_true(our_module in ev)
    assert_false('unknown' in ev)

    # all are LooseVersions now
    assert_true(isinstance(ev[our_module], LooseVersion))
    version_str = __version__
    assert_equal(ev.dumps(), "Versions: %s=%s" % (our_module, version_str))

    # For non-existing one we get None
    assert_equal(ev['custom__nonexisting'], None)
    # and nothing gets added to _versions for nonexisting
    assert_equal(set(ev.versions.keys()), {our_module})

    # but if it is a module without version, we get it set to UNKNOWN
    assert_equal(ev['os'], ev.UNKNOWN)
    # And get a record on that inside
    assert_equal(ev.versions.get('os'), ev.UNKNOWN)
    # And that thing is "True", i.e. present
    assert (ev['os'])
    # but not comparable with anything besides itself (was above)
    assert_raises(TypeError, cmp, ev['os'], '0')
    assert_raises(TypeError, assert_greater, ev['os'], '0')

    return
Esempio n. 30
0
def test_blocking_thread_exit():
    read_queue = queue.Queue()

    (read_descriptor, write_descriptor) = os.pipe()
    read_file = os.fdopen(read_descriptor, "rb")
    read_thread = ReadThread(
        identifier="test thread",
        user_info=read_descriptor,
        source=read_file,
        destination_queue=read_queue,
        signal_queues=[]
    )
    read_thread.start()

    os.write(write_descriptor, b"some data")
    assert_true(read_thread.is_alive())
    identifier, state, data = read_queue.get()
    eq_(data, b"some data")

    read_thread.request_exit()

    # Check the blocking part
    sleep(.3)
    assert_true(read_thread.is_alive())

    # Check actual exit, we will not get
    # "more data" when exit was requested,
    # because the thread will not attempt
    # a write
    os.write(write_descriptor, b"more data")
    read_thread.join()
    print(read_queue.queue)
    assert_true(read_queue.empty())