• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

4dn-dcic / dcicwrangling / 8545209979

03 Apr 2024 08:37PM UTC coverage: 33.718% (+1.6%) from 32.1%
8545209979

push

github

web-flow
Merge pull request #113 from 4dn-dcic/ajs_add_del_script

New property or item status change script

81 of 95 new or added lines in 3 files covered. (85.26%)

8 existing lines in 8 files now uncovered.

1256 of 3725 relevant lines covered (33.72%)

1.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.16
/tests/test_script_utils.py
1
import pytest
4✔
2
from functions import script_utils as scu
4✔
3
import argparse
4✔
4
from collections import OrderedDict
4✔
5

6

7
@pytest.fixture
4✔
8
def eset_json():
4✔
9
    return {
4✔
10
        "schema_version": "2",
11
        "accession": "4DNES4GSP9S4",
12
        "award": "4871e338-b07d-4665-a00a-357648e5bad6",
13
        "alternate_accessions": [],
14
        "aliases": [
15
            "ren:HG00512_repset"
16
        ],
17
        "experimentset_type": "replicate",
18
        "status": "released",
19
        "experiments_in_set": [
20
            "d4b0e597-8c81-43e3-aeda-e9842fc18e8f",
21
            "8d10f11f-95a8-4b8d-8ff2-748ea8631a23"
22
        ],
23
        "lab": "795847de-20b6-4f8c-ba8d-185215469cbf",
24
        "public_release": "2017-06-30",
25
        "uuid": "9eb40c13-cf85-487c-9819-71ef74a22dcc",
26
        "documents": [],
27
        "description": "Dilution Hi-C experiment on HG00512",
28
        "submitted_by": "da4f53e5-4e54-4ae7-ad75-ba47316a8bfa",
29
        "date_created": "2017-04-28T17:46:08.642218+00:00",
30
        "replicate_exps": [
31
            {
32
                "replicate_exp": "d4b0e597-8c81-43e3-aeda-e9842fc18e8f",
33
                "bio_rep_no": 1,
34
                "tec_rep_no": 1
35
            },
36
            {
37
                "replicate_exp": "8d10f11f-95a8-4b8d-8ff2-748ea8631a23",
38
                "bio_rep_no": 2,
39
                "tec_rep_no": 1
40
            }
41
        ],
42
    }
43

44

45
@pytest.fixture
4✔
46
def bs_embed_json():
4✔
47
    return {
4✔
48
        "lab": {
49
            "display_title": "David Gilbert, FSU",
50
            "uuid": "6423b207-8176-4f06-a127-951b98d6a53a",
51
            "link_id": "~labs~david-gilbert-lab~",
52
            "@id": "/labs/david-gilbert-lab/"
53
        },
54
        "display_title": "4DNBSLACJHX1"
55
    }
56

57

58
@pytest.fixture
4✔
59
def profiles():
4✔
60
    return {
4✔
61
        "ExperimentSetReplicate": {
62
            "title": "Replicate Experiments",
63
            "description": "Experiment Set for technical/biological replicates.",
64
            "properties": {
65
                "tags": {"uniqueItems": "true", "description": "Key words that can tag an item - useful for filtering.", "type": "array", "ff_clear": "clone", "items": {"title": "Tag", "description": "A tag for the item.", "type": "string"}, "title": "Tags"},  # noqa: E501
66
                "documents": {"uniqueItems": "true", "description": "Documents that provide additional information (not data file).", "type": "array", "default": [], "comment": "See Documents sheet or collection for existing items.", "title": "Documents", "items": {"title": "Document", "description": "A document that provides additional information (not data file).", "type": "string", "linkTo": "Document"}},  # noqa: E501
67
                "notes": {"exclude_from": ["submit4dn", "FFedit-create"], "title": "Notes", "description": "DCIC internal notes.", "type": "string", "elasticsearch_mapping_index_type": {"title": "Field mapping index type", "description": "Defines one of three types of indexing available", "type": "string", "default": "analyzed", "enum": ["analyzed", "not_analyzed", "no"]}}  # noqa: E501
68
            }
69
        },
70
        "TreatmentChemical": {
71
            "title": "Chemical Treatment",
72
            "description": "A Chemical or Drug Treatment on Biosample.",
73
            "properties": {
74
                "documents": {"uniqueItems": "true", "description": "Documents that provide additional information (not data file).", "type": "array", "default": [], "comment": "See Documents sheet or collection for existing items.", "title": "Documents", "items": {"title": "Document", "description": "A document that provides additional information (not data file).", "type": "string", "linkTo": "Document"}},  # noqa: E501
75
                "public_release": {"anyOf": [{"format": "date-time"}, {"format": "date"}], "exclude_from": ["submit4dn", "FFedit-create"], "description": "The date which the item was released to the public", "permission": "import_items", "type": "string", "comment": "Do not submit, value is assigned when released.", "title": "Public Release Date"},  # noqa: E501
76
            }
77
        }
78
    }
