text: # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
  # vi: set ft=python sts=4 ts=4 sw=4 et:
  """ Tests for data module """
  import os
  from os.path import join as pjoin
  from os import environ as env
  import sys
  import tempfile
  
  from ..data import (get_data_path, find_data_dir,
                      DataError, _cfg_value, make_datasource,
                      Datasource, VersionedDatasource, Bomber,
                      datasource_or_bomber)
  
  from ..tmpdirs import TemporaryDirectory
  
  from .. import data as nibd
  
  
  import pytest
  
  from .test_environment import with_environment, DATA_KEY, USER_KEY
  
  
  @pytest.fixture
  def with_nimd_env(request, with_environment):
      DATA_FUNCS = {}
      DATA_FUNCS['home_dir_func'] = nibd.get_nipy_user_dir
      DATA_FUNCS['sys_dir_func'] = nibd.get_nipy_system_dir
      DATA_FUNCS['path_func'] = nibd.get_data_path
      yield
      nibd.get_nipy_user_dir = DATA_FUNCS['home_dir_func']
      nibd.get_nipy_system_dir = DATA_FUNCS['sys_dir_func']
      nibd.get_data_path = DATA_FUNCS['path_func']
  
  
  def test_datasource():
      # Tests for DataSource
      pth = pjoin('some', 'path')
      ds = Datasource(pth)
      assert ds.get_filename('unlikeley') == pjoin(pth, 'unlikeley')
      assert ds.get_filename('un', 'like', 'ley') == pjoin(pth, 'un', 'like', 'ley')
  
  
  def test_versioned():
      with TemporaryDirectory() as tmpdir:
          with pytest.raises(DataError):
              VersionedDatasource(tmpdir)
          tmpfile = pjoin(tmpdir, 'config.ini')
          # ini file, but wrong section
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[SOMESECTION]\n')
              fobj.write('version = 0.1\n')
          with pytest.raises(DataError):
              VersionedDatasource(tmpdir)
          # ini file, but right section, wrong key
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DEFAULT]\n')
              fobj.write('somekey = 0.1\n')
          with pytest.raises(DataError):
              VersionedDatasource(tmpdir)
          # ini file, right section and key
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DEFAULT]\n')
              fobj.write('version = 0.1\n')
          vds = VersionedDatasource(tmpdir)
          assert vds.version == '0.1'
          assert vds.version_no == 0.1
          assert vds.major_version == 0
          assert vds.minor_version == 1
          assert vds.get_filename('config.ini') == tmpfile
          # ini file, right section and key, funny value
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DEFAULT]\n')
              fobj.write('version = 0.1.2.dev\n')
          vds = VersionedDatasource(tmpdir)
          assert vds.version == '0.1.2.dev'
          assert vds.version_no == 0.1
          assert vds.major_version == 0
          assert vds.minor_version == 1
  
  
  def test__cfg_value():
      # no file, return ''
      assert _cfg_value('/implausible_file') == ''
      # try files
      try:
          fd, tmpfile = tempfile.mkstemp()
          fobj = os.fdopen(fd, 'wt')
          # wrong section, right key
          fobj.write('[strange section]\n')
          fobj.write('path = /some/path\n')
          fobj.flush()
          assert _cfg_value(tmpfile) == ''
          # right section, wrong key
          fobj.write('[DATA]\n')
          fobj.write('funnykey = /some/path\n')
          fobj.flush()
          assert _cfg_value(tmpfile) == ''
          # right section, right key
          fobj.write('path = /some/path\n')
          fobj.flush()
          assert _cfg_value(tmpfile) == '/some/path'
          fobj.close()
      finally:
          try:
              os.unlink(tmpfile)
          except:
              pass
  
  
  def test_data_path(with_nimd_env):
      # wipe out any sources of data paths
      if DATA_KEY in env:
          del env[DATA_KEY]
      if USER_KEY in env:
          del os.environ[USER_KEY]
      fake_user_dir = '/user/path'
      nibd.get_nipy_system_dir = lambda: '/unlikely/path'
      nibd.get_nipy_user_dir = lambda: fake_user_dir
      # now we should only have anything pointed to in the user's dir
      old_pth = get_data_path()
      # We should have only sys.prefix and, iff sys.prefix == /usr,
      # '/usr/local'.  This last to is deal with Debian patching to
      # distutils.
      def_dirs = [pjoin(sys.prefix, 'share', 'nipy')]
      if sys.prefix == '/usr':
          def_dirs.append(pjoin('/usr/local', 'share', 'nipy'))
      assert old_pth == def_dirs + ['/user/path']
      # then we'll try adding some of our own
      tst_pth = '/a/path' + os.path.pathsep + '/b/ path'
      tst_list = ['/a/path', '/b/ path']
      # First, an environment variable
      os.environ[DATA_KEY] = tst_list[0]
      assert get_data_path() == tst_list[:1] + old_pth
      os.environ[DATA_KEY] = tst_pth
      assert get_data_path() == tst_list + old_pth
      del os.environ[DATA_KEY]
      # Next, make a fake user directory, and put a file in there
      with TemporaryDirectory() as tmpdir:
          tmpfile = pjoin(tmpdir, 'config.ini')
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DATA]\n')
              fobj.write(f'path = {tst_pth}')
          nibd.get_nipy_user_dir = lambda: tmpdir
          assert get_data_path() == tst_list + def_dirs + [tmpdir]
      nibd.get_nipy_user_dir = lambda: fake_user_dir
      assert get_data_path() == old_pth
      # with some trepidation, the system config files
      with TemporaryDirectory() as tmpdir:
          nibd.get_nipy_system_dir = lambda: tmpdir
          tmpfile = pjoin(tmpdir, 'an_example.ini')
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DATA]\n')
              fobj.write(f'path = {tst_pth}\n')
          tmpfile = pjoin(tmpdir, 'another_example.ini')
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DATA]\n')
              fobj.write('path = %s\n' % '/path/two')
          assert get_data_path() == tst_list + ['/path/two'] + old_pth
  
  
  def test_find_data_dir():
      here, fname = os.path.split(__file__)
      # here == '<rootpath>/nipy/utils/tests'
      under_here, subhere = os.path.split(here)
      # under_here == '<rootpath>/nipy/utils'
      # subhere = 'tests'
      # fails with non-existant path
      with pytest.raises(DataError):
          find_data_dir([here], 'implausible', 'directory')
      # fails with file, when directory expected
      with pytest.raises(DataError):
          find_data_dir([here], fname)
      # passes with directory that exists
      dd = find_data_dir([under_here], subhere)
      assert dd == here
      # and when one path in path list does not work
      dud_dir = pjoin(under_here, 'implausible')
      dd = find_data_dir([dud_dir, under_here], subhere)
      assert dd == here
  
  
  def test_make_datasource(with_nimd_env):
      pkg_def = dict(
          relpath='pkg')
      with TemporaryDirectory() as tmpdir:
          nibd.get_data_path = lambda: [tmpdir]
          with pytest.raises(DataError):
              make_datasource(pkg_def)
          pkg_dir = pjoin(tmpdir, 'pkg')
          os.mkdir(pkg_dir)
          with pytest.raises(DataError):
              make_datasource(pkg_def)
          tmpfile = pjoin(pkg_dir, 'config.ini')
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DEFAULT]\n')
              fobj.write('version = 0.1\n')
          ds = make_datasource(pkg_def, data_path=[tmpdir])
          assert ds.version == '0.1'
  
  
  @pytest.mark.xfail(raises=DataError)
  def test_bomber():
      b = Bomber('bomber example', 'a message')
      b.any_attribute  # no error
  
  
  def test_bomber_inspect():
      b = Bomber('bomber example', 'a message')
      assert not hasattr(b, 'any_attribute')
  
  
  def test_datasource_or_bomber(with_nimd_env):
      pkg_def = dict(relpath='pkg')
      with TemporaryDirectory() as tmpdir:
          nibd.get_data_path = lambda: [tmpdir]
          ds = datasource_or_bomber(pkg_def)
          with pytest.raises(DataError):
              ds.get_filename('some_file.txt')
          pkg_dir = pjoin(tmpdir, 'pkg')
          os.mkdir(pkg_dir)
          tmpfile = pjoin(pkg_dir, 'config.ini')
          with open(tmpfile, 'wt') as fobj:
              fobj.write('[DEFAULT]\n')
              fobj.write('version = 0.2\n')
          ds = datasource_or_bomber(pkg_def)
          ds.get_filename('some_file.txt')
          # check that versioning works
          pkg_def['min version'] = '0.2'
          ds = datasource_or_bomber(pkg_def)  # OK
          ds.get_filename('some_file.txt')
          pkg_def['min version'] = '0.3'
          ds = datasource_or_bomber(pkg_def)  # not OK
          with pytest.raises(DataError):
              ds.get_filename('some_file.txt')
  