├── pyalma
├── __init__.py
└── alma.py
├── test
├── __init__.py
├── loan.dat
├── availability.dat
├── request2.dat
├── request.dat
├── item_loan.dat
├── hold.dat
├── hold2.dat
├── holds.dat
├── item.dat
├── item2.dat
├── items.dat
├── bib.dat
├── bib2.dat
├── bib.dat.xml
├── bib2.dat.xml
├── test_coroutines.py
├── test_alma.py
└── mms_holdings_items_with_requests.csv
├── .gitignore
├── requirements.txt
├── .travis.yml
├── setup.py
├── speedtest
├── time_get_bibs.py
└── coroutines_speedtest.py
└── README.md
/pyalma/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Python cahce directories
2 | __pycache__/
3 | *.pyc
4 |
5 | # virtual environment
6 | ENV
7 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pymarc
2 | requests
3 | responses
4 | asyncio
5 | aiohttp<2.0
6 | ratelimiter
7 | asynctest
8 | aioresponses
9 |
--------------------------------------------------------------------------------
/test/loan.dat:
--------------------------------------------------------------------------------
1 | {
2 | "circ_desk": {
3 | "value": "DEFAULT_CIRC_DESK"
4 | },
5 | "library": {
6 | "value": "MAIN"
7 | }
8 | }
--------------------------------------------------------------------------------
/test/availability.dat:
--------------------------------------------------------------------------------
1 | {
2 | "from_time": 1401691527672,
3 | "to_time": 1401691527672,
4 | "user_id": null,
5 | "user_full_name": null,
6 | "reason": null
7 | }
--------------------------------------------------------------------------------
/test/request2.dat:
--------------------------------------------------------------------------------
1 | {
2 | "request_type": "HOLD",
3 | "pickup_location": "Burns",
4 | "pickup_location_type": "LIBRARY",
5 | "pickup_location_library": "BURNS",
6 | "comment": "my comment"
7 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - '3.5'
4 | - '3.6'
5 | install:
6 | - pip install -r requirements.txt
7 | - pip install coveralls
8 | notifications:
9 | email:
10 | recipients:
11 | - jgomez@getty.edu
12 | script:
13 | coverage run --source=pyalma setup.py test
14 | after_success:
15 | coveralls
16 |
17 |
--------------------------------------------------------------------------------
/test/request.dat:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Test title",
3 | "author": null,
4 | "description": null,
5 | "comment": null,
6 | "request_id": "83013520000121",
7 | "request_type": "HOLD",
8 | "pickup_location": "Burns",
9 | "pickup_location_type": "LIBRARY",
10 | "pickup_location_library": "BURNS",
11 | "material_type": {
12 | "value": "BK",
13 | "desc": "Book"
14 | },
15 | "request_status": "NOT_STARTED",
16 | "place_in_queue": 1,
17 | "request_date": "2013-11-12Z"
18 | }
19 |
--------------------------------------------------------------------------------
/test/item_loan.dat:
--------------------------------------------------------------------------------
1 | {
2 | "circ_desk": {
3 | "value": "DEFAULT_CIRC_DESK",
4 | "desc": "default circ desk"
5 | },
6 | "loan_id": "1234",
7 | "library": {
8 | "value": "MAIN",
9 | "desc": "Main Library"
10 | },
11 | "userId": "ID1234",
12 | "itemBarcode": "000237055710000121",
13 | "dueDate": "2014-06-23T14:00:00Z",
14 | "loanStatus": "ACTIVE",
15 | "loanDate": "2014-06-22T11:00:28Z",
16 | "processStatus": "NORMAL",
17 | "title": "History",
18 | "author": null,
19 | "description": "v2",
20 | "publicationYear": null,
21 | "locationCode": {
22 | "value": "Location 1",
23 | "name": "LOC1"
24 | }
25 | }
--------------------------------------------------------------------------------
/test/hold.dat:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "holding_id": "22115858660001551",
4 | "created_by": "import",
5 | "created_date": "2013-07-14Z",
6 | "anies": [
7 | "\n\n 00214cx a22000973 4500\n 398498\n 333281\n 20010412173201.0\n 0104120p 8 4001aueng0000000\n \n 94-B3418\n \n \n GC\n BOOKS:L2\n P93.5\n .T84 1992\n Copy 1\n \n "
8 | ]
9 |
10 | }
--------------------------------------------------------------------------------
/test/hold2.dat:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "holding_id": "22115858660001551",
4 | "created_by": "import",
5 | "created_date": "2013-07-14Z",
6 | "anies": [
7 | "\n\n 00214cx a22000973 4500\n 398498\n 333281\n 20010412173201.0\n 0104120p 8 4001aueng0000000\n \n 94-B3418\n \n \n GC\n BOOKS:L2\n P93.5\n .T84 1992\n Copy 2\n \n "
8 | ]
9 |
10 | }
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name = 'pyalma',
5 | packages = find_packages(),
6 | test_suite="test",
7 | version = '0.0.1',
8 | description = 'Python client for ExLibris Alma',
9 | author = 'Getty Research Institute',
10 | author_email = 'jgomez@getty.edu',
11 | url = 'https://stash.getty.edu/projects/GRIIS/repos/pyalma/browse',
12 | install_requires = ['pymarc', 'requests', 'aiohttp==1.3', 'ratelimiter'],
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "License :: OSI Approved :: MIT License",
17 | "Development Status :: pre-Alpha",
18 | "Intended Audience :: Developers",
19 | "Operating System :: OS Independent",
20 | "Topic :: Software Development :: Libraries :: Python Modules",
21 | ]
22 | )
23 |
--------------------------------------------------------------------------------
/test/holds.dat:
--------------------------------------------------------------------------------
1 | {
2 | "holding": [
3 | {
4 | "library": {
5 | "value": "65144020000121",
6 | "desc": "BURNS"
7 | },
8 | "location": {
9 | "value": "UNASSIGNED",
10 | "desc": "UNASSIGNED location"
11 | },
12 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221159990000121",
13 | "holding_id": "2221159990000121"
14 | },
15 | {
16 | "library": {
17 | "value": "5867020000121",
18 | "desc": "Main Library"
19 | },
20 | "location": {
21 | "value": "MICR",
22 | "desc": "Microforms"
23 | },
24 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221410000000121",
25 | "holding_id": "2221410000000121"
26 | }
27 | ],
28 | "bib_data": {
29 | "title": "Data base",
30 | "issn": "0095-0033",
31 | "publisher": "Association for Computing Machinery",
32 | "link": "/almaws/v1/bibs/99100383900121",
33 | "mms_id": 99100383900121,
34 | "place_of_publication": "New York :",
35 | "network_number": [
36 | "(CONSER) 2011250895",
37 | "(CKB)954926959913",
38 | "(OCoLC)604911177"
39 | ]
40 | },
41 | "total_record_count": 2
42 | }
43 |
--------------------------------------------------------------------------------
/test/item.dat:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "link": "https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9922405930001551/holdings/22115858660001551/items/23115858650001551",
4 | "bib_data": {
5 | "title": "Envisioning information /",
6 | "author": "Tufte, Edward R.,",
7 | "issn": null,
8 | "link": "https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9922405930001551",
9 | "mms_id": 9922405930001552,
10 | "complete_edition": "3rd printing, with revisions.",
11 | "place_of_publication": "Cheshire, Conn. :",
12 | "publisher_const": "Graphics Press",
13 | "network_number": [
14 | "(CMalG)333281-gettydb-Voyager",
15 | "(OCoLC)28384525",
16 | "333281"
17 | ]
18 | },
19 | "holding_data": {
20 | "link": "https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9922405930001551/holdings/22115858660001551",
21 | "holding_id": "22115858660001551",
22 | "call_number": "P93.5 .T84 1992",
23 | "temp_library": {
24 | "value": null,
25 | "desc": null
26 | },
27 | "temp_location": {
28 | "value": null,
29 | "desc": null
30 | }
31 | },
32 | "item_data": {
33 | "pid": "23115858650001551",
34 | "barcode": "33125006577916",
35 | "description": null,
36 | "library": {
37 | "value": "GC",
38 | "desc": "General Collections"
39 | },
40 | "location": {
41 | "value": "BOOKS:L2",
42 | "desc": "BOOKS:L2"
43 | },
44 | "requested": false,
45 | "physical_material_type": {
46 | "value": "BOOK",
47 | "desc": "Book"
48 | },
49 | "process_type": {
50 | "value": "LOAN",
51 | "desc": "Loan"
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/test/item2.dat:
--------------------------------------------------------------------------------
1 | {
2 | "link": "/almaws/v1/bibs/99110223950001021/holdings/22344156400001021/items/23344156380001021",
3 | "bib_data": {
4 | "title": "Visualizing data /",
5 | "author": "Fry, Ben.",
6 | "issn": null,
7 | "isbn": "9780596514556 (pbk.)",
8 | "link": "/almaws/v1/bibs/99110223950001021",
9 | "mms_id": 99110223950001020,
10 | "place_of_publication": "Sebastopol, CA :",
11 | "publisher_const": "O'Reilly Media Inc",
12 | "network_number": [
13 | "(OCoLC)ocn190865378",
14 | "(Aleph)002401490BCL01"
15 | ]
16 | },
17 | "holding_data": {
18 | "link": "/almaws/v1/bibs/99110223950001021/holdings/22344156400001021",
19 | "holding_id": "22344156400001021",
20 | "call_number": "T385 .F79 2008",
21 | "accession_number": "",
22 | "copy_id": "",
23 | "in_temp_location": false,
24 | "temp_library": {
25 | "value": null,
26 | "desc": null
27 | },
28 | "temp_location": {
29 | "value": null,
30 | "desc": null
31 | },
32 | "temp_call_number_type": {
33 | "value": "",
34 | "desc": null
35 | },
36 | "temp_call_number": "",
37 | "temp_policy": {
38 | "value": "",
39 | "desc": null
40 | }
41 | },
42 | "item_data": {
43 | "pid": "23344156380001021",
44 | "barcode": "39031031697261",
45 | "policy": {
46 | "value": "01",
47 | "desc": "01"
48 | },
49 | "provenance": {
50 | "value": "",
51 | "desc": null
52 | },
53 | "description": "",
54 | "library": {
55 | "value": "ONL",
56 | "desc": "O'Neill"
57 | },
58 | "location": {
59 | "value": "STACK",
60 | "desc": "Stacks (STACK)"
61 | },
62 | "pages": "",
63 | "pieces": "",
64 | "requested": false,
65 | "edition": null,
66 | "imprint": null,
67 | "language": null,
68 | "creation_date": "2012-06-10Z",
69 | "modification_date": "2012-06-10Z",
70 | "base_status": {
71 | "value": "1",
72 | "desc": "Item in place"
73 | },
74 | "physical_material_type": {
75 | "value": "BOOK",
76 | "desc": "Book"
77 | },
78 | "po_line": "08-000030003",
79 | "is_magnetic": false,
80 | "year_of_issue": "",
81 | "enumeration_a": "",
82 | "chronology_i": "",
83 | "receiving_operator": "",
84 | "process_type": {
85 | "value": "",
86 | "desc": null
87 | },
88 | "alternative_call_number": "",
89 | "alternative_call_number_type": {
90 | "value": "",
91 | "desc": null
92 | },
93 | "storage_location_id": "",
94 | "public_note": "",
95 | "fulfillment_note": "",
96 | "internal_note_1": "",
97 | "internal_note_2": "",
98 | "internal_note_3": "",
99 | "statistics_note_1": "",
100 | "statistics_note_2": "",
101 | "statistics_note_3": ""
102 | }
103 | }
--------------------------------------------------------------------------------
/speedtest/time_get_bibs.py:
--------------------------------------------------------------------------------
1 | from pprint import pprint
2 | # first import the library and create an api object
3 | from pyalma.alma import Alma
4 | from datetime import datetime
5 | import csv
6 |
7 | api = Alma(apikey='', region='')
8 |
9 |
10 | # creates a list of ids of number length
11 | # def create_id_list(number):
12 | # ids = []
13 | # counter = number
14 | # while counter > 0:
15 | # ids.append('9927390750001551')
16 | # counter -= 1
17 | # return ids
18 |
19 |
20 | # def test_normal(mm_ids):
21 | # # creates a datetime object showing how long it took for mm_ids
22 | # # to be retrieved serially
23 | # begin = datetime.now()
24 | # bibs = []
25 | # for mm_id in mm_ids:
26 | # bib = api.get_bib(mm_id)
27 | # bibs.append(bib)
28 | # # pprint(bib)
29 | # end = datetime.now()
30 | # diff = end - begin
31 | # print('Returned {} normal bibs'.format(len(bibs)))
32 | # return diff
33 |
34 |
35 | def test_coroutines(mms_ids):
36 | # creates a datetime object showing long it took for mm_ids
37 | # to be retrieved async via coroutines
38 | begin = datetime.now()
39 | input_params = [{"ids": {'mms_id': mms_id}, "data": None} for mms_id in mms_ids]
40 | bibs = api.cor_get_bibs(input_params)
41 | end = datetime.now()
42 | diff = end - begin
43 | count = 0
44 | for bib in bibs:
45 | if bib[1] > 200:
46 | count += 1
47 | print('\n\nReturned {} coroutine bibs, with {} errors'.format((len(bibs)-count),count))
48 | return [diff, bibs]
49 |
50 |
51 | def list_from_csv(csvfile, number):
52 | with open(csvfile, 'rt', encoding='utf8') as handle:
53 | reader = csv.reader(handle)
54 | ids = []
55 | counter = number
56 | for row in reader:
57 | if counter > 0:
58 | ids.append(row[0])
59 | counter -= 1
60 | return ids
61 |
62 |
63 | def test_repeat_bibs():
64 | num = int(input("Enter number of items to test: "))
65 | ids = create_id_list(num)
66 | t_coroutine = test_coroutines(ids)
67 | print("\n\nTime elapsed for {} ids: \n Coroutines: {} \n ".format(num, t_coroutine[0]))
68 |
69 |
70 | def write_to_csv(coroutines):
71 | with open('bibs_output.csv', 'w') as csvfile:
72 | bibwriter = csv.writer(csvfile)
73 | # bibwriter.writerow(['mms_id', 'status', 'msg'])
74 | bib_list = coroutines
75 | bibwriter.writerow(["ids", "status", "msg"])
76 | for bib in bib_list:
77 | bibwriter.writerow(bib)
78 |
79 |
80 | def test_from_csv(handle, num):
81 | ids = list_from_csv(handle, num)
82 | t_coroutine = test_coroutines(ids)
83 | print("\n\nTime elapsed for {} ids: \n Coroutines: {} \n ".format(num, t_coroutine[0]))
84 | return t_coroutine[1]
85 |
86 |
87 | if __name__ == '__main__':
88 | num = int(input("Enter number of items to test: "))
89 | handle = 'bibs.csv'
90 | bib_list = test_from_csv(handle, num)
91 | write_to_csv(bib_list)
92 |
--------------------------------------------------------------------------------
/test/items.dat:
--------------------------------------------------------------------------------
1 | {
2 | "item": [
3 | {
4 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221159990000121/items/2321159970000121",
5 | "bib_data": {
6 | "title": "Data base",
7 | "issn": "0095-0033",
8 | "link": "/almaws/v1/bibs/99100383900121",
9 | "mms_id": 99100383900121,
10 | "place_of_publication": "New York :",
11 | "publisher_const": "Association for Computing Machinery",
12 | "network_number": [
13 | "(CONSER) 2011250895",
14 | "(CKB)954926959913",
15 | "(OCoLC)604911177"
16 | ]
17 | },
18 | "holding_data": {
19 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221159990000121",
20 | "holding_id": "2221159990000121",
21 | "temp_library": {
22 | "value": null,
23 | "desc": null
24 | },
25 | "temp_location": {
26 | "value": null,
27 | "desc": null
28 | }
29 | },
30 | "item_data": {
31 | "pid": "2321159970000121",
32 | "description": null,
33 | "library": {
34 | "value": "65144020000121",
35 | "desc": "BURNS"
36 | },
37 | "location": {
38 | "value": "UNASSIGNED",
39 | "desc": "UNASSIGNED location"
40 | },
41 | "requested": false,
42 | "physical_material_type": {
43 | "value": "ISSUE",
44 | "desc": "journal"
45 | },
46 | "process_type": {
47 | "value": "ACQ",
48 | "desc": "Acquisition"
49 | },
50 | "po_line": "POL-67552"
51 | }
52 | },
53 | {
54 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221159990000121/items/2321159980000121",
55 | "bib_data": {
56 | "title": "Data base",
57 | "issn": "0095-0033",
58 | "link": "/almaws/v1/bibs/99100383900121",
59 | "mms_id": 99100383900121,
60 | "place_of_publication": "New York :",
61 | "publisher_const": "Association for Computing Machinery",
62 | "network_number": [
63 | "(CONSER) 2011250895",
64 | "(CKB)954926959913",
65 | "(OCoLC)604911177"
66 | ]
67 | },
68 | "holding_data": {
69 | "link": "/almaws/v1/bibs/99100383900121/holdings/2221159990000121",
70 | "holding_id": "2221159990000121",
71 | "temp_library": {
72 | "value": null,
73 | "desc": null
74 | },
75 | "temp_location": {
76 | "value": null,
77 | "desc": null
78 | }
79 | },
80 | "item_data": {
81 | "pid": "2321159980000121",
82 | "description": null,
83 | "library": {
84 | "value": "65144020000121",
85 | "desc": "BURNS"
86 | },
87 | "location": {
88 | "value": "UNASSIGNED",
89 | "desc": "UNASSIGNED location"
90 | },
91 | "requested": false,
92 | "physical_material_type": {
93 | "value": "ISSUE",
94 | "desc": "journal"
95 | },
96 | "process_type": {
97 | "value": "ACQ",
98 | "desc": "Acquisition"
99 | },
100 | "po_line": "POL-67551"
101 | }
102 | }
103 | ],
104 | "total_record_count": 2
105 | }
106 |
--------------------------------------------------------------------------------
/test/bib.dat:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "mms_id": 9922405930001552,
4 | "holdings": {
5 | "value": null,
6 | "link": "https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9922405930001551/holdings"
7 | },
8 | "created_by": "import",
9 | "created_date": "2013-07-14Z",
10 | "anies": [
11 | "\n\n 01229cam a2200397 a 4504\n 333281\n 20130704111532.0\n 940217s1992 ctua b 001 0 eng d\n \n 94-B3418\n \n \n 333281\n \n \n (OCoLC)28384525\n \n \n (CMalG)333281-gettydb-Voyager\n \n \n CPaHP\n CPaHP\n CMalG\n \n \n P93.5\n .T84 1992\n \n \n Tufte, Edward R.,\n 1942-\n \n \n Envisioning information /\n Edward R. Tufte.\n \n \n 3rd printing, with revisions.\n \n \n Cheshire, Conn. :\n Graphics Press,\n 1992.\n \n \n 126 p. :\n ill. (some col.) ;\n 28 cm.\n \n \n Includes bibliographical references and index.\n \n \n Visual communication.\n \n \n 1\n 02/17/94 SMT\n MAI\n DZ\n \n \n BKH\n \n \n LCON02\n 48.00\n \n \n pr/48.00,inv#016687,invd940126,inrd940217\n \n \n JRA\n \n \n cica\n \n \n b1336991x\n 12-20-00\n 04-28-95\n cc\n 01-01-95\n a\n \n \n c\n \n \n CONS\n \n \n 1\n 94-B3418-1\n 33125006577916\n 07/28/94 C\n \n \n 33125006577916\n \n \n 0\n \n \n 1\n 07/27/94 CAT\n CONS\n CONS\n 02/17/94 REC\n \n \n 94-B03418\n \n \n Conservation collection (Getty Research Institute)\n \n \n 9116\n CMalG\n MSW\n MSW\n CJPA\n \n "
12 | ],
13 | "link": null
14 |
15 | }
--------------------------------------------------------------------------------
/test/bib2.dat:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "mms_id": 9922405930001552,
4 | "holdings": {
5 | "value": null,
6 | "link": "https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9922405930001551/holdings"
7 | },
8 | "created_by": "import",
9 | "created_date": "2013-07-14Z",
10 | "anies": [
11 | "\n\n 01229cam a2200397 a 4504\n 333281\n 20130704111532.0\n 940217s1992 ctua b 001 0 eng d\n \n 94-B3418\n \n \n 333281\n \n \n (OCoLC)28384525\n \n \n (CMalG)333281-gettydb-Voyager\n \n \n CPaHP\n CPaHP\n CMalG\n \n \n P93.5\n .T84 1992\n \n \n Tuft, Edward R.,\n 1942-\n \n \n Envisioning information /\n Edward R. Tuft.\n \n \n 3rd printing, with revisions.\n \n \n Cheshire, Conn. :\n Graphics Press,\n 1992.\n \n \n 126 p. :\n ill. (some col.) ;\n 28 cm.\n \n \n Includes bibliographical references and index.\n \n \n Visual communication.\n \n \n 1\n 02/17/94 SMT\n MAI\n DZ\n \n \n BKH\n \n \n LCON02\n 48.00\n \n \n pr/48.00,inv#016687,invd940126,inrd940217\n \n \n JRA\n \n \n cica\n \n \n b1336991x\n 12-20-00\n 04-28-95\n cc\n 01-01-95\n a\n \n \n c\n \n \n CONS\n \n \n 1\n 94-B3418-1\n 33125006577916\n 07/28/94 C\n \n \n 33125006577916\n \n \n 0\n \n \n 1\n 07/27/94 CAT\n CONS\n CONS\n 02/17/94 REC\n \n \n 94-B03418\n \n \n Conservation collection (Getty Research Institute)\n \n \n 9116\n CMalG\n MSW\n MSW\n CJPA\n \n "
12 | ],
13 | "link": null
14 |
15 | }
--------------------------------------------------------------------------------
/test/bib.dat.xml:
--------------------------------------------------------------------------------
1 | 9922405930001551import2013-07-14Z
2 | 01229cam a2200397 a 4504
3 | 333281
4 | 20130704111532.0
5 | 940217s1992 ctua b 001 0 eng d
6 |
7 | 94-B3418
8 |
9 |
10 | 333281
11 |
12 |
13 | (OCoLC)28384525
14 |
15 |
16 | (CMalG)333281-gettydb-Voyager
17 |
18 |
19 | CPaHP
20 | CPaHP
21 | CMalG
22 |
23 |
24 | P93.5
25 | .T84 1992
26 |
27 |
28 | Tufte, Edward R.,
29 | 1942-
30 |
31 |
32 | Envisioning information /
33 | Edward R. Tufte.
34 |
35 |
36 | 3rd printing, with revisions.
37 |
38 |
39 | Cheshire, Conn. :
40 | Graphics Press,
41 | 1992.
42 |
43 |
44 | 126 p. :
45 | ill. (some col.) ;
46 | 28 cm.
47 |
48 |
49 | Includes bibliographical references and index.
50 |
51 |
52 | Visual communication.
53 |
54 |
55 | 1
56 | 02/17/94 SMT
57 | MAI
58 | DZ
59 |
60 |
61 | BKH
62 |
63 |
64 | LCON02
65 | 48.00
66 |
67 |
68 | pr/48.00,inv#016687,invd940126,inrd940217
69 |
70 |
71 | JRA
72 |
73 |
74 | cica
75 |
76 |
77 | b1336991x
78 | 12-20-00
79 | 04-28-95
80 | cc
81 | 01-01-95
82 | a
83 |
84 |
85 | c
86 |
87 |
88 | CONS
89 |
90 |
91 | 1
92 | 94-B3418-1
93 | 33125006577916
94 | 07/28/94 C
95 |
96 |
97 | 33125006577916
98 |
99 |
100 | 0
101 |
102 |
103 | 1
104 | 07/27/94 CAT
105 | CONS
106 | CONS
107 | 02/17/94 REC
108 |
109 |
110 | 94-B03418
111 |
112 |
113 | Conservation collection (Getty Research Institute)
114 |
115 |
116 | 9116
117 | CMalG
118 | MSW
119 | MSW
120 | CJPA
121 |
122 |
--------------------------------------------------------------------------------
/test/bib2.dat.xml:
--------------------------------------------------------------------------------
1 | 9922405930001551import2013-07-14Z
2 | 01229cam a2200397 a 4504
3 | 333281
4 | 20130704111532.0
5 | 940217s1992 ctua b 001 0 eng d
6 |
7 | 94-B3418
8 |
9 |
10 | 333281
11 |
12 |
13 | (OCoLC)28384525
14 |
15 |
16 | (CMalG)333281-gettydb-Voyager
17 |
18 |
19 | CPaHP
20 | CPaHP
21 | CMalG
22 |
23 |
24 | P93.5
25 | .T84 1992
26 |
27 |
28 | Tuft, Edward R.,
29 | 1942-
30 |
31 |
32 | Envisioning information /
33 | Edward R. Tuft.
34 |
35 |
36 | 3rd printing, with revisions.
37 |
38 |
39 | Cheshire, Conn. :
40 | Graphics Press,
41 | 1992.
42 |
43 |
44 | 126 p. :
45 | ill. (some col.) ;
46 | 28 cm.
47 |
48 |
49 | Includes bibliographical references and index.
50 |
51 |
52 | Visual communication.
53 |
54 |
55 | 1
56 | 02/17/94 SMT
57 | MAI
58 | DZ
59 |
60 |
61 | BKH
62 |
63 |
64 | LCON02
65 | 48.00
66 |
67 |
68 | pr/48.00,inv#016687,invd940126,inrd940217
69 |
70 |
71 | JRA
72 |
73 |
74 | cica
75 |
76 |
77 | b1336991x
78 | 12-20-00
79 | 04-28-95
80 | cc
81 | 01-01-95
82 | a
83 |
84 |
85 | c
86 |
87 |
88 | CONS
89 |
90 |
91 | 1
92 | 94-B3418-1
93 | 33125006577916
94 | 07/28/94 C
95 |
96 |
97 | 33125006577916
98 |
99 |
100 | 0
101 |
102 |
103 | 1
104 | 07/27/94 CAT
105 | CONS
106 | CONS
107 | 02/17/94 REC
108 |
109 |
110 | 94-B03418
111 |
112 |
113 | Conservation collection (Getty Research Institute)
114 |
115 |
116 | 9116
117 | CMalG
118 | MSW
119 | MSW
120 | CJPA
121 |
122 |
--------------------------------------------------------------------------------
/speedtest/coroutines_speedtest.py:
--------------------------------------------------------------------------------
1 | from pyalma import alma
2 | from datetime import datetime
3 | import csv
4 | import ast
5 |
6 | '''
7 | The following is a series of functional tests that will
8 | allow you to run speed tests on coroutine methods.
9 | To use, set the number of items you want to test in "TEST_NUM"
10 | You can only test one method at a time.
11 | However, the suite is designed to be run sequentially, to generate the
12 | files you need for later tests.
13 | '''
14 |
15 |
16 | # set the number of items you would like to test
17 | TEST_NUM = 1000
18 | API_KEY = ''
19 | REGION = ''
20 |
21 | api = alma.Alma(API_KEY, REGION)
22 |
23 |
24 | def list_from_csv(csvfile, number):
25 | '''
26 | Takes a csv file, column headings may be either:
27 | - ids (with each row containin a dictionary of mms_id,
28 | holding_id, item_pid, and/or request_id)and data,
29 | OR
30 | - mms_id, holding_id, item_pid, and or request_id; and data
31 | Returns a list of dictionaries in format required for coroutines:
32 | [{
33 | 'data': data,
34 | 'ids': {
35 | 'mms_id': mms_id,
36 | 'holding_id': holding_id,
37 | 'item_pid': item_pid,
38 | 'request_id': request_id
39 | }
40 | },
41 | ...
42 | ]
43 | '''
44 | with open(csvfile, 'rt') as handle:
45 | reader = csv.DictReader(handle, delimiter=',')
46 | headers = reader.fieldnames
47 | dict_rows = []
48 | count = number
49 | for row in reader:
50 | dict_row = {}
51 | if 'ids' not in headers:
52 | dict_row['ids'] = {}
53 | if count > 0:
54 | if 'data' not in headers:
55 | dict_row['data'] = None
56 | for header in headers:
57 | if header == 'data':
58 | dict_row[header] = row[header]
59 | elif header == "":
60 | continue
61 | else:
62 | dict_row['ids'][header] = row[header]
63 | dict_rows.append(dict_row)
64 | count -= 1
65 | else:
66 | break
67 | else:
68 | if count > 0:
69 | dict_row['ids'] = ast.literal_eval(row['ids'])
70 | dict_row['data'] = row['data']
71 | dict_rows.append(dict_row)
72 | count -= 1
73 | else:
74 | break
75 |
76 | return dict_rows
77 |
78 |
79 | def write_to_csv(results, handle):
80 | '''
81 | Takes a list of results (a list of dictionaries),
82 | Returns a CSV file with the given filename.
83 | '''
84 | with open(handle, 'w') as csvfile:
85 | linewriter = csv.writer(csvfile)
86 | linewriter.writerow(["ids", "status", "data"])
87 | for line in results:
88 | linewriter.writerow(line)
89 |
90 |
91 | def test_general(input_file, output_file, test_func):
92 | '''
93 | Takes a CSV of the data you wish to feed into a function, the filename you
94 | desire for the output, and the name of the function you wish to test.
95 | Returns a list of results (a list of dictionaries).
96 | '''
97 | begin = datetime.now()
98 | test_input = list_from_csv(input_file, TEST_NUM)
99 | test_output = test_func(test_input)
100 | output_len = len(test_output)
101 | end = datetime.now()
102 | diff = end - begin
103 | errors = 0
104 | for line in test_output:
105 | if line[1] > 200:
106 | errors += 1
107 | print('\n\nReturned {} rows, with {} errors'.format((output_len - errors), errors))
108 | print("\n\nTime elapsed for {} ids: \n Coroutines: {} \n ".format(output_len, diff))
109 | write_to_csv(test_output, output_file)
110 | return test_output
111 |
112 |
113 | '''
114 | Below are tests for each coroutine method.
115 | '''
116 |
117 |
118 | def test_cor_get_bib(input_file='test/mms.csv',
119 | output_file='test/output_get_bib.csv', content_type='xml', accept='xml'):
120 | print("\n\nTesting cor_get_bib")
121 | test_func = api.cor_get_bib
122 | return test_general(input_file, output_file, test_func)
123 |
124 |
125 | def test_cor_put_bib(input_file="test/output_get_bib.csv",
126 | output_file='test/output_put_bib.csv', content_type='xml', accept='xml'):
127 | print("\n\nTesting cor_put_bib")
128 | test_func = api.cor_put_bib
129 | return test_general(input_file, output_file, test_func)
130 |
131 |
132 | def test_cor_get_holdings(input_file='test/mms_in.csv',
133 | output_file='test/output_get_holdings.csv'):
134 | print("\n\nTesting cor_get_holdings")
135 | test_func = api.cor_get_holdings
136 | test_general(input_file, output_file, test_func)
137 |
138 |
139 | def test_cor_get_holding(input_file='test/mms_holding.csv',
140 | output_file="test/output_get_holding.csv"):
141 | print("\n\nTesting cor_get_holding")
142 | test_func = api.cor_get_holding
143 | test_general(input_file, output_file, test_func)
144 |
145 |
146 | def test_cor_put_holding(input_file='test/output_get_holding.csv',
147 | output_file='test/output_put_holding.csv'):
148 | print("\n\nTesting cor_put_holding")
149 | test_func = api.cor_put_holding
150 | test_general(input_file, output_file, test_func)
151 |
152 | def test_cor_get_items(input_file='test/mms_holding.csv',
153 | output_file='test/output_get_items.csv'):
154 | print("\n\nTesting cor_get_items")
155 | test_func = api.cor_get_items
156 | test_general(input_file, output_file, test_func)
157 |
158 |
159 | def test_cor_get_item(input_file='test/mms_holding_item.csv',
160 | output_file='test/output_get_item.csv'):
161 | print("\n\nTesting cor_get_item")
162 | test_func = api.cor_get_item
163 | test_general(input_file, output_file, test_func)
164 |
165 |
166 | def test_cor_put_item(input_file='test/output_get_item.csv',
167 | output_file='test/output_put_item.csv'):
168 | print("\n\nTesting cor_put_item")
169 | test_func = api.cor_put_item
170 | test_general(input_file, output_file, test_func)
171 |
172 |
173 | def test_cor_post_loan(input_file='test/mms_holding_item_data.csv',
174 | output_file='test/output_post_loan.csv'):
175 | print("\n\nTesting cor_post_loan")
176 | test_func = api.cor_post_loan
177 | test_general(input_file, output_file, test_func)
178 |
179 |
180 | def test_cor_get_bib_requests(input_file='test/mms_in.csv',
181 | output_file='test/output_get_bib_requests.csv'):
182 | print("\n\nTesting cor_get_bib_requests")
183 | test_func = api.cor_get_bib_requests
184 | test_general(input_file, output_file, test_func)
185 |
186 |
187 | def test_cor_get_item_requests(input_file='test/mms_holdings_items_with_requests.csv',
188 | output_file='test/output_get_item_requests.csv'):
189 | print("\n\nTesting cor_get_item_requests")
190 | test_func = api.cor_get_item_requests
191 | test_general(input_file, output_file, test_func)
192 |
193 |
194 | def test_cor_post_bib_request(input_file='test/item_request_objects.csv',
195 | output_file='test/output_post_bib_request.csv'):
196 | print("\n\nTesting cor_post_bib_request")
197 | test_func = api.cor_post_bib_request
198 | test_general(input_file, output_file, test_func)
199 |
200 |
201 | def test_cor_post_item_request(input_file='test/item_request_objects.csv',
202 | output_file='test/output_put_item_request.csv'):
203 | print("\n\nTesting cor_post_item_request")
204 | test_func = api.cor_post_item_request
205 | test_general(input_file, output_file, test_func)
206 |
207 |
208 | def test_cor_put_bib_request(input_file='test/output_get_bib_requests.csv',
209 | output_file='test/output_put_bib_request.csv'):
210 | print("\n\nTesting cor_put_bib_request")
211 | test_func = api.cor_put_bib_request
212 | test_general(input_file, output_file, test_func)
213 |
214 | def test_cor_put_item_request(input_file='test/output_get_item_requests.csv',
215 | output_file='test/output_put_item_request.csv'):
216 | print("\n\nTesting cor_put_item_request")
217 | test_func = api.cor_put_item_request
218 | test_general(input_file, output_file, test_func)
219 |
220 |
221 | def test_cor_del_item_request(input_file='test/item_request_objects.csv',
222 | output_file='test/output_del_item_request.csv'):
223 | print("\n\nTesting cor_del_item_request")
224 | test_func = api.cor_del_item_request
225 | test_general(input_file, output_file, test_func)
226 |
227 |
228 | def test_cor_del_bib_request(input_file='test/item_request_objects.csv',
229 | output_file='test/output_del_bib_request.csv'):
230 | print("\n\nTesting cor_del_bib_request")
231 | test_func = api.cor_del_bib_request
232 | test_general(input_file, output_file, test_func)
233 |
234 |
235 | def test_cor_get_bib_booking_availability(input_file='test/mms.csv',
236 | output_file='test/output_get_bib_booking_availability.csv'):
237 | print("\n\nTesting cor_get_bib_booking_availability")
238 | test_func = api.cor_get_bib_booking_availability
239 | test_general(input_file, output_file, test_func)
240 |
241 |
242 | def test_cor_get_item_booking_availability(input_file='test/mms_holding_item.csv',
243 | output_file='test/output_get_item_booking_availability.csv'):
244 | print("\n\nTesting cor_get_item_booking_availability")
245 | test_func = api.cor_get_item_booking_availability
246 | test_general(input_file, output_file, test_func)
247 |
248 |
249 | if __name__ == '__main__':
250 |
251 | test_cor_get_bib()
252 | # test_cor_put_bib()
253 |
254 | # test_cor_get_holdings()
255 |
256 | # test_cor_get_holding()
257 | # test_cor_put_holding()
258 |
259 | # test_cor_get_items()
260 |
261 | # test_cor_get_item()
262 | # test_cor_put_item()
263 |
264 | # test_cor_get_bib_requests()
265 | # test_cor_get_item_requests()
266 |
267 |
268 |
269 | '''
270 | Tests below are for not finalized methods:
271 | '''
272 |
273 | # test_cor_del_bib_request()
274 | # test_cor_del_item_request()
275 |
276 | # test_cor_post_loan()
277 |
278 | # test_cor_post_bib_request()
279 | # test_cor_post_item_request()
280 |
281 | # test_cor_put_bib_request()
282 | # test_cor_put_item_request()
283 |
284 | # test_cor_get_bib_booking_availability()
285 | # test_cor_get_item_booking_availability()
286 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/gri-is/pyalma)
2 |
3 | [](https://coveralls.io/github/gri-is/pyalma?branch=master)
4 |
5 | PyAlma
6 | ======
7 |
8 | Developer Installation
9 | ----------------------
10 |
11 | 0. Ensure that Python 3 is installed on your machine (https://www.python.org/downloads/)
12 |
13 | 1. Create a directory for development projects on your machine
14 |
15 | $ mkdir //projects
16 | $ cd //projects
17 |
18 | 2. Clone the repository
19 |
20 | $ git clone https://@stash.getty.edu/scm/griis/pyalma.git
21 | $ cd pyalma
22 |
23 | 3. Create a virtual environment and activate it
24 |
25 | $ pyvenv ENV
26 | $ source ENV/bin/activate
27 |
28 | 4. Install dependencies to the virtual environment
29 |
30 | (ENV)$ pip install -r requirements.txt
31 |
32 | 5. Run the tests to make sure everything works correctly
33 |
34 | (ENV)$ python -m unittest
35 |
36 | Developer Changes
37 | -----------------
38 |
39 | 6. When working on a new issue, be sure to do so in a new branch
40 |
41 | (ENV)$ git branch
42 | (ENV)$ git checkout
43 |
44 | 7. Run a status check before doing any adds, commits or pushes
45 |
46 | (ENV)$ git status
47 |
48 | 8. Stage edited or newly created files
49 |
50 | (ENV)$ git status
51 | (ENV)$ git add
52 |
53 | 9. Commit the staged changes and ALWAYS explain the changes in a message
54 |
55 | (ENV)$ git status
56 | (ENV)$ git commit -m
57 |
58 | 10. Push the changes to the shared repository, using the same branch name
59 |
60 | (ENV)$ git status
61 | (ENV)$ git push origin
62 |
63 | 11. On the repository website create a pull request from your branch to the master branch
64 |
65 | 12. When your branch has been reviewed, approved, and merged, you can pull the master and delete your issue branch
66 |
67 | (ENV)$ git checkout master
68 | (ENV)$ git status
69 | (ENV)$ git pull origin master
70 | (ENV)$ git branch -d
71 |
72 |
73 | API KEY Configuration
74 | ---------------------
75 |
76 | The Alma API requires a secret API key. You must also point to correct regional endpoint, of which there are three:
77 |
78 | 1. US: https://api-na.hosted.exlibrisgroup.com
79 | 2. EU: https://api-eu.hosted.exlibrisgroup.com
80 | 3. APAC: https://api-ap.hosted.exlibrisgroup.com
81 |
82 | You can pass the key and region directly to the Alma object at the time of creation, like so:
83 |
84 | from pyalma.alma import Alma
85 | api = alma.Alma(apikey='xxxxxxxxxx', region='US')
86 |
87 | Or, you can create environment variables in your operating system and the Python client will find it. On a linux machine you can do this by editing the `/etc/environment` file, like so:
88 |
89 | ALMA_API_KEY=xxxxxxxxx
90 | ALMA_API_REGION=US
91 |
92 | After editing the `/etc/environment` file, be sure to reload it, like so:
93 |
94 | :$ source /etc/environment
95 |
96 | For Mac OSX, this may be slightly different. This document may be of some help: http://www.dowdandassociates.com/blog/content/howto-set-an-environment-variable-in-mac-os-x-terminal-only/
97 |
98 | PyAlma Usage Example:
99 | ---------------------
100 |
101 | 1. After starting up a Python session, import the library and create an api object:
102 |
103 | >>> from pyalma.alma import Alma
104 | >>> api = Alma()
105 |
106 | Note: you can only do the above if you set your environment as described above. Otherwise you have to pass in your API key and region like so:
107 |
108 | >>> api = alma.Alma(apikey='xxxxxxxxxx', region='US')
109 |
110 | 2. Now go get your record:
111 |
112 | >>> bib = api.get_bib('9927390750001551')
113 |
114 | Note: The bib is in json format by default unless you pass in accept='xml' to the method.
115 |
116 | 3. To see the content of the bib you can print it:
117 |
118 | >>> from pprint import pprint
119 | >>> pprint(bib)
120 | {'anies': ['\n'
121 | '01523cam a2200481 a 4500992739075000155120160713120531.0940411s1992 cs a c 000 0 cze '
125 | '3375229322573294-B7378337522(CMalG)337522-gettydb-Voyager(OCoLC)29550137DLCDLCCMalGczeengfregeritaspaN6834.5.M8A4 '
144 | '1992N6834.5.M8A4 1992Kusák, '
148 | 'Dalibor.Mucha /Dalibor Kusák, Marta '
151 | 'Kadlečíková.Vyd. '
153 | '1.Prague :BB/art,1992.1 v. (unpaged) :chiefly col. ill. ;31 '
159 | 'cm.Text in Czech, English, French, '
161 | 'German, Italian, and Spanish.Mucha, '
163 | 'Alphonse,1860-1939Catalogs.Kadlečíková, '
167 | 'Marta.Mucha, Alphonse,1860-1939.104/11/94 AGRMAIDAWSMLGET02pr/140.00,zc/gdm,inv#2652,invd940307,inrd940411JMEOCLC REC '
182 | 'TESTb1341286302-20-9704-28-95cc01-01-95acOCLC '
191 | 'D160706.R807645 20160708MAIN194-B7378-13312500703729004/13/94 '
197 | 'C331250070372900104/13/94 CATMAINMAIN04/11/94 '
206 | 'REC94-B073789110CMalGAGRGCSCJPA'],
213 | 'author': 'Kusák, Dalibor.',
214 | 'complete_edition': 'Vyd. 1.',
215 | 'created_by': 'import',
216 | 'created_date': '2013-07-14Z',
217 | 'holdings': {'link': 'https://api-na.hosted.exlibrisgroup.com/almaws/v1/bibs/9927390750001551/holdings',
218 | 'value': None},
219 | 'isbn': None,
220 | 'issn': None,
221 | 'last_modified_by': 'System',
222 | 'last_modified_date': '2016-07-13Z',
223 | 'link': None,
224 | 'linked_record_id': {'type': None, 'value': None},
225 | 'mms_id': '9927390750001551',
226 | 'network_number': ['(OCoLC)29550137',
227 | '(CMalG)337522-gettydb-Voyager',
228 | '337522'],
229 | 'originating_system': 'OTHER',
230 | 'originating_system_id': '337522-gettydb',
231 | 'place_of_publication': 'Prague :',
232 | 'publisher_const': 'BB/art',
233 | 'record_format': 'marc21',
234 | 'suppress_from_publishing': 'false',
235 | 'title': 'Mucha /'}
236 |
237 | Note: the MARC data appears as an XML string inside the JSON.
238 |
--------------------------------------------------------------------------------
/test/test_coroutines.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | from importlib import reload
4 |
5 | from pyalma import alma
6 |
7 | import asyncio
8 | import aiohttp
9 | import asynctest
10 | from aioresponses import aioresponses
11 |
12 | from datetime import datetime
13 |
14 |
15 | def setUpModule():
16 | os.environ['ALMA_API_KEY'] = 'my fake key'
17 | os.environ['ALMA_API_REGION'] = 'APAC'
18 | reload(alma)
19 |
20 |
21 | class TestAsyncRequests(asynctest.TestCase):
22 |
23 | maxDiff = None
24 |
25 | def setUp(self):
26 | self.api = alma.Alma(apikey='unreal', region='US')
27 |
28 | def test_cor_run(self):
29 | loop = asyncio.get_event_loop()
30 | ids = {'mms_id': 9922405930001552}
31 | url = self.api.fullurl('bib', ids)
32 | fh = open('test/bib.dat', 'r')
33 | body = fh.read()
34 | fh.close()
35 | # session = aiohttp.ClientSession()
36 | with aioresponses() as m:
37 | m.get(url,
38 | status=200,
39 | content_type='application/json',
40 | body=body)
41 | resp = loop.run_until_complete(self.api.cor_run('GET', 'bib', [{'ids': ids, 'data':None}], accept='json'))
42 | data = resp[0][2]
43 | self.assertEqual(data, json.loads(body))
44 |
45 | def test_cor_request(self):
46 | loop = asyncio.get_event_loop()
47 | ids = {'mms_id': 9922405930001552}
48 | url = self.api.fullurl('bib', ids)
49 | fh = open('test/bib.dat', 'r')
50 | body = fh.read()
51 | fh.close()
52 | session = aiohttp.ClientSession()
53 | # creating a session outside of a coroutine is not advised
54 | # and throws a warning.
55 | # but I could not figure out another way
56 | with aioresponses() as m:
57 | m.get(url,
58 | status=200,
59 | content_type='application/json',
60 | body=body)
61 | resp = loop.run_until_complete(self.api.cor_request('GET', 'bib', ids, session, accept='json'))
62 | data = resp[2]
63 | self.assertEqual(data, json.loads(body))
64 | session.close()
65 |
66 | '''
67 | Below test is not working because searching the long list of
68 | mock objects slows it down so much that the program becomes too slow
69 | to test the semaphore limit
70 | '''
71 |
72 | # def test_semaphore(self):
73 | # self.api.max_calls = 100000
74 | # self.semaphore_limit = 2
75 | # ids = {'mms_id': 9922405930001552}
76 | # ids_in = {'ids': {'mms_id': 9922405930001552}, 'data': None}
77 | # ids_list = [ids_in] * 100
78 | # url = self.api.fullurl('bib', ids)
79 | # fh = open('test/bib.dat', 'r')
80 | # body = fh.read()
81 | # fh.close()
82 | # with aioresponses() as m:
83 | # for i in enumerate(ids_list):
84 | # m.get(url,
85 | # status=200,
86 | # content_type='application/json',
87 | # body=body)
88 | # begin = datetime.now()
89 | # resp = self.api.cor_get_bib(ids_list)
90 | # end = datetime.now()
91 | # time_to_finish = (end - begin).total_seconds()
92 | # items_finished = len(resp)
93 | # print(self.api.max_calls)
94 | # print(items_finished/time_to_finish)
95 | # self.assertTrue(self.api.max_calls >= items_finished/time_to_finish)
96 |
97 | def test_rate_limit(self):
98 | self.api.max_calls = 20
99 | # self.semaphore_limit = 500
100 | ids = {'mms_id': 9922405930001552}
101 | ids_in = {'ids': {'mms_id': 9922405930001552}, 'data': None}
102 | ids_list = [ids_in] * 40
103 | url = self.api.fullurl('bib', ids)
104 | fh = open('test/bib.dat', 'r')
105 | body = fh.read()
106 | fh.close()
107 | with aioresponses() as m:
108 | for i in enumerate(ids_list):
109 | m.get(url,
110 | status=200,
111 | content_type='application/json',
112 | body=body)
113 | begin = datetime.now()
114 | resp = self.api.cor_get_bib(ids_list)
115 | end = datetime.now()
116 | time_to_finish = (end - begin).total_seconds()
117 | items_finished = len(resp)
118 | self.assertTrue(self.api.max_calls >= items_finished/time_to_finish)
119 |
120 |
121 | def test_cor_get_bib(self):
122 | ids = {'mms_id': 9922405930001552}
123 | url = self.api.fullurl('bib', ids)
124 | fh = open('test/bib.dat', 'r')
125 | body = fh.read()
126 | fh.close()
127 | # session = aiohttp.ClientSession()
128 | with aioresponses() as m:
129 | m.get(url,
130 | status=200,
131 | content_type='application/json',
132 | body=body)
133 | resp = self.api.cor_get_bib([{'ids':ids,'data':None}])
134 | bib = resp[0][2]
135 | self.assertEqual(bib, json.loads(body))
136 |
137 | def test_cor_get_holdings(self):
138 | ids = {'mms_id': 99100383900121}
139 | url = self.api.fullurl('holdings', ids)
140 | fh = open('test/holds.dat', 'r')
141 | body = fh.read()
142 | fh.close()
143 | # session = aiohttp.ClientSession()
144 | with aioresponses() as m:
145 | m.get(url,
146 | status=200,
147 | content_type='application/json',
148 | body=body)
149 | resp = self.api.cor_get_holdings([{'ids':ids,'data':None}])
150 | holdings = resp[0][2]
151 | self.assertEqual(holdings, json.loads(body))
152 |
153 | def test_cor_get_holding(self):
154 | ids = {'mms_id': 9922405930001552, 'holding_id': 22115858660001551}
155 | url = self.api.fullurl('holding', ids)
156 | fh = open('test/hold.dat', 'r')
157 | body = fh.read()
158 | fh.close()
159 | # session = aiohttp.ClientSession()
160 | with aioresponses() as m:
161 | m.get(url,
162 | status=200,
163 | content_type='application/json',
164 | body=body)
165 | resp = self.api.cor_get_holding([{'ids':ids,'data':None}])
166 | holding_data = resp[0][2]
167 | self.assertEqual(holding_data, json.loads(body))
168 |
169 | def test_cor_get_items(self):
170 | ids = {'mms_id': 9922405930001552, 'holding_id': 22115858660001551}
171 | url = self.api.fullurl('items', ids)
172 | fh = open('test/items.dat', 'r')
173 | body = fh.read()
174 | fh.close()
175 | # session = aiohttp.ClientSession()
176 | with aioresponses() as m:
177 | m.get(url,
178 | status=200,
179 | content_type='application/json',
180 | body=body)
181 | resp = self.api.cor_get_items([{'ids': ids, 'data':None}])
182 | items_data = resp[0][2]
183 | self.assertEqual(items_data, json.loads(body))
184 |
185 | def test_cor_get_bib_requests(self):
186 | ids = {'mms_id': 9922405930001552}
187 | url = self.api.fullurl('bib_requests', ids)
188 | fh = open('test/request.dat', 'r')
189 | body = fh.read()
190 | fh.close()
191 | # session = aiohttp.ClientSession()
192 | with aioresponses() as m:
193 | m.get(url,
194 | status=200,
195 | content_type='application/json',
196 | body=body)
197 | resp = self.api.cor_get_bib_requests([{'ids': ids, 'data':None}])
198 | bib_requests_data = resp[0][2]
199 | self.assertEqual(bib_requests_data, json.loads(body))
200 |
201 | def test_cor_get_item_requests(self):
202 | ids = {'mms_id': 9922405930001552, 'holding_id': 22115858660001551, 'item_pid': 23115858650001551}
203 | url = self.api.fullurl('item_requests', ids)
204 | fh = open('test/request.dat', 'r')
205 | body = fh.read()
206 | fh.close()
207 | # session = aiohttp.ClientSession()
208 | with aioresponses() as m:
209 | m.get(url,
210 | status=200,
211 | content_type='application/json',
212 | body=body)
213 | resp = self.api.cor_get_item_requests([{'ids': ids, 'data':None}])
214 | item_requests_data = resp[0][2]
215 | self.assertEqual(item_requests_data, json.loads(body))
216 |
217 | def test_cor_put_bib(self):
218 | ids = {'mms_id': 9922405930001552}
219 | url = self.api.fullurl('bib', ids)
220 | fh = open('test/bib2.dat', 'r')
221 | original_bib = fh.read()
222 | fh.close()
223 | # session = aiohttp.ClientSession()
224 | with aioresponses() as m:
225 | m.put(url,
226 | status=200,
227 | content_type='application/xml',
228 | body=original_bib)
229 | resp = self.api.cor_put_bib([{'ids': ids, 'data': original_bib}])
230 | returned_bib = resp[0][2]
231 | self.assertEqual(original_bib, returned_bib)
232 |
233 | def test_cor_put_holding(self):
234 | ids = {'mms_id': 9922405930001552, 'holding_id': 22115858660001551}
235 | url = self.api.fullurl('holding', ids)
236 | fh = open('test/hold2.dat', 'r')
237 | original_holding = fh.read()
238 | fh.close()
239 | # session = aiohttp.ClientSession()
240 | with aioresponses() as m:
241 | m.put(url,
242 | status=200,
243 | content_type='application/xml',
244 | body=original_holding)
245 | resp = self.api.cor_put_holding([{'ids': ids, 'data': original_holding}])
246 | returned_holding = resp[0][2]
247 | self.assertEqual(original_holding, returned_holding)
248 |
249 | def test_cor_put_item(self):
250 | ids = {'mms_id': 99110223950001020, 'holding_id': 22344156400001021, 'item_pid': 23344156380001021}
251 | url = self.api.fullurl('item', ids)
252 | fh = open('test/item2.dat', 'r')
253 | original_item = fh.read()
254 | fh.close()
255 | # session = aiohttp.ClientSession()
256 | with aioresponses() as m:
257 | m.put(url,
258 | status=200,
259 | content_type='application/xml',
260 | body=original_item)
261 | resp = self.api.cor_put_item([{'ids': ids, 'data': original_item}])
262 | returned_item = resp[0][2]
263 | self.assertEqual(original_item, returned_item)
264 |
265 | def test_cor_del_bib_request(self):
266 | ids = {'mms_id': 9922405930001552, 'request_id': 83013520000121}
267 | url = self.api.fullurl('bib_request', ids)
268 | with aioresponses() as m:
269 | m.delete(url,
270 | status=200,
271 | content_type='application/xml',
272 | body='')
273 | expected = ''
274 | resp = self.api.cor_del_bib_request([{'ids': ids, 'data': None}])
275 | bib_request_response = resp[0][2]
276 | self.assertEqual(expected, bib_request_response)
277 |
278 | def test_cor_del_item_request(self):
279 | ids = {'mms_id': 9922405930001552, 'holding_id': 22115858660001551, 'item_pid': 23115858650001551, 'request_id': 83013520000121}
280 | url = self.api.fullurl('item_request', ids)
281 | with aioresponses() as m:
282 | m.delete(url,
283 | status=200,
284 | content_type='application/xml',
285 | body='')
286 | expected = ''
287 | resp = self.api.cor_del_item_request([{'ids': ids, 'data': None}])
288 | item_request_response = resp[0][2]
289 | self.assertEqual(expected, item_request_response)
290 |
291 | if __name__ == '__main__':
292 | asynctest.main()
293 |
--------------------------------------------------------------------------------
/test/test_alma.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 | import re
4 | from importlib import reload
5 | import unittest
6 |
7 | import responses
8 |
9 | from pyalma import alma
10 |
11 |
12 | def setUpModule():
13 | os.environ['ALMA_API_KEY'] = 'my fake key'
14 | os.environ['ALMA_API_REGION'] = 'APAC'
15 | reload(alma)
16 |
17 |
18 | class TestAlmaSetup(unittest.TestCase):
19 |
20 | def test_init(self):
21 | api = alma.Alma(apikey='unreal', region='EU')
22 | self.assertEqual(api.apikey, 'unreal')
23 | self.assertEqual(api.endpoint, alma.ENDPOINTS['EU'])
24 |
25 | def test_init_errors(self):
26 | self.assertRaises(Exception, alma.Alma, **{'apikey': None})
27 | self.assertRaises(Exception, alma.Alma, **{'region': None})
28 | self.assertRaises(Exception, alma.Alma, **{'region': 'XX'})
29 |
30 | def test_init_env_vars(self):
31 | api = alma.Alma()
32 | self.assertEqual(api.apikey, 'my fake key')
33 | self.assertEqual(api.endpoint, alma.ENDPOINTS['APAC'])
34 |
35 | def test_baseurl(self):
36 | api = alma.Alma()
37 | url = 'https://api-ap.hosted.exlibrisgroup.com/almaws/v1/'
38 | self.assertEqual(api.baseurl, url)
39 |
40 | def test_fullurl(self):
41 | ids = {'mms_id': 7777777, 'holding_id': 55555, 'item_pid': 333}
42 | expect = 'https://api-ap.hosted.exlibrisgroup.com/almaws/v1/'
43 | expect += 'bibs/7777777/holdings/55555/items/333'
44 | url = alma.Alma().fullurl('item', ids)
45 | self.assertEqual(url, expect)
46 |
47 | def test_headers(self):
48 | expect = {
49 | 'User-Agent': 'pyalma/0.1.0',
50 | 'Authorization': 'apikey my fake key',
51 | 'Accept': 'application/json',
52 | 'Content-Type': 'application/xml'
53 | }
54 | headers = alma.Alma().headers(content_type='xml')
55 | self.assertEqual(headers, expect)
56 |
57 |
58 | class TestAlmaGETRequests(unittest.TestCase):
59 | maxDiff = None
60 |
61 | def setUp(self):
62 | self.api = alma.Alma(apikey='unreal', region='EU')
63 |
64 | def buildResponses(self):
65 | # bib mock response
66 | biburl = self.api.baseurl + r'bibs/\d+$'
67 | bib_re = re.compile(biburl)
68 | with open('test/bib.dat', 'r') as b:
69 | responses.add(responses.GET, bib_re,
70 | status=200,
71 | content_type='application/json',
72 | body=b.read())
73 |
74 | # holdings mock response
75 | holdsurl = self.api.baseurl + r'bibs/\d+/holdings$'
76 | holds_re = re.compile(holdsurl)
77 | with open('test/holds.dat', 'r') as hs:
78 | responses.add(responses.GET, holds_re,
79 | status=200,
80 | content_type='application/json',
81 | body=hs.read())
82 |
83 | # holding mock response
84 | holdurl = self.api.baseurl + r'bibs/\d+/holdings/\d+$'
85 | hold_re = re.compile(holdurl)
86 | with open('test/hold.dat', 'r') as h:
87 | responses.add(responses.GET, hold_re,
88 | status=200,
89 | content_type='application/json',
90 | body=h.read())
91 |
92 | #items mock response
93 | itemsurl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items$'
94 | items_re = re.compile(itemsurl)
95 | with open('test/items.dat', 'r') as its:
96 | responses.add(responses.GET, items_re,
97 | status=200,
98 | content_type='application/json',
99 | body=its.read())
100 |
101 | # item mock response
102 | itemurl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+$'
103 | item_re = re.compile(itemurl)
104 | with open('test/item.dat', 'r') as i:
105 | responses.add(responses.GET, item_re,
106 | status=200,
107 | content_type='application/json',
108 | body=i.read())
109 |
110 | # bib_requests mock response
111 | bib_requestsurl = self.api.baseurl + r'bibs/\d+/requests'
112 | bib_requests_re = re.compile(bib_requestsurl)
113 | with open('test/request.dat', 'r') as f:
114 | responses.add(responses.GET, bib_requests_re,
115 | status=200,
116 | content_type='application/json',
117 | body=f.read())
118 |
119 | # item_requests mock response
120 | item_requestsurl = self.api.baseurl + \
121 | r'bibs/\d+/holdings/\d+/items/\d+/requests'
122 | item_requests_re = re.compile(item_requestsurl)
123 | with open('test/request.dat', 'r') as f:
124 | responses.add(responses.GET, item_requests_re,
125 | status=200,
126 | content_type='application/json',
127 | body=f.read())
128 |
129 | # bib_booking_availability mock response
130 | bib_booking_availabilityurl = self.api.baseurl + \
131 | r'bibs/\d+/booking-availability'
132 | bib_booking_availability_re = re.compile(bib_booking_availabilityurl)
133 | with open('test/availability.dat', 'r') as f:
134 | responses.add(responses.GET, bib_booking_availability_re,
135 | status=200,
136 | content_type='application/json',
137 | body=f.read())
138 |
139 | # item_booking_availability mock response
140 | item_booking_availabilityurl = self.api.baseurl + \
141 | r'bibs/\d+/holdings/\d+/items/\d+/booking-availability'
142 | item_booking_availability_re = re.compile(item_booking_availabilityurl)
143 | with open('test/availability.dat', 'r') as f:
144 | responses.add(responses.GET, item_booking_availability_re,
145 | status=200,
146 | content_type='application/json',
147 | body=f.read())
148 |
149 |
150 | def buildXMLResponses(self):
151 | # bib mock response
152 | biburl = self.api.baseurl + r'bibs/\d+'
153 | bib_re = re.compile(biburl)
154 | with open('test/bib.dat.xml', 'r') as f:
155 | responses.add(responses.GET, bib_re,
156 | status=200,
157 | content_type='application/xml',
158 | body=f.read())
159 |
160 | @responses.activate
161 | def test_alma_request(self):
162 | self.buildResponses()
163 | resp = self.api.request('GET', 'bib', {'mms_id': 9922405930001552})
164 | data = resp.json()
165 | self.assertEqual(data['created_date'], '2013-07-14Z')
166 |
167 | @responses.activate
168 | def test_extract_content_xml(self):
169 | self.buildXMLResponses()
170 | resp = self.api.request('GET', 'bib', {'mms_id': 9922405930001552})
171 | data = self.api.extract_content(resp)
172 | with open('test/bib.dat.xml', 'r') as dat:
173 | self.assertEqual(data, dat.read())
174 |
175 | @responses.activate
176 | def test_extract_content_json(self):
177 | self.buildResponses()
178 | resp = self.api.request('GET', 'bib', {'mms_id': 9922405930001552})
179 | data = self.api.extract_content(resp)
180 | with open('test/bib.dat', 'r') as dat:
181 | self.assertEqual(data, json.loads(dat.read()))
182 |
183 | @responses.activate
184 | def test_alma_get_bib(self):
185 | self.buildResponses()
186 | bib_data = self.api.get_bib(9922405930001552)
187 | with open('test/bib.dat', 'r') as dat:
188 | self.assertEqual(bib_data, json.loads(dat.read()))
189 |
190 | @responses.activate
191 | def test_alma_get_holdings(self):
192 | self.buildResponses()
193 | holdings_data = self.api.get_holdings(99100383900121)
194 | with open('test/holds.dat', 'r') as dat:
195 | self.assertEqual(holdings_data, json.loads(dat.read()))
196 |
197 | @responses.activate
198 | def test_alma_get_holding(self):
199 | self.buildResponses()
200 | holding_data = self.api.get_holding(
201 | 9922405930001552,
202 | 22115858660001551)
203 | with open('test/hold.dat', 'r') as dat:
204 | self.assertEqual(holding_data, json.loads(dat.read()))
205 |
206 | @responses.activate
207 | def test_alma_get_items(self):
208 | self.buildResponses()
209 | items_data = self.api.get_items(99100383900121, 2221159990000121)
210 | with open('test/items.dat', 'r') as dat:
211 | self.assertEqual(items_data, json.loads(dat.read()))
212 |
213 | @responses.activate
214 | def test_alma_get_item(self):
215 | self.buildResponses()
216 | item_data = self.api.get_item(
217 | 9922405930001552,
218 | 22115858660001551,
219 | 23115858650001551)
220 | with open('test/item.dat', 'r') as dat:
221 | self.assertEqual(item_data, json.loads(dat.read()))
222 |
223 | @responses.activate
224 | def test_alma_get_bib_requests(self):
225 | self.buildResponses()
226 | bib_requests_data = self.api.get_bib_requests(9922405930001552)
227 | with open('test/request.dat', 'r') as dat:
228 | self.assertEqual(bib_requests_data, json.loads(dat.read()))
229 |
230 | @responses.activate
231 | def test_alma_get_item_requests(self):
232 | self.buildResponses()
233 | item_requests_data = self.api.get_item_requests(9922405930001552,
234 | 22115858660001551,
235 | 23115858650001551)
236 | with open('test/request.dat', 'r') as dat:
237 | self.assertEqual(item_requests_data, json.loads(dat.read()))
238 |
239 | @responses.activate
240 | def test_alma_get_bib_booking_availability(self):
241 | self.buildResponses()
242 | bib_booking_availability_data = self.api.get_bib_booking_availability(
243 | 9922405930001552)
244 | with open('test/availability.dat', 'r') as dat:
245 | self.assertEqual(
246 | bib_booking_availability_data, json.loads(dat.read()))
247 |
248 | @responses.activate
249 | def test_alma_get_item_booking_availability(self):
250 | self.buildResponses()
251 | item_booking_availability_data = \
252 | self.api.get_item_booking_availability(9922405930001552,
253 | 22115858660001551,
254 | 23115858650001551)
255 | with open('test/availability.dat', 'r') as dat:
256 | self.assertEqual(
257 | item_booking_availability_data,
258 | json.loads(
259 | dat.read()))
260 |
261 |
262 | class TestAlmaPUTRequests(unittest.TestCase):
263 | maxDiff = None
264 |
265 | def setUp(self):
266 | self.api = alma.Alma(apikey='unreal', region='EU')
267 |
268 | def buildResponses(self):
269 |
270 | def echo_body(request):
271 | return (200, {}, request.body)
272 |
273 | # bib mock response
274 | biburl = self.api.baseurl + r'bibs/\d+$'
275 | bib_re = re.compile(biburl)
276 | responses.add_callback(
277 | responses.PUT, bib_re,
278 | callback=echo_body,
279 | content_type='application/json',
280 | )
281 |
282 | # holding mock response
283 | holdurl = self.api.baseurl + r'bibs/\d+/holdings/\d+$'
284 | hold_re = re.compile(holdurl)
285 | responses.add_callback(
286 | responses.PUT, hold_re,
287 | callback=echo_body,
288 | content_type='application/json',
289 | )
290 |
291 | # item mock response
292 | itemurl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+$'
293 | item_re = re.compile(itemurl)
294 | responses.add_callback(
295 | responses.PUT, item_re,
296 | callback=echo_body,
297 | content_type='application/json',
298 | )
299 |
300 | # bib_request mock response
301 | bib_requesturl = self.api.baseurl + r'bibs/\d+/requests/\d+$'
302 | bib_request_re = re.compile(bib_requesturl)
303 | responses.add_callback(
304 | responses.PUT, bib_request_re,
305 | callback=echo_body,
306 | content_type='application/json'
307 | )
308 |
309 | # item_request mock response
310 | item_requesturl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+/requests/\d+$'
311 | item_request_re = re.compile(item_requesturl)
312 | responses.add_callback(
313 | responses.PUT, item_request_re,
314 | callback=echo_body,
315 | content_type='application/json',
316 | )
317 |
318 | @responses.activate
319 | def test_alma_put_bib(self):
320 | self.buildResponses()
321 | with open('test/bib2.dat', 'r') as dat:
322 | original_bib = dat.read()
323 | returned_bib = self.api.put_bib(9922405930001552, original_bib)
324 | self.assertEqual(len(responses.calls), 1)
325 | self.assertEqual(returned_bib, json.loads(original_bib))
326 |
327 | @responses.activate
328 | def test_alma_put_holding(self):
329 | self.buildResponses()
330 | with open('test/hold2.dat', 'r') as dat:
331 | original_holding = dat.read()
332 | returned_holding = self.api.put_holding(9922405930001552,
333 | 22115858660001551,
334 | original_holding)
335 | self.assertEqual(len(responses.calls), 1)
336 | self.assertEqual(returned_holding, json.loads(original_holding))
337 |
338 | @responses.activate
339 | def test_alma_put_item(self):
340 | self.buildResponses()
341 | with open('test/item2.dat', 'r') as dat:
342 | original_item = dat.read()
343 | returned_item = self.api.put_item(99110223950001020,
344 | 22344156400001021,
345 | 23344156380001021,
346 | original_item)
347 | self.assertEqual(len(responses.calls), 1)
348 | self.assertEqual(returned_item, json.loads(original_item))
349 |
350 | @responses.activate
351 | def test_alma_put_bib_request(self):
352 | self.buildResponses()
353 | with open('test/request.dat', 'r') as dat:
354 | original_bib_request = dat.read()
355 | returned_bib_request = self.api.put_bib_request(9922405930001552,
356 | 83013520000121,
357 | original_bib_request)
358 | self.assertEqual(len(responses.calls), 1)
359 | self.assertEqual(returned_bib_request, json.loads(original_bib_request))
360 |
361 | @responses.activate
362 | def test_alma_put_item_request(self):
363 | self.buildResponses()
364 | with open('test/request.dat', 'r') as dat:
365 | original_item_request = dat.read()
366 | returned_item_request = self.api.put_item_request(9922405930001552,
367 | 22115858660001551,
368 | 23115858650001551,
369 | 83013520000121,
370 | original_item_request)
371 | self.assertEqual(len(responses.calls), 1)
372 | self.assertEqual(returned_item_request, json.loads(original_item_request))
373 |
374 |
375 | class TestAlmaPOSTRequests(unittest.TestCase):
376 | maxDiff = None
377 |
378 | def setUp(self):
379 | self.api = alma.Alma(apikey='unreal', region='EU')
380 |
381 | def buildResponses(self):
382 |
383 | def echo_body(request):
384 | return (200, {}, request.body)
385 |
386 | # bib_request mock responses
387 | bib_requesturl = self.api.baseurl + r'bibs/\d+/requests$'
388 | bib_request_re = re.compile(bib_requesturl)
389 | responses.add_callback(
390 | responses.POST, bib_request_re,
391 | callback=echo_body,
392 | content_type='application/json',
393 | )
394 |
395 | with open('test/request.dat', 'r') as r:
396 | responses.add(responses.POST, bib_request_re,
397 | status=200,
398 | content_type='application/json',
399 | body=r.read())
400 |
401 | #item_request mock responses
402 | item_requesturl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+/requests$'
403 | item_request_re = re.compile(item_requesturl)
404 | responses.add_callback(
405 | responses.POST, item_request_re,
406 | callback=echo_body,
407 | content_type='application/json',
408 | )
409 |
410 | with open('test/request.dat', 'r') as r:
411 | responses.add(responses.POST, item_request_re,
412 | status=200,
413 | content_type='application/json',
414 | body=r.read())
415 |
416 | #loan mock responses
417 | loanurl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+/loans'
418 | loan_re = re.compile(loanurl)
419 | responses.add_callback(
420 | responses.POST, loan_re,
421 | callback=echo_body,
422 | content_type='application/json',
423 | )
424 |
425 | with open('test/item_loan.dat', 'r') as r:
426 | responses.add(responses.POST, loan_re,
427 | status=200,
428 | content_type='application/json',
429 | body=r.read())
430 |
431 | @responses.activate
432 | def test_alma_post_bib_request(self):
433 | self.buildResponses()
434 | with open ('test/request2.dat', 'r') as dat:
435 | original_bib_request = dat.read()
436 | returned_bib_request = self.api.post_bib_request(9922405930001552,
437 | original_bib_request)
438 | self.assertEqual(len(responses.calls), 1)
439 | self.assertEqual(returned_bib_request, json.loads(original_bib_request))
440 |
441 | with open('test/request.dat', 'r') as dat:
442 | bib_request_return = dat.read()
443 | bib_request_response = self.api.post_bib_request(9922405930001552,
444 | bib_request_return)
445 | self.assertEqual(bib_request_response, json.loads(bib_request_return))
446 |
447 | @responses.activate
448 | def test_alma_post_item_request(self):
449 | self.buildResponses()
450 | with open ('test/request2.dat', 'r') as dat:
451 | original_item_request = dat.read()
452 | returned_item_request = self.api.post_item_request(9922405930001552,
453 | 22115858660001551,
454 | 23115858650001551,
455 | original_item_request)
456 | self.assertEqual(len(responses.calls), 1)
457 | self.assertEqual(returned_item_request, json.loads(original_item_request))
458 |
459 | with open('test/request.dat', 'r') as dat:
460 | item_request_return = dat.read()
461 | item_request_response = self.api.post_item_request(9922405930001552,
462 | 22115858660001551,
463 | 23115858650001551,
464 | item_request_return)
465 | self.assertEqual(item_request_response, json.loads(item_request_return))
466 |
467 | @responses.activate
468 | def test_alma_post_loan(self):
469 | self.buildResponses()
470 | with open ('test/loan.dat', 'r') as dat:
471 | original_loan = dat.read()
472 | returned_loan = self.api.post_loan(9922405930001552,
473 | 22115858660001551,
474 | 23115858650001551,
475 | original_loan)
476 | self.assertEqual(len(responses.calls), 1)
477 | self.assertEqual(returned_loan, json.loads(original_loan))
478 |
479 | with open('test/item_loan.dat', 'r') as dat:
480 | loan_return = dat.read()
481 | loan_response = self.api.post_loan(9922405930001552,
482 | 22115858660001551,
483 | 23115858650001551,
484 | loan_return)
485 | self.assertEqual(loan_response, json.loads(loan_return))
486 |
487 |
488 | class TestAlmaDELETERequests(unittest.TestCase):
489 | maxDiff = None
490 |
491 | def setUp(self):
492 | self.api = alma.Alma(apikey='unreal', region='EU')
493 |
494 | def buildResponses(self):
495 |
496 | # bib_request mock response
497 | bib_requesturl = self.api.baseurl + r'bibs/\d+/requests/\d+$'
498 | bib_request_re = re.compile(bib_requesturl)
499 | responses.add(responses.DELETE, bib_request_re, body='', status=204,)
500 |
501 | #item_request mock response
502 | item_requesturl = self.api.baseurl + r'bibs/\d+/holdings/\d+/items/\d+/requests/\d+$'
503 | item_request_re = re.compile(item_requesturl)
504 | responses.add(responses.DELETE, item_request_re, body='', status=204,)
505 |
506 | @responses.activate
507 | def test_alma_delete_bib_request(self):
508 | self.buildResponses()
509 | expected = ''
510 | bib_request_response = self.api.del_bib_request(9922405930001552,
511 | 83013520000121,)
512 | self.assertEqual(expected, bib_request_response)
513 |
514 | @responses.activate
515 | def test_alma_delete_item_request(self):
516 | self.buildResponses()
517 | expected = ''
518 | item_request_response = self.api.del_item_request(9922405930001552,
519 | 22115858660001551,
520 | 23115858650001551,
521 | 83013520000121,)
522 | self.assertEqual(expected, item_request_response)
523 |
524 | if __name__ == '__main__':
525 | unittest.main()
526 |
--------------------------------------------------------------------------------
/pyalma/alma.py:
--------------------------------------------------------------------------------
1 | import os
2 | # external imports
3 | import requests
4 |
5 | # imports for coroutines
6 | import asyncio
7 | import aiohttp
8 | from aiohttp import ClientSession, web, errors
9 | import time
10 | from ratelimiter import RateLimiter
11 |
12 |
13 | __version__ = '0.1.0'
14 | __api_version__ = 'v1'
15 | __apikey__ = os.getenv('ALMA_API_KEY')
16 | __region__ = os.getenv('ALMA_API_REGION')
17 | __circ_desk__ = os.getenv('ALMA_API_CIRC_DESK')
18 | __library__ = os.getenv('ALMA_API_LIBRARY')
19 |
20 | ENDPOINTS = {
21 | 'US': 'https://api-na.hosted.exlibrisgroup.com',
22 | 'EU': 'https://api-eu.hosted.exlibrisgroup.com',
23 | 'APAC': 'https://api-ap.hosted.exlibrisgroup.com'
24 | }
25 |
26 | FORMATS = {
27 | 'json': 'application/json',
28 | 'xml': 'application/xml'
29 | }
30 |
31 | RESOURCES = {
32 | 'bib': 'bibs/{mms_id}',
33 | 'holdings': 'bibs/{mms_id}/holdings',
34 | 'holding': 'bibs/{mms_id}/holdings/{holding_id}',
35 | 'items': 'bibs/{mms_id}/holdings/{holding_id}/items',
36 | 'item': 'bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}',
37 | 'bib_requests': 'bibs/{mms_id}/requests',
38 | 'item_requests':
39 | 'bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}/requests',
40 | 'bib_requests': 'bibs/{mms_id}/requests',
41 | 'bib_request': 'bibs/{mms_id}/requests/{request_id}',
42 | 'item_requests': 'bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}/requests',
43 | 'item_request': 'bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}/requests/{request_id}',
44 | 'bib_booking_availability': 'bibs/{mms_id}/booking-availability',
45 | 'item_booking_availability':
46 | 'bibs/{mms_id}/holdings/{holding_id}/items/' +
47 | '{item_pid}/booking-availability',
48 | 'loan': 'bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}/loans',
49 | 'requested_resources': 'task-lists/requested-resources',
50 | 'users': 'users',
51 | 'user': 'users/{user_id}'
52 | }
53 |
54 | MAX_CALLS_PER_SEC = 25
55 | SEMAPHORE_LIM = 500
56 |
57 |
58 | class Alma(object):
59 |
60 | def __init__(self, apikey=__apikey__, region=__region__):
61 | if apikey is None:
62 | raise Exception("Please supply an API key")
63 | if region not in ENDPOINTS:
64 | msg = 'Invalid Region. Must be one of {}'.format(list(ENDPOINTS))
65 | raise Exception(msg)
66 | self.apikey = apikey
67 | self.endpoint = ENDPOINTS[region]
68 | self.max_calls = MAX_CALLS_PER_SEC
69 | self.semaphore_limit = SEMAPHORE_LIM
70 |
71 | @property
72 | def baseurl(self):
73 | return '{}/almaws/{}/'.format(self.endpoint, __api_version__)
74 |
75 | def fullurl(self, resource, ids={}):
76 | return self.baseurl + RESOURCES[resource].format(**ids)
77 |
78 | def headers(self, accept='json', content_type=None):
79 | headers = {
80 | "User-Agent": "pyalma/{}".format(__version__),
81 | "Authorization": "apikey {}".format(self.apikey),
82 | "Accept": FORMATS[accept]
83 | }
84 | if content_type is not None:
85 | headers['Content-Type'] = FORMATS[content_type]
86 | return headers
87 |
88 | def request(self, httpmethod, resource, ids={}, params={}, data=None,
89 | accept='json', content_type=None):
90 | response = requests.request(
91 | method=httpmethod,
92 | headers=self.headers(accept=accept, content_type=content_type),
93 | url=self.fullurl(resource, ids),
94 | params=params,
95 | data=data)
96 | try:
97 | response.raise_for_status()
98 | return response
99 | except requests.exceptions.HTTPError:
100 | raise HTTPError(response)
101 |
102 | def extract_content(self, response):
103 | ctype = response.headers['Content-Type']
104 | if 'json' in ctype:
105 | return response.json()
106 | else:
107 | return response.content.decode('utf-8')
108 |
109 | '''
110 | Below are convenience methods that call request() and extract_content() and
111 | return the response data in json or xml
112 | '''
113 |
114 | def get_bib(self, mms_id, accept='xml'):
115 | response = self.request('GET', 'bib', {'mms_id': mms_id},
116 | accept=accept)
117 | return self.extract_content(response)
118 |
119 | def put_bib(self, mms_id, data, content_type='xml', accept='xml'):
120 | response = self.request('PUT', 'bib', {'mms_id': mms_id},
121 | data=data, content_type=content_type, accept=accept)
122 | return self.extract_content(response)
123 |
124 | def get_holdings(self, mms_id, accept='json'):
125 | response = self.request('GET', 'holdings', {'mms_id': mms_id},
126 | accept=accept)
127 | return self.extract_content(response)
128 |
129 | def get_holding(self, mms_id, holding_id, accept='json'):
130 | response = self.request('GET', 'holding',
131 | {'mms_id': mms_id, 'holding_id': holding_id},
132 | accept=accept)
133 | return self.extract_content(response)
134 |
135 | def put_holding(self, mms_id, holding_id, data, content_type='json',
136 | accept='json'):
137 | response = self.request('PUT', 'holding',
138 | {'mms_id': mms_id, 'holding_id': holding_id},
139 | data=data, content_type=content_type, accept=accept)
140 | return self.extract_content(response)
141 |
142 | def get_items(self, mms_id, holding_id, accept='json'):
143 | response = self.request('GET', 'items',
144 | {'mms_id': mms_id,
145 | 'holding_id': holding_id},
146 | accept=accept)
147 | return self.extract_content(response)
148 |
149 | def get_item(self, mms_id, holding_id, item_pid, accept='json'):
150 | response = self.request('GET', 'item',
151 | {'mms_id': mms_id,
152 | 'holding_id': holding_id,
153 | 'item_pid': item_pid},
154 | accept=accept)
155 | return self.extract_content(response)
156 |
157 | def put_item(self, mms_id, holding_id, item_pid, data, content_type='json',
158 | accept='json'):
159 | response = self.request('PUT', 'item',
160 | {'mms_id': mms_id,
161 | 'holding_id': holding_id,
162 | 'item_pid': item_pid},
163 | data=data, content_type=content_type, accept=accept)
164 | return self.extract_content(response)
165 |
166 | def del_item(self, mms_id, holding_id, item_pid):
167 | pass
168 |
169 | def post_loan(self, mms_id, holding_id, item_pid, data,
170 | content_type='json', accept='json'):
171 | response = self.request('POST', 'loan',
172 | {'mms_id': mms_id,
173 | 'holding_id': holding_id,
174 | 'item_pid': item_pid},
175 | data=data, content_type=content_type, accept=accept)
176 | return self.extract_content(response)
177 |
178 | def get_bib_requests(self, mms_id, accept='json'):
179 | response = self.request('GET', 'bib_requests', {'mms_id': mms_id},
180 | accept=accept)
181 | return self.extract_content(response)
182 |
183 | def get_item_requests(self, mms_id, holding_id, item_pid, accept='json'):
184 | response = self.request('GET', 'item_requests',
185 | {'mms_id': mms_id,
186 | 'holding_id': holding_id,
187 | 'item_pid': item_pid},
188 | accept=accept)
189 | return self.extract_content(response)
190 |
191 | def post_bib_request(self, mms_id, data, content_type='json', accept='json'):
192 | response = self.request('POST', 'bib_requests',
193 | {'mms_id': mms_id},
194 | data=data, content_type=content_type, accept=accept)
195 | return self.extract_content(response)
196 |
197 | def post_item_request(self, mms_id, holding_id, item_pid, data,
198 | content_type='json', accept='json'):
199 | response = self.request('POST', 'item_requests',
200 | {'mms_id': mms_id,
201 | 'holding_id': holding_id,
202 | 'item_pid': item_pid},
203 | data=data, content_type=content_type, accept=accept)
204 | return self.extract_content(response)
205 |
206 | def put_bib_request(self, mms_id, request_id, data, content_type='json', accept='json'):
207 | response = self.request('PUT', 'bib_request',
208 | {'mms_id': mms_id,
209 | 'request_id': request_id},
210 | data=data, content_type=content_type, accept=accept)
211 | return self.extract_content(response)
212 |
213 | def put_item_request(self, mms_id, holding_id, item_pid, request_id,
214 | data, content_type='json', accept='json'):
215 | response = self.request('PUT', 'item_request',
216 | {'mms_id': mms_id,
217 | 'holding_id': holding_id,
218 | 'item_pid': item_pid,
219 | 'request_id': request_id},
220 | data=data, content_type=content_type, accept=accept)
221 | return self.extract_content(response)
222 |
223 | def del_item_request(self, mms_id, holding_id, item_pid, request_id):
224 | response = self.request('DELETE', 'item_request',
225 | {'mms_id': mms_id,
226 | 'holding_id': holding_id,
227 | 'item_pid': item_pid,
228 | 'request_id': request_id},)
229 | return self.extract_content(response)
230 |
231 | def del_bib_request(self, mms_id, request_id):
232 | response = self.request('DELETE', 'bib_request',
233 | {'mms_id': mms_id,
234 | 'request_id': request_id},)
235 | return self.extract_content(response)
236 |
237 | def get_bib_booking_availability(self, mms_id, accept='json'):
238 | response = self.request('GET', 'bib_booking_availability',
239 | {'mms_id': mms_id}, accept=accept)
240 | return self.extract_content(response)
241 |
242 | def get_item_booking_availability(
243 | self, mms_id, holding_id, item_pid, accept='json'):
244 | response = self.request('GET', 'item_booking_availability',
245 | {'mms_id': mms_id,
246 | 'holding_id': holding_id,
247 | 'item_pid': item_pid},
248 | accept=accept)
249 | return self.extract_content(response)
250 |
251 | def get_users(self, accept='json'):
252 | response = self.request('GET', 'users', accept=accept)
253 | return self.extract_content(response)
254 |
255 | def get_user(self, user_id, accept='json'):
256 | response = self.request('GET', 'user', {'user_id': user_id},
257 | accept=accept)
258 | return self.extract_content(response)
259 |
260 | def put_user(self, user_id, data, content_type='json',
261 | accept='json'):
262 | response = self.request('PUT', 'user',
263 | {'user_id': user_id}, data=data,
264 | content_type=content_type, accept=accept)
265 | return self.extract_content(response)
266 |
267 | def get_digreps(self, mms_id, accept='json'):
268 | pass
269 |
270 | def get_digrep(self, mms_id, rep_id, accept='json'):
271 | pass
272 |
273 | def post_digrep(self, mms_id, data, content_type='json', accept='json'):
274 | pass
275 |
276 | def del_digrep(self, mms_id, rep_id):
277 | pass
278 |
279 | def get_requested_resources(self, library=__library__,
280 | circ_desk=__circ_desk__):
281 | params = {'library': library, 'circ_desk': circ_desk}
282 | response = self.request('GET', 'requested_resources', params=params)
283 | return self.extract_content(response)
284 |
285 | '''
286 | Below are coroutine methods.
287 | Note that they currently all default to xml input and output,
288 | for ease of use in receiving data in a GET and sending it back as a PUT.
289 | '''
290 |
291 | async def cor_request(self, httpmethod, resource, ids, session, params={},
292 | data=None, accept='xml', content_type=None, max_attempts=5):
293 | """
294 | Asynchronous request method
295 | Uses session.request, an aiohttp method
296 |
297 | To set rate limit:
298 | - max_attempts is the maximum number of times you want to repeat a
299 | call before giving up.
300 | - set maximum calls per second in global variable MAX_CALLS_PER_SEC
301 | """
302 | attempts_left = max_attempts
303 | rate_limiter = RateLimiter(max_calls=self.max_calls,
304 | period=(6-attempts_left),
305 | callback=self.cor_limited)
306 |
307 | async with session.request(method=httpmethod,
308 | headers=self.headers(accept='xml', content_type='xml'),
309 | url=self.fullurl(resource, ids),
310 | params=params,
311 | data=data) as response:
312 | try:
313 | try:
314 | ctype = response.headers['Content-Type']
315 | except:
316 | ctype = ''
317 | status = response.status
318 | method = response.method
319 | url = response.url_obj
320 | async with rate_limiter:
321 | response.raise_for_status()
322 | if 'json' in ctype:
323 | body = await response.json()
324 | else:
325 | body = await response.text(encoding='utf-8')
326 | return (ids, status, body)
327 | except aiohttp.errors.HttpProcessingError:
328 | body = await response.text()
329 | msg = "\nError in {} \n HTTP Status: {}\n Method: {}\n URL: {}\n Response: {}".format(ids, status, method, url, body)
330 |
331 | if status == 429:
332 | attempts_left -= 1
333 | if attempts_left < 0:
334 | print(msg)
335 | return (ids, status, msg)
336 | else:
337 | until = time.time() + (rate_limiter.period)
338 | asyncio.ensure_future(self.cor_limited(until))
339 | await asyncio.sleep(rate_limiter.period)
340 | async with rate_limiter:
341 | result = await self.cor_request(httpmethod, resource, ids, session, params=params, data=data, accept=accept, content_type=content_type, max_attempts=attempts_left)
342 | return result
343 | else:
344 | return (ids, status, msg)
345 |
346 | async def cor_bound_request(self, sem, httpmethod, resource, ids, session, params={},
347 | data=None, accept='xml', content_type='xml'):
348 | """
349 | Bounds request, so that no more than x connections can be
350 | open at once (set inside self.cor_run)
351 | """
352 | async with sem:
353 | request = await self.cor_request(httpmethod, resource, ids, session, data=data, accept=accept, content_type=content_type)
354 | return request
355 |
356 | async def cor_limited(self, until):
357 | """
358 | Rate limits calls to the server (set in cor_run)
359 | """
360 | duration = int(round(until - time.time()))
361 | print("Rate limited, sleeping for {:d} seconds".format(duration))
362 |
363 | async def cor_run(self, httpmethod, resource, input_params, accept='xml', content_type=None):
364 | """
365 | Takes a list of input_params, makes requests, returns responses
366 | """
367 | tasks = []
368 |
369 | # set the simultaneous connection limit here
370 | sem = asyncio.Semaphore(self.semaphore_limit)
371 |
372 | # set the rate limit here
373 | rate_limiter = RateLimiter(max_calls=self.max_calls,
374 | period=1,
375 | callback=self.cor_limited)
376 |
377 | async with ClientSession() as session:
378 | for input_param in input_params:
379 |
380 | task = asyncio.ensure_future(self.cor_bound_request(sem,
381 | httpmethod,
382 | resource,
383 | input_param['ids'],
384 | session,
385 | data=input_param['data'],
386 | accept=accept,
387 | content_type=content_type))
388 | # create a delay of between calls
389 | # to help prevent API rate errors
390 | await asyncio.sleep(1/self.max_calls)
391 | tasks.append(task)
392 | async with rate_limiter:
393 | responses = await asyncio.gather(*tasks)
394 | return responses
395 |
396 | """
397 | Each of the below asynchronous methods takes input_params as a variable,
398 | and returns a list of tuples.
399 |
400 | input_params is a list of dictionaries in the following form:
401 | [{
402 | 'data': data,
403 | 'ids': {
404 | 'mms_id': mms_id,
405 | 'holding_id': holding_id,
406 | 'item_pid': item_pid,
407 | 'request_id': request_id
408 | }
409 | },
410 | ...
411 | ]
412 |
413 | Returns a list of tuples in form
414 | [(ids, status, response),
415 | ...
416 | ]
417 | """
418 |
419 | def cor_get_bib(self, input_params, accept='xml'):
420 | # input_params includes mms_id
421 | loop = asyncio.get_event_loop()
422 | try:
423 | responses = loop.run_until_complete(self.cor_run('GET',
424 | 'bib',
425 | input_params,
426 | accept=accept))
427 | finally:
428 | loop.close()
429 | return responses
430 |
431 | def cor_put_bib(self, input_params, content_type='xml', accept='xml'):
432 | # input_params includes mms_id, data
433 | loop = asyncio.get_event_loop()
434 | try:
435 | responses = loop.run_until_complete(self.cor_run('PUT',
436 | 'bib',
437 | input_params,
438 | content_type=content_type,
439 | accept=accept))
440 | finally:
441 | loop.close()
442 | return responses
443 |
444 | def cor_get_holdings(self, input_params, accept='xml'):
445 | # input_params includes mms_id
446 | loop = asyncio.get_event_loop()
447 | try:
448 | responses = loop.run_until_complete(self.cor_run('GET',
449 | 'holdings',
450 | input_params,
451 | accept=accept))
452 | finally:
453 | loop.close()
454 | return responses
455 |
456 | def cor_get_holding(self, input_params, accept='xml'):
457 | # input_params includes mms_id, holding_id
458 | loop = asyncio.get_event_loop()
459 | try:
460 | responses = loop.run_until_complete(self.cor_run('GET',
461 | 'holding',
462 | input_params,
463 | accept=accept))
464 | finally:
465 | loop.close()
466 | return responses
467 |
468 | def cor_put_holding(self, input_params, content_type='xml',
469 | accept='xml'):
470 | # input_params includes mms_id, holding_id, data
471 | loop = asyncio.get_event_loop()
472 | try:
473 | responses = loop.run_until_complete(self.cor_run('PUT',
474 | 'holding',
475 | input_params,
476 | content_type=content_type,
477 | accept=accept))
478 | finally:
479 | loop.close()
480 | return responses
481 |
482 | def cor_get_items(self, input_params, accept='xml'):
483 | # input_params includes mms_id, holding_id
484 | loop = asyncio.get_event_loop()
485 | try:
486 | responses = loop.run_until_complete(self.cor_run('GET',
487 | 'items',
488 | input_params,
489 | accept=accept))
490 | finally:
491 | loop.close()
492 | return responses
493 |
494 | def cor_get_item(self, input_params, accept='xml'):
495 | # input_params includes mms_id, holding_id, item_pid
496 | loop = asyncio.get_event_loop()
497 | try:
498 | responses = loop.run_until_complete(self.cor_run('GET',
499 | 'item',
500 | input_params,
501 | accept=accept))
502 | finally:
503 | loop.close()
504 | return responses
505 |
506 | def cor_put_item(self, input_params, content_type='xml',
507 | accept='xml'):
508 | # input_params includes mms_id, holding_id, item_pid, data
509 | loop = asyncio.get_event_loop()
510 | try:
511 | responses = loop.run_until_complete(self.cor_run('PUT',
512 | 'item',
513 | input_params,
514 | content_type=content_type,
515 | accept=accept))
516 | finally:
517 | loop.close()
518 | return responses
519 |
520 | def cor_get_bib_requests(self, input_params, accept='xml'):
521 | # input_params includes mms_id
522 | loop = asyncio.get_event_loop()
523 | try:
524 | responses = loop.run_until_complete(self.cor_run('GET',
525 | 'bib_requests',
526 | input_params,
527 | accept=accept))
528 | finally:
529 | loop.close()
530 | return responses
531 |
532 | def cor_get_item_requests(self, input_params, accept='xml'):
533 | # input_params includes mms_id, holding_id, item_pid
534 | loop = asyncio.get_event_loop()
535 | try:
536 | responses = loop.run_until_complete(self.cor_run('GET',
537 | 'item_requests',
538 | input_params,
539 | accept=accept))
540 | finally:
541 | loop.close()
542 | return responses
543 |
544 | def cor_del_item_request(self, input_params):
545 | # input_params includes mms_id, holding_id, item_pid, request_id
546 | loop = asyncio.get_event_loop()
547 | try:
548 | responses = loop.run_until_complete(self.cor_run('DELETE',
549 | 'item_request',
550 | input_params))
551 | finally:
552 | loop.close()
553 | return responses
554 |
555 | def cor_del_bib_request(self, input_params):
556 | # input_params includes mms_id, request_id
557 | loop = asyncio.get_event_loop()
558 | try:
559 | responses = loop.run_until_complete(self.cor_run('DELETE',
560 | 'bib_request',
561 | input_params))
562 | finally:
563 | loop.close()
564 | return responses
565 |
566 | '''
567 | WARNING: below methods have not been fully implemented or
568 | been tested. To be complete, tehse methods will require the
569 | appropriate query strings parameters to be passed into session.request
570 | within self.cor_request, which has not yet been implemented.
571 | '''
572 | def cor_del_item(self, input_params):
573 | pass
574 |
575 | def cor_post_loan(self, input_params,
576 | content_type='xml', accept='xml'):
577 | # input_params includes mms_id, holding_id, item_pid, data
578 | loop = asyncio.get_event_loop()
579 | try:
580 | responses = loop.run_until_complete(self.cor_run('POST',
581 | 'loan',
582 | input_params,
583 | content_type=content_type,
584 | accept=accept))
585 | finally:
586 | loop.close()
587 | return responses
588 |
589 | def cor_post_bib_request(self, input_params,
590 | content_type='xml', accept='xml'):
591 | # input_params includes mms_id, data
592 | loop = asyncio.get_event_loop()
593 | try:
594 | responses = loop.run_until_complete(self.cor_run('POST',
595 | 'bib_requests',
596 | input_params,
597 | content_type=content_type,
598 | accept=accept))
599 | finally:
600 | loop.close()
601 | return responses
602 |
603 | def cor_post_item_request(self, input_params,
604 | content_type='xml', accept='xml'):
605 | # input_params includes mms_id, holding_id, item_pid, data
606 | loop = asyncio.get_event_loop()
607 | try:
608 | responses = loop.run_until_complete(self.cor_run('POST',
609 | 'item_requests',
610 | input_params,
611 | content_type=content_type,
612 | accept=accept))
613 | finally:
614 | loop.close()
615 | return responses
616 |
617 | def cor_put_bib_request(self, input_params,
618 | content_type='xml', accept='xml'):
619 | # input_params includes mms_id, request_id, data
620 | loop = asyncio.get_event_loop()
621 | try:
622 | responses = loop.run_until_complete(self.cor_run('PUT',
623 | 'bib_request',
624 | input_params,
625 | content_type=content_type,
626 | accept=accept))
627 | finally:
628 | loop.close()
629 | return responses
630 |
631 | def cor_put_item_request(self, input_params,
632 | content_type='xml', accept='xml'):
633 | # input_params includes mms_id, holding_id, item_pid, request_id, data
634 | loop = asyncio.get_event_loop()
635 | try:
636 | responses = loop.run_until_complete(self.cor_run('PUT',
637 | 'item_request',
638 | input_params,
639 | content_type=content_type,
640 | accept=accept))
641 | finally:
642 | loop.close()
643 | return responses
644 |
645 | def cor_get_bib_booking_availability(self, input_params, accept='xml'):
646 | # input_params includes mms_id
647 | loop = asyncio.get_event_loop()
648 | try:
649 | responses = loop.run_until_complete(self.cor_run('GET',
650 | 'bib_booking_availability',
651 | input_params,
652 | accept=accept))
653 | finally:
654 | loop.close()
655 | return responses
656 |
657 | def cor_get_item_booking_availability(
658 | self, input_params, accept='xml'):
659 | # input_params includes mms_id, holding_id, item_pid
660 | loop = asyncio.get_event_loop()
661 | try:
662 | responses = loop.run_until_complete(self.cor_run('GET',
663 | 'item_booking_availability',
664 | input_params,
665 | accept=accept))
666 | finally:
667 | loop.close()
668 | return responses
669 |
670 | def cor_get_digreps(self, input_params, accept='json'):
671 | pass
672 |
673 | def cor_get_digrep(self, input_params, accept='json'):
674 | pass
675 |
676 | def cor_post_digrep(self, input_params, content_type='json', accept='json'):
677 | pass
678 |
679 | def cor_del_digrep(self, input_params, rep_id):
680 | pass
681 |
682 |
683 | class HTTPError(Exception):
684 |
685 | def __init__(self, response):
686 | super().__init__(self.msg(response))
687 |
688 | def msg(self, response):
689 | msg = "\n HTTP Status: {}\n Method: {}\n URL: {}\n Response: {}"
690 | return msg.format(response.status_code, response.request.method,
691 | response.url, response.text)
692 |
--------------------------------------------------------------------------------
/test/mms_holdings_items_with_requests.csv:
--------------------------------------------------------------------------------
1 | ids,data
2 | "{'item_pid': '23137888170001551', 'mms_id': '9928519370001551', 'holding_id': '22137888180001551'}"
3 | "{'item_pid': '23137867060001551', 'mms_id': '9928503600001551', 'holding_id': '22137867220001551'}"
4 | "{'item_pid': '23137617400001551', 'mms_id': '9928448450001551', 'holding_id': '22137617410001551'}"
5 | "{'item_pid': '23137474520001551', 'mms_id': '9928407390001551', 'holding_id': '22137474560001551'}"
6 | "{'item_pid': '23136958180001551', 'mms_id': '9928241780001551', 'holding_id': '22136958190001551'}"
7 | "{'item_pid': '23136486090001551', 'mms_id': '9928114970001551', 'holding_id': '22136486100001551'}"
8 | "{'item_pid': '23136319210001551', 'mms_id': '9928066790001551', 'holding_id': '22136319220001551'}"
9 | "{'item_pid': '23136091410001551', 'mms_id': '9928007560001551', 'holding_id': '22136091430001551'}"
10 | "{'item_pid': '23135692920001551', 'mms_id': '9927887590001551', 'holding_id': '22135692990001551'}"
11 | "{'item_pid': '23135574960001551', 'mms_id': '9927842310001551', 'holding_id': '22135574970001551'}"
12 | "{'item_pid': '23134060280001551', 'mms_id': '9927432230001551', 'holding_id': '22157819480001551'}"
13 | "{'item_pid': '23151392950001551', 'mms_id': '9927400050001551', 'holding_id': '22151392960001551'}"
14 | "{'item_pid': '23133912040001551', 'mms_id': '9927399090001551', 'holding_id': '22155677470001551'}"
15 | "{'item_pid': '23151555810001551', 'mms_id': '9927374370001551', 'holding_id': '22151555820001551'}"
16 | "{'item_pid': '23133805180001551', 'mms_id': '9927356110001551', 'holding_id': '22133805190001551'}"
17 | "{'item_pid': '23133745410001551', 'mms_id': '9927334950001551', 'holding_id': '22133745420001551'}"
18 | "{'item_pid': '23133674880001551', 'mms_id': '9927316920001551', 'holding_id': '22133674890001551'}"
19 | "{'item_pid': '23133561330001551', 'mms_id': '9927290210001551', 'holding_id': '22133561340001551'}"
20 | "{'item_pid': '23132178580001551', 'mms_id': '9926910530001551', 'holding_id': '22132178610001551'}"
21 | "{'item_pid': '23132167630001551', 'mms_id': '9926892350001551', 'holding_id': '22132167660001551'}"
22 | "{'item_pid': '23131844720001551', 'mms_id': '9926819240001551', 'holding_id': '22157575790001551'}"
23 | "{'item_pid': '23131538790001551', 'mms_id': '9926726440001551', 'holding_id': '22131538800001551'}"
24 | "{'item_pid': '23131418080001551', 'mms_id': '9926700310001551', 'holding_id': '22131418090001551'}"
25 | "{'item_pid': '23131149600001551', 'mms_id': '9926618750001551', 'holding_id': '22131149620001551'}"
26 | "{'item_pid': '23130730590001551', 'mms_id': '9926494000001551', 'holding_id': '22157479830001551'}"
27 | "{'item_pid': '23129957550001551', 'mms_id': '9926273430001551', 'holding_id': '22129957560001551'}"
28 | "{'item_pid': '23129805870001551', 'mms_id': '9926235880001551', 'holding_id': '22129805880001551'}"
29 | "{'item_pid': '23129756310001551', 'mms_id': '9926230760001551', 'holding_id': '22129756330001551'}"
30 | "{'item_pid': '23129564010001551', 'mms_id': '9926167460001551', 'holding_id': '22157360340001551'}"
31 | "{'item_pid': '23129391590001551', 'mms_id': '9926116910001551', 'holding_id': '22129391600001551'}"
32 | "{'item_pid': '23129093920001551', 'mms_id': '9926028600001551', 'holding_id': '22129093930001551'}"
33 | "{'item_pid': '23128485250001551', 'mms_id': '9925845740001551', 'holding_id': '22128485260001551'}"
34 | "{'item_pid': '23128354500001551', 'mms_id': '9925803820001551', 'holding_id': '22128354510001551'}"
35 | "{'item_pid': '23128062760001551', 'mms_id': '9925725310001551', 'holding_id': '22157226090001551'}"
36 | "{'item_pid': '23127554250001551', 'mms_id': '9925563340001551', 'holding_id': '22157177020001551'}"
37 | "{'item_pid': '23127144550001551', 'mms_id': '9925443910001551', 'holding_id': '22159898660001551'}"
38 | "{'item_pid': '23126522880001551', 'mms_id': '9925275630001551', 'holding_id': '22126522890001551'}"
39 | "{'item_pid': '23126339650001551', 'mms_id': '9925214020001551', 'holding_id': '22126339660001551'}"
40 | "{'item_pid': '23126014700001551', 'mms_id': '9925122840001551', 'holding_id': '22126014710001551'}"
41 | "{'item_pid': '23125608330001551', 'mms_id': '9925016030001551', 'holding_id': '22125608340001551'}"
42 | "{'item_pid': '23125525390001551', 'mms_id': '9924998710001551', 'holding_id': '22125525400001551'}"
43 | "{'item_pid': '23125151050001551', 'mms_id': '9924886480001551', 'holding_id': '22125151060001551'}"
44 | "{'item_pid': '23125148070001551', 'mms_id': '9924871610001551', 'holding_id': '22156943040001551'}"
45 | "{'item_pid': '23123691020001551', 'mms_id': '9924491520001551', 'holding_id': '22123691030001551'}"
46 | "{'item_pid': '23123561630001551', 'mms_id': '9924469390001551', 'holding_id': '22123561640001551'}"
47 | "{'item_pid': '23122896620001551', 'mms_id': '9924265730001551', 'holding_id': '22122896630001551'}"
48 | "{'item_pid': '23122556550001551', 'mms_id': '9924178830001551', 'holding_id': '22122556560001551'}"
49 | "{'item_pid': '23122160890001551', 'mms_id': '9924079520001551', 'holding_id': '22122160900001551'}"
50 | "{'item_pid': '23122106430001551', 'mms_id': '9924060560001551', 'holding_id': '22122106440001551'}"
51 | "{'item_pid': '23122113940001551', 'mms_id': '9924056540001551', 'holding_id': '22163633520001551'}"
52 | "{'item_pid': '23121961610001551', 'mms_id': '9924020680001551', 'holding_id': '22156580430001551'}"
53 | "{'item_pid': '23121798850001551', 'mms_id': '9923952350001551', 'holding_id': '22156566150001551'}"
54 | "{'item_pid': '23120522220001551', 'mms_id': '9923700150001551', 'holding_id': '22120522230001551'}"
55 | "{'item_pid': '23120478200001551', 'mms_id': '9923677370001551', 'holding_id': '22156497530001551'}"
56 | "{'item_pid': '23119085500001551', 'mms_id': '9923290030001551', 'holding_id': '22119085510001551'}"
57 | "{'item_pid': '23118932650001551', 'mms_id': '9923249760001551', 'holding_id': '22118932660001551'}"
58 | "{'item_pid': '23118543960001551', 'mms_id': '9923127190001551', 'holding_id': '22118543970001551'}"
59 | "{'item_pid': '23118154530001551', 'mms_id': '9923019460001551', 'holding_id': '22118154540001551'}"
60 | "{'item_pid': '23117447230001551', 'mms_id': '9922806100001551', 'holding_id': '22117447240001551'}"
61 | "{'item_pid': '23116862210001551', 'mms_id': '9922642840001551', 'holding_id': '22116862220001551'}"
62 | "{'item_pid': '23116820400001551', 'mms_id': '9922634750001551', 'holding_id': '22116820420001551'}"
63 | "{'item_pid': '23115776050001551', 'mms_id': '9922389020001551', 'holding_id': '22156065690001551'}"
64 | "{'item_pid': '23115792870001551', 'mms_id': '9922382490001551', 'holding_id': '22115792900001551'}"
65 | "{'item_pid': '23115282890001551', 'mms_id': '9922249960001551', 'holding_id': '22115282900001551'}"
66 | "{'item_pid': '23114985050001551', 'mms_id': '9922169960001551', 'holding_id': '22114985070001551'}"
67 | "{'item_pid': '23114643180001551', 'mms_id': '9922100080001551', 'holding_id': '22114643190001551'}"
68 | "{'item_pid': '23113300420001551', 'mms_id': '9921702180001551', 'holding_id': '22113300450001551'}"
69 | "{'item_pid': '23113116920001551', 'mms_id': '9921658460001551', 'holding_id': '22113116930001551'}"
70 | "{'item_pid': '23113035550001551', 'mms_id': '9921621340001551', 'holding_id': '22155770740001551'}"
71 | "{'item_pid': '23113034570001551', 'mms_id': '9921621090001551', 'holding_id': '22155771250001551'}"
72 | "{'item_pid': '23112750340001551', 'mms_id': '9921542170001551', 'holding_id': '22112750350001551'}"
73 | "{'item_pid': '23163758310001551', 'mms_id': '9933570608001551', 'holding_id': '22163758320001551'}"
74 | "{'item_pid': '23163567800001551', 'mms_id': '9933569403901551', 'holding_id': '22163567810001551'}"
75 | "{'item_pid': '23162619320001551', 'mms_id': '9933563610001551', 'holding_id': '22162619340001551'}"
76 | "{'item_pid': '23162523720001551', 'mms_id': '9933563306001551', 'holding_id': '22162523730001551'}"
77 | "{'item_pid': '23162779650001551', 'mms_id': '9933561061201551', 'holding_id': '22162779640001551'}"
78 | "{'item_pid': '23162246270001551', 'mms_id': '9933559447601551', 'holding_id': '22162246280001551'}"
79 | "{'item_pid': '23161757590001551', 'mms_id': '9933555607001551', 'holding_id': '22161757600001551'}"
80 | "{'item_pid': '23161359480001551', 'mms_id': '9933552311201551', 'holding_id': '22161359490001551'}"
81 | "{'item_pid': '23161223350001551', 'mms_id': '9933551166401551', 'holding_id': '22161223360001551'}"
82 | "{'item_pid': '23161289440001551', 'mms_id': '9933551009101551', 'holding_id': '22161289250001551'}"
83 | "{'item_pid': '23160895920001551', 'mms_id': '9933548302701551', 'holding_id': '22160895930001551'}"
84 | "{'item_pid': '23160765960001551', 'mms_id': '9933547094501551', 'holding_id': '22161697930001551'}"
85 | "{'item_pid': '23160710670001551', 'mms_id': '9933547006601551', 'holding_id': '22160710680001551'}"
86 | "{'item_pid': '23160291860001551', 'mms_id': '9933542891801551', 'holding_id': '22160291870001551'}"
87 | "{'item_pid': '23159949710001551', 'mms_id': '9933539911401551', 'holding_id': '22159949720001551'}"
88 | "{'item_pid': '23159889280001551', 'mms_id': '9933539610601551', 'holding_id': '22159889300001551'}"
89 | "{'item_pid': '23154301240001551', 'mms_id': '9933289140001551', 'holding_id': '22154301250001551'}"
90 | "{'item_pid': '23152712100001551', 'mms_id': '9932669120001551', 'holding_id': '22152712110001551'}"
91 | "{'item_pid': '23152069160001551', 'mms_id': '9931439020001551', 'holding_id': '22152069170001551'}"
92 | "{'item_pid': '23144289730001551', 'mms_id': '9930253150001551', 'holding_id': '22158682840001551'}"
93 | "{'item_pid': '23144200760001551', 'mms_id': '9930233450001551', 'holding_id': '22144200800001551'}"
94 | "{'item_pid': '23142699780001551', 'mms_id': '9929795880001551', 'holding_id': '22142699790001551'}"
95 | "{'item_pid': '23141807490001551', 'mms_id': '9929531830001551', 'holding_id': '22141807500001551'}"
96 | "{'item_pid': '23141536350001551', 'mms_id': '9929453090001551', 'holding_id': '22141536360001551'}"
97 | "{'item_pid': '23141280930001551', 'mms_id': '9929384340001551', 'holding_id': '22141280940001551'}"
98 | "{'item_pid': '23140758790001551', 'mms_id': '9929269220001551', 'holding_id': '22158371000001551'}"
99 | "{'item_pid': '23140571080001551', 'mms_id': '9929212140001551', 'holding_id': '22140571090001551'}"
100 | "{'item_pid': '23140304560001551', 'mms_id': '9929150500001551', 'holding_id': '22158332580001551'}"
101 | "{'item_pid': '23140311770001551', 'mms_id': '9929146490001551', 'holding_id': '22140311780001551'}"
102 | "{'item_pid': '23140326950001551', 'mms_id': '9929144970001551', 'holding_id': '22140326960001551'}"
103 | "{'item_pid': '23140255460001551', 'mms_id': '9929126010001551', 'holding_id': '22140255470001551'}"
104 | "{'item_pid': '23140195370001551', 'mms_id': '9929104290001551', 'holding_id': '22163649950001551'}"
105 | "{'item_pid': '23138801370001551', 'mms_id': '9928693370001551', 'holding_id': '22138801420001551'}"
106 | "{'item_pid': '23138814460001551', 'mms_id': '9928691410001551', 'holding_id': '22138814470001551'}"
107 | "{'item_pid': '23138625930001551', 'mms_id': '9928642410001551', 'holding_id': '22158162630001551'}"
108 | "{'item_pid': '23137640520001551', 'mms_id': '9928458200001551', 'holding_id': '22158092020001551'}"
109 | "{'item_pid': '23134658580001551', 'mms_id': '9927604800001551', 'holding_id': '22157872900001551'}"
110 | "{'item_pid': '23133956010001551', 'mms_id': '9927406220001551', 'holding_id': '22157808320001551'}"
111 | "{'item_pid': '23129863810001551', 'mms_id': '9926257390001551', 'holding_id': '22158853000001551'}"
112 | "{'item_pid': '23128220070001551', 'mms_id': '9925778920001551', 'holding_id': '22157248990001551'}"
113 | "{'item_pid': '23127413250001551', 'mms_id': '9925524500001551', 'holding_id': '22157156700001551'}"
114 | "{'item_pid': '23159569640001551', 'mms_id': '9924228370001551', 'holding_id': '22122733650001551'}"
115 | "{'item_pid': '23160683790001551', 'mms_id': '9924228370001551', 'holding_id': '22122733650001551'}"
116 | "{'item_pid': '23120434030001551', 'mms_id': '9923668600001551', 'holding_id': '22156450850001551'}"
117 | "{'item_pid': '23118549420001551', 'mms_id': '9923128860001551', 'holding_id': '22156297730001551'}"
118 | "{'item_pid': '23118511340001551', 'mms_id': '9923115210001551', 'holding_id': '22156287830001551'}"
119 | "{'item_pid': '23118464730001551', 'mms_id': '9923109780001551', 'holding_id': '22118464740001551'}"
120 | "{'item_pid': '23117702170001551', 'mms_id': '9922872830001551', 'holding_id': '22156227200001551'}"
121 | "{'item_pid': '23117473210001551', 'mms_id': '9922816470001551', 'holding_id': '22156207780001551'}"
122 | "{'item_pid': '23117438810001551', 'mms_id': '9922809380001551', 'holding_id': '22156199350001551'}"
123 | "{'item_pid': '23117325890001551', 'mms_id': '9922780100001551', 'holding_id': '22117325900001551'}"
124 | "{'item_pid': '23117306010001551', 'mms_id': '9922765780001551', 'holding_id': '22117306020001551'}"
125 | "{'item_pid': '23117161990001551', 'mms_id': '9922725450001551', 'holding_id': '22156161380001551'}"
126 | "{'item_pid': '23116141300001551', 'mms_id': '9922488180001551', 'holding_id': '22116141340001551'}"
127 | "{'item_pid': '23116141260001551', 'mms_id': '9922488180001551', 'holding_id': '22116141290001551'}"
128 | "{'item_pid': '23116034220001551', 'mms_id': '9922457670001551', 'holding_id': '22116034230001551'}"
129 | "{'item_pid': '23115926310001551', 'mms_id': '9922423730001551', 'holding_id': '22156088050001551'}"
130 | "{'item_pid': '23144986950001551', 'mms_id': '9930467740001551', 'holding_id': '22158750920001551'}"
131 | "{'item_pid': '23144807200001551', 'mms_id': '9930401080001551', 'holding_id': '22158724210001551'}"
132 | "{'item_pid': '23142148720001551', 'mms_id': '9929634850001551', 'holding_id': '22158497010001551'}"
133 | "{'item_pid': '23140909170001551', 'mms_id': '9929296360001551', 'holding_id': '22159048350001551'}"
134 | "{'item_pid': '23140135880001551', 'mms_id': '9929083490001551', 'holding_id': '22158328820001551'}"
135 | "{'item_pid': '23151886760001551', 'mms_id': '9922920440001551', 'holding_id': '22151886790001551'}"
136 | "{'item_pid': '23155429500001551', 'mms_id': '9922920440001551', 'holding_id': '22151886790001551'}"
137 | "{'item_pid': '23117826680001551', 'mms_id': '9922920440001551', 'holding_id': '22117826700001551'}"
138 | "{'item_pid': '23161883180001551', 'mms_id': '9933556899201551', 'holding_id': '22161883190001551'}"
139 | "{'item_pid': '23162718770001551', 'mms_id': '9933556899201551', 'holding_id': '22161883190001551'}"
140 | "{'item_pid': '23143505570001551', 'mms_id': '9930039030001551', 'holding_id': '22143505590001551'}"
141 | "{'item_pid': '23143420650001551', 'mms_id': '9930001190001551', 'holding_id': '22143420660001551'}"
142 | "{'item_pid': '23139822650001551', 'mms_id': '9928991230001551', 'holding_id': '22139822660001551'}"
143 | "{'item_pid': '23161828960001551', 'mms_id': '9928991230001551', 'holding_id': '22139822660001551'}"
144 | "{'item_pid': '23137872690001551', 'mms_id': '9928520150001551', 'holding_id': '22137872730001551'}"
145 | "{'item_pid': '23137872720001551', 'mms_id': '9928520150001551', 'holding_id': '22137872730001551'}"
146 | "{'item_pid': '23137872610001551', 'mms_id': '9928520150001551', 'holding_id': '22137872680001551'}"
147 | "{'item_pid': '23137872640001551', 'mms_id': '9928520150001551', 'holding_id': '22137872680001551'}"
148 | "{'item_pid': '23137816450001551', 'mms_id': '9928494920001551', 'holding_id': '22158113330001551'}"
149 | "{'item_pid': '23137816470001551', 'mms_id': '9928494920001551', 'holding_id': '22158113700001551'}"
150 | "{'item_pid': '23135592820001551', 'mms_id': '9927856400001551', 'holding_id': '22135592830001551'}"
151 | "{'item_pid': '23135592800001551', 'mms_id': '9927856400001551', 'holding_id': '22135592810001551'}"
152 | "{'item_pid': '23133748040001551', 'mms_id': '9927335780001551', 'holding_id': '22133748050001551'}"
153 | "{'item_pid': '23133748060001551', 'mms_id': '9927335780001551', 'holding_id': '22133748070001551'}"
154 | "{'item_pid': '23132201730001551', 'mms_id': '9926901100001551', 'holding_id': '22132201760001551'}"
155 | "{'item_pid': '23132201700001551', 'mms_id': '9926901100001551', 'holding_id': '22132201710001551'}"
156 | "{'item_pid': '23129211930001551', 'mms_id': '9926052090001551', 'holding_id': '22129211940001551'}"
157 | "{'item_pid': '23129211950001551', 'mms_id': '9926052090001551', 'holding_id': '22129212020001551'}"
158 | "{'item_pid': '23128783700001551', 'mms_id': '9925939220001551', 'holding_id': '22128783710001551'}"
159 | "{'item_pid': '23128783720001551', 'mms_id': '9925939220001551', 'holding_id': '22128783730001551'}"
160 | "{'item_pid': '23126407600001551', 'mms_id': '9925233730001551', 'holding_id': '22126407610001551'}"
161 | "{'item_pid': '23126407620001551', 'mms_id': '9925233730001551', 'holding_id': '22126407630001551'}"
162 | "{'item_pid': '23126128620001551', 'mms_id': '9925152820001551', 'holding_id': '22126128630001551'}"
163 | "{'item_pid': '23126128640001551', 'mms_id': '9925152820001551', 'holding_id': '22126128650001551'}"
164 | "{'item_pid': '23123250570001551', 'mms_id': '9924361390001551', 'holding_id': '22123250580001551'}"
165 | "{'item_pid': '23123250590001551', 'mms_id': '9924361390001551', 'holding_id': '22123250670001551'}"
166 | "{'item_pid': '23122738100001551', 'mms_id': '9924229180001551', 'holding_id': '22122738130001551'}"
167 | "{'item_pid': '23122738140001551', 'mms_id': '9924229180001551', 'holding_id': '22122738170001551'}"
168 | "{'item_pid': '23119011050001551', 'mms_id': '9923267030001551', 'holding_id': '22119011060001551'}"
169 | "{'item_pid': '23119011030001551', 'mms_id': '9923267030001551', 'holding_id': '22119011040001551'}"
170 | "{'item_pid': '23117816770001551', 'mms_id': '9922903400001551', 'holding_id': '22117816780001551'}"
171 | "{'item_pid': '23117816750001551', 'mms_id': '9922903400001551', 'holding_id': '22163649450001551'}"
172 | "{'item_pid': '23116902730001551', 'mms_id': '9922651290001551', 'holding_id': '22116902740001551'}"
173 | "{'item_pid': '23116902760001551', 'mms_id': '9922651290001551', 'holding_id': '22116902780001551'}"
174 | "{'item_pid': '23134046630001551', 'mms_id': '9927440080001551', 'holding_id': '22134046640001551'}"
175 | "{'item_pid': '23134046690001551', 'mms_id': '9927440080001551', 'holding_id': '22134046700001551'}"
176 | "{'item_pid': '23121779040001551', 'mms_id': '9923957970001551', 'holding_id': '22121779080001551'}"
177 | "{'item_pid': '23121779100001551', 'mms_id': '9923957970001551', 'holding_id': '22121779110001551'}"
178 | "{'item_pid': '23144670210001551', 'mms_id': '9930375790001551', 'holding_id': '22144670220001551'}"
179 | "{'item_pid': '23144670230001551', 'mms_id': '9930375790001551', 'holding_id': '22144670240001551'}"
180 | "{'item_pid': '23143712800001551', 'mms_id': '9930094580001551', 'holding_id': '22143712810001551'}"
181 | "{'item_pid': '23143712770001551', 'mms_id': '9930094580001551', 'holding_id': '22143712780001551'}"
182 | "{'item_pid': '23138236720001551', 'mms_id': '9928600050001551', 'holding_id': '22138236750001551'}"
183 | "{'item_pid': '23138236760001551', 'mms_id': '9928600050001551', 'holding_id': '22138236770001551'}"
184 | "{'item_pid': '23138236780001551', 'mms_id': '9928600050001551', 'holding_id': '22138236790001551'}"
185 | "{'item_pid': '23131343430001551', 'mms_id': '9926680180001551', 'holding_id': '22131343440001551'}"
186 | "{'item_pid': '23131343450001551', 'mms_id': '9926680180001551', 'holding_id': '22131343460001551'}"
187 | "{'item_pid': '23131343470001551', 'mms_id': '9926680180001551', 'holding_id': '22131343480001551'}"
188 | "{'item_pid': '23126331770001551', 'mms_id': '9925211970001551', 'holding_id': '22126331780001551'}"
189 | "{'item_pid': '23126331730001551', 'mms_id': '9925211970001551', 'holding_id': '22157065930001551'}"
190 | "{'item_pid': '23126061060001551', 'mms_id': '9925147690001551', 'holding_id': '22157010100001551'}"
191 | "{'item_pid': '23126061090001551', 'mms_id': '9925147690001551', 'holding_id': '22126061120001551'}"
192 | "{'item_pid': '23125920190001551', 'mms_id': '9925106940001551', 'holding_id': '22125920200001551'}"
193 | "{'item_pid': '23125920170001551', 'mms_id': '9925106940001551', 'holding_id': '22157007730001551'}"
194 | "{'item_pid': '23122213640001551', 'mms_id': '9924084050001551', 'holding_id': '22156614870001551'}"
195 | "{'item_pid': '23122213660001551', 'mms_id': '9924084050001551', 'holding_id': '22156614970001551'}"
196 | "{'item_pid': '23120860180001551', 'mms_id': '9923782290001551', 'holding_id': '22156514970001551'}"
197 | "{'item_pid': '23120860160001551', 'mms_id': '9923782290001551', 'holding_id': '22156515430001551'}"
198 | "{'item_pid': '23120006910001551', 'mms_id': '9923531760001551', 'holding_id': '22156422170001551'}"
199 | "{'item_pid': '23120006950001551', 'mms_id': '9923531760001551', 'holding_id': '22156422200001551'}"
200 | "{'item_pid': '23120006930001551', 'mms_id': '9923531760001551', 'holding_id': '22156422290001551'}"
201 | "{'item_pid': '23118255460001551', 'mms_id': '9923049630001551', 'holding_id': '22118255470001551'}"
202 | "{'item_pid': '23118255420001551', 'mms_id': '9923049630001551', 'holding_id': '22118255430001551'}"
203 | "{'item_pid': '23118255440001551', 'mms_id': '9923049630001551', 'holding_id': '22118255450001551'}"
204 | "{'item_pid': '23139585800001551', 'mms_id': '9928924640001551', 'holding_id': '22139585810001551'}"
205 | "{'item_pid': '23139585820001551', 'mms_id': '9928924640001551', 'holding_id': '22158268830001551'}"
206 | "{'item_pid': '23139168610001551', 'mms_id': '9928810200001551', 'holding_id': '22139168640001551'}"
207 | "{'item_pid': '23139168580001551', 'mms_id': '9928810200001551', 'holding_id': '22158227780001551'}"
208 | "{'item_pid': '23116322440001551', 'mms_id': '9922530710001551', 'holding_id': '22116322480001551'}"
209 | "{'item_pid': '23116322450001551', 'mms_id': '9922530710001551', 'holding_id': '22116322480001551'}"
210 | "{'item_pid': '23116322460001551', 'mms_id': '9922530710001551', 'holding_id': '22116322480001551'}"
211 | "{'item_pid': '23116322470001551', 'mms_id': '9922530710001551', 'holding_id': '22116322480001551'}"
212 | "{'item_pid': '23116322490001551', 'mms_id': '9922530710001551', 'holding_id': '22116322500001551'}"
213 | "{'item_pid': '23116322510001551', 'mms_id': '9922530710001551', 'holding_id': '22116322520001551'}"
214 | "{'item_pid': '23116322530001551', 'mms_id': '9922530710001551', 'holding_id': '22116322540001551'}"
215 | "{'item_pid': '23116322420001551', 'mms_id': '9922530710001551', 'holding_id': '22116322430001551'}"
216 | "{'item_pid': '23113619600001551', 'mms_id': '9921798680001551', 'holding_id': '22113619610001551'}"
217 | "{'item_pid': '23113619620001551', 'mms_id': '9921798680001551', 'holding_id': '22113619630001551'}"
218 | "{'item_pid': '23113619560001551', 'mms_id': '9921798680001551', 'holding_id': '22113619570001551'}"
219 | "{'item_pid': '23113619580001551', 'mms_id': '9921798680001551', 'holding_id': '22113619590001551'}"
220 | "{'item_pid': '23142561560001551', 'mms_id': '9929752620001551', 'holding_id': '22142561570001551'}"
221 | "{'item_pid': '23142561580001551', 'mms_id': '9929752620001551', 'holding_id': '22142561590001551'}"
222 | "{'item_pid': '23142561540001551', 'mms_id': '9929752620001551', 'holding_id': '22142561550001551'}"
223 | "{'item_pid': '23141884920001551', 'mms_id': '9929567440001551', 'holding_id': '22141884930001551'}"
224 | "{'item_pid': '23141884880001551', 'mms_id': '9929567440001551', 'holding_id': '22141884890001551'}"
225 | "{'item_pid': '23141884900001551', 'mms_id': '9929567440001551', 'holding_id': '22141884910001551'}"
226 | "{'item_pid': '23121743420001551', 'mms_id': '9923945040001551', 'holding_id': '22121743440001551'}"
227 | "{'item_pid': '23121743430001551', 'mms_id': '9923945040001551', 'holding_id': '22121743440001551'}"
228 | "{'item_pid': '23121743450001551', 'mms_id': '9923945040001551', 'holding_id': '22121743460001551'}"
229 | "{'item_pid': '23121743480001551', 'mms_id': '9923945040001551', 'holding_id': '22121743490001551'}"
230 | "{'item_pid': '23163049460001551', 'mms_id': '9933556805101551', 'holding_id': '22163049470001551'}"
231 | "{'item_pid': '23163748830001551', 'mms_id': '9933556805101551', 'holding_id': '22163748840001551'}"
232 | "{'item_pid': '23161487930001551', 'mms_id': '9933556805101551', 'holding_id': '22161487940001551'}"
233 | "{'item_pid': '23161879080001551', 'mms_id': '9933556805101551', 'holding_id': '22161487940001551'}"
234 | "{'item_pid': '23135432580001551', 'mms_id': '9927820730001551', 'holding_id': '22135432600001551'}"
235 | "{'item_pid': '23135432480001551', 'mms_id': '9927820730001551', 'holding_id': '22135432510001551'}"
236 | "{'item_pid': '23135432520001551', 'mms_id': '9927820730001551', 'holding_id': '22135432530001551'}"
237 | "{'item_pid': '23135432540001551', 'mms_id': '9927820730001551', 'holding_id': '22135432550001551'}"
238 | "{'item_pid': '23135432560001551', 'mms_id': '9927820730001551', 'holding_id': '22135432570001551'}"
239 | "{'item_pid': '23132345050001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
240 | "{'item_pid': '23132345060001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
241 | "{'item_pid': '23132345090001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
242 | "{'item_pid': '23132345100001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
243 | "{'item_pid': '23132345110001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
244 | "{'item_pid': '23132345120001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
245 | "{'item_pid': '23132345130001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
246 | "{'item_pid': '23132345160001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
247 | "{'item_pid': '23132345170001551', 'mms_id': '9926949460001551', 'holding_id': '22132345220001551'}"
248 | "{'item_pid': '23140599780001551', 'mms_id': '9929228680001551', 'holding_id': '22140599800001551'}"
249 | "{'item_pid': '23140599850001551', 'mms_id': '9929228680001551', 'holding_id': '22158906510001551'}"
250 | "{'item_pid': '23140599810001551', 'mms_id': '9929228680001551', 'holding_id': '22158906360001551'}"
251 | "{'item_pid': '23127974320001551', 'mms_id': '9925694500001551', 'holding_id': '22127974340001551'}"
252 | "{'item_pid': '23127974330001551', 'mms_id': '9925694500001551', 'holding_id': '22127974340001551'}"
253 | "{'item_pid': '23127974410001551', 'mms_id': '9925694500001551', 'holding_id': '22127974450001551'}"
254 | "{'item_pid': '23127974440001551', 'mms_id': '9925694500001551', 'holding_id': '22127974450001551'}"
255 | "{'item_pid': '23127974350001551', 'mms_id': '9925694500001551', 'holding_id': '22127974400001551'}"
256 | "{'item_pid': '23127974370001551', 'mms_id': '9925694500001551', 'holding_id': '22127974400001551'}"
257 | "{'item_pid': '23124637980001551', 'mms_id': '9924744740001551', 'holding_id': '22124638020001551'}"
258 | "{'item_pid': '23124638030001551', 'mms_id': '9924744740001551', 'holding_id': '22124638040001551'}"
259 | "{'item_pid': '23124638050001551', 'mms_id': '9924744740001551', 'holding_id': '22124638060001551'}"
260 | "{'item_pid': '23124637960001551', 'mms_id': '9924744740001551', 'holding_id': '22124637970001551'}"
261 | "{'item_pid': '23124637920001551', 'mms_id': '9924744740001551', 'holding_id': '22124637930001551'}"
262 | "{'item_pid': '23124637940001551', 'mms_id': '9924744740001551', 'holding_id': '22124637950001551'}"
263 | "{'item_pid': '23116764900001551', 'mms_id': '9922614830001551', 'holding_id': '22116764920001551'}"
264 | "{'item_pid': '23116764910001551', 'mms_id': '9922614830001551', 'holding_id': '22116764920001551'}"
265 | "{'item_pid': '23116764840001551', 'mms_id': '9922614830001551', 'holding_id': '22116764860001551'}"
266 | "{'item_pid': '23116764850001551', 'mms_id': '9922614830001551', 'holding_id': '22116764860001551'}"
267 | "{'item_pid': '23116764930001551', 'mms_id': '9922614830001551', 'holding_id': '22116764950001551'}"
268 | "{'item_pid': '23116764940001551', 'mms_id': '9922614830001551', 'holding_id': '22116764950001551'}"
269 | "{'item_pid': '23116764870001551', 'mms_id': '9922614830001551', 'holding_id': '22116764890001551'}"
270 | "{'item_pid': '23116764880001551', 'mms_id': '9922614830001551', 'holding_id': '22116764890001551'}"
271 | "{'item_pid': '23130766860001551', 'mms_id': '9926507720001551', 'holding_id': '22130766870001551'}"
272 | "{'item_pid': '23130766880001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
273 | "{'item_pid': '23130766890001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
274 | "{'item_pid': '23130766900001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
275 | "{'item_pid': '23130766910001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
276 | "{'item_pid': '23130766920001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
277 | "{'item_pid': '23130766930001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
278 | "{'item_pid': '23130766940001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
279 | "{'item_pid': '23130766950001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
280 | "{'item_pid': '23130766960001551', 'mms_id': '9926507720001551', 'holding_id': '22130766970001551'}"
281 | "{'item_pid': '23122085390001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
282 | "{'item_pid': '23122085400001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
283 | "{'item_pid': '23122085410001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
284 | "{'item_pid': '23122085420001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
285 | "{'item_pid': '23122085430001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
286 | "{'item_pid': '23122085440001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
287 | "{'item_pid': '23122085450001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
288 | "{'item_pid': '23122085460001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
289 | "{'item_pid': '23154759810001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
290 | "{'item_pid': '23160685100001551', 'mms_id': '9924046600001551', 'holding_id': '22122085480001551'}"
291 | "{'item_pid': '23122085370001551', 'mms_id': '9924046600001551', 'holding_id': '22122085380001551'}"
292 | "{'item_pid': '23142696170001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
293 | "{'item_pid': '23142696180001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
294 | "{'item_pid': '23142696190001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
295 | "{'item_pid': '23142696200001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
296 | "{'item_pid': '23142696210001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
297 | "{'item_pid': '23142696220001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
298 | "{'item_pid': '23142696230001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
299 | "{'item_pid': '23142696240001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
300 | "{'item_pid': '23142696250001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
301 | "{'item_pid': '23142696260001551', 'mms_id': '9929794780001551', 'holding_id': '22142696300001551'}"
302 | "{'item_pid': '23132827080001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
303 | "{'item_pid': '23132827090001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
304 | "{'item_pid': '23132827100001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
305 | "{'item_pid': '23132827110001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
306 | "{'item_pid': '23132827120001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
307 | "{'item_pid': '23132827130001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
308 | "{'item_pid': '23132827140001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
309 | "{'item_pid': '23132827150001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
310 | "{'item_pid': '23132827160001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
311 | "{'item_pid': '23132827170001551', 'mms_id': '9927069540001551', 'holding_id': '22132827350001551'}"
312 | "{'item_pid': '23116460070001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
313 | "{'item_pid': '23116460080001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
314 | "{'item_pid': '23116460090001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
315 | "{'item_pid': '23116460100001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
316 | "{'item_pid': '23116460110001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
317 | "{'item_pid': '23116460120001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
318 | "{'item_pid': '23116460130001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
319 | "{'item_pid': '23116460150001551', 'mms_id': '9922551310001551', 'holding_id': '22116460190001551'}"
320 | "{'item_pid': '23116460010001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
321 | "{'item_pid': '23116460020001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
322 | "{'item_pid': '23116460030001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
323 | "{'item_pid': '23116479750001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
324 | "{'item_pid': '23116479760001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
325 | "{'item_pid': '23116479770001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
326 | "{'item_pid': '23116479780001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
327 | "{'item_pid': '23116479790001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
328 | "{'item_pid': '23116479800001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
329 | "{'item_pid': '23116479810001551', 'mms_id': '9922551310001551', 'holding_id': '22116460040001551'}"
330 | "{'item_pid': '23116460050001551', 'mms_id': '9922551310001551', 'holding_id': '22116460060001551'}"
331 | "{'item_pid': '23124283770001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
332 | "{'item_pid': '23124283780001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
333 | "{'item_pid': '23124283790001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
334 | "{'item_pid': '23124283800001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
335 | "{'item_pid': '23124283810001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
336 | "{'item_pid': '23124283820001551', 'mms_id': '9924656440001551', 'holding_id': '22124283900001551'}"
337 | "{'item_pid': '23124283910001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
338 | "{'item_pid': '23124283920001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
339 | "{'item_pid': '23124283930001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
340 | "{'item_pid': '23124283940001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
341 | "{'item_pid': '23124283950001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
342 | "{'item_pid': '23124283960001551', 'mms_id': '9924656440001551', 'holding_id': '22124283970001551'}"
343 | "{'item_pid': '23124284050001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
344 | "{'item_pid': '23124284060001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
345 | "{'item_pid': '23124284070001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
346 | "{'item_pid': '23124284080001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
347 | "{'item_pid': '23124284090001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
348 | "{'item_pid': '23124284100001551', 'mms_id': '9924656440001551', 'holding_id': '22124284110001551'}"
349 | "{'item_pid': '23124283980001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
350 | "{'item_pid': '23124283990001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
351 | "{'item_pid': '23124284000001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
352 | "{'item_pid': '23124284010001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
353 | "{'item_pid': '23124284020001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
354 | "{'item_pid': '23124284030001551', 'mms_id': '9924656440001551', 'holding_id': '22124284040001551'}"
355 | "{'item_pid': '23119498170001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
356 | "{'item_pid': '23119498180001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
357 | "{'item_pid': '23119498190001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
358 | "{'item_pid': '23119498200001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
359 | "{'item_pid': '23119498210001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
360 | "{'item_pid': '23119498220001551', 'mms_id': '9923395690001551', 'holding_id': '22119498230001551'}"
361 | "{'item_pid': '23119498780001551', 'mms_id': '9923395690001551', 'holding_id': '22119498810001551'}"
362 | "{'item_pid': '23119498790001551', 'mms_id': '9923395690001551', 'holding_id': '22119498810001551'}"
363 | "{'item_pid': '23119498800001551', 'mms_id': '9923395690001551', 'holding_id': '22119498810001551'}"
364 | "{'item_pid': '23119498240001551', 'mms_id': '9923395690001551', 'holding_id': '22119498250001551'}"
365 | "{'item_pid': '23119498280001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
366 | "{'item_pid': '23119498290001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
367 | "{'item_pid': '23119498300001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
368 | "{'item_pid': '23119498310001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
369 | "{'item_pid': '23119498320001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
370 | "{'item_pid': '23119498330001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
371 | "{'item_pid': '23119498370001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
372 | "{'item_pid': '23119498380001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
373 | "{'item_pid': '23119498390001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
374 | "{'item_pid': '23119498400001551', 'mms_id': '9923395690001551', 'holding_id': '22119498750001551'}"
375 | "{'item_pid': '23119498260001551', 'mms_id': '9923395690001551', 'holding_id': '22119498270001551'}"
376 | "{'item_pid': '23119498760001551', 'mms_id': '9923395690001551', 'holding_id': '22119498770001551'}"
377 | "{'item_pid': '23120920010001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
378 | "{'item_pid': '23120920020001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
379 | "{'item_pid': '23120920030001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
380 | "{'item_pid': '23120920040001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
381 | "{'item_pid': '23120920050001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
382 | "{'item_pid': '23120920060001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
383 | "{'item_pid': '23120920070001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
384 | "{'item_pid': '23120920080001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
385 | "{'item_pid': '23120920090001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
386 | "{'item_pid': '23120920100001551', 'mms_id': '9923803820001551', 'holding_id': '22158996320001551'}"
387 | "{'item_pid': '23120939700001551', 'mms_id': '9923803820001551', 'holding_id': '22159127040001551'}"
388 | "{'item_pid': '23142944650001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
389 | "{'item_pid': '23142944660001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
390 | "{'item_pid': '23142944670001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
391 | "{'item_pid': '23142944680001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
392 | "{'item_pid': '23142944690001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
393 | "{'item_pid': '23142944700001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
394 | "{'item_pid': '23142944710001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
395 | "{'item_pid': '23142944720001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
396 | "{'item_pid': '23142944730001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
397 | "{'item_pid': '23142944740001551', 'mms_id': '9929877310001551', 'holding_id': '22142945090001551'}"
398 | "{'item_pid': '23163739290001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
399 | "{'item_pid': '23163739300001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
400 | "{'item_pid': '23163739310001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
401 | "{'item_pid': '23163739320001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
402 | "{'item_pid': '23163739330001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
403 | "{'item_pid': '23163739340001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
404 | "{'item_pid': '23163739350001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
405 | "{'item_pid': '23163739360001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
406 | "{'item_pid': '23163899640001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
407 | "{'item_pid': '23163899650001551', 'mms_id': '9929867770001551', 'holding_id': '22142901070001551'}"
408 | "{'item_pid': '23163899620001551', 'mms_id': '9929867770001551', 'holding_id': '22142901080001551'}"
409 | "{'item_pid': '23163899630001551', 'mms_id': '9929867770001551', 'holding_id': '22142901080001551'}"
410 | "{'item_pid': '23136678840001551', 'mms_id': '9928175590001551', 'holding_id': '22136678860001551'}"
411 | "{'item_pid': '23136678850001551', 'mms_id': '9928175590001551', 'holding_id': '22136678860001551'}"
412 | "{'item_pid': '23136677930001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
413 | "{'item_pid': '23136677940001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
414 | "{'item_pid': '23136677950001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
415 | "{'item_pid': '23136677960001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
416 | "{'item_pid': '23136677970001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
417 | "{'item_pid': '23136677980001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
418 | "{'item_pid': '23136677990001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
419 | "{'item_pid': '23136678000001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
420 | "{'item_pid': '23136678010001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
421 | "{'item_pid': '23136678020001551', 'mms_id': '9928175590001551', 'holding_id': '22136678530001551'}"
422 | "{'item_pid': '23136678890001551', 'mms_id': '9928175590001551', 'holding_id': '22136678900001551'}"
423 | "{'item_pid': '23136678540001551', 'mms_id': '9928175590001551', 'holding_id': '22136678550001551'}"
424 | "{'item_pid': '23136678560001551', 'mms_id': '9928175590001551', 'holding_id': '22136678590001551'}"
425 | "{'item_pid': '23136678570001551', 'mms_id': '9928175590001551', 'holding_id': '22136678590001551'}"
426 | "{'item_pid': '23136678580001551', 'mms_id': '9928175590001551', 'holding_id': '22136678590001551'}"
427 | "{'item_pid': '23136678870001551', 'mms_id': '9928175590001551', 'holding_id': '22136678880001551'}"
428 | "{'item_pid': '23136678600001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
429 | "{'item_pid': '23136678610001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
430 | "{'item_pid': '23136678620001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
431 | "{'item_pid': '23136678630001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
432 | "{'item_pid': '23136678640001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
433 | "{'item_pid': '23136678650001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
434 | "{'item_pid': '23136678660001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
435 | "{'item_pid': '23136678670001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
436 | "{'item_pid': '23136678680001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
437 | "{'item_pid': '23136678690001551', 'mms_id': '9928175590001551', 'holding_id': '22136678830001551'}"
438 | "{'item_pid': '23136236000001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
439 | "{'item_pid': '23136236010001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
440 | "{'item_pid': '23136236020001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
441 | "{'item_pid': '23136236030001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
442 | "{'item_pid': '23136236040001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
443 | "{'item_pid': '23136236050001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
444 | "{'item_pid': '23136236060001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
445 | "{'item_pid': '23136236070001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
446 | "{'item_pid': '23136236080001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
447 | "{'item_pid': '23136236090001551', 'mms_id': '9928049720001551', 'holding_id': '22159036830001551'}"
448 | "{'item_pid': '23117699070001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
449 | "{'item_pid': '23117699080001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
450 | "{'item_pid': '23117699090001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
451 | "{'item_pid': '23117699100001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
452 | "{'item_pid': '23117699110001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
453 | "{'item_pid': '23117699120001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
454 | "{'item_pid': '23117699130001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
455 | "{'item_pid': '23117699140001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
456 | "{'item_pid': '23117699150001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
457 | "{'item_pid': '23117699160001551', 'mms_id': '9922876790001551', 'holding_id': '22117699430001551'}"
458 | "{'item_pid': '23117699440001551', 'mms_id': '9922876790001551', 'holding_id': '22117699450001551'}"
459 | "{'item_pid': '23117680010001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
460 | "{'item_pid': '23117680020001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
461 | "{'item_pid': '23117680030001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
462 | "{'item_pid': '23117680040001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
463 | "{'item_pid': '23117680080001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
464 | "{'item_pid': '23117680090001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
465 | "{'item_pid': '23117680100001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
466 | "{'item_pid': '23117680110001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
467 | "{'item_pid': '23117680120001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
468 | "{'item_pid': '23117680130001551', 'mms_id': '9922876790001551', 'holding_id': '22117681080001551'}"
469 | "{'item_pid': '23117681090001551', 'mms_id': '9922876790001551', 'holding_id': '22117681110001551'}"
470 | "{'item_pid': '23117681100001551', 'mms_id': '9922876790001551', 'holding_id': '22117681110001551'}"
471 | "{'item_pid': '23117699040001551', 'mms_id': '9922876790001551', 'holding_id': '22117699060001551'}"
472 | "{'item_pid': '23117699050001551', 'mms_id': '9922876790001551', 'holding_id': '22117699060001551'}"
473 | "{'item_pid': '23121016890001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
474 | "{'item_pid': '23121016900001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
475 | "{'item_pid': '23121016910001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
476 | "{'item_pid': '23121016920001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
477 | "{'item_pid': '23121016930001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
478 | "{'item_pid': '23121016940001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
479 | "{'item_pid': '23121016950001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
480 | "{'item_pid': '23121016960001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
481 | "{'item_pid': '23121016970001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
482 | "{'item_pid': '23121016980001551', 'mms_id': '9923814820001551', 'holding_id': '22121019270001551'}"
483 | "{'item_pid': '23113523520001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
484 | "{'item_pid': '23113523530001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
485 | "{'item_pid': '23113523840001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
486 | "{'item_pid': '23113523850001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
487 | "{'item_pid': '23113524250001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
488 | "{'item_pid': '23113524650001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
489 | "{'item_pid': '23113524660001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
490 | "{'item_pid': '23155049950001551', 'mms_id': '9921761370001551', 'holding_id': '22155049960001551'}"
491 | "{'item_pid': '23113525240001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
492 | "{'item_pid': '23113525250001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
493 | "{'item_pid': '23113525260001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
494 | "{'item_pid': '23113525270001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
495 | "{'item_pid': '23113525280001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
496 | "{'item_pid': '23113525290001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
497 | "{'item_pid': '23113525300001551', 'mms_id': '9921761370001551', 'holding_id': '22113525310001551'}"
498 | "{'item_pid': '23155049940001551', 'mms_id': '9921761370001551', 'holding_id': '22155028950001551'}"
499 | "{'item_pid': '23155028920001551', 'mms_id': '9921761370001551', 'holding_id': '22155028940001551'}"
500 | "{'item_pid': '23155028930001551', 'mms_id': '9921761370001551', 'holding_id': '22155028940001551'}"
501 | "{'item_pid': '23113523820001551', 'mms_id': '9921761370001551', 'holding_id': '22155029540001551'}"
502 | "{'item_pid': '23155029430001551', 'mms_id': '9921761370001551', 'holding_id': '22155029540001551'}"
503 | "{'item_pid': '23113525210001551', 'mms_id': '9921761370001551', 'holding_id': '22113525230001551'}"
504 | "{'item_pid': '23113525220001551', 'mms_id': '9921761370001551', 'holding_id': '22113525230001551'}"
505 | "{'item_pid': '23113523230001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
506 | "{'item_pid': '23113523240001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
507 | "{'item_pid': '23113523250001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
508 | "{'item_pid': '23113523260001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
509 | "{'item_pid': '23113523270001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
510 | "{'item_pid': '23113523280001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
511 | "{'item_pid': '23113523290001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
512 | "{'item_pid': '23113523300001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
513 | "{'item_pid': '23113523310001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
514 | "{'item_pid': '23113523380001551', 'mms_id': '9921761370001551', 'holding_id': '22113525200001551'}"
515 | "{'item_pid': '23161810010001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
516 | "{'item_pid': '23161810020001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
517 | "{'item_pid': '23161810030001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
518 | "{'item_pid': '23161810040001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
519 | "{'item_pid': '23161810050001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
520 | "{'item_pid': '23161810060001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
521 | "{'item_pid': '23161810070001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
522 | "{'item_pid': '23161810080001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
523 | "{'item_pid': '23161810090001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
524 | "{'item_pid': '23161810100001551', 'mms_id': '9933545407701551', 'holding_id': '22160535940001551'}"
525 | "{'item_pid': '23122228660001551', 'mms_id': '9924083760001551', 'holding_id': '22122228690001551'}"
526 | "{'item_pid': '23122228670001551', 'mms_id': '9924083760001551', 'holding_id': '22122228690001551'}"
527 | "{'item_pid': '23122228680001551', 'mms_id': '9924083760001551', 'holding_id': '22122228690001551'}"
528 | "{'item_pid': '23122229720001551', 'mms_id': '9924083760001551', 'holding_id': '22122229730001551'}"
529 | "{'item_pid': '23122210370001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
530 | "{'item_pid': '23122210380001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
531 | "{'item_pid': '23122210390001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
532 | "{'item_pid': '23122210400001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
533 | "{'item_pid': '23122210410001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
534 | "{'item_pid': '23122210420001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
535 | "{'item_pid': '23122210430001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
536 | "{'item_pid': '23122210440001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
537 | "{'item_pid': '23122210450001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
538 | "{'item_pid': '23122210460001551', 'mms_id': '9924083760001551', 'holding_id': '22122212770001551'}"
539 | "{'item_pid': '23122229230001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
540 | "{'item_pid': '23122229240001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
541 | "{'item_pid': '23122229250001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
542 | "{'item_pid': '23122229260001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
543 | "{'item_pid': '23122229270001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
544 | "{'item_pid': '23122229280001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
545 | "{'item_pid': '23122229290001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
546 | "{'item_pid': '23122229300001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
547 | "{'item_pid': '23122229310001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
548 | "{'item_pid': '23122229320001551', 'mms_id': '9924083760001551', 'holding_id': '22122229710001551'}"
549 | "{'item_pid': '23122228700001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
550 | "{'item_pid': '23122228710001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
551 | "{'item_pid': '23122228720001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
552 | "{'item_pid': '23122228730001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
553 | "{'item_pid': '23122228740001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
554 | "{'item_pid': '23122228750001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
555 | "{'item_pid': '23122228760001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
556 | "{'item_pid': '23122228770001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
557 | "{'item_pid': '23122228780001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
558 | "{'item_pid': '23122228790001551', 'mms_id': '9924083760001551', 'holding_id': '22122229220001551'}"
559 | "{'item_pid': '23122210040001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
560 | "{'item_pid': '23122210050001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
561 | "{'item_pid': '23122210060001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
562 | "{'item_pid': '23122210070001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
563 | "{'item_pid': '23122210080001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
564 | "{'item_pid': '23122210090001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
565 | "{'item_pid': '23122210100001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
566 | "{'item_pid': '23122210110001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
567 | "{'item_pid': '23122210120001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
568 | "{'item_pid': '23122210130001551', 'mms_id': '9924083760001551', 'holding_id': '22122210360001551'}"
569 | "{'item_pid': '23122210010001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
570 | "{'item_pid': '23122210020001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
571 | "{'item_pid': '23122229740001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
572 | "{'item_pid': '23122229750001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
573 | "{'item_pid': '23122229760001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
574 | "{'item_pid': '23122229770001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
575 | "{'item_pid': '23122229780001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
576 | "{'item_pid': '23122229790001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
577 | "{'item_pid': '23122229800001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
578 | "{'item_pid': '23122229810001551', 'mms_id': '9924083760001551', 'holding_id': '22122210030001551'}"
579 | "{'item_pid': '23116116300001551', 'mms_id': '9922475050001551', 'holding_id': '22116116320001551'}"
580 | "{'item_pid': '23116110290001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
581 | "{'item_pid': '23116110300001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
582 | "{'item_pid': '23116110310001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
583 | "{'item_pid': '23116110320001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
584 | "{'item_pid': '23116110330001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
585 | "{'item_pid': '23116110340001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
586 | "{'item_pid': '23116110350001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
587 | "{'item_pid': '23116110360001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
588 | "{'item_pid': '23116110650001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
589 | "{'item_pid': '23116110660001551', 'mms_id': '9922475050001551', 'holding_id': '22116111920001551'}"
590 | "{'item_pid': '23116112060001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
591 | "{'item_pid': '23116112070001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
592 | "{'item_pid': '23116112080001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
593 | "{'item_pid': '23116112090001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
594 | "{'item_pid': '23116112100001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
595 | "{'item_pid': '23116112110001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
596 | "{'item_pid': '23116112270001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
597 | "{'item_pid': '23116112280001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
598 | "{'item_pid': '23116112290001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
599 | "{'item_pid': '23116112300001551', 'mms_id': '9922475050001551', 'holding_id': '22116113070001551'}"
600 | "{'item_pid': '23116113080001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
601 | "{'item_pid': '23116113090001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
602 | "{'item_pid': '23116113100001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
603 | "{'item_pid': '23116113110001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
604 | "{'item_pid': '23116113120001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
605 | "{'item_pid': '23116113130001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
606 | "{'item_pid': '23116113150001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
607 | "{'item_pid': '23116113180001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
608 | "{'item_pid': '23116113190001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
609 | "{'item_pid': '23116113200001551', 'mms_id': '9922475050001551', 'holding_id': '22116113240001551'}"
610 | "{'item_pid': '23116110040001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
611 | "{'item_pid': '23116110050001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
612 | "{'item_pid': '23116110070001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
613 | "{'item_pid': '23116110100001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
614 | "{'item_pid': '23116110110001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
615 | "{'item_pid': '23116110120001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
616 | "{'item_pid': '23116110130001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
617 | "{'item_pid': '23116110140001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
618 | "{'item_pid': '23116110150001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
619 | "{'item_pid': '23116110160001551', 'mms_id': '9922475050001551', 'holding_id': '22116110210001551'}"
620 | "{'item_pid': '23116114160001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
621 | "{'item_pid': '23116114170001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
622 | "{'item_pid': '23116114190001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
623 | "{'item_pid': '23116114210001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
624 | "{'item_pid': '23116114220001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
625 | "{'item_pid': '23116114230001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
626 | "{'item_pid': '23116114320001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
627 | "{'item_pid': '23116114330001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
628 | "{'item_pid': '23116114340001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
629 | "{'item_pid': '23116114350001551', 'mms_id': '9922475050001551', 'holding_id': '22116116180001551'}"
630 | "{'item_pid': '23116113260001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
631 | "{'item_pid': '23116113370001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
632 | "{'item_pid': '23116113380001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
633 | "{'item_pid': '23116113390001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
634 | "{'item_pid': '23116113400001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
635 | "{'item_pid': '23116113410001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
636 | "{'item_pid': '23116113420001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
637 | "{'item_pid': '23116113430001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
638 | "{'item_pid': '23116113440001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
639 | "{'item_pid': '23116113450001551', 'mms_id': '9922475050001551', 'holding_id': '22116113940001551'}"
640 | "{'item_pid': '23116110220001551', 'mms_id': '9922475050001551', 'holding_id': '22116110280001551'}"
641 | "{'item_pid': '23116110230001551', 'mms_id': '9922475050001551', 'holding_id': '22116110280001551'}"
642 | "{'item_pid': '23116110260001551', 'mms_id': '9922475050001551', 'holding_id': '22116110280001551'}"
643 | "{'item_pid': '23116110270001551', 'mms_id': '9922475050001551', 'holding_id': '22116110280001551'}"
644 | "{'item_pid': '23116113280001551', 'mms_id': '9922475050001551', 'holding_id': '22116110280001551'}"
645 | "{'item_pid': '23116111940001551', 'mms_id': '9922475050001551', 'holding_id': '22116112050001551'}"
646 | "{'item_pid': '23116111950001551', 'mms_id': '9922475050001551', 'holding_id': '22116112050001551'}"
647 | "{'item_pid': '23116111990001551', 'mms_id': '9922475050001551', 'holding_id': '22116112050001551'}"
648 | "{'item_pid': '23116112040001551', 'mms_id': '9922475050001551', 'holding_id': '22116112050001551'}"
649 | "{'item_pid': '23116112590001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
650 | "{'item_pid': '23116113950001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
651 | "{'item_pid': '23116113960001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
652 | "{'item_pid': '23116113970001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
653 | "{'item_pid': '23116113980001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
654 | "{'item_pid': '23116113990001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
655 | "{'item_pid': '23116114000001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
656 | "{'item_pid': '23116114010001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
657 | "{'item_pid': '23116114020001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
658 | "{'item_pid': '23116114030001551', 'mms_id': '9922475050001551', 'holding_id': '22116114140001551'}"
659 | "{'item_pid': '23116116260001551', 'mms_id': '9922475050001551', 'holding_id': '22116116290001551'}"
660 | "{'item_pid': '23116116270001551', 'mms_id': '9922475050001551', 'holding_id': '22116116290001551'}"
661 | "{'item_pid': '23116116280001551', 'mms_id': '9922475050001551', 'holding_id': '22116116290001551'}"
662 | "{'item_pid': '23116116190001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
663 | "{'item_pid': '23116116200001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
664 | "{'item_pid': '23116116210001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
665 | "{'item_pid': '23116116220001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
666 | "{'item_pid': '23116116230001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
667 | "{'item_pid': '23116116240001551', 'mms_id': '9922475050001551', 'holding_id': '22116116250001551'}"
668 | "{'item_pid': '23116110010001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
669 | "{'item_pid': '23116110020001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
670 | "{'item_pid': '23116128960001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
671 | "{'item_pid': '23116128970001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
672 | "{'item_pid': '23116128980001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
673 | "{'item_pid': '23116128990001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
674 | "{'item_pid': '23116129000001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
675 | "{'item_pid': '23116129010001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
676 | "{'item_pid': '23116129020001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
677 | "{'item_pid': '23116129030001551', 'mms_id': '9922475050001551', 'holding_id': '22116110030001551'}"
678 | "{'item_pid': '23160230350001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
679 | "{'item_pid': '23160230360001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
680 | "{'item_pid': '23160535700001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
681 | "{'item_pid': '23160535710001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
682 | "{'item_pid': '23160535720001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
683 | "{'item_pid': '23160535730001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
684 | "{'item_pid': '23160535740001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
685 | "{'item_pid': '23160535750001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
686 | "{'item_pid': '23160535760001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
687 | "{'item_pid': '23160535770001551', 'mms_id': '9927990200001551', 'holding_id': '22136024830001551'}"
688 | "{'item_pid': '23160534590001551', 'mms_id': '9927990200001551', 'holding_id': '22160534600001551'}"
689 | "{'item_pid': '23130030010001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
690 | "{'item_pid': '23130030020001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
691 | "{'item_pid': '23130030030001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
692 | "{'item_pid': '23130030040001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
693 | "{'item_pid': '23130030050001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
694 | "{'item_pid': '23130030060001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
695 | "{'item_pid': '23130030070001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
696 | "{'item_pid': '23130030080001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
697 | "{'item_pid': '23130030090001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
698 | "{'item_pid': '23130030100001551', 'mms_id': '9926293280001551', 'holding_id': '22130030940001551'}"
699 | "{'item_pid': '23130030980001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
700 | "{'item_pid': '23130030990001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
701 | "{'item_pid': '23130031000001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
702 | "{'item_pid': '23130031010001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
703 | "{'item_pid': '23130031020001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
704 | "{'item_pid': '23130031030001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
705 | "{'item_pid': '23130031040001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
706 | "{'item_pid': '23130031050001551', 'mms_id': '9926293280001551', 'holding_id': '22130031060001551'}"
707 | "{'item_pid': '23130049260001551', 'mms_id': '9926293280001551', 'holding_id': '22130049270001551'}"
708 | "{'item_pid': '23130031070001551', 'mms_id': '9926293280001551', 'holding_id': '22130031120001551'}"
709 | "{'item_pid': '23130031080001551', 'mms_id': '9926293280001551', 'holding_id': '22130031120001551'}"
710 | "{'item_pid': '23130031090001551', 'mms_id': '9926293280001551', 'holding_id': '22130031120001551'}"
711 | "{'item_pid': '23130031100001551', 'mms_id': '9926293280001551', 'holding_id': '22130031120001551'}"
712 | "{'item_pid': '23130031110001551', 'mms_id': '9926293280001551', 'holding_id': '22130031120001551'}"
713 | "{'item_pid': '23130031130001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
714 | "{'item_pid': '23130031140001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
715 | "{'item_pid': '23130031150001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
716 | "{'item_pid': '23130031160001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
717 | "{'item_pid': '23130031170001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
718 | "{'item_pid': '23130031180001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
719 | "{'item_pid': '23130031200001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
720 | "{'item_pid': '23130031220001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
721 | "{'item_pid': '23130031230001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
722 | "{'item_pid': '23130031240001551', 'mms_id': '9926293280001551', 'holding_id': '22130031620001551'}"
723 | "{'item_pid': '23130020030001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
724 | "{'item_pid': '23130020060001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
725 | "{'item_pid': '23130020070001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
726 | "{'item_pid': '23130020080001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
727 | "{'item_pid': '23130020090001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
728 | "{'item_pid': '23130020100001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
729 | "{'item_pid': '23130020110001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
730 | "{'item_pid': '23130020130001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
731 | "{'item_pid': '23130020160001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
732 | "{'item_pid': '23130020170001551', 'mms_id': '9926293280001551', 'holding_id': '22130028170001551'}"
733 | "{'item_pid': '23130049290001551', 'mms_id': '9926293280001551', 'holding_id': '22130049300001551'}"
734 | "{'item_pid': '23130049280001551', 'mms_id': '9926293280001551', 'holding_id': '22130049320001551'}"
735 | "{'item_pid': '23130049310001551', 'mms_id': '9926293280001551', 'holding_id': '22130049320001551'}"
736 | "{'item_pid': '23128680010001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
737 | "{'item_pid': '23128680040001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
738 | "{'item_pid': '23128680060001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
739 | "{'item_pid': '23128680100001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
740 | "{'item_pid': '23128680110001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
741 | "{'item_pid': '23128680140001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
742 | "{'item_pid': '23128680150001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
743 | "{'item_pid': '23128680160001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
744 | "{'item_pid': '23128680170001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
745 | "{'item_pid': '23128680180001551', 'mms_id': '9925905280001551', 'holding_id': '22128685330001551'}"
746 | "{'item_pid': '23128691450001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
747 | "{'item_pid': '23128691460001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
748 | "{'item_pid': '23128691470001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
749 | "{'item_pid': '23128691480001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
750 | "{'item_pid': '23128691490001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
751 | "{'item_pid': '23128691500001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
752 | "{'item_pid': '23128691720001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
753 | "{'item_pid': '23128691730001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
754 | "{'item_pid': '23151466430001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
755 | "{'item_pid': '23151466460001551', 'mms_id': '9925905280001551', 'holding_id': '22128691740001551'}"
756 | "{'item_pid': '23128692360001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
757 | "{'item_pid': '23128692370001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
758 | "{'item_pid': '23128692380001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
759 | "{'item_pid': '23128692390001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
760 | "{'item_pid': '23128692400001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
761 | "{'item_pid': '23128692410001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
762 | "{'item_pid': '23128692420001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
763 | "{'item_pid': '23128692430001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
764 | "{'item_pid': '23128692440001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
765 | "{'item_pid': '23128692450001551', 'mms_id': '9925905280001551', 'holding_id': '22128694380001551'}"
766 | "{'item_pid': '23128680960001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
767 | "{'item_pid': '23128680970001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
768 | "{'item_pid': '23128685360001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
769 | "{'item_pid': '23128685370001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
770 | "{'item_pid': '23128685380001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
771 | "{'item_pid': '23128685390001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
772 | "{'item_pid': '23128685400001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
773 | "{'item_pid': '23128685410001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
774 | "{'item_pid': '23128685420001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
775 | "{'item_pid': '23128685430001551', 'mms_id': '9925905280001551', 'holding_id': '22128687580001551'}"
776 | "{'item_pid': '23128694390001551', 'mms_id': '9925905280001551', 'holding_id': '22128694400001551'}"
777 | "{'item_pid': '23151979600001551', 'mms_id': '9925905280001551', 'holding_id': '22151979620001551'}"
778 |
--------------------------------------------------------------------------------