Skip to content

Commit

Permalink
Merge pull request #274 from whole-tale/publish-refactor
Browse files Browse the repository at this point in the history
Add publishInfo as array
  • Loading branch information
craig-willis committed Mar 25, 2019
2 parents 562b36e + cd9f4d8 commit 59559c2
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 104 deletions.
1 change: 1 addition & 0 deletions plugin.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ add_python_test(dataset
EXTERNAL_DATA
plugins/wholetale/dataset_register.txt
)
add_python_test(publish PLUGIN wholetale)
add_python_style_test(python_static_analysis_wholetale
"${PROJECT_SOURCE_DIR}/plugins/wholetale/server")
98 changes: 98 additions & 0 deletions plugin_tests/publish_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from bson import ObjectId
import mock
from tests import base


def setUpModule():
base.enabledPlugins.append('wholetale')
base.startServer()

global JobStatus, Tale
from girder.plugins.jobs.constants import JobStatus
from girder.plugins.wholetale.models.tale import Tale


def tearDownModule():
base.stopServer()


class FakeJob:

job = {}

def delay(self, *args, **kwargs):
return self.job


class PublishTestCase(base.TestCase):
def setUp(self):
super(PublishTestCase, self).setUp()
users = (
{
'email': 'root@dev.null',
'login': 'admin',
'firstName': 'Root',
'lastName': 'van Klompf',
'password': 'secret',
},
{
'email': 'joe@dev.null',
'login': 'joeregular',
'firstName': 'Joe',
'lastName': 'Regular',
'password': 'secret',
},
)
self.admin, self.user = [
self.model('user').createUser(**user) for user in users
]

self.tale = self.model('tale', 'wholetale').createTale(
{'_id': ObjectId()},
data=[],
authors=self.user['firstName'] + ' ' + self.user['lastName'],
creator=self.user,
public=True,
description="blah",
title="Test",
illustration='linkToImage',
)

def testPublish(self):
with mock.patch('gwvolman.tasks.publish.apply_async'), mock.patch(
'gwvolman.tasks.publish.delay'
) as dl:

dl.return_value = FakeJob()
remoteMemberNode = 'remoteMemberURL'
authToken = 'tokenXXX'

resp = self.request(
path='/publish/dataone',
method='GET',
user=self.user,
params={
'taleId': str(self.tale['_id']),
'remoteMemberNode': remoteMemberNode,
'authToken': authToken,
},
)
self.assertStatusOk(resp)
job_call = dl.call_args_list[-1][-1]
job_call.pop('girder_client_token')
self.assertDictEqual(
job_call,
(
{
'dataone_auth_token': authToken,
'dataone_node': remoteMemberNode,
'tale': str(self.tale['_id']),
'user_id': str(self.user['_id']),
}
),
)

def tearDown(self):
self.model('user').remove(self.user)
self.model('user').remove(self.admin)
super(PublishTestCase, self).tearDown()
60 changes: 33 additions & 27 deletions plugin_tests/tale_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,16 @@ def testTaleFlow(self):
'title': 'new name',
'description': 'new description',
'config': {'memLimit': '2g'},
'public': True,
'published': False,
'doi': 'doi:10.x.x.xx',
'publishedURI': 'publishedURI_URL',
'licenseSPDX': taleLicense
'public': False,
'licenseSPDX': taleLicense,
'publishInfo': [
{

'pid': 'published_pid',
'uri': 'published_url',
'date': '2019-01-23T15:48:17.476000+00:00',
}
]
})
)
self.assertStatusOk(resp)
Expand Down Expand Up @@ -512,7 +517,7 @@ def testTaleValidation(self):
"folderId": data_dir['_id'],
"imageId": "5873dcdbaec030000144d233",
"public": True,
"published": False,
"publishInfo": [],
"title": "Fake Unvalidated Tale"
}
tale = self.model('tale', 'wholetale').save(tale) # get's id
Expand Down Expand Up @@ -572,9 +577,6 @@ def testTaleUpdate(self):
description = 'new description'
config = {'memLimit': '2g'}
public = True
published = True
doi = 'doi:10.x.zz'
published_uri = 'atestURI'
tale_licenses = WholeTaleLicense()
taleLicense = tale_licenses.supported_spdxes().pop()