79

80

81
@pytest.fixture
4✔
82
def auth():
4✔
83
    return {'key': 'portal_key', 'secret': 'super_secret_access', 'server': 'https://test_portal'}
4✔
84

85

86
def test_authenticate_no_key_or_env():
4✔
87
    with pytest.raises(Exception):
4✔
88
        scu.authenticate()
4✔
89
 
90

91
def test_authenicate_w_key_no_keyfile():
4✔
92
    with pytest.raises(SystemExit):
4✔
93
        scu.authenticate(key='testkey')
4✔
94

95

96
def test_authenticate_w_key_and_keyfile(mocker, auth):
4✔
97
    mocker.patch('functions.script_utils.get_key', return_value=auth)
4✔
98
    test_auth = scu.authenticate(key='testkey', keyfile='test_keyfile')
4✔
99
    assert test_auth == auth
4✔
100

101

102
def test_authenticate_w_env(mocker, auth):
4✔
103
    mocker.patch('functions.script_utils.get_authentication_with_server', return_value=auth)
4✔
104
    test_auth = scu.authenticate(env='testenv')
4✔
105
    assert test_auth == auth
4✔
106

107

108
def test_is_uuid():
4✔
109
    uuids = [
4✔
110
        '231111bc-8535-4448-903e-854af460b254',
111
        '231111bc-8535-4448-903e-854af460b25',
112
        '231111bc85354448903e854af460b254'
113
    ]
114
    for i, u in enumerate(uuids):
4✔
115
        if i == 0:
4✔
116
            assert scu.is_uuid(u)
4✔
117
        else:
118
            assert not scu.is_uuid(u)
4✔
119

120

121
def test_find_uuids_from_eset(eset_json):
4✔
122
    field2uuid = {
4✔
123
        "award": "4871e338-b07d-4665-a00a-357648e5bad6",
124
        "lab": "795847de-20b6-4f8c-ba8d-185215469cbf",
125
        "uuid": "9eb40c13-cf85-487c-9819-71ef74a22dcc",
126
        "submitted_by": "da4f53e5-4e54-4ae7-ad75-ba47316a8bfa"
127
    }
128
    exps = ["d4b0e597-8c81-43e3-aeda-e9842fc18e8f", "8d10f11f-95a8-4b8d-8ff2-748ea8631a23"]
4✔
129
    for field, val in eset_json.items():
4✔
130
        ulist = scu.find_uuids(val)
4✔
131
        if field in field2uuid:
4✔
132
            assert field2uuid[field] == ulist[0]
4✔
133
        elif field in ["experiments_in_set", "replicate_exps"]:
4✔
134
            for u in ulist:
4✔
135
                assert u in exps
4✔
136

137

138
def test_filter_dict_by_value(eset_json):
4✔
139
    to_filter = {
4✔
140
        "schema_version": "2",
141
        "accession": "4DNES4GSP9S4",
142
        "aliases": ["ren:HG00512_repset"]
143
    }
144
    vals = list(to_filter.values())
