Skip to content

Commit

Permalink
bugfix test zenodo tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasprobst committed Apr 18, 2024
1 parent b80424e commit 4af3bdf
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 13 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

*Note, that the project is still under development!*

The "HDF5 Research Data Management Toolbox" (h5RDMtoolbox) is a python package supporting everybody who is working with
The "HDF5 Research Data Management Toolbox" (h5RDMtoolbox) is a Python package supporting everybody who is working with
HDF5 to achieve a sustainable data lifecycle which follows
the [FAIR (Findable, Accessible, Interoperable, Reusable)](https://www.nature.com/articles/sdata201618)
principles. It specifically supports the five main steps of *planning*, *collecting*, *analyzing*, *sharing* and
Expand All @@ -18,7 +18,7 @@ information of try the [quickstart using colab](#quickstart).

- Combining HDF5 and [xarray](https://docs.xarray.dev/en/stable/) to allow easy access to metadata and data during
analysis and processing (
see [here](https://h5rdmtoolbox.readthedocs.io/en/latest/gettingstarted/quickoverview.html#datasets-xarray-interface).
see [here](https://h5rdmtoolbox.readthedocs.io/en/latest/gettingstarted/quickoverview.html#datasets-xarray-interface)).
- Assigning [metadata with "globally unique and persistent identifiers"]() as required
by [F1 of the FAIR principles](https://www.go-fair.org/fair-principles/f1-meta-data-assigned-globally-unique-persistent-identifiers/)
. This "remove[s] ambiguity in the meaning of your published data...".
Expand Down
8 changes: 8 additions & 0 deletions h5rdmtoolbox/_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,18 @@ def __init__(self):
'tmp': tmp_dir,
'convention': _user_root_dir / 'convention',
'layouts': _user_root_dir / 'layouts',
'repository': _user_root_dir / 'repository',
'standard_name_tables': _user_root_dir / 'standard_name_tables',
'cache': _user_root_dir / 'cache'}
self.clear_cache(6)

def __str__(self):
dirs = ', '.join(f'{k}' for k in self.user_dirs.keys())
return f'{self.__class__.__name__}({dirs})'

def __repr__(self):
return self.__str__()

def __getitem__(self, item):
return self._get_dir(item)

Expand Down
21 changes: 21 additions & 0 deletions h5rdmtoolbox/repository/zenodo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Zenodo repository interface


## Provide Token(s)
In order to connect to Zenodo and interact with it, tokens for either the productive or
sandbox version must be provided. Either by providing a `zenodo.ini` file in the local
user directory (find it here: `h5rdmtoolbox.get_user_dir()`)

The file content should look like the following (displayed tokens are not real, replace them
with yours):

[zenodo:sandbox]
access_token = 123kwadhulahw7d8o141lhualwedhuao810g208
[zenodo]
access_token = jdalwd814o8h3aulih7o3r01h12ulieh218e7081

You may alo set them as environment variables. Please use `ZENODO_API_TOKEN` and `ZENODO_SANDBOX_API_TOKEN`,
respectively.

**Note**, that environment variables are checked first! If set the ini-file is not
checked!
18 changes: 14 additions & 4 deletions h5rdmtoolbox/repository/zenodo/tokens.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import appdirs
import configparser
import logging
import os
Expand All @@ -11,7 +10,8 @@

def _parse_ini_file(zenodo_ini_filename: Union[str, pathlib.Path]):
if zenodo_ini_filename is None:
zenodo_ini_filename = pathlib.Path(appdirs.user_data_dir('h5rdmtoolbox')) / 'zenodo.ini'
from h5rdmtoolbox import UserDir
zenodo_ini_filename = UserDir['repository'] / 'zenodo.ini'
else:
zenodo_ini_filename = pathlib.Path(zenodo_ini_filename)
if not zenodo_ini_filename.exists():
Expand All @@ -21,7 +21,8 @@ def _parse_ini_file(zenodo_ini_filename: Union[str, pathlib.Path]):

def get_api_token(sandbox: bool,
zenodo_ini_filename: Union[str, pathlib.Path] = None):
"""Read the Zenodo API token from the config file."""
"""Read the Zenodo API token from the environment variable or config file.
If an environment variable is found, a possibly existing ini file is ignored!"""
if sandbox:
env_token = os.environ.get('ZENODO_SANDBOX_API_TOKEN', None)
# logger.debug('Took token from environment variable ZENODO_SANDBOX_API_TOKEN: %s', env_token)
Expand All @@ -32,29 +33,38 @@ def get_api_token(sandbox: bool,
if env_token is not None:
# logger.debug('Took zenodo token from environment variable:: %s', env_token)
env_token = env_token.strip()
logger.debug(' Took token from environment variable ZENODO_SANDBOX_API_TOKEN.')
logger.debug(' Took token from environment variable ZENODO_SANDBOX_API_TOKEN.')
return env_token

logger.debug('No environment variable found for the zenodo token. Trying to read it from the config file '
'%s .' % zenodo_ini_filename)

zenodo_ini_filename = _parse_ini_file(zenodo_ini_filename)
if zenodo_ini_filename.exists():
logger.debug(f'Zenodo ini file found: {zenodo_ini_filename}')

config = configparser.ConfigParser()
config.read(zenodo_ini_filename)
if sandbox:
try:
access_token = config['zenodo:sandbox']['access_token']
logger.debug('Token read successfully.')
except KeyError:
access_token = None
logger.debug('Error reading sandbox token from section "zenodo:sandbox"')
else:
try:
access_token = config['zenodo']['access_token']
logger.debug('Token read successfully.')
except KeyError:
access_token = None
logger.debug('Error reading sandbox token from section "zenodo"')

if not access_token:
warnings.warn(f'No API token found in {zenodo_ini_filename}. Please verify the correctness of the file '
f'{zenodo_ini_filename}. The access_token entry must be in the section [zenodo] or '
f'[zenodo:sandbox].')
logger.error('No token read. Neither file nor env variable found.')
return access_token


Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,4 @@ python-gitlab
pypandoc>=1.11
pydantic >= 2.3.0
# other:
tqdm>=4.64.0
ontolutils
23 changes: 18 additions & 5 deletions tests/repository/test_zenodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
import logging
import os
import pathlib
import pydantic
import unittest
from datetime import datetime

import pydantic

import h5rdmtoolbox as h5tbx
from h5rdmtoolbox import UserDir
from h5rdmtoolbox.repository import zenodo, upload_file
from h5rdmtoolbox.repository.zenodo.metadata import Metadata, Creator, Contributor
from h5rdmtoolbox.repository.zenodo.tokens import get_api_token, set_api_token
Expand Down Expand Up @@ -145,15 +147,18 @@ def test_get_api(self):
else:
bak_fname = None

zenodo_ini_filename = UserDir['repository'] / 'zenodo.ini'
if zenodo_ini_filename.exists():
tmp_zenodo_ini_filename = zenodo_ini_filename.rename(zenodo_ini_filename.with_suffix('.ini_bak'))
else:
tmp_zenodo_ini_filename = None

with self.assertRaises(FileNotFoundError):
_parse_ini_file(None)

with self.assertRaises(FileNotFoundError):
_parse_ini_file('invalid.ini')

with self.assertRaises(FileNotFoundError):
_parse_ini_file(None)

if bak_fname:
bak_fname.rename(fname)

Expand All @@ -163,6 +168,9 @@ def test_get_api(self):
self.assertTrue(ini_filename.exists())
ini_filename.unlink()

if tmp_zenodo_ini_filename:
tmp_zenodo_ini_filename.rename(tmp_zenodo_ini_filename.with_suffix('.ini'))

def test_get_api_token(self):
env_token_sb = os.environ.pop('ZENODO_SANDBOX_API_TOKEN', None)
env_token = os.environ.pop('ZENODO_API_TOKEN', None)
Expand All @@ -181,9 +189,14 @@ def test_get_api_token(self):
# reset environment variable
if env_token_sb is not None:
os.environ['ZENODO_SANDBOX_API_TOKEN'] = env_token_sb
self.assertEqual(env_token_sb, os.environ.get('ZENODO_SANDBOX_API_TOKEN', None))
self.assertEqual(env_token_sb, os.environ.get('ZENODO_SANDBOX_API_TOKEN', None))
else:
os.environ.pop('ZENODO_SANDBOX_API_TOKEN')

if env_token is not None:
os.environ['ZENODO_API_TOKEN'] = env_token
else:
os.environ.pop('ZENODO_API_TOKEN', None)
self.assertEqual(env_token, os.environ.get('ZENODO_API_TOKEN', None))

def test_set_api_token(self):
Expand Down
3 changes: 2 additions & 1 deletion tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def tearDownClass(cls) -> None:

def test_user_dir(self):
self.assertListEqual(sorted(h5tbx.UserDir.names),
sorted(('root', 'tmp', 'layouts', 'standard_name_tables', 'cache', 'convention')))
sorted(('root', 'tmp', 'layouts', 'repository',
'standard_name_tables', 'cache', 'convention')))
self.assertTrue('root' in h5tbx.UserDir)

cache_dir = h5tbx.UserDir['cache']
Expand Down

0 comments on commit 4af3bdf

Please sign in to comment.