Skip to content

Commit

Permalink
add Object getattr for #287
Browse files Browse the repository at this point in the history
  • Loading branch information
jsh2134 committed Apr 24, 2020
1 parent d7a587c commit a42c8aa
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 38 deletions.
23 changes: 13 additions & 10 deletions solvebio/cli/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

from solvebio import Vault
from solvebio import Object
from solvebio import Dataset
from solvebio import DatasetImport
from solvebio import DatasetTemplate
from solvebio.utils.files import check_gzip_path
from solvebio.errors import SolveError
from solvebio.errors import NotFoundError
Expand Down Expand Up @@ -157,11 +160,11 @@ def _create_template_from_file(template_file, dry_run=False):
sys.exit(1)

if dry_run:
template = solvebio.DatasetTemplate(**template_json)
template = DatasetTemplate(**template_json)
print("A new dataset template will be created from: {0}"
.format(template_file))
else:
template = solvebio.DatasetTemplate.create(**template_json)
template = DatasetTemplate.create(**template_json)
print("A new dataset template was created with id: {0}"
.format(template.id))

Expand Down Expand Up @@ -189,7 +192,7 @@ def create_dataset(args, template=None):

try:
# Fail if a dataset already exists.
solvebio.Dataset.get_by_full_path(full_path)
Object.get_by_full_path(full_path, assert_type='dataset')
print('A dataset already exists at path: {0}'.format(full_path))
sys.exit(1)
except NotFoundError:
Expand All @@ -202,8 +205,8 @@ def create_dataset(args, template=None):
pass
elif args.template_id:
try:
template = solvebio.DatasetTemplate.retrieve(args.template_id)
except solvebio.SolveError as e:
template = DatasetTemplate.retrieve(args.template_id)
except SolveError as e:
if e.status_code != 404:
raise e
print("No template with ID {0} found!".format(args.template_id))
Expand Down Expand Up @@ -256,7 +259,7 @@ def create_dataset(args, template=None):
print("Metadata: {}".format(metadata))
return