4✔
145
    included = scu.filter_dict_by_value(eset_json, vals)
4✔
146
    assert len(included) == len(to_filter)
4✔
147
    for f in to_filter.keys():
4✔
148
        assert f in included
4✔
149

150
    excluded = scu.filter_dict_by_value(eset_json, vals, include=False)
4✔
151
    assert len(excluded) == len(eset_json) - len(to_filter)
4✔
152
    for f in to_filter.keys():
4✔
153
        assert f not in excluded
4✔
154

155

156
def test_has_field_value_check_for_field_only(eset_json):
4✔
157
    fieldnames = ['schema_version', 'award', 'alternate_accessions']
4✔
158
    for f in fieldnames:
4✔
159
        assert scu.has_field_value(eset_json, f)
4✔
160

161

162
def test_has_field_value_no_it_doesnt(eset_json):
4✔
163
    fieldnames = ['biosample', 'blah', 'bio_rep_no']
4✔
164
    for f in fieldnames:
4✔
165
        assert not scu.has_field_value(eset_json, f)
4✔
166

167

168
def test_has_field_value_check_for_field_and_value(eset_json):
4✔
169
    fields_w_values = {
4✔
170
        "schema_version": "2",
171
        "accession": "4DNES4GSP9S4",
172
        "aliases": "ren:HG00512_repset"
173
    }
174
    for f, v in fields_w_values.items():
4✔
175
        assert scu.has_field_value(eset_json, f, v)
4✔
176

177

178
def test_has_field_value_check_for_field_w_item(bs_embed_json):
4✔
179
    f = "lab"
4✔
180
    v = "/labs/david-gilbert-lab/"
4✔
181
    assert scu.has_field_value(bs_embed_json, f, v, True)
4✔
182

183

184
def test_has_field_value_check_for_field_w_item_not_found(bs_embed_json):
4✔
185
    f = "lab"
4✔
186
    v = "/labs/nobodys-lab/"
4✔
187
    assert not scu.has_field_value(bs_embed_json, f, v, True)
4✔
188

189

190
def test_has_field_value_check_for_field_w_item_no_dict():
4✔
191
    f = "b"
4✔
192
    v = "/labs/david-gilbert-lab/"
4✔
193
    assert not scu.has_field_value('blah', f, v, True)
4✔
194

195

196
def test_has_field_value_value_not_found_in_list(eset_json):
4✔
197
    not_found = 'unfound'
4✔
198
    assert not scu.has_field_value(eset_json, 'experiments_in_set', not_found)
4✔
199

200

201
def test_has_field_value_value_not_found_as_string(eset_json):
4✔
202
    not_found = 'unfound'
4✔
203
    assert not scu.has_field_value(eset_json, 'status', not_found)
4✔
204

205

206
def test_get_types_that_can_have_field(mocker, profiles):
4✔
207
    field = 'tags'
4✔
208
    mocker.patch('functions.script_utils.get_metadata', return_value=profiles)
4✔
209
    types_w_field = scu.get_types_that_can_have_field('conn', field)
4✔
210
    assert 'ExperimentSetReplicate' in types_w_field
4✔
211
    assert 'TreatmentChemical' not in types_w_field
4✔
212

213

214
def test_get_item_type_from_dict(eset_json):
4✔
215
    eset_json['@type'] = ['ExperimentSetReplicate', 'ExperimentSet', 'Item']
4✔
216
    es_ty = scu.get_item_type('blah', eset_json)
4✔
217
    assert es_ty == 'ExperimentSetReplicate'
4✔
218

219

220
def test_get_item_type_from_id(mocker, auth):
4✔
221
    mocker.patch('functions.script_utils.get_metadata', return_value={'@type': ['ExperimentSetReplicate']})
4✔
222
    result = scu.get_item_type(auth, 'blah')
4✔
223
    assert result == 'ExperimentSetReplicate'
4✔
224

225

226
def test_get_item_type_no_type(mocker, auth, capsys):
4✔
227
    mocker.patch('functions.script_utils.get_metadata', return_value={'description': 'blah'})
