diff --git a/CHANGELOG.md b/CHANGELOG.md index fe740b2..12e39c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +## [0.1.0] - 2021-09-16 +### Added +- Add support for pagination +- More examples and documentation +- New error superclass + ## [0.0.3] - 2021-09-14 ### Added - Workflows to lint and publish the code @@ -34,7 +40,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - `Fixed` for any bug fixes. - `Security` to invite users to upgrade in case of vulnerabilities. -[Unreleased]: https://github.com/metaodi/museumpy/compare/v0.0.3...HEAD +[Unreleased]: https://github.com/metaodi/museumpy/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/metaodi/museumpy/compare/v0.0.3...v0.1.0 [0.0.3]: https://github.com/metaodi/museumpy/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/metaodi/museumpy/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/metaodi/museumpy/releases/tag/v0.0.1 diff --git a/README.md b/README.md index 00e80d2..1988770 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ $ pip install museumpy ## Usage -See the [`examples` directory](https://github.com/metaodi/museumpy/tree/master/examples) for more scripts. +See the [`examples` directory](/examples) for more scripts. ### `search` @@ -96,7 +96,7 @@ import museumpy id = '98977' module = 'Multimedia' -# download attachment to a direcory called `files` +# download attachment to a directory called `files` attachment_path = client.download_attachment(id, module, 'files') print(attachment_path) ``` @@ -124,9 +124,10 @@ For convenience a default mapping is provided to access some fields more easily: ```python for record in records: print(record['hasAttachments']) + print(record['ObjObjectNumberTxt']) ``` -If you want to customize this mapping, you can pass a `map_function` to `search` and `fulltext_search`: +If you want to customize this mapping, you can pass a `map_function` to the client, which is then used on all subsequent calls to `search` and `fulltext_search`: ```python @@ -149,6 +150,15 @@ client = museumpy.MuseumPlusClient( base_url='https://test.zetcom.com/MpWeb-mpTest', map_function=my_custom_map, ) + +records = client.search( + base_url='https://test.zetcom.com/MpWeb-mpTest', + query='Patolu', +) +for record in records: + print(record['my_id']) + print(record['my_title']) + ``` ## Release diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..9807d15 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,13 @@ +Examples +======== + +The examples in this directory make use of `.env` files to specify the username and password for a user. + +You can either create a `.env` file (here or in the root of the repository) like this: + +```bash +MP_USER=my_username +MP_PASS=supersecretpassword +``` + +...or simply provide those values as environment variables. diff --git a/examples/download_attachent.py b/examples/download_attachent.py index 53a1534..5b19819 100644 --- a/examples/download_attachent.py +++ b/examples/download_attachent.py @@ -2,22 +2,31 @@ import museumpy from dotenv import load_dotenv, find_dotenv import os +from pprint import pprint +import tempfile load_dotenv(find_dotenv()) user = os.getenv('MP_USER') pw = os.getenv('MP_PASS') -client = museumpy.client( +client = museumpy.MuseumPlusClient( base_url='https://mpzurichrietberg.zetcom.com/MpWeb-mpZurichRietberg', requests_kwargs={'auth': (user, pw)}, ) -group_result = client.search('ObjObjectGroupTxt', 'MyGroup') +group_result = client.search( + field='OgrNameTxt', + value='Patolu, MAP', + module='ObjectGroup' +) group = group_result[0]['raw'] -ref = group['moduleIm']['moduleReference'] +ref = group['moduleItem']['moduleReference'] + -for ref_item in ref['moduleReferenceItem']: +for ref_item in ref['moduleReferenceItem'][:5]: item = client.module_item(ref_item['moduleItemId'], ref['targetModule']) + pprint(item, depth=1) if item['hasAttachments'] == 'true': - attachment_path = client.download_attachment(ref_item['moduleItemId'], ref['targetModule'], 'files') - print(f"Attachment downloaded and saved at {attachment_path}") + with tempfile.TemporaryDirectory() as tmpdir: + attachment_path = client.download_attachment(ref_item['moduleItemId'], ref['targetModule'], tmpdir) + print(f"Attachment downloaded and saved at {attachment_path}") diff --git a/examples/pagination.py b/examples/pagination.py new file mode 100644 index 0000000..060be04 --- /dev/null +++ b/examples/pagination.py @@ -0,0 +1,25 @@ +import museumpy +from dotenv import load_dotenv, find_dotenv +from pprint import pprint +import os + +load_dotenv(find_dotenv()) +user = os.getenv('MP_USER') +pw = os.getenv('MP_PASS') + + +client = museumpy.MuseumPlusClient( + base_url='https://mpzurichrietberg.zetcom.com/MpWeb-mpZurichRietberg', + requests_kwargs={'auth': (user, pw)} +) + +result = client.fulltext_search( + query='Patolu', + limit=2 +) + +print(result) +print(result.count) +for rec in result[:5]: + pprint(rec, depth=1) +print(result) diff --git a/examples/simple_search.py b/examples/simple_search.py index c6439e5..418b59a 100644 --- a/examples/simple_search.py +++ b/examples/simple_search.py @@ -15,5 +15,5 @@ ) pprint(records) -print(len(records)) +print(records.count) pprint(records[0], depth=1) diff --git a/museumpy/__init__.py b/museumpy/__init__.py index 489afd6..52e54fa 100644 --- a/museumpy/__init__.py +++ b/museumpy/__init__.py @@ -1,7 +1,7 @@ -__version__ = '0.0.3' +__version__ = '0.1.0' __all__ = ['client', 'errors', 'response', 'xmlparse'] -from .errors import MuseumPlusError # noqa +from .errors import MuseumpyError # noqa from .client import MuseumPlusClient def fulltext_search(base_url, query, **kwargs): # noqa diff --git a/museumpy/client.py b/museumpy/client.py index b89d69c..1999708 100644 --- a/museumpy/client.py +++ b/museumpy/client.py @@ -45,61 +45,61 @@ def __init__(self, base_url=None, map_function=None, requests_kwargs=None): def fulltext_search(self, query, module='Object', limit=100, offset=0): url = f"{self.base_url}/ria-ws/application/module/{module}/search" - data = FULLTEXT_TEMPLATE.format( - module_name=module, - limit=limit, - offset=offset, - query=query, - ) - xml = data.encode("utf-8") - xml_response = self._post_xml(url, xml) - return response.SearchResponse(xml_response, self.map_function) + params = { + 'module_name': module, + 'query': query, + } + data_loader = DataPoster(url, params, FULLTEXT_TEMPLATE, self.requests_kwargs) + return response.SearchResponse(data_loader, limit, offset, self.map_function) def search(self, field, value, module='Object', limit=100, offset=0): url = f"{self.base_url}/ria-ws/application/module/{module}/search" - data = SEARCH_TEMPLATE.format( - module_name=module, - limit=limit, - offset=offset, - field=field, - value=value, - ) - xml = data.encode("utf-8") - xml_response = self._post_xml(url, xml) - return response.SearchResponse(xml_response, self.map_function) + params = { + 'module_name': module, + 'field': field, + 'value': value, + } + data_loader = DataPoster(url, params, SEARCH_TEMPLATE, self.requests_kwargs) + return response.SearchResponse(data_loader, limit, offset, self.map_function) def module_item(self, id, module='Object'): url = f"{self.base_url}/ria-ws/application/module/{module}/{id}" - xml_response = self._get_xml(url) - resp = response.SearchResponse(xml_response) - if len(resp) == 1: + data_loader = DataLoader(url, self.requests_kwargs) + resp = response.SearchResponse(data_loader) + if resp.count == 1: return resp[0] return resp def download_attachment(self, id, module='Object', dir='.'): url = f"{self.base_url}/ria-ws/application/module/{module}/{id}/attachment" - return self._download_file(url, dir) + data_loader = DataLoader(url, self.requests_kwargs) + return data_loader.download_file(url, dir) - def _download_file(self, url, dir): - headers = {'Accept': 'application/octet-stream'} - res = self._get_content(url, headers) - d = res.headers.get('Content-Disposition') - fname = re.findall("filename=(.+)", d)[0] - assert fname, "Could not find filename in Content-Disposition header" - path = os.path.join(dir, fname) - with open(path, 'wb') as f: - for chunk in res.iter_content(1024): - f.write(chunk) - return path - def _get_xml(self, url): - res = self._get_content(url) +class DataPoster(object): + def __init__(self, url, params=None, template=None, requests_kwargs=None): + self.session = requests.Session() + self.url = url + self.params = params + self.template = template + self.xmlparser = xmlparse.XMLParser() + self.requests_kwargs = requests_kwargs or {} + + def load(self, **kwargs): + self.params.update(kwargs) + xml = self.template.format(**self.params).encode('utf-8') + return self._post_xml(self.url, xml) + + def _post_xml(self, url, xml): + headers = {'Content-Type': 'application/xml'} + res = self._post_content(url, xml, headers) return self.xmlparser.parse(res.content) - def _get_content(self, url, headers={}): + def _post_content(self, url, data, headers): try: - res = self.session.get( + res = self.session.post( url, + data=data, headers=headers, **self.requests_kwargs ) @@ -111,16 +111,38 @@ def _get_content(self, url, headers={}): return res - def _post_xml(self, url, xml): - headers = {'Content-Type': 'application/xml'} - res = self._post_content(url, xml, headers) + +class DataLoader(object): + def __init__(self, url, requests_kwargs=None): + self.session = requests.Session() + self.url = url + self.xmlparser = xmlparse.XMLParser() + self.requests_kwargs = requests_kwargs or {} + + def load(self, **kwargs): + xml = self._get_xml(self.url) + return xml + + def download_file(self, url, dir): + headers = {'Accept': 'application/octet-stream'} + res = self._get_content(url, headers) + d = res.headers.get('Content-Disposition') + fname = re.findall("filename=(.+)", d)[0] + assert fname, "Could not find filename in Content-Disposition header" + path = os.path.join(dir, fname) + with open(path, 'wb') as f: + for chunk in res.iter_content(1024): + f.write(chunk) + return path + + def _get_xml(self, url): + res = self._get_content(url) return self.xmlparser.parse(res.content) - def _post_content(self, url, data, headers): + def _get_content(self, url, headers={}): try: - res = self.session.post( + res = self.session.get( url, - data=data, headers=headers, **self.requests_kwargs ) @@ -129,4 +151,5 @@ def _post_content(self, url, data, headers): raise errors.MuseumPlusError("HTTP error: %s" % e) except requests.exceptions.RequestException as e: raise errors.MuseumPlusError("Request error: %s" % e) + return res diff --git a/museumpy/errors.py b/museumpy/errors.py index 0d14e8a..eef48c0 100644 --- a/museumpy/errors.py +++ b/museumpy/errors.py @@ -1,10 +1,23 @@ -class MuseumPlusError(Exception): +class MuseumpyError(Exception): """ General MuseumPlus error class to provide a superclass for all other errors """ -class XMLParsingError(MuseumPlusError): +class MuseumPlusError(MuseumpyError): + """ + MuseumPlus error raised when an error with the communication with MuseumPlus occurs + """ + + +class XMLParsingError(MuseumpyError): """ The error raised when parsing the XML. """ + + +class NoMoreRecordsError(MuseumpyError): + """ + This error is raised if all records have been loaded (or no records are + present) + """ diff --git a/museumpy/response.py b/museumpy/response.py index 52952d8..9bf0ed4 100644 --- a/museumpy/response.py +++ b/museumpy/response.py @@ -1,24 +1,42 @@ # -*- coding: utf-8 -*- from . import xmlparse +from . import errors ZETCOM_NS = "http://www.zetcom.com/ria/ws/module" class SearchResponse(object): - def __init__(self, xml_response, map_function=None): + def __init__(self, data_loader, limit=100, offset=0, map_function=None): + self.data_loader = data_loader self.xmlparser = xmlparse.XMLParser() self.records = [] - self._extract_records(xml_response, map_function) + self.count = 0 + self.limit = limit + self.offset = offset + self.map_function = map_function - def _extract_records(self, xml, map_function): + xml = data_loader.load(limit=limit, offset=offset) + self._parse_content(xml) + + def _parse_content(self, xml): + self.count = self.maybe_int(self.xmlparser.find(xml, f'.//{{{ZETCOM_NS}}}module').attrib['totalSize']) # noqa + self._extract_records(xml) + + def maybe_int(self, s): + try: + return int(s) + except (ValueError, TypeError): + return s + + def _extract_records(self, xml): new_records = [] xml_recs = self.xmlparser.findall(xml, f'.//{{{ZETCOM_NS}}}module/{{{ZETCOM_NS}}}moduleItem') # noqa for xml_rec in xml_recs: record = self._map_xml(xml_rec) record['raw'] = self.xmlparser.todict(xml_rec, xml_attribs=True) - if map_function: - record = map_function(record, xml_rec) + if self.map_function: + record = self.map_function(record, xml_rec) new_records.append(record) self.records.extend(new_records) @@ -93,18 +111,60 @@ def __repr__(self): try: return ( 'SearchResponse(' - 'count=%r)' + 'count=%r,' + 'limit=%r,' + 'offset=%r)' ) % ( - len(self.records), + self.count, + self.limit, + self.offset ) except AttributeError: return 'SearchResponse(empty)' - def __len__(self): - return len(self.records) + def __length_hint__(self): + return self.count def __iter__(self): - yield from self.records + # use while loop since self.records could grow while iterating + i = 0 + while True: + # load new data when near end + if i == len(self.records): + try: + self._load_new_data() + except errors.NoMoreRecordsError: + break + yield self.records[i] + i += 1 def __getitem__(self, key): + if isinstance(key, slice): + limit = max(key.start or 0, key.stop or self.count) + self._load_new_data_until(limit) + count = len(self.records) + return [self.records[k] for k in range(*key.indices(count))] + + if not isinstance(key, int): + raise TypeError("Index must be an integer or slice") + + limit = key + if limit < 0: + # if we get a negative index, load all data + limit = self.count + self._load_new_data_until(limit) return self.records[key] + + def _load_new_data_until(self, limit): + while limit >= len(self.records): + try: + self._load_new_data() + except errors.NoMoreRecordsError: + break + + def _load_new_data(self): + self.offset = self.offset + self.limit + if self.offset >= self.count: + raise errors.NoMoreRecordsError("There are no more records") + xml = self.data_loader.load(limit=self.limit, offset=self.offset) + self._parse_content(xml) diff --git a/setup.sh b/setup.sh index a911485..9398f5a 100755 --- a/setup.sh +++ b/setup.sh @@ -5,4 +5,4 @@ source pyenv/bin/activate pip install --upgrade pip pip install -r requirements.txt -pip install . +pip install -e . diff --git a/tests/client_test.py b/tests/client_test.py index 589fdcc..d497003 100644 --- a/tests/client_test.py +++ b/tests/client_test.py @@ -14,7 +14,8 @@ class TestClient(MuseumpyTestCase): def test_simple_search(self): client = MuseumPlusClient('http://test.com/MpWeb-test') r = client.search(field='TestField', value='TestValue') - self.assertEqual(len(r), 1) + self.assertEqual(r.__length_hint__(), 1) + self.assertEqual(r.count, 1) self.assertEqual(r[0]['hasAttachments'], 'true') # noqa self.assertEqual(r[0]['ObjCreditlineGrp'], 'Geschenk Gisela Müller und Erich Gross') # noqa diff --git a/tests/fixtures/response_multiple_1.xml b/tests/fixtures/response_multiple_1.xml new file mode 100644 index 0000000..fcf4f9f --- /dev/null +++ b/tests/fixtures/response_multiple_1.xml @@ -0,0 +1,969 @@ + + + + + + 35894 + + + mrzhaa + + + 2021-09-07 10:56:34.615 + 07/09/2021 10:56 + + + bon + + + 2007-10-08 00:00:00.0 + 08/10/2007 00:00 + + + IndienOrgUnit + + + 71235 + + + Zugang: 2009 + + + EF 103 + +Grundstoff +Material Kette: Seide +Material Eintrag: Seide +Farben Kette: weiss, gelb, orange, rot, violett, blau, hellgrün, braunschwarz +Farben Eintrag: weiss, gelb, orange, rot, violett, blau, braunschwarz + +Faden: ungezwirnt +Bindung: Leinwand +Dichte: 24 x 16 / cm2 + +Musterung +Rapporte Kette: 2 (? abgeschnitten) +Rapporte Eintrag: 4 und seitenverkehrt nochmals 4 +Satzgrösse Kette: 7 +Satzgrösse Eintrag: 8 + +Färbung / Musterungtechniken +Reservemusterung im Garn +Zusatz-Eintrag: Zari-Faden (mit Silber umwickelter gelber Baumwollfaden) + +Musterung/Ornamente + +Das rote Hauptfeld zeigt "popat kunjar bhat". +Gruppe 3; Variation von Motiv Typ 14 (?), da die Querstreifen der Endbordüren der Musterung des Motiv Typs 31 ? (Bühler Alfred und E. Fischer, 1979, "The Patola of Gujarat", Vol. 1, S. 119; Fig. 124) ensprechen. + +Die Längsbordüre fehlt auf einer Seite; rund um die ganze Patolu wurde eine ca.10 cm breites uni-rote Seidenband angenäht. +Einen breiten Streifen mit Silberfaden ziert die obere Endbordüre. +Darunter im weissen Querstreifen ist von Hand mit schwarzer Tinte in ?? wahrscheinlich der Name des Besitzers dieses Patolu geschrieben. + +Dokumentation: +Feldnotizen EF: +Feldfotos EF: +Literaturhinweise: +Publikation + + + 1890 + 1,890 + + + 1910 + 1,910 + + + um 1900 + + + 2009.181 + + + + Geschenk + + + + + Eigentum + + + + + Object + + + + + Textil + + + + + ja + + + + + + + 2009.0181 + + + + + + 71235 + + + + + + Patolu, Doppel-Ikat Seidensari, popat kunjar bhat + + + 2009.181, Standardkünstler, Patolu, Doppel-Ikat Seidensari, popat kunjar bhat, um 1900 + + + + + + + + + Textillager: 2.12. + + + + + + + + + + + + 2009.181 + + + CH-001319-0.Obj.35894 + + + + + + + + + + + 2009 + + + . + + + 181 + + + 1 + 1 + + + false + no + + + 2009.0181 + + + + + + 2009181 + + + 2009.181 + + + + Inventarnummer + + + + + __Rietberg neu + + + + + + + + 1 + 1 + + + Patolu, Doppel-Ikat Seidensari, popat kunjar bhat + + + false + no + + + + Title/subtitle + + + + + + + + 1 + 1 + + + 2012-11-29 + 29/11/2012 + + + 5000 + 5,000 + + + + CHF + + + + + Insurance value + + + + + + + + 1 + 1 + + + Seide und Zari-Faden (Silberfaden) / Doppel-Ikat + + + false + no + + + + + + + + + + + + + 1 + 1 + + + + Indien, Gujarat + + + + + de Land / Region + + + + + + + + 1 + 1 + + + 103 + 103 + + + 425 + 425 + + + false + no + + + Textilfläche: 425 x 103 cm + + + Textilfläche 425.00 x 103.00 cm + + + + Textilfläche + + + + + cm + + + + + 2 D + + + + + + + + Textillager: 2.12. + + + + + + + Geschenk Eberhard und Barbara Fischer + + + + de + + + + + Geschenk Eberhard und Barbara Fischer + + + + + + + + Textillager: 2.12. + + + + aktuell + + + + + + + + um 1900 + + + false + no + + + 1890 + + + 1910 + + + 1 + 1 + + + 783100 + 783,100 + + + 774900 + 774,900 + + + um 1900 + + + um 1900 + + + + Production + + + + + + + + in gutem Zustand, das zusammengenähte uni-rote Seidenband rund um die Patolu weist dunkle Flecken auf + +weisses Etikett: EF 103 (1978) + + + + + + Kontext: Textilien: Die Sammlung Eberhard Fischer: Geschenk (Teil 1: 2009) an das Museum Rietberg Zürich, hrsg./übers.: Museum Rietberg Zürich; Autor/in: Fischer, Eberhard; Zürich, 2009 + + + Kontext + + + + + + + Bild, 2009.181.JPG + + true + yes + + + + Bild, 2009.181_1.JPG + + false + no + + + + + + Patolu, MAP + + + + + Standardkünstler + + 1 + 1 + + + + + + Kunsthandel, Ahmedabad, Indien + + 10 + 10 + + + + CHF + + + + + Eberhard Fischer + + 5 + 5 + + + + CHF + + + + + + + Museum Rietberg Zürich + + + + + Museum Rietberg Zürich + + + + + + 37142 + + + mrzhaa + + + 2021-09-07 10:56:34.615 + 07/09/2021 10:56 + + + bon + + + 2007-09-03 00:00:00.0 + 03/09/2007 00:00 + + + IndienOrgUnit + + + 71111 + + + Zugang: 2009 + + + EF 105 + +Grundstoff +Hauptteil (gross): +Material Kette und Eintrag: Seide +Farben Kette und Eintrag: weiss, gelb, rot, grün, schwarz + +Hauptteil (klein): +Material Kette und Eintrag: Seide +Farben Kette und Eintrag: weiss, oragne, lila, hellgrün + +Rückseite: +Material Kette und Eintrag: Baumwolle +Farbe: blau + +Färbung / Musterungtechniken +Reservemusterung im Garn + + +Musterung/Ornamente + +Beide Hauptfelder zeigen "tran ful bhat" Design; das grössere gehört zur Gruppe 2, Motiv Typ 7; das kleinere Individelle Motive ?? + +Ein Karton wurde auf der Vorderseite aus mehreren Stoffstücken desselben Hauptteils eines Patolu überzogen und ein Ende eines anderen Patolu Hauptteils. Auf der Rückseite wurde die Patola Stoffe auf blauem Baumwollstoff auf der einen Seite angenäht und auf der andern aufgeklebt. + + + +Dokumentation +Feldnotizen EF: +Feldfotos EF: +Literaturhinweise: Bühler Alfred und Eberhard Fischer, 1979, "The Patola of Gujarat", Vol. 1, S.52, Fig.44 +Vergleichstextilien: +Publikation + + + 1890 + 1,890 + + + 1910 + 1,910 + + + um 1900 + + + 2009.114 + + + + Geschenk + + + + + Eigentum + + + + + Object + + + + + Textil + + + + + ja + + + + + + + 2009.0114 + + + + + + 71111 + + + + + + Patolu, Doppel-Ikat Gürtel ?, tran ful bhat + + + 2009.114, Standardkünstler, Patolu, Doppel-Ikat Gürtel ?, tran ful bhat, um 1900 + + + + + + + + + Textillager: B1 + + + + + + + + + + + + 2009.114 + + + CH-001319-0.Obj.37142 + + + + + + + + + + + 2009 + + + . + + + 114 + + + 1 + 1 + + + false + no + + + 2009.0114 + + + + + + 2009114 + + + 2009.114 + + + + Inventarnummer + + + + + __Rietberg neu + + + + + + + + 1 + 1 + + + Patolu, Doppel-Ikat Gürtel ?, tran ful bhat + + + false + no + + + + Title/subtitle + + + + + + + + 1 + 1 + + + 2012-11-29 + 29/11/2012 + + + 200 + 200 + + + + CHF + + + + + Insurance value + + + + + + + + 1 + 1 + + + Seide / Doppel-Ikat + + + false + no + + + + + + + + + + + + + 1 + 1 + + + + Indien, Gujarat + + + + + de Land / Region + + + + + + + + 1 + 1 + + + 12 + 12 + + + 161 + 161 + + + false + no + + + Textilfläche: 161 x 12 cm + + + Textilfläche 161.00 x 12.00 cm + + + + Textilfläche + + + + + cm + + + + + 2 D + + + + + + + + Textillager: B1 + + + + + + + Geschenk Eberhard und Barbara Fischer + + + + de + + + + + Geschenk Eberhard und Barbara Fischer + + + + + + + + Textillager: B1 + + + + aktuell + + + + + + + + um 1900 + + + false + no + + + 1890 + + + 1910 + + + 1 + 1 + + + 783100 + 783,100 + + + 774900 + 774,900 + + + um 1900 + + + um 1900 + + + + Production + + + + + + + + in gutem Zustand + +weisses Etikett: EF 105 + + + + + + Kontext: Textilien: Die Sammlung Eberhard Fischer: Geschenk (Teil 1: 2009) an das Museum Rietberg Zürich, hrsg./übers.: Museum Rietberg Zürich; Autor/in: Fischer, Eberhard; Zürich, 2009 + + + Kontext + + + + + + + Bild, 2009.114.JPG + + true + yes + + + + + + Patolu, MAP + + + + + Standardkünstler + + 1 + 1 + + + + + + Eberhard Fischer + + 5 + 5 + + + + CHF + + + + + Kunsthandel, Ahmedabad, Indien + + 10 + 10 + + + + CHF + + + + + + + Museum Rietberg Zürich + + + + + Museum Rietberg Zürich + + + + + + diff --git a/tests/fixtures/response_multiple_2.xml b/tests/fixtures/response_multiple_2.xml new file mode 100644 index 0000000..deeecb5 --- /dev/null +++ b/tests/fixtures/response_multiple_2.xml @@ -0,0 +1,927 @@ + + + + + + 38595 + + + mrzhaa + + + 2021-09-07 10:56:34.615 + 07/09/2021 10:56 + + + bon + + + 2007-08-30 00:00:00.0 + 30/08/2007 00:00 + + + IndienOrgUnit + + + 71110 + + + Zugang: 2009 + + + Grundstoff + +Material Kette: Seide +Material Eintrag: Seide +Farben Kette: weiss, rot, grün, violett +Farben Eintrag: weiss, rot, grün, violett + +Futter: +Material Kette: Baumwolle +Material Eintrag: Seide +Farben Kette: weiss, rot, grün +Farben Eintrag: rot + +Faden: ungezwirnt +Bindung: Leinwand +Dichte: + +Musterung +Rapporte Kette: +Rapporte Eintrag: +Satzgrösse Kette: +Satzgrösse Eintrag: + +Färbung / Musterungstechniken +Reservemusterung im Garn +Dekoration: gemustertes Goldband mit goldenen Fransen + + +Musterung/Ornamente +Die Vorderseiten dieser Fragmente sind aus dem Hauptfeld eines Patolu-Stoffs der Gruppe 2; Motiv Typ 8g (? es fehlen gewisse Zickzacklinien!); es fehlen die weisse Punkte in der Mitte der Blüten. +Das Hauptfeld zeigt "fulvadi bhat" Design. +Aufgenäht auf gestreifte Längsbordüren mit wenig Doppel-Ikat Musterung eines anderen Patolu. +Ein goldenes Band gemustert mit einer Blumenranke und als Abschluss einen Streifen Zickzacklinie ist an einem Ende aufgenäht. Die Fransen aus feinem Metall sind wie gelockte. + +Dokumentation +Feldnotizen EF: +Feldfotos EF: +Literaturhinweise: Bühler Alfred und Eberhard Fischer, 1979, "The Patola of Gujarat", Vol. 1, S.59, Fig.58; Vol. 2, Abb. 251 +Vergleichstextilien: +Publikation + + + 1890 + 1,890 + + + 1910 + 1,910 + + + um 1900 + + + 2009.113 + + + + Geschenk + + + + + Eigentum + + + + + Object + + + + + Textil + + + + + ja + + + + + + + 2009.0113 + + + + + + 71110 + + + + + + Patolu, Fragmente eines Doppel-Ikat Tanzkostüms, fulvadi bhat + + + 2009.113, Standardkünstler, Patolu, Fragmente eines Doppel-Ikat Tanzkostüms, fulvadi bhat, um 1900 + + + + + + + + + Textillager: B1 + + + + + + + + + + + + 2009.113 + + + CH-001319-0.Obj.38595 + + + + + + + + + + + 2009 + + + . + + + 113 + + + 1 + 1 + + + false + no + + + 2009.0113 + + + + + + 2009113 + + + 2009.113 + + + + Inventarnummer + + + + + __Rietberg neu + + + + + + + + 1 + 1 + + + Patolu, Fragmente eines Doppel-Ikat Tanzkostüms, fulvadi bhat + + + false + no + + + + Title/subtitle + + + + + + + + 1 + 1 + + + 2012-11-29 + 29/11/2012 + + + 200 + 200 + + + + CHF + + + + + Insurance value + + + + + + + + 1 + 1 + + + Seide, Baumwolle / Doppel-Ikat + + + false + no + + + + + + + + + + + + + 1 + 1 + + + + Indien, Gujarat + + + + + de Land / Region + + + + + + + + Textillager: B1 + + + + + + + Geschenk Eberhard und Barbara Fischer + + + + de + + + + + Geschenk Eberhard und Barbara Fischer + + + + + + + + Textillager: B1 + + + + aktuell + + + + + + + + um 1900 + + + false + no + + + 1890 + + + 1910 + + + 1 + 1 + + + 783100 + 783,100 + + + 774900 + 774,900 + + + um 1900 + + + um 1900 + + + + Production + + + + + + + + in gutem Zustand; + + + + + + Kontext: Textilien: Die Sammlung Eberhard Fischer: Geschenk (Teil 1: 2009) an das Museum Rietberg Zürich, hrsg./übers.: Museum Rietberg Zürich; Autor/in: Fischer, Eberhard; Zürich, 2009 + + + Kontext + + + + + + + Bild, 2009.113.JPG + + true + yes + + + + + + Patolu, MAP + + + + + Standardkünstler + + 1 + 1 + + + + + + Eberhard Fischer + + 5 + 5 + + + + CHF + + + + + Kunsthandel, Ahmedabad, Indien + + 10 + 10 + + + + CHF + + + + + + + Museum Rietberg Zürich + + + + + Museum Rietberg Zürich + + + + + + 35963 + + + mrzhaa + + + 2021-09-07 10:56:23.524 + 07/09/2021 10:56 + + + bon + + + 2007-08-03 00:00:00.0 + 03/08/2007 00:00 + + + IndienOrgUnit + + + 71044 + + + Zugang: 2009 + + + EF: 12 + +Grundstoff +Material Kette: Seide +Material Eintrag: Seide +Farben Kette: +Farben Eintrag: + +Faden: ungezwirnt +Bindung: Leinwand +Dichte: + +Musterung +Rapporte Kette: +Rapporte Eintrag: +Satzgrösse Kette: +Satzgrösse Eintrag: + +Färbung / Musterungtechniken +Reservemusterung im Garn + +Eintrag-Abschluss: Fransen; die andere Endbordüre fehlt + +Musterung/Ornamente + +Ursprünglicher Stoff: +Gruppe 1; Motiv Typ 1 +Das Hauptfeld zeigt "pan bhat" Design. + +Das stark beschädigte Hauptfeld wurde unterlegt mit einem doppelten Patolu-Stoffstück im Muster Motif type 4; an den Längsbordüren unterlegt von einem seidenen zartgrünen Stoffstück. + +Dokumentationen: +Feldnotizen EF: +Feldfotos EF: +Literaturhinweise: +Vergleichstextilien: +Publikation + + + 1890 + 1,890 + + + 1910 + 1,910 + + + um 1900 + + + 2009.63 + + + + Geschenk + + + + + Eigentum + + + + + Object + + + + + Textil + + + + + ja + + + + + + + 2009.0063 + + + + + + 71044 + + + + + + Patolu, Fragment eines Doppel-Ikat Seidensaris, pan bhat + + + 2009.63, Standardkünstler, Patolu, Fragment eines Doppel-Ikat Seidensaris, pan bhat, um 1900 + + + + + + + + + Textillager: 2.2. + + + + + + + + + + + + 2009.63 + + + CH-001319-0.Obj.35963 + + + + + + + + + + + 2009 + + + . + + + 63 + + + 1 + 1 + + + false + no + + + 2009.0063 + + + + + + 200963 + + + 2009.63 + + + + Inventarnummer + + + + + __Rietberg neu + + + + + + + + 1 + 1 + + + Patolu, Fragment eines Doppel-Ikat Seidensaris, pan bhat + + + false + no + + + + Title/subtitle + + + + + + + + 1 + 1 + + + 2012-11-23 + 23/11/2012 + + + 500 + 500 + + + + CHF + + + + + Insurance value + + + + + + + + 1 + 1 + + + Seide / Doppel-Ikat + + + false + no + + + + + + + + + + + + + 1 + 1 + + + + Indien, Gujarat + + + + + de Land / Region + + + + + + + + 1 + 1 + + + 128 + 128 + + + 180 + 180 + + + false + no + + + Textilfläche: 180 x 128 cm + + + Textilfläche 180.00 x 128.00 cm + + + + Textilfläche + + + + + cm + + + + + 2 D + + + + + + + + Textillager: 2.2. + + + + + + + Geschenk Eberhard und Barbara Fischer + + + + de + + + + + Geschenk Eberhard und Barbara Fischer + + + + + + + + Textillager: 2.2. + + + + aktuell + + + + + + + + um 1900 + + + false + no + + + 1890 + + + 1910 + + + 1 + 1 + + + 783100 + 783,100 + + + 774900 + 774,900 + + + um 1900 + + + um 1900 + + + + Production + + + + + + + + Die grob "gewifelten" Stellen sind mit violettem Oberfaden und rotem Unterfaden maschinell zusammen genäht worden. Zwei Stoffstücke mit Motiv Typ 4c oder d wurden eingesetzt. + +weisses Etikett: EF 12 + + + + + + Kontext: Textilien: Die Sammlung Eberhard Fischer: Geschenk (Teil 1: 2009) an das Museum Rietberg Zürich, hrsg./übers.: Museum Rietberg Zürich; Autor/in: Fischer, Eberhard; Zürich, 2009 + + + Kontext + + + + + + + Bild, 2009.63.JPG + + true + yes + + + + + + Patolu, MAP + + + + + Standardkünstler + + 1 + 1 + + + + + + Kunsthandel, Ahmedabad, Indien + + 10 + 10 + + + + CHF + + + + + Eberhard Fischer + + 5 + 5 + + + + CHF + + + + + + + Museum Rietberg Zürich + + + + + Museum Rietberg Zürich + + + + + + diff --git a/tests/fixtures/response_multiple_3.xml b/tests/fixtures/response_multiple_3.xml new file mode 100644 index 0000000..71deb54 --- /dev/null +++ b/tests/fixtures/response_multiple_3.xml @@ -0,0 +1,452 @@ + + + + + + 36199 + + + mrzhaa + + + 2021-09-07 10:56:34.615 + 07/09/2021 10:56 + + + bon + + + 2007-08-30 00:00:00.0 + 30/08/2007 00:00 + + + IndienOrgUnit + + + 71109 + + + Zugang: 2009 + + + EF 104 + +Grundstoff +Hose: +Material Kette: Seide +Material Eintrag: Seide +Farben Kette: weiss, gelb, rot, grün, violett +Farben Eintrag: weiss, gelb, rot, grün, violett + +Bund und Futter: +Material Kette: Baumwolle +Material Eintrag: Baumwolle +Farben Kette: rot +Farben Eintrag: rot + +Faden: ungezwirnt +Bindung: Leinwand +Dichte: + +Musterung +Rapporte Kette: +Rapporte Eintrag: +Satzgrösse Kette: +Satzgrösse Eintrag: + +Färbung / Musterungtechniken +Reservemusterung im Garn +Zusatz-Eintrag: Zari-Faden (Goldfaden) in unterem Bund + + +Musterung/Ornamente +Die Hosenbeine sind aus dem Hauptfeld eines Patolu-Stoffs der Gruppe 2; Motiv Typ 8g angefertigt; es fehlen die weisse Punkte in der Mitte der Blüten. +Das Hauptfeld zeigt "fulvadi bhat" Design. +Jedes Hosenbein endet mit einem ca. 2,5 cm breiten goldenen Band. Der untere Bund ist aus einer Partie mit Goldfaden angefertigt, wobei an der hinteren Naht wenig der Längsbordüre mit weiss/gelb/orange/schwarzen Kettfäden aus Baumwolle sichtbar ist. Aus dem gleichen roten Baumwollstoff ist sowohl der Bund als auch das Futter genäht. + + + +Dokumentation +Feldnotizen EF: +Feldfotos EF: +Literaturhinweise: Bühler Alfred und Eberhard Fischer, 1979, "The Patola of Gujarat", Vol. 1, S.59, Fig.58; Vol. 2, Abb. 251 +Vergleichstextilien: +Publikation + + + 1890 + 1,890 + + + 1910 + 1,910 + + + um 1900 + + + 2009.112 + + + + Geschenk + + + + + Eigentum + + + + + Object + + + + + Textil + + + + + ja + + + + + + + 2009.0112 + + + + + + 71109 + + + + + + Patolu, Doppel-Ikat Hose, fulvadi bhat + + + 2009.112, Standardkünstler, Patolu, Doppel-Ikat Hose, fulvadi bhat, um 1900 + + + + + + + + + Textillager: B1 + + + + + + + + + + + + 2009.112 + + + CH-001319-0.Obj.36199 + + + + + + + + + + + 2009 + + + . + + + 112 + + + 1 + 1 + + + false + no + + + 2009.0112 + + + + + + 2009112 + + + 2009.112 + + + + Inventarnummer + + + + + __Rietberg neu + + + + + + + + 1 + 1 + + + Patolu, Doppel-Ikat Hose, fulvadi bhat + + + false + no + + + + Title/subtitle + + + + + + + + 1 + 1 + + + 2012-11-29 + 29/11/2012 + + + 800 + 800 + + + + CHF + + + + + Insurance value + + + + + + + + 1 + 1 + + + Seide, Baumwolle und Zari-Faden (Goldfaden) / Doppel-Ikat + + + false + no + + + + + + + + + + + + + 1 + 1 + + + + Indien, Gujarat + + + + + de Land / Region + + + + + + + + Textillager: B1 + + + + + + + Geschenk Eberhard und Barbara Fischer + + + + de + + + + + Geschenk Eberhard und Barbara Fischer + + + + + + + + Textillager: B1 + + + + aktuell + + + + + + + + um 1900 + + + false + no + + + 1890 + + + 1910 + + + 1 + 1 + + + 783100 + 783,100 + + + 774900 + 774,900 + + + um 1900 + + + um 1900 + + + + Production + + + + + + + + in gutem Zustand; + +weisses Etikett: EF 104 + + + + + + Kontext: Textilien: Die Sammlung Eberhard Fischer: Geschenk (Teil 1: 2009) an das Museum Rietberg Zürich, hrsg./übers.: Museum Rietberg Zürich; Autor/in: Fischer, Eberhard; Zürich, 2009 + + + Kontext + + + + + + + Bild, 2009.112.JPG + + true + yes + + + + + + Patolu, MAP + + + + + Standardkünstler + + 1 + 1 + + + + + + Eberhard Fischer + + 5 + 5 + + + + CHF + + + + + Kunsthandel, Ahmedabad, Indien + + 10 + 10 + + + + CHF + + + + + + + Museum Rietberg Zürich + + + + + Museum Rietberg Zürich + + + + + + diff --git a/tests/response_test.py b/tests/response_test.py new file mode 100644 index 0000000..1d3f886 --- /dev/null +++ b/tests/response_test.py @@ -0,0 +1,28 @@ +from museumpy_test import ResponseTestCase +from museumpy.response import SearchResponse + + +class TestSearchResponse(ResponseTestCase): + def test_response_single(self): + data_loader = self._data_loader_mock(['test_simple_search.xml']) + res = SearchResponse(data_loader) + + self.assertEqual(res.count, 1) + + def test_response_iterator(self): + filenames = [ + 'response_multiple_1.xml', + 'response_multiple_2.xml', + 'response_multiple_3.xml', + ] + data_loader = self._data_loader_mock(filenames) + res = SearchResponse(data_loader, limit=2, offset=0) + + next_res = next(iter(res)) + self.assertIsNotNone(next_res) + self.assertIsInstance(next_res, dict) + self.assertEqual(res.count, 5) + + records = [r for r in res] + self.assertEqual(len(records), 5) + self.assertEqual(data_loader.load.call_count, 3)