return solvebio.Dataset.get_or_create_by_full_path(
return Dataset.get_or_create_by_full_path(
full_path,
capacity=args.capacity,
fields=fields,
Expand Down Expand Up @@ -394,8 +397,8 @@ def import_file(args):

if args.template_id:
try:
template = solvebio.DatasetTemplate.retrieve(args.template_id)
except solvebio.SolveError as e:
template = DatasetTemplate.retrieve(args.template_id)
except SolveError as e:
if e.status_code != 404:
raise e
print("No template with ID {0} found!".format(args.template_id))
Expand All @@ -410,7 +413,7 @@ def import_file(args):
dataset = create_dataset(args, template=template)
else:
try:
dataset = solvebio.Dataset.get_by_full_path(full_path)
dataset = Object.get_by_full_path(full_path, assert_type='dataset')
except solvebio.errors.NotFoundError:
print("Dataset not found: {0}".format(full_path))
print("Tip: use the --create-dataset flag "
Expand Down Expand Up @@ -442,7 +445,7 @@ def import_file(args):
kwargs.update(template.import_params)

# Create the import
import_ = solvebio.DatasetImport.create(
import_ = DatasetImport.create(
dataset_id=dataset.id,
commit_mode=args.commit_mode,
**kwargs
Expand Down
5 changes: 5 additions & 0 deletions solvebio/resource/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class Dataset(CreateableAPIResource,
def make_full_path(cls, vault_name, path, name, **kwargs):
from solvebio import SolveError

print('[Deprecated] Warning this method has been deprecated'
'and will be removed in a future released.'
'Use self.vault_object.full_path')

_client = kwargs.pop('client', None) or cls._client or client

try:
Expand Down Expand Up @@ -69,6 +73,7 @@ def get_or_create_by_full_path(cls, full_path, **kwargs):
from solvebio import Object
# Assert this is a dataset
kwargs['assert_type'] = 'dataset'
kwargs['object_type'] = 'dataset'
return Object.get_or_create_by_full_path(full_path, **kwargs)

def saved_queries(self, **params):
Expand Down
30 changes: 20 additions & 10 deletions solvebio/resource/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,17 +418,27 @@ def objects(self, **params):
def ls(self, **params):
return self.objects(**params)

def query(self, query=None, **params):
"""Shortcut to query the underlying Dataset object"""
from solvebio import Dataset
def __getattr__(self, name):
"""Shortcut to access attributes of the underlying Dataset resource"""
from solvebio.resource import Dataset

valid_attrs = [
# query data
'query', 'lookup',
# transform data
'import_file', 'export', 'migrate',
# dataset meta
'fields', 'template', 'imports', 'commits',
# helpers
'activity', 'saved_queries'
]
if name in valid_attrs and self.is_dataset:
return getattr(Dataset(self.dataset_id, client=self._client), name)

if not self.is_dataset:
raise SolveError(
"The query method can only be used by a dataset. Found a {}"
.format(self.object_type))

return Dataset(self.dataset_id, client=self._client).query(
query=query, **params)
try:
return self[name]
except KeyError as err:
raise AttributeError(*err.args)

@property
def parent(self):
Expand Down
10 changes: 9 additions & 1 deletion solvebio/test/client_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def solve_objects(self):
return ExtendedList([self.create()])

def update_paths(self):
"""Sets vault_name, path and full_path"""
"""Sets vault_name, path and full_path based on mock inputs"""
if not self.object['vault_name']:
self.object['vault_name'] = 'mock_vault'

Expand All @@ -55,6 +55,11 @@ def update_paths(self):
self.object['full_path'] = 'solvebio:{0}:{1}'.format(
self.object['vault_name'], self.object['path'])

def update_dataset(self):
"""Sets dataset_id if object is a dataset"""
if self.object['object_type'] == 'dataset':
self.object['dataset_id'] = self.object['id']


class FakeMigrationResponse(Fake201Response):

Expand Down Expand Up @@ -122,6 +127,7 @@ def __init__(self, data):
}
self.object.update(data)
self.update_paths()
self.update_dataset()


class FakeDatasetResponse(Fake201Response):
Expand Down Expand Up @@ -220,6 +226,8 @@ def fake_object_retrieve(*args, **kwargs):


def fake_dataset_create(*args, **kwargs):
# Dataset.create() is deprecated
print("WARNING: Your code likely wants to be using FakeObjectCreate.")
return FakeDatasetResponse(kwargs).create()


Expand Down
33 changes: 16 additions & 17 deletions solvebio/test/test_shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from solvebio.test.client_mocks import fake_object_all
from solvebio.test.client_mocks import fake_object_create
from solvebio.test.client_mocks import fake_object_retrieve
from solvebio.test.client_mocks import fake_dataset_create
from solvebio.test.client_mocks import fake_dataset_tmpl_create
from solvebio.test.client_mocks import fake_dataset_tmpl_retrieve
from solvebio.test.client_mocks import fake_dataset_import_create
Expand All @@ -43,23 +42,23 @@ def setUp(self):

@mock.patch('solvebio.resource.Vault.all')
@mock.patch('solvebio.resource.Object.all')
@mock.patch('solvebio.resource.Dataset.create')
@mock.patch('solvebio.resource.Object.create')
def test_create_dataset(self, DatasetCreate, ObjectAll, VaultAll):
DatasetCreate.side_effect = fake_dataset_create
DatasetCreate.side_effect = fake_object_create
ObjectAll.side_effect = fake_object_all
VaultAll.side_effect = fake_vault_all
args = ['create-dataset', 'solvebio:test_vault:/test-dataset',
'--capacity', 'small']
ds = main.main(args)
self.assertEqual(ds.name, 'test-dataset')
self.assertEqual(ds.filename, 'test-dataset')
self.assertEqual(ds.path, '/test-dataset')

@mock.patch('solvebio.resource.Vault.all')
@mock.patch('solvebio.resource.Object.all')
@mock.patch('solvebio.resource.Dataset.create')
@mock.patch('solvebio.resource.Object.create')
def test_create_dataset_by_filename(self, DatasetCreate, ObjectAll,
VaultAll):
DatasetCreate.side_effect = fake_dataset_create
DatasetCreate.side_effect = fake_object_create
ObjectAll.side_effect = fake_object_all
VaultAll.side_effect = fake_vault_all
args = [
Expand All @@ -71,7 +70,7 @@ def test_create_dataset_by_filename(self, DatasetCreate, ObjectAll,
'--metadata', 'TEST2=tag2',
]
ds = main.main(args)
self.assertEqual(ds.name, 'test-dataset-filename')
self.assertEqual(ds.filename, 'test-dataset-filename')
self.assertEqual(ds.path, '/test-dataset-filename')
self.assertEqual(ds.capacity, 'small')
self.assertEqual(ds.tags, ['tag_test'])
Expand All @@ -90,13 +89,13 @@ def _validate_tmpl_fields(self, fields):

@mock.patch('solvebio.resource.Vault.all')
@mock.patch('solvebio.resource.Object.all')
@mock.patch('solvebio.resource.Dataset.create')
@mock.patch('solvebio.resource.Object.create')
@mock.patch('solvebio.resource.DatasetTemplate.create')
def test_create_dataset_upload_template(self, TmplCreate,
DatasetCreate, ObjectAll,
VaultAll):
TmplCreate.side_effect = fake_dataset_tmpl_create
DatasetCreate.side_effect = fake_dataset_create
DatasetCreate.side_effect = fake_object_create
ObjectAll.side_effect = fake_object_all
VaultAll.side_effect = fake_vault_all

Expand All @@ -112,14 +111,14 @@ def test_create_dataset_upload_template(self, TmplCreate,

@mock.patch('solvebio.resource.Vault.all')
@mock.patch('solvebio.resource.Object.all')
@mock.patch('solvebio.resource.Dataset.create')
@mock.patch('solvebio.resource.Object.create')
@mock.patch('solvebio.resource.DatasetTemplate.retrieve')
@mock.patch('solvebio.resource.DatasetTemplate.create')
def test_create_dataset_template_id(self, TmplCreate, TmplRetrieve,
DatasetCreate, ObjectAll, VaultAll):
VaultAll.side_effect = fake_vault_all
ObjectAll.side_effect = fake_object_all
DatasetCreate.side_effect = fake_dataset_create
DatasetCreate.side_effect = fake_object_create
TmplRetrieve.side_effect = fake_dataset_tmpl_retrieve
TmplCreate.side_effect = fake_dataset_tmpl_create

Expand All @@ -145,15 +144,15 @@ def test_create_dataset_template_id(self, TmplCreate, TmplRetrieve,
@mock.patch('solvebio.resource.Vault.all')
@mock.patch('solvebio.resource.Object.all')
@mock.patch('solvebio.resource.Object.upload_file')
@mock.patch('solvebio.resource.Dataset.create')
@mock.patch('solvebio.resource.Object.create')
@mock.patch('solvebio.resource.DatasetImport.create')
def _test_import_file(self, args, DatasetImportCreate, DatasetCreate,
ObjectCreate, ObjectAll, VaultAll, VaultLookup,
def _test_import_file(self, args, DatasetImportCreate, ObjectCreate,
UploadFile, ObjectAll, VaultAll, VaultLookup,
UploadPath, TmplCreate, TmplRetrieve):
DatasetImportCreate.side_effect = fake_dataset_import_create
DatasetCreate.side_effect = fake_dataset_create
ObjectAll.side_effect = fake_object_all
ObjectCreate.side_effect = fake_object_create
UploadFile.side_effect = fake_object_create
ObjectAll.side_effect = fake_object_all
VaultAll.side_effect = fake_vault_all
UploadPath.side_effect = upload_path
VaultLookup.side_effect = fake_vault_create
Expand Down Expand Up @@ -199,7 +198,7 @@ def test_import_tilde(self):
]:
args = ['import', '--create-dataset', dataset_path, file_]
imports, ds = self._test_import_file(args)
self.assertEqual(ds.name, 'test-dataset')
self.assertEqual(ds.filename, 'test-dataset')
# should be a manifest with a single file
self.assertEqual(len(imports[0].manifest['files']), 1)

Expand Down

0 comments on commit a42c8aa

Please sign in to comment.