4✔
228
    result = scu.get_item_type(auth, 'blah')
4✔
229
    out = capsys.readouterr()[0]
4✔
230
    assert out == "Can't find a type for item blah\n"
4✔
231
    assert result is None
4✔
232

233

234
@pytest.fixture
4✔
235
def items_w_uuids():
4✔
236
    return [
4✔
237
        {'name': 'one', 'uuid': 'a'},
238
        {'name': 'two', 'uuid': 'b'},
239
        {'name': 'three', 'uuid': 'c'},
240
    ]
241

242

243
def test_get_item_ids_from_list(auth):
4✔
244
    ids = ['a', 'b', 'c']
4✔
245
    result = scu.get_item_ids_from_args(ids, auth)
4✔
246
    for a in [i in ids for i in result]:
4✔
247
        assert a
4✔
248

249

250
def test_get_item_ids_from_search(mocker, auth, items_w_uuids):
4✔
251
    ids = ['a', 'b', 'c']
4✔
252
    mocker.patch('functions.script_utils.search_metadata', return_value=[])
4✔
253
    mocker.patch('functions.script_utils.get_metadata', return_value=items_w_uuids)
4✔
254
    result = scu.get_item_ids_from_args('search', auth, True)
4✔
255
    for a in [i in ids for i in result]:
4✔
256
        assert a
×
257

258

259
def test_get_item_uuid_w_uuid(auth):
4✔
260
    uid = '7868f960-50ac-11e4-916c-0800200c9a66'
4✔
261
    result = scu.get_item_uuid(uid, auth)
4✔
262
    assert result == uid
4✔
263

264

265
def test_get_item_uuid_w_atid(mocker, auth):
4✔
266
    atid = '/labs/test-lab'
4✔
267
    mt = mocker.patch('functions.script_utils.get_metadata', return_value={'uuid': 'test_uuid'})
4✔
268
    result = scu.get_item_uuid(atid, auth)
4✔
269
    assert mt.called_with(atid, auth)
4✔
270
    assert result == 'test_uuid'
4✔
271

272

273
def test_get_item_uuid_not_found(mocker, auth):
4✔
274
    atid = '/labs/non-lab'
4✔
275
    mt = mocker.patch('functions.script_utils.get_metadata', return_value={'status': 'error'})
4✔
276
    result = scu.get_item_uuid(atid, auth)
4✔
277
    assert mt.called_with(atid, auth)
4✔
278
    assert result is None
4✔
279

280

281
def test_create_ff_arg_parser(capsys):
4✔
282
    helpout = ['--env', '--key', '--dbupdate']
4✔
283
    parser = scu.create_ff_arg_parser()
4✔
284
    assert isinstance(parser, argparse.ArgumentParser)
4✔
285
    parser.print_help()
4✔
286
    out = capsys.readouterr()[0]
4✔
287
    for o in helpout:
4✔
288
        assert o in out
4✔
289

290

291
def test_create_input_arg_parser(capsys):
4✔
292
    helpout = ['input', '--search']
4✔
293
    parser = scu.create_input_arg_parser()
4✔
294
    assert isinstance(parser, argparse.ArgumentParser)
4✔
295
    parser.print_help()
4✔
296
    out = capsys.readouterr()[0]
4✔
297
    for o in helpout:
4✔
298
        assert o in out
4✔
299

300

301
def test_convert_key_arg_to_dict_good_key():
4✔
302
    inkey = "{'key': 'ABCDEF', 'secret': 'supersecret', 'server': 'https://data.4dnucleome.org'}"
4✔
303
    outkey = scu.convert_key_arg_to_dict(inkey)
4✔
304
    assert outkey == {'key': 'ABCDEF', 'secret': 'supersecret', 'server': 'https://data.4dnucleome.org'}
4✔
305

306

307
def test_convert_key_arg_to_dict_bad_key(capsys):
4✔
308
    inkey = "{'key': 'ABCDEF', 'secret': 'supersecret'}"
