Skip to content

Commit

Permalink
Merge pull request #44 from Sage-Bionetworks/update-login
Browse files Browse the repository at this point in the history
Create login utility function
  • Loading branch information
thomasyu888 committed Jul 22, 2021
2 parents 02b5940 + 7dea25e commit 2d5edf8
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ RetrieveCls = create.SynapseCreation(syn, only_get=True)
```

## Contributing
Please view our [contributing guide](CONTRIBUTING.md)
Please view our [contributing guide](CONTRIBUTING.md)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
click
synapseclient==2.3.0
synapseclient==2.4.0
pyyaml
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
python_requires='>=3.6',
entry_points={'console_scripts': ['synapseformation = synapseformation.__main__:cli']},
install_requires=['click',
'synapseclient>=2.0.0',
'synapseclient>=2.4.0',
'pyyaml'],
project_urls={
"Documentation": "https://github.com/Sage-Bionetworks/synapseformation",
Expand Down
14 changes: 9 additions & 5 deletions synapseformation/__main__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""synapseformation command line client"""
import click

import synapseclient

from .client import create_synapse_resources
from .utils import synapse_login
from .__version__ import __version__


Expand Down Expand Up @@ -37,11 +39,13 @@ def cli():

@cli.command()
@click.option('--template_path', help='Template path', type=click.Path())
def create(template_path):
"""Creates Synapse Resources"""
# syn = utils.synapse_login()
# syn = synapseclient.login()
create_synapse_resources(template_path)
@click.option('-c', '--config_path', help='Synapse configuration file',
type=click.Path(), show_default=True,
default=synapseclient.client.CONFIG_FILE)
def create(template_path, config_path):
"""Creates Synapse Resources given a yaml or json"""
syn = synapse_login(synapse_config=config_path)
create_synapse_resources(syn=syn, template_path=template_path)


if __name__ == "__main__":
Expand Down
4 changes: 1 addition & 3 deletions synapseformation/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,8 @@ def _create_synapse_resources(config_list: List[dict],
parentid=parent_id)


def create_synapse_resources(template_path: str):
def create_synapse_resources(syn: synapseclient.Synapse, template_path: str):
"""Creates synapse resources from template"""
# TODO: abstract out login function
syn = synapseclient.login()
# Function will attempt to read template as yaml then try to read in json
config = utils.read_config(template_path)
# Expands shortended configuration into full configuration. This should
Expand Down
71 changes: 35 additions & 36 deletions synapseformation/utils.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,49 @@
"""Utility functions"""
import yaml

import synapseclient
from synapseclient.core.exceptions import (
SynapseNoCredentialsError,
SynapseAuthenticationError,
)

# def read_yaml_config(template_path: str) -> dict:
# """Get yaml synapse formation template

# Args:
# template_path: Path to yaml synapse formation template
def read_config(template_path: str) -> dict:
"""Read in yaml or json configuration
# Returns:
# dict for synapse configuration
# """
# with open(template_path, "r") as template_f:
# template = yaml.safe_load(template_f)
# return template
Args:
template_path: Path to yaml or json configuration

# def read_json_config(template_path):
# """Get json synapse formation template

# Args:
# template_path: Path to yaml synapse formation template

# Returns:
# dict for synapse configuration
# """
# with open(template_path, "r") as template_f:
# template = json.load(template_f)
# return template


def read_config(template_path: str):
"""Read in yaml or json configuration"""
Returns:
Configuration
"""
# JSON is technically yaml but not the other way around.
# yaml.safe_load can actually read in json files.
with open(template_path, "r") as template_f:
config = yaml.safe_load(template_f)
return config

# class Ref(yaml.YAMLObject):
# yaml_loader = yaml.SafeLoader
# yaml_tag = '!Ref'
# def __init__(self, val):
# self.val = val

# @classmethod
# def from_yaml(cls, loader, node):
# return cls(node.value)
# # yaml.safe_load('Foo: !Ref bar')
def synapse_login(synapse_config=synapseclient.client.CONFIG_FILE):
"""Login to Synapse
Args:
synapse_config: Path to synapse configuration file.
Defaults to ~/.synapseConfig
Returns:
Synapse connection
"""
try:
syn = synapseclient.Synapse(configPath=synapse_config)
syn.login(silent=True)
except (SynapseNoCredentialsError, SynapseAuthenticationError):
raise ValueError(
"Login error: please make sure you have correctly "
"configured your client. Instructions here: "
"https://help.synapse.org/docs/Client-Configuration.1985446156.html. "
"You can also create a Synapse Personal Access Token and set it "
"as an environmental variable: "
"SYNAPSE_AUTH_TOKEN='<my_personal_access_token>'"
)
return(syn)
73 changes: 73 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Test utility functions"""
import json
import tempfile
from unittest import mock
from unittest.mock import patch, Mock

import pytest
import synapseclient
from synapseclient.core.exceptions import (
SynapseAuthenticationError,
SynapseNoCredentialsError,
)

from synapseformation import utils


def test_read_config_yaml():
"""Test reading in yaml configuration"""
test_yaml = "Test:\n name: foo\n test: bar"
expected = {'Test': {'name': 'foo', 'test': 'bar'}}
mock_open = mock.mock_open(read_data=test_yaml)
with mock.patch("builtins.open", mock_open):
yaml_dict = utils.read_config('file')
assert yaml_dict == expected


def test_read_config_json():
"""Test JSON config can be read with yaml.safe_load"""
expected = {'Test': {'name': 'foo', 'test': 'bar'}}
mock_open = mock.mock_open(read_data=json.dumps(expected))
with mock.patch("builtins.open", mock_open):
json_dict = utils.read_config('file')
assert json_dict == expected


def test_synapse_login_default():
"""Test default synapse login config path"""
syn = Mock()
with patch.object(synapseclient, "Synapse",
return_value=syn) as patch_synapse,\
patch.object(syn, "login") as patch_login:
syn_conn = utils.synapse_login()
assert syn_conn == syn
patch_synapse.assert_called_once_with(
configPath=synapseclient.client.CONFIG_FILE
)
patch_login.assert_called_once()


def test_synapse_login_specify():
"""Test default synapse login config path"""
syn = Mock()
temp_config = tempfile.NamedTemporaryFile()
with patch.object(synapseclient, "Synapse",
return_value=syn) as patch_synapse:
syn_conn = utils.synapse_login(synapse_config=temp_config.name)
assert syn_conn == syn
patch_synapse.assert_called_once_with(
configPath=temp_config.name
)
temp_config.close()


@pytest.mark.parametrize("error", [SynapseAuthenticationError,
SynapseNoCredentialsError])
def test_synapse_login_error(error):
"""Test default synapse login config path"""
syn = Mock()
with patch.object(synapseclient, "Synapse", return_value=syn),\
patch.object(syn, "login", side_effect=error),\
pytest.raises(ValueError,
match=r"Login error: please make sure you .*"):
utils.synapse_login()

0 comments on commit 2d5edf8

Please sign in to comment.