Expand All @@ -592,10 +594,14 @@ def testTaleUpdate(self):
'description': 'description',
'config': {},
'public': False,
'published': False,
'doi': 'doi',
'publishedURI': 'published_uri',
'licenseSPDX': taleLicense
'licenseSPDX': taleLicense,
'publishInfo': [
{
'pid': 'published_pid',
'uri': 'published_url',
'date': '2019-01-23T15:48:17.476000+00:00',
}
]
})
)

Expand All @@ -618,10 +624,14 @@ def testTaleUpdate(self):
'description': description,
'config': config,
'public': public,
'published': published,
'doi': doi,
'publishedURI': published_uri,
'licenseSPDX': newLicense
'licenseSPDX': newLicense,
'publishInfo': [
{
'pid': 'published_pid',
'uri': 'published_url',
'date': '2019-01-23T15:48:17.476000+00:00',
}
]
})
)

Expand All @@ -632,9 +642,9 @@ def testTaleUpdate(self):
self.assertEqual(resp.json['description'], description)
self.assertEqual(resp.json['config'], config)
self.assertEqual(resp.json['public'], public)
self.assertEqual(resp.json['published'], published)
self.assertEqual(resp.json['doi'], doi)
self.assertEqual(resp.json['publishedURI'], published_uri)
self.assertEqual(resp.json['publishInfo'][0]['pid'], 'published_pid')
self.assertEqual(resp.json['publishInfo'][0]['uri'], 'published_url')
self.assertEqual(resp.json['publishInfo'][0]['date'], '2019-01-23T15:48:17.476000+00:00')
self.assertEqual(resp.json['licenseSPDX'], newLicense)

def testManifest(self):
Expand All @@ -650,9 +660,7 @@ def testManifest(self):
'description': 'description',
'config': {},
'public': False,
'published': False,
'doi': 'doi',
'publishedURI': 'published_uri',
'publishInfo': [],
'licenseSPDX': WholeTaleLicense.default_spdx()
})
)
Expand All @@ -661,7 +669,7 @@ def testManifest(self):
pth = '/tale/{}/manifest'.format(str(resp.json['_id']))
resp = self.request(
path=pth, method='GET', user=self.user)
# The contents of the manifes are checked in the manifest tests, so
# The contents of the manifest are checked in the manifest tests, so
# just make sure that we get the right response
self.assertStatus(resp, 200)

Expand Down Expand Up @@ -765,9 +773,7 @@ def testExport(self):
'description': 'description',
'config': {},
'public': False,
'published': False,
'doi': 'doi',
'publishedURI': 'published_uri',
'publishInfo': [],
'licenseSPDX': WholeTaleLicense.default_spdx()
})
)
Expand Down
29 changes: 7 additions & 22 deletions server/models/tale.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@ def initialize(self):
})
self.modifiableFields = {
'title', 'description', 'public', 'config', 'updated', 'authors',
'category', 'icon', 'iframe', 'illustration', 'dataSet',
'published', 'doi', 'publishedURI', 'licenseSPDX', 'workspaceModified'
'category', 'icon', 'iframe', 'illustration', 'dataSet', 'licenseSPDX',
'workspaceModified', 'publishInfo'
}
self.exposeFields(
level=AccessType.READ,
fields=({'_id', 'folderId', 'imageId', 'creatorId', 'created',
'format', 'dataSet', 'narrative', 'narrativeId', 'licenseSPDX',
'imageInfo', 'doi', 'publishedURI', 'workspaceId',
'imageInfo', 'publishInfo', 'workspaceId',
'workspaceModified'} | self.modifiableFields))
self.exposeFields(level=AccessType.ADMIN, fields={'published'})

def validate(self, tale):
if 'iframe' not in tale:
Expand All @@ -49,11 +48,8 @@ def validate(self, tale):
if '_id' not in tale:
return tale

if 'doi' not in tale:
tale['doi'] = None

if 'publishedURI' not in tale:
tale['publishedURI'] = None
if 'publishInfo' not in tale:
tale['publishInfo'] = []

