Skip to content

Commit f238420

Browse files
committed
get id from handle and misc refactoring
1 parent 59fc7a6 commit f238420

File tree

6 files changed

+90
-74
lines changed

6 files changed

+90
-74
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
language: python
22
python:
3-
- "3.7"
3+
- "3.8"
44
install:
55
- pipenv install --dev
66
script:

Pipfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ requests-mock = "*"
1010
[packages]
1111
requests = "*"
1212
structlog = "*"
13-
attr = "*"
13+
attrs = "*"
1414
click = "*"
1515
lxml = "*"
1616

1717
[requires]
18-
python_version = "3.7"
18+
python_version = "3.8"
1919

2020
[scripts]
2121
dsaps = "python -c \"from dsaps.cli import main; main()\""

dsaps/cli.py

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
@click.pass_context
2525
def main(ctx, url, email, password):
2626
ctx.obj = {}
27+
if os.path.isdir('logs') is False:
28+
os.mkdir('logs')
2729
dt = datetime.datetime.utcnow().isoformat(timespec='seconds')
2830
log_suffix = f'{dt}.log'
2931
structlog.configure(processors=[
@@ -47,31 +49,6 @@ def main(ctx, url, email, password):
4749
ctx.obj['start_time'] = start_time
4850

4951

50-
@click.group()
51-
def aux():
52-
pass
53-
54-
55-
@main.command()
56-
@click.option('-f', '--field', prompt='Enter the field to be searched',
57-
help='The field to search.')
58-
@click.option('-s', '--string', prompt='Enter the string',
59-
help='The field to search.')
60-
@click.option('-t', '--search_type', prompt='Enter the type of search',
61-
help='The type of search.',
62-
type=click.Choice(['exists', 'doesnt_exist', 'equals',
63-
'not_equals', 'contains', 'doesnt_contain']),
64-
default='contains')
65-
@click.pass_context
66-
def search(ctx, field, string, search_type):
67-
# Temp function for testing
68-
client = ctx.obj['client']
69-
start_time = ctx.obj['start_time']
70-
item_links = client.filtered_item_search(field, string, search_type)
71-
logger.info(item_links)
72-
models.elapsed_time(start_time, 'Elapsed time')
73-
74-
7552
@main.command()
7653
@click.option('-c', '--comm_handle', prompt='Enter the community handle',
7754
help='The handle of the community in which to create the ,'
@@ -111,7 +88,7 @@ def newcoll(ctx, comm_handle, coll_name, metadata, file_path, file_type,
11188
models.elapsed_time(start_time, 'Total runtime:')
11289

11390

114-
@aux.command()
91+
@main.command()
11592
@click.option('-m', '--metadata_csv', prompt='Enter the metadata CSV file',
11693
help='The path of the CSV file of metadata.')
11794
@click.option('-f', '--file_path', prompt='Enter the path',
@@ -150,7 +127,7 @@ def reconcile(metadata_csv, file_path, file_type):
150127
models.create_csv_from_list(metadata_matches, 'metadata_matches.csv')
151128

152129

153-
@aux.command()
130+
@main.command()
154131
@click.option('-m', '--metadata_csv', prompt='Enter the metadata CSV file',
155132
help='The path of the CSV file of metadata.')
156133
def metadatajson(metadata_csv):
@@ -190,7 +167,5 @@ def metadatajson(metadata_csv):
190167
json.dump(metadata_group, f)
191168

192169

193-
cli = click.CommandCollection(sources=[main, aux])
194-
195170
if __name__ == '__main__':
196-
cli()
171+
main()

dsaps/models.py

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ def filtered_item_search(self, key, string, query_type,
7777
offset = offset + 200
7878
return item_links
7979

80+
def get_id_from_handle(self, handle):
81+
"""Posts a collection to a specified community."""
82+
endpoint = f'{self.url}/handle/{handle}'
83+
rec_obj = requests.get(endpoint, headers=self.header,
84+
cookies=self.cookies).json()
85+
return rec_obj['uuid']
86+
8087
def post_coll_to_comm(self, comm_handle, coll_name):
8188
"""Posts a collection to a specified community."""
8289
endpoint = f'{self.url}/handle/{comm_handle}'
@@ -119,13 +126,17 @@ def post_bitstreams_to_item(self, item_id, file_identifier, file_dict,
119126
ingest_type):
120127
"""Posts bitstreams to a specified item."""
121128
for k, v in file_dict.items():
129+
bitstreams = []
122130
if k.startswith(file_identifier):
123-
bitstream = file_dict[k]
124-
file_name = os.path.basename(bitstream)
131+
bitstreams.append(k)
132+
bitstreams.sort()
133+
for bitstream in bitstreams:
134+
bitstream_path = file_dict[bitstream]
135+
file_name = os.path.basename(bitstream_path)
125136
if ingest_type == 'local':
126-
data = open(bitstream, 'rb')
137+
data = open(bitstream_path, 'rb')
127138
elif ingest_type == 'remote':
128-
data = requests.get(bitstream)
139+
data = requests.get(bitstream_path)
129140
endpoint = (f'{self.url}/items/{item_id}'
130141
+ f'/bitstreams?name={file_name}')
131142
header_upload = {'accept': 'application/json'}
@@ -192,7 +203,7 @@ def build_file_dict_remote(directory_url, file_type, file_dict):
192203
"""Build list of files in a remote directory."""
193204
response = requests.get(directory_url)
194205
links = html.fromstring(response.content).iterlinks()
195-
for link in [l for l in links if l[2].endswith(file_type)]:
206+
for link in [i for i in links if i[2].endswith(file_type)]:
196207
file_identifier = link[2].replace(f'.{file_type}', '')
197208
file_dict[file_identifier] = f'{directory_url}{link[2]}'
198209
return file_dict
@@ -213,24 +224,38 @@ def elapsed_time(start_time, label):
213224
logger.info(f'{label} : {td}')
214225

215226

216-
def metadata_csv(row, key, field, language=None):
227+
def metadata_csv(row, key, field, language=None, delimiter=''):
217228
"""Create metadata element from CSV."""
218-
value = row[field]
219-
if language is not None:
220-
metadata_elem = {'key': key, 'language': language, 'value':
221-
value}
222-
else:
223-
metadata_elem = {'key': key, 'value': value}
224-
return metadata_elem
229+
metadata_elems = []
230+
if row[field] != '':
231+
if delimiter != '' and delimiter in row[field]:
232+
values = row[field].split(delimiter)
233+
for value in values:
234+
if language is not None:
235+
metadata_elem = {'key': key, 'language': language, 'value':
236+
value}
237+
metadata_elems.append(metadata_elem)
238+
else:
239+
metadata_elem = {'key': key, 'value': value}
240+
metadata_elems.append(metadata_elem)
241+
else:
242+
value = row[field]
243+
if language is not None:
244+
metadata_elem = {'key': key, 'language': language, 'value':
245+
value}
246+
else:
247+
metadata_elem = {'key': key, 'value': value}
248+
metadata_elems.append(metadata_elem)
249+
return metadata_elems
225250

226251

227252
def create_metadata_rec(mapping_dict, row, metadata_rec):
228253
"""Create metadata record from CSV."""
229254
for k, v in mapping_dict.items():
230-
if len(v) == 2:
231-
metadata_elem = metadata_csv(row, k, v[0], v[1])
255+
if len(v) == 3:
256+
metadata_elems = metadata_csv(row, k, v[0], v[1], v[2])
232257
else:
233-
metadata_elem = metadata_csv(row, k, v[0])
234-
if metadata_elem['value'] != '':
258+
metadata_elems = metadata_csv(row, k, v[0])
259+
for metadata_elem in metadata_elems:
235260
metadata_rec.append(metadata_elem)
236261
return metadata_rec

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from setuptools import setup, find_packages
22

33
setup(
4-
name='DSpace API Python Scripts',
4+
name='dsaps',
55
version='1.0.0',
66
description='',
77
packages=find_packages(exclude=['tests']),
@@ -10,7 +10,7 @@
1010
install_requires=[
1111
'requests',
1212
'structlog',
13-
'attr',
13+
'attrs',
1414
'click',
1515
'lxml',
1616
],
@@ -19,5 +19,5 @@
1919
'dsaps=dsaps.cli:main',
2020
]
2121
},
22-
python_requires='>=3.7.1',
22+
python_requires='>=3.8',
2323
)

tests/test_models.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ def test_authenticate(client):
3030
email = 'test@test.mock'
3131
password = '1234'
3232
cookies = {'JSESSIONID': '11111111'}
33-
json_object = {'fullname': 'User Name'}
33+
user_json = {'fullname': 'User Name'}
3434
m.post('mock://example.com/login', cookies=cookies)
35-
m.get('mock://example.com/status', json=json_object)
35+
m.get('mock://example.com/status', json=user_json)
3636
client.authenticate(email, password)
3737
assert client.user_full_name == 'User Name'
3838
assert client.cookies == cookies
@@ -42,10 +42,10 @@ def test_get_record(client):
4242
"""Test get_record method."""
4343
with requests_mock.Mocker() as m:
4444
uri = 'mock://example.com/items/123?expand=all'
45-
json_object = {'metadata': {'title': 'Sample title'}, 'type': 'item'}
46-
m.get(uri, json=json_object)
45+
rec_json = {'metadata': {'title': 'Sample title'}, 'type': 'item'}
46+
m.get(uri, json=rec_json)
4747
rec_obj = client.get_record('123', 'items')
48-
assert attr.asdict(rec_obj)['metadata'] == json_object['metadata']
48+
assert attr.asdict(rec_obj)['metadata'] == rec_json['metadata']
4949

5050

5151
def test_filtered_item_search(client):
@@ -55,25 +55,35 @@ def test_filtered_item_search(client):
5555
string = 'test'
5656
query_type = 'contains'
5757
endpoint = 'mock://example.com/filtered-items?'
58-
json_object_1 = {'items': [{'link': '1234'}]}
59-
json_object_2 = {'items': []}
60-
m.get(endpoint, [{'json': json_object_1}, {'json': json_object_2}])
58+
results_json1 = {'items': [{'link': '1234'}]}
59+
results_json2 = {'items': []}
60+
m.get(endpoint, [{'json': results_json1}, {'json': results_json2}])
6161

6262
item_links = client.filtered_item_search(key, string, query_type,
6363
selected_collections='')
6464
assert '1234' in item_links
6565

6666

67+
def test_get_id_from_handle(client):
68+
"""Test get_id_from_handle method."""
69+
with requests_mock.Mocker() as m:
70+
handle = 'mock://example.com/handle/111.1111'
71+
rec_json = {'uuid': '123'}
72+
m.get(handle, json=rec_json)
73+
id = client.get_id_from_handle('111.1111')
74+
assert id == '123'
75+
76+
6777
def test_post_coll_to_comm(client):
6878
"""Test post_coll_to_comm method."""
6979
with requests_mock.Mocker() as m:
7080
comm_handle = '1234'
7181
coll_name = 'Test Collection'
72-
json_object_1 = {'uuid': 'a1b2'}
73-
json_object_2 = {'uuid': '5678'}
74-
m.get('mock://example.com/handle/1234', json=json_object_1)
82+
comm_json = {'uuid': 'a1b2'}
83+
coll_json = {'uuid': '5678'}
84+
m.get('mock://example.com/handle/1234', json=comm_json)
7585
m.post('mock://example.com/communities/a1b2/collections',
76-
json=json_object_2)
86+
json=coll_json)
7787
coll_id = client.post_coll_to_comm(comm_handle, coll_name)
7888
assert coll_id == '5678'
7989

@@ -86,15 +96,17 @@ def test_post_items_to_coll(client, sample_content):
8696
"value": "123"},
8797
{"key": "dc.title", "value":
8898
"Monitoring Works: Getting Teachers",
89-
"language": "en_US"}]}]
99+
"language": "en_US"},
100+
{"key": "dc.relation.isversionof",
101+
"value": "repo/0/ao/123"}]}]
90102
coll_id = '789'
91103
ingest_type = 'local'
92104
file_dict = {'123': sample_content}
93-
json_object_1 = {'uuid': 'a1b2'}
94-
m.post('mock://example.com/collections/789/items', json=json_object_1)
105+
item_json = {'uuid': 'a1b2', 'handle': '1111.1/1111'}
106+
m.post('mock://example.com/collections/789/items', json=item_json)
95107
url = 'mock://example.com/items/a1b2/bitstreams?name=123.pdf'
96-
json_object_2 = {'uuid': 'c3d4'}
97-
m.post(url, json=json_object_2)
108+
b_json = {'uuid': 'c3d4'}
109+
m.post(url, json=b_json)
98110
item_ids = client.post_items_to_coll(coll_id, coll_metadata, file_dict,
99111
ingest_type)
100112
for item_id in item_ids:
@@ -108,9 +120,9 @@ def test_post_bitstreams_to_item(client, sample_content):
108120
ingest_type = 'local'
109121
file_identifier = '123'
110122
file_dict = {'123': sample_content}
111-
json_object_1 = {'uuid': 'c3d4'}
123+
b_json = {'uuid': 'c3d4'}
112124
url = 'mock://example.com/items/a1b2/bitstreams?name=123.pdf'
113-
m.post(url, json=json_object_1)
125+
m.post(url, json=b_json)
114126
bit_ids = client.post_bitstreams_to_item(item_id, file_identifier,
115127
file_dict, ingest_type)
116128
for bit_id in bit_ids:
@@ -161,8 +173,12 @@ def test_metadata_csv():
161173
"""Test metadata_csv function."""
162174
row = {'title': 'Test title'}
163175
metadata_elem = models.metadata_csv(row, 'dc.title', 'title', 'en_US')
164-
assert metadata_elem['key'] == 'dc.title'
165-
assert metadata_elem['value'] == 'Test title'
176+
assert metadata_elem[0]['key'] == 'dc.title'
177+
assert metadata_elem[0]['value'] == 'Test title'
178+
179+
180+
# def test_create_ingest_report():
181+
# assert False
166182

167183

168184
def test_create_metadata_rec():

0 commit comments

Comments
 (0)