4✔
309
    with pytest.raises(SystemExit):
4✔
310
        scu.convert_key_arg_to_dict(inkey)
4✔
311
        out = capsys.readouterr()[0]
×
UNCOV
312
        assert out == "You included a key argument but it appears to be malformed or missing required info - see --help"
1✔
313

314

315
def test_get_linked_items_w_item_in_found(auth):
4✔
316
    itemid = 'itemid'
4✔
317
    found_items = {itemid: 1}
4✔
318
    iid = scu.get_linked_items(auth, itemid, found_items)
4✔
319
    assert itemid in iid
4✔
320

321

322
def test_get_linked_items_w_error_status(auth, mocker):
4✔
323
    mocker.patch('functions.script_utils.get_metadata', return_value={'status': 'error'})
4✔
324
    iids = scu.get_linked_items(auth, 'test_id')
4✔
325
    assert not iids
4✔
326

327

328
def test_get_linked_items_w_no_type(auth, mocker):
4✔
329
    mocker.patch('functions.script_utils.get_metadata',
4✔
330
                 side_effect=[{'status': 'released'}, {'field': 'value'}])
331
    iids_emp = scu.get_linked_items(auth, 'test_id')
4✔
332
    assert not iids_emp
4✔
333

334

335
def test_get_linked_items_w_type_in_no_children(auth, mocker):
4✔
336
    mocker.patch('functions.script_utils.get_metadata',
4✔
337
                 side_effect=[{'status': 'current'}, {'@type': ['Publication']}])
338
    iids = scu.get_linked_items(auth, 'test_id')
4✔
339
    assert iids['test_id'] == 'Publication'
4✔
340

341

342
def test_get_linked_items_w_linked_items(auth, mocker):
4✔
343
    goodids = ['test_id', '7256801c-9c6e-4563-a97a-a295fccf5f07']
4✔
344
    badids = ['6256801c-9c6e-4563-a97a-a295fccf5f07']
4✔
345
    resp1 = {
4✔
346
        'status': 'released',
347
        '@type': ['Biosample', 'Item'],
348
        'biosource': '7256801c-9c6e-4563-a97a-a295fccf5f07',
349
        'attachment': '6256801c-9c6e-4563-a97a-a295fccf5f07'
350
    }
351
    found = {'7256801c-9c6e-4563-a97a-a295fccf5f07': 'Biosource'}
4✔
352
    mocker.patch('functions.script_utils.get_metadata', side_effect=[resp1, {'@type': ['Biosample']}])
4✔
353
    mocker.patch('functions.script_utils.find_uuids', return_value=['7256801c-9c6e-4563-a97a-a295fccf5f07'])
4✔
354
    iids = scu.get_linked_items(auth, 'test_id', found)
4✔
355
    for i in iids:
4✔
356
        assert i in goodids
4✔
357
        assert i not in badids
4✔
358

359

360
def test_get_linked_items_w_no_linked_foundids(auth, mocker):
4✔
361
    goodids = ['test_id']
4✔
362
    badids = ['6256801c-9c6e-4563-a97a-a295fccf5f07']
4✔
363
    resp1 = {
4✔
364
        'status': 'released',
365
        '@type': ['Biosample', 'Item'],
366
        'biosource': '7256801c-9c6e-4563-a97a-a295fccf5f07',
367
        'attachment': '6256801c-9c6e-4563-a97a-a295fccf5f07'
368
    }
369
    found = {}
4✔
370
    mocker.patch('functions.script_utils.get_metadata', side_effect=[resp1, {'@type': ['Biosample']}])
4✔
371
    mocker.patch('functions.script_utils.find_uuids', return_value=None)
4✔
372
    iids = scu.get_linked_items(auth, 'test_id', found)
4✔
373
    for i in iids:
4✔
374
        assert i in goodids
4✔
375
        assert i not in badids
4✔
376

377

378
def test_get_linked_item_ids_w_recursive(auth, mocker):
4✔
379
    goodids = ['test_id', '7256801c-9c6e-4563-a97a-a295fccf5f07', '5256801c-9c6e-4563-a97a-a295fccf5f07']