if 'dataSet' not in tale:
tale['dataSet'] = []
Expand All @@ -66,13 +62,6 @@ def validate(self, tale):

return tale

def setPublished(self, tale, publish, save=False):
assert isinstance(publish, bool)
tale['published'] = publish or tale['published']
if save:
tale = self.save(tale)
return tale

def list(self, user=None, data=None, image=None, limit=0, offset=0,
sort=None, currentUser=None, level=AccessType.READ):
"""
Expand Down Expand Up @@ -104,9 +93,8 @@ def list(self, user=None, data=None, image=None, limit=0, offset=0,
yield r

def createTale(self, image, data, creator=None, save=True, title=None,
description=None, public=None, config=None, published=False,
authors=None, icon=None, category=None, illustration=None,
narrative=None, doi=None, publishedURI=None,
description=None, public=None, config=None, authors=None,
icon=None, category=None, illustration=None, narrative=None,
licenseSPDX=WholeTaleLicense.default_spdx()):

if creator is None:
Expand Down Expand Up @@ -136,10 +124,7 @@ def createTale(self, image, data, creator=None, save=True, title=None,
'narrative': narrative or [],
'title': title,
'public': public,
'published': published,
'updated': now,
'doi': doi,
'publishedURI': publishedURI,
'licenseSPDX': licenseSPDX
}
if public is not None and isinstance(public, bool):
Expand Down
73 changes: 39 additions & 34 deletions server/rest/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@

from girder.api import access
from girder.api.describe import Description, autoDescribeRoute
from girder.constants import TokenScope
from girder.api.rest import Resource
from girder.constants import AccessType, TokenScope
from girder.api.rest import Resource, filtermodel
from girder.plugins.jobs.models.job import Job


from ..models.tale import Tale

from gwvolman.tasks import publish


class Publish(Resource):
"""
Endpoint for publishing Tales to DataOne and Globus.
Expand All @@ -18,42 +23,42 @@ def __init__(self):
self.route('GET', ('dataone',), self.dataonePublish)

@access.user(scope=TokenScope.DATA_WRITE)
@filtermodel(model=Job)
@autoDescribeRoute(
Description('Publish a tale to a repository running Metacat')
.notes('')
.param('taleId',
description='The ID of the tale that is going to be published.',
required=True)
.param('remoteMemberNode',
description='The endpoint for the Metacat instance, including the endpoint.\n'
'Example: \'https://dev.nceas.ucsb.edu/knb/d1/mn/v2\'',
required=True)
.param('authToken',
description='The user\'s authentication token for interacting with the '
'DataONE API. In DataONE\'s case, this is the user\'s JWT'
'token.',
required=True))
def dataonePublish(self,
taleId,
remoteMemberNode,
authToken):
.modelParam(
'taleId',
description='The ID of the tale that is going to be published.',
model=Tale,
paramType="query",
level=AccessType.ADMIN,
required=True,
)
.param(
'remoteMemberNode',
description='The endpoint for the Metacat instance, including the endpoint.\n'
'Example: \'https://dev.nceas.ucsb.edu/knb/d1/mn/v2\'',
required=True,
)
.param(
'authToken',
description='The user\'s authentication token for interacting with the '
'DataONE API. In DataONE\'s case, this is the user\'s JWT'
'token.',
required=True,
)
)
def dataonePublish(self, tale, remoteMemberNode, authToken):

user = self.getCurrentUser()
token = self.getCurrentToken()

jobTitle = 'Publishing Tale to DataONE'
jobModel = Job()

args = (taleId,
remoteMemberNode,
authToken,
str(token['_id']),
str(user['_id']))
job = jobModel.createJob(
title=jobTitle, type='publish', handler='worker_handler',
user=user, public=False, args=args, kwargs={},
otherFields={
'celeryTaskName': 'gwvolman.tasks.publish'
})
jobModel.scheduleJob(job)
return job
publishTask = publish.delay(
tale=str(tale['_id']),
dataone_node=remoteMemberNode,
dataone_auth_token=authToken,
user_id=str(user['_id']),
girder_client_token=str(token['_id'])
)
return publishTask.job

0 comments on commit 59559c2

Please sign in to comment.