4✔
380
    badids = ['6256801c-9c6e-4563-a97a-a295fccf5f07']
4✔
381
    resp1 = {
4✔
382
        'status': 'released',
383
        '@type': ['Biosample', 'Item'],
384
        'biosource': '7256801c-9c6e-4563-a97a-a295fccf5f07',
385
        'attachment': '6256801c-9c6e-4563-a97a-a295fccf5f07'
386
    }
387
    resp1 = OrderedDict(sorted(resp1.items(), key=lambda t: t[0]))
4✔
388
    resp2 = {
4✔
389
        'status': 'released',
390
        '@type': ['Biosource', 'Item'],
391
        'biosource_vendor': '5256801c-9c6e-4563-a97a-a295fccf5f07'
392
    }
393
    resp2 = OrderedDict(sorted(resp2.items(), key=lambda t: t[0]))
4✔
394
    resp3 = {
4✔
395
        'status': 'released',
396
    }
397
    mocker.patch('functions.script_utils.get_metadata', side_effect=[
4✔
398
        resp1, {'@type': ['Biosample']},
399
        resp2, {'@type': ['Biosource']},
400
        resp3, {'@type': ['Vendor']}
401
    ])
402
    mocker.patch('functions.script_utils.find_uuids', side_effect=[
4✔
403
        None,
404
        ['7256801c-9c6e-4563-a97a-a295fccf5f07'],
405
        None,
406
        None,
407
        ['5256801c-9c6e-4563-a97a-a295fccf5f07'],
408
        None,
409
        None
410
    ])
411
    iids = scu.get_linked_items(auth, 'test_id')
4✔
412
    for i in iids:
4✔
413
        assert i in goodids
4✔
414
        assert i not in badids
4✔
415

416

417
@pytest.fixture
4✔
418
def cell_line_json():
4✔
419
    return {
4✔
420
        "is_slim_for": "cell",
421
        "namespace": "http://www.ebi.ac.uk/efo",
422
        "term_id": "EFO:0000322",
423
        "term_name": "cell line",
424
        "source_ontology": "530006bc-8535-4448-903e-854af460b254",
425
        "term_url": "http://www.ebi.ac.uk/efo/EFO_0000322"
426
    }
427

428

429
def test_get_item_if_you_can_json_w_uuid(auth, eset_json):
4✔
430
    result = scu.get_item_if_you_can(auth, eset_json)
4✔
431
    assert result == eset_json
4✔
432

433

434
def test_get_item_if_you_can_w_uuid(mocker, auth, eset_json):
4✔
435
    mocker.patch('functions.script_utils.get_metadata', return_value=eset_json)
4✔
436
    result = scu.get_item_if_you_can(auth, eset_json['uuid'])
4✔
437
    assert result == eset_json
4✔
438

439

440
def test_get_item_if_you_can_w_termname_and_itype(mocker, auth, cell_line_json):
4✔
441
    mocker.patch('functions.script_utils.get_metadata', side_effect=[None, cell_line_json])
4✔
442
    result = scu.get_item_if_you_can(auth, cell_line_json['term_name'], 'OntologyTerm')
4✔
443
    assert result == cell_line_json
4✔
444

445

446
def test_get_item_if_you_can_w_termname_and_no_itype_no_item(mocker, auth, cell_line_json):
4✔
447
    mocker.patch('functions.script_utils.get_metadata', side_effect=[None, None])
4✔
448
    result = scu.get_item_if_you_can(auth, cell_line_json['term_name'])
4✔
449
    assert result is None
4✔
450

451

452
def test_get_item_if_you_can_w_fakename_and_itype_no_item(mocker, auth):
4✔
453
    mocker.patch('functions.script_utils.get_metadata', side_effect=[None, None])
4✔
454
    result = scu.get_item_if_you_can(auth, 'fake name', 'OntologyTerm')
4✔
455
    assert result is None
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc