diff --git a/.gitignore b/.gitignore index d7b3982..d741a5d 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,4 @@ checklink/cookies.txt .gitconfig *.sqlite +omeka_s_tools.code-workspace diff --git a/api.ipynb b/api.ipynb index 632204a..959cf1d 100644 --- a/api.ipynb +++ b/api.ipynb @@ -340,6 +340,10 @@ " '''\n", " if template_id:\n", " payload['o:resource_template'] = self.format_resource_id(template_id, 'resource_templates')\n", + " # If class is not set explicitly, use class associated with template\n", + " if not class_id:\n", + " template = self.get_resource_by_id(template_id, 'resource_templates')\n", + " class_id = template['o:resource_class']['o:id']\n", " if class_id:\n", " payload['o:resource_class'] = self.format_resource_id(class_id, 'resource_classes')\n", " if item_set_id:\n", @@ -484,38 +488,47 @@ " response = self.s.put(f'{self.api_url}/{resource_type}/{payload[\"o:id\"]}', json=payload, params=self.params)\n", " return response.json()\n", " \n", - " def add_media_to_item(self, item_id, media_file):\n", + " def add_media_to_item(self, item_id, media_file, payload={}, template_id=None, class_id=None):\n", " '''\n", " Upload a media file and associate it with an existing item.\n", " \n", " Parameters:\n", " * `item_id` - the Omeka id of the item this media file should be added to\n", - " * `media_file` - the media file to be uploaded, c\n", - " \n", - " The value of `media_file` can be either:\n", - " * a path to an image/media file (filename is used as title)\n", - " * a dict containing `title` and `path` values\n", - " \n", - " The path values can either be strings or pathlib Paths.\n", + " * `media_path` - a path to an image/media file (string or pathlib Path)\n", + " * `payload` (optional) - metadata to attach to media object, either \n", + " a dict generated by `prepare_item_payload()` or `prepare_item_payload_using_template()`,\n", + " or a string which is used as the value for `dcterms:title`.\n", + " * `template_id` - internal Omeka identifier of a resource template you want to attach to this item\n", + " * `class_id` - internal Omeka identifier of a resource class you want to attach to this item\n", " \n", " Returns: \n", " * a dict providing a JSON-LD representation of the new media object\n", " '''\n", " files = {}\n", + " # For backwards compatibility\n", " if isinstance(media_file, dict):\n", - " title = media_file['title']\n", - " path = Path(media_file['path'])\n", - " else:\n", - " path = Path(media_file)\n", - " title = path.name\n", + " path = media_file['path']\n", + " payload = media_file['title']\n", + " # Make sure path is a Path object\n", + " path = Path(media_file)\n", + " if isinstance(payload, str):\n", + " payload = self.prepare_item_payload({'dcterms:title': [payload]})\n", + " if template_id:\n", + " payload['o:resource_template'] = self.format_resource_id(template_id, 'resource_templates')\n", + " if not class_id:\n", + " template = self.get_resource_by_id(template_id, 'resource_templates')\n", + " class_id = template['o:resource_class']['o:id']\n", + " if class_id:\n", + " payload['o:resource_class'] = self.format_resource_id(class_id, 'resource_classes')\n", " file_data = {\n", " 'o:ingester': 'upload', \n", " 'file_index': '0',\n", + " 'o:source': path.name,\n", " 'o:item': {'o:id': item_id},\n", - " 'dcterms:title': [{'property_id': 1, '@value': title, 'type': 'literal'}]\n", " }\n", + " payload.update(file_data)\n", " files[f'file[0]'] = path.read_bytes()\n", - " files['data'] = (None, json.dumps(file_data), 'application/json')\n", + " files['data'] = (None, json.dumps(payload), 'application/json')\n", " response = self.s.post(f'{self.api_url}/media', files=files, params=self.params)\n", " return response.json()\n", " \n", @@ -750,7 +763,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_resources[source]

\n", + "

OmekaAPIClient.get_resources[source]

\n", "\n", "> OmekaAPIClient.get_resources(**`resource_type`**, **\\*\\*`kwargs`**)\n", "\n", @@ -786,7 +799,7 @@ { "data": { "text/plain": [ - "87" + "101" ] }, "execution_count": null, @@ -828,7 +841,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_resource_by_id[source]

\n", + "

OmekaAPIClient.get_resource_by_id[source]

\n", "\n", "> OmekaAPIClient.get_resource_by_id(**`resource_id`**, **`resource_type`**=*`'items'`*)\n", "\n", @@ -886,7 +899,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_template_by_label[source]

\n", + "

OmekaAPIClient.get_template_by_label[source]

\n", "\n", "> OmekaAPIClient.get_template_by_label(**`label`**)\n", "\n", @@ -947,7 +960,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_resource_by_term[source]

\n", + "

OmekaAPIClient.get_resource_by_term[source]

\n", "\n", "> OmekaAPIClient.get_resource_by_term(**`term`**, **`resource_type`**=*`'properties'`*)\n", "\n", @@ -1019,7 +1032,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_resource_from_vocab[source]

\n", + "

OmekaAPIClient.get_resource_from_vocab[source]

\n", "\n", "> OmekaAPIClient.get_resource_from_vocab(**`local_name`**, **`vocabulary_namespace_uri`**=*`'http://schema.org/'`*, **`resource_type`**=*`'properties'`*)\n", "\n", @@ -1098,7 +1111,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_property_id[source]

\n", + "

OmekaAPIClient.get_property_id[source]

\n", "\n", "> OmekaAPIClient.get_property_id(**`term`**)\n", "\n", @@ -1163,7 +1176,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.filter_items_by_property[source]

\n", + "

OmekaAPIClient.filter_items_by_property[source]

\n", "\n", "> OmekaAPIClient.filter_items_by_property(**`filter_property`**=*`'schema:name'`*, **`filter_value`**=*`''`*, **`filter_type`**=*`'eq'`*, **`page`**=*`1`*, **\\*\\*`extra_filters`**)\n", "\n", @@ -1204,10 +1217,30 @@ "metadata": {}, "outputs": [], "source": [ - "items = omeka.filter_items_by_property(filter_property='schema:name', filter_value='WRAGGE.')\n", + "items = omeka.filter_items_by_property(filter_property='schema:name', filter_value='wragge', filter_type='in')\n", "\n", "assert len(items['results']) > 0\n", - "assert items['results'][0]['schema:name'][0]['@value'] == 'WRAGGE.'" + "assert 'wragge' in items['results'][0]['schema:name'][0]['@value'].lower()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Clement Wragge at Home. - UPDATED!'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "items['results'][0]['schema:name'][0]['@value']" ] }, { @@ -1218,7 +1251,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.search_items[source]

\n", + "

OmekaAPIClient.search_items[source]

\n", "\n", "> OmekaAPIClient.search_items(**`query`**, **`search_type`**=*`'fulltext_search'`*, **`page`**=*`1`*, **\\*\\*`extra_filters`**)\n", "\n", @@ -1326,7 +1359,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.prepare_item_payload[source]

\n", + "

OmekaAPIClient.prepare_item_payload[source]

\n", "\n", "> OmekaAPIClient.prepare_item_payload(**`terms`**)\n", "\n", @@ -1423,7 +1456,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.prepare_item_payload_using_template[source]

\n", + "

OmekaAPIClient.prepare_item_payload_using_template[source]

\n", "\n", "> OmekaAPIClient.prepare_item_payload_using_template(**`terms`**, **`template_id`**)\n", "\n", @@ -1515,7 +1548,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.add_media_to_payload[source]

\n", + "

OmekaAPIClient.add_media_to_payload[source]

\n", "\n", "> OmekaAPIClient.add_media_to_payload(**`payload`**, **`media_files`**)\n", "\n", @@ -1579,7 +1612,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.add_item[source]

\n", + "

OmekaAPIClient.add_item[source]

\n", "\n", "> OmekaAPIClient.add_item(**`payload`**, **`media_files`**=*`None`*, **`template_id`**=*`None`*, **`class_id`**=*`None`*, **`item_set_id`**=*`None`*)\n", "\n", @@ -1623,9 +1656,9 @@ "data": { "text/plain": [ "{'@context': 'https://timsherratt.org/collections/api-context',\n", - " '@id': 'https://timsherratt.org/collections/api/items/896',\n", + " '@id': 'https://timsherratt.org/collections/api/items/992',\n", " '@type': 'o:Item',\n", - " 'o:id': 896,\n", + " 'o:id': 992,\n", " 'o:is_public': True,\n", " 'o:owner': {'@id': 'https://timsherratt.org/collections/api/users/1',\n", " 'o:id': 1},\n", @@ -1634,9 +1667,9 @@ " 'o:thumbnail': None,\n", " 'o:title': 'My first resource!',\n", " 'thumbnail_display_urls': {'large': None, 'medium': None, 'square': None},\n", - " 'o:created': {'@value': '2022-02-14T10:39:11+00:00',\n", + " 'o:created': {'@value': '2022-04-03T06:43:24+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", - " 'o:modified': {'@value': '2022-02-14T10:39:11+00:00',\n", + " 'o:modified': {'@value': '2022-04-03T06:43:24+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", " 'o:media': [],\n", " 'o:item_set': [],\n", @@ -1707,7 +1740,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.delete_resource[source]

\n", + "

OmekaAPIClient.delete_resource[source]

\n", "\n", "> OmekaAPIClient.delete_resource(**`resource_id`**, **`resource_type`**)\n", "\n", @@ -1762,7 +1795,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.update_resource[source]

\n", + "

OmekaAPIClient.update_resource[source]

\n", "\n", "> OmekaAPIClient.update_resource(**`payload`**, **`resource_type`**=*`'items'`*)\n", "\n", @@ -1796,7 +1829,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "ARCHITECT of TWO EPOCHS TRAVELS OF INIGO JONES - UPDATED!\n" + "The Courier-Mail (Brisbane, Qld. : 1933 - 1954) - UPDATED!\n" ] } ], @@ -1833,21 +1866,20 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.add_media_to_item[source]

\n", + "

OmekaAPIClient.add_media_to_item[source]

\n", "\n", - "> OmekaAPIClient.add_media_to_item(**`item_id`**, **`media_file`**)\n", + "> OmekaAPIClient.add_media_to_item(**`item_id`**, **`media_file`**, **`payload`**=*`{}`*, **`template_id`**=*`None`*, **`class_id`**=*`None`*)\n", "\n", "Upload a media file and associate it with an existing item.\n", "\n", "Parameters:\n", "* `item_id` - the Omeka id of the item this media file should be added to\n", - "* `media_file` - the media file to be uploaded, c\n", - "\n", - "The value of `media_file` can be either:\n", - "* a path to an image/media file (filename is used as title)\n", - "* a dict containing `title` and `path` values\n", - "\n", - "The path values can either be strings or pathlib Paths.\n", + "* `media_path` - a path to an image/media file (string or pathlib Path)\n", + "* `payload` (optional) - metadata to attach to media object, either \n", + " a dict generated by `prepare_item_payload()` or `prepare_item_payload_using_template()`,\n", + " or a string which is used as the value for `dcterms:title`.\n", + "* `template_id` - internal Omeka identifier of a resource template you want to attach to this item\n", + "* `class_id` - internal Omeka identifier of a resource class you want to attach to this item\n", "\n", "Returns: \n", "* a dict providing a JSON-LD representation of the new media object" @@ -1864,6 +1896,26 @@ "show_doc(OmekaAPIClient.add_media_to_item)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "omeka_auth = OmekaAPIClient(\n", + " api_url='https://timsherratt.org/collections/api',\n", + " key_identity=os.getenv('KEY_IDENTITY'), \n", + " key_credential=os.getenv('KEY_CREDENTIAL')\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a media file to an item without any additional metadata." + ] + }, { "cell_type": "code", "execution_count": null, @@ -1876,7 +1928,7 @@ "item_id = item['o:id']\n", "\n", "# Add a new media file to the item\n", - "media_resource = omeka_auth.add_media_to_item(item_id, media_file='media/nla.news-article226799674-24144902.jpg')\n", + "media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg')\n", "\n", "# Check that the media resource is the expected type\n", "assert media_resource['@type'] == 'o:Media'\n", @@ -1885,6 +1937,79 @@ "assert media_resource['o:item']['o:id'] == item_id" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Include a title for a new media item by supplying a string value to the `payload` parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Add a new media file with a title to the item\n", + "media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload='This has a title')\n", + "\n", + "# The title should be saved as dcterms:title\n", + "assert media_resource['dcterms:title'][0]['@value'] == 'This has a title'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Include more detailed metadata with a new media item by generating a payload and supplying it using the `payload` parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define some metadata\n", + "media_metadata = {\n", + " 'schema:name': ['This is a different title'],\n", + " 'schema:identifier': ['myidis3']\n", + "}\n", + "\n", + "# Convert metadata into an Omeka payload\n", + "media_payload = omeka_auth.prepare_item_payload(media_metadata)\n", + "\n", + "# Add a new media file with a metadata payload to the item\n", + "media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload=media_payload)\n", + "\n", + "assert media_resource['schema:name'][0]['@value'] == 'This is a different title'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use a specific resource template with the new media item by using the `template_id` parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Get a random template from a list of available templates for testing\n", + "data = omeka_auth.get_resources('resource_templates')\n", + "template = random.choice(data['results'])\n", + "template_id = template['o:id']\n", + "\n", + "# Add a new media file and assign it to a template using the `template_id` parameter\n", + "media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload=media_payload, template_id=template_id)\n", + "\n", + "# Check the new media object has the correct template id\n", + "assert media_resource['o:resource_template']['o:id'] == template_id" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1893,7 +2018,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.add_marker_to_item[source]

\n", + "

OmekaAPIClient.add_marker_to_item[source]

\n", "\n", "> OmekaAPIClient.add_marker_to_item(**`item_id`**, **`coords`**=*`None`*, **`terms`**=*`None`*, **`label`**=*`None`*, **`media_id`**=*`None`*)\n", "\n", @@ -2031,7 +2156,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.prepare_template_payload[source]

\n", + "

OmekaAPIClient.prepare_template_payload[source]

\n", "\n", "> OmekaAPIClient.prepare_template_payload(**`template_file`**)\n", "\n", @@ -2092,14 +2217,14 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.upload_template[source]

\n", + "

OmekaAPIClient.upload_template[source]

\n", "\n", - "> OmekaAPIClient.upload_template(**`template_file`**)\n", + "> OmekaAPIClient.upload_template(**`template_payload`**)\n", "\n", "Upload a template exported from an instance of Omeka to the current local instance.\n", "\n", "Parameters:\n", - "* `template_file` - path to a template exported from Omeka (str or pathlib Path)\n", + "* `template_payload` - dict payload generated by `prepare_template_payload`\n", "\n", "Return:\n", "* dict containing a JSON-LD representation of the uploaded template" @@ -2152,7 +2277,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.localise_custom_vocabs[source]

\n", + "

OmekaAPIClient.localise_custom_vocabs[source]

\n", "\n", "> OmekaAPIClient.localise_custom_vocabs(**`data_types`**)\n", "\n", @@ -2214,7 +2339,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_template_class_id[source]

\n", + "

OmekaAPIClient.get_template_class_id[source]

\n", "\n", "> OmekaAPIClient.get_template_class_id(**`template`**)\n", "\n", @@ -2263,7 +2388,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_template_property_id[source]

\n", + "

OmekaAPIClient.get_template_property_id[source]

\n", "\n", "> OmekaAPIClient.get_template_property_id(**`template`**, **`term`**)\n", "\n", @@ -2322,7 +2447,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.format_resource_id[source]

\n", + "

OmekaAPIClient.format_resource_id[source]

\n", "\n", "> OmekaAPIClient.format_resource_id(**`resource_id`**, **`resource_type`**)\n", "\n", @@ -2369,7 +2494,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.prepare_property_value[source]

\n", + "

OmekaAPIClient.prepare_property_value[source]

\n", "\n", "> OmekaAPIClient.prepare_property_value(**`value`**, **`property_id`**)\n", "\n", @@ -2440,7 +2565,7 @@ { "data": { "text/markdown": [ - "

OmekaAPIClient.get_template_properties[source]

\n", + "

OmekaAPIClient.get_template_properties[source]

\n", "\n", "> OmekaAPIClient.get_template_properties(**`template_id`**)\n", "\n", @@ -2734,21 +2859,22 @@ "data": { "text/plain": [ "{'@context': 'http://timsherratt.org/collections/api-context',\n", - " '@id': 'http://timsherratt.org/collections/api/items/899',\n", - " '@type': 'o:Item',\n", - " 'o:id': 899,\n", + " '@id': 'http://timsherratt.org/collections/api/items/999',\n", + " '@type': ['o:Item', 'schema:Newspaper'],\n", + " 'o:id': 999,\n", " 'o:is_public': True,\n", " 'o:owner': {'@id': 'http://timsherratt.org/collections/api/users/1',\n", " 'o:id': 1},\n", - " 'o:resource_class': None,\n", + " 'o:resource_class': {'@id': 'http://timsherratt.org/collections/api/resource_classes/161',\n", + " 'o:id': 161},\n", " 'o:resource_template': {'@id': 'http://timsherratt.org/collections/api/resource_templates/5',\n", " 'o:id': 5},\n", " 'o:thumbnail': None,\n", " 'o:title': 'The Bendigo Independent (Vic. : 1891 - 1918)',\n", " 'thumbnail_display_urls': {'large': None, 'medium': None, 'square': None},\n", - " 'o:created': {'@value': '2022-02-14T10:39:41+00:00',\n", + " 'o:created': {'@value': '2022-04-03T06:44:57+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", - " 'o:modified': {'@value': '2022-02-14T10:39:41+00:00',\n", + " 'o:modified': {'@value': '2022-04-03T06:44:57+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", " 'o:media': [],\n", " 'o:item_set': [],\n", @@ -2959,8 +3085,8 @@ " '@value': \"MR WRAGGE'S PREDICTION. RENEWAL OF CYCLONE FORETOLD.\"}],\n", " 'schema:isPartOf': [{'property_id': 736,\n", " 'type': 'resource:item',\n", - " '@id': 'http://timsherratt.org/collections/api/items/899',\n", - " 'value_resource_id': 899,\n", + " '@id': 'http://timsherratt.org/collections/api/items/999',\n", + " 'value_resource_id': 999,\n", " 'value_resource_name': 'items'}],\n", " 'schema:datePublished': [{'property_id': 928,\n", " 'type': 'numeric:timestamp',\n", @@ -3016,26 +3142,27 @@ "data": { "text/plain": [ "{'@context': 'http://timsherratt.org/collections/api-context',\n", - " '@id': 'http://timsherratt.org/collections/api/items/900',\n", - " '@type': 'o:Item',\n", - " 'o:id': 900,\n", + " '@id': 'http://timsherratt.org/collections/api/items/1000',\n", + " '@type': ['o:Item', 'schema:NewsArticle'],\n", + " 'o:id': 1000,\n", " 'o:is_public': True,\n", " 'o:owner': {'@id': 'http://timsherratt.org/collections/api/users/1',\n", " 'o:id': 1},\n", - " 'o:resource_class': None,\n", + " 'o:resource_class': {'@id': 'http://timsherratt.org/collections/api/resource_classes/543',\n", + " 'o:id': 543},\n", " 'o:resource_template': {'@id': 'http://timsherratt.org/collections/api/resource_templates/4',\n", " 'o:id': 4},\n", " 'o:thumbnail': None,\n", " 'o:title': \"MR WRAGGE'S PREDICTION. RENEWAL OF CYCLONE FORETOLD.\",\n", - " 'thumbnail_display_urls': {'large': 'http://timsherratt.org/collections/files/large/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg',\n", - " 'medium': 'http://timsherratt.org/collections/files/medium/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg',\n", - " 'square': 'http://timsherratt.org/collections/files/square/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg'},\n", - " 'o:created': {'@value': '2022-02-14T10:39:49+00:00',\n", + " 'thumbnail_display_urls': {'large': 'http://timsherratt.org/collections/files/large/4ad01b874e1d7f94c659638f681b93287b231263.jpg',\n", + " 'medium': 'http://timsherratt.org/collections/files/medium/4ad01b874e1d7f94c659638f681b93287b231263.jpg',\n", + " 'square': 'http://timsherratt.org/collections/files/square/4ad01b874e1d7f94c659638f681b93287b231263.jpg'},\n", + " 'o:created': {'@value': '2022-04-03T06:45:04+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", - " 'o:modified': {'@value': '2022-02-14T10:39:49+00:00',\n", + " 'o:modified': {'@value': '2022-04-03T06:45:04+00:00',\n", " '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},\n", - " 'o:media': [{'@id': 'http://timsherratt.org/collections/api/media/901',\n", - " 'o:id': 901}],\n", + " 'o:media': [{'@id': 'http://timsherratt.org/collections/api/media/1001',\n", + " 'o:id': 1001}],\n", " 'o:item_set': [],\n", " 'o:site': [],\n", " 'schema:name': [{'type': 'literal',\n", @@ -3053,8 +3180,8 @@ " 'property_id': 736,\n", " 'property_label': 'isPartOf',\n", " 'is_public': True,\n", - " '@id': 'http://timsherratt.org/collections/api/items/899',\n", - " 'value_resource_id': 899,\n", + " '@id': 'http://timsherratt.org/collections/api/items/999',\n", + " 'value_resource_id': 999,\n", " 'value_resource_name': 'items',\n", " 'url': None,\n", " 'display_title': 'The Bendigo Independent (Vic. : 1891 - 1918)'}],\n", diff --git a/docs/api.html b/docs/api.html index a27b870..0b5cefd 100644 --- a/docs/api.html +++ b/docs/api.html @@ -168,7 +168,7 @@

OmekaAPIClient.ge
-
87
+
101
@@ -692,16 +692,49 @@

OmekaA
-
items = omeka.filter_items_by_property(filter_property='schema:name', filter_value='WRAGGE.')
+
items = omeka.filter_items_by_property(filter_property='schema:name', filter_value='wragge', filter_type='in')
 
 assert len(items['results']) > 0
-assert items['results'][0]['schema:name'][0]['@value'] == 'WRAGGE.'
+assert 'wragge' in items['results'][0]['schema:name'][0]['@value'].lower()
 
+ + {% endraw %} + + {% raw %} + +
+
+ +
+
+
items['results'][0]['schema:name'][0]['@value']
+
+ +
+
+
+ +
+
+ +
+ + + +
+
'Clement Wragge at Home. - UPDATED!'
+
+ +
+ +
+
+
{% endraw %} @@ -854,7 +887,7 @@

Prepare an item payload -

OmekaAPIClient.prepare_item_payload[source]

OmekaAPIClient.prepare_item_payload(terms)

+

OmekaAPIClient.prepare_item_payload[source]

OmekaAPIClient.prepare_item_payload(terms)

Prepare an item payload, ready for upload.

Parameters:

@@ -981,7 +1014,7 @@

OmekaAPICl
-

OmekaAPIClient.prepare_item_payload_using_template[source]

OmekaAPIClient.prepare_item_payload_using_template(terms, template_id)

+

OmekaAPIClient.prepare_item_payload_using_template[source]

OmekaAPIClient.prepare_item_payload_using_template(terms, template_id)

Prepare an item payload, checking the supplied terms and values against the specified template. Note:

@@ -1105,7 +1138,7 @@

<
-

OmekaAPIClient.add_media_to_payload[source]

OmekaAPIClient.add_media_to_payload(payload, media_files)

+

OmekaAPIClient.add_media_to_payload[source]

OmekaAPIClient.add_media_to_payload(payload, media_files)

Add media files to the item payload.

Parameters:

@@ -1241,9 +1274,9 @@

Add a simple item
{'@context': 'https://timsherratt.org/collections/api-context',
- '@id': 'https://timsherratt.org/collections/api/items/896',
+ '@id': 'https://timsherratt.org/collections/api/items/992',
  '@type': 'o:Item',
- 'o:id': 896,
+ 'o:id': 992,
  'o:is_public': True,
  'o:owner': {'@id': 'https://timsherratt.org/collections/api/users/1',
   'o:id': 1},
@@ -1252,9 +1285,9 @@ 

Add a simple itemUpdating resources -

OmekaAPIClient.delete_resource[source]

OmekaAPIClient.delete_resource(resource_id, resource_type)

+

OmekaAPIClient.delete_resource[source]

OmekaAPIClient.delete_resource(resource_id, resource_type)

Deletes a resource. No confirmation is requested, so use carefully.

Parameters:

@@ -1403,7 +1436,7 @@

OmekaAPIClient.
-

OmekaAPIClient.update_resource[source]

OmekaAPIClient.update_resource(payload, resource_type='items')

+

OmekaAPIClient.update_resource[source]

OmekaAPIClient.update_resource(payload, resource_type='items')

Update an existing resource.

Parameters:

@@ -1464,7 +1497,7 @@

OmekaAPIClient.
-
ARCHITECT of TWO EPOCHS TRAVELS OF INIGO JONES - UPDATED!
+
The Courier-Mail (Brisbane, Qld. : 1933 - 1954) - UPDATED!
 
@@ -1486,20 +1519,19 @@

OmekaAPIClient.
-

OmekaAPIClient.add_media_to_item[source]

OmekaAPIClient.add_media_to_item(item_id, media_file)

+

OmekaAPIClient.add_media_to_item[source]

OmekaAPIClient.add_media_to_item(item_id, media_file, payload={}, template_id=None, class_id=None)

Upload a media file and associate it with an existing item.

Parameters:

  • item_id - the Omeka id of the item this media file should be added to
  • -
  • media_file - the media file to be uploaded, c
  • -
-

The value of media_file can be either:

-
    -
  • a path to an image/media file (filename is used as title)
  • -
  • a dict containing title and path values
  • +
  • media_path - a path to an image/media file (string or pathlib Path)
  • +
  • payload (optional) - metadata to attach to media object, either + a dict generated by prepare_item_payload() or prepare_item_payload_using_template(), + or a string which is used as the value for dcterms:title.
  • +
  • template_id - internal Omeka identifier of a resource template you want to attach to this item
  • +
  • class_id - internal Omeka identifier of a resource class you want to attach to this item
-

The path values can either be strings or pathlib Paths.

Returns:

  • a dict providing a JSON-LD representation of the new media object
  • @@ -1520,6 +1552,34 @@

    OmekaAPIClien
    +
    +
    +
    omeka_auth = OmekaAPIClient(
    +    api_url='https://timsherratt.org/collections/api',
    +    key_identity=os.getenv('KEY_IDENTITY'), 
    +    key_credential=os.getenv('KEY_CREDENTIAL')
    +)
    +
    + +
    +
    +
    + +
    + {% endraw %} + +
    +
    +

    Add a media file to an item without any additional metadata.

    + +
    +
    +
    + {% raw %} + +
    +
    +
    data = omeka_auth.get_resources('items')
    @@ -1527,7 +1587,7 @@ 

    OmekaAPIClien item_id = item['o:id'] # Add a new media file to the item -media_resource = omeka_auth.add_media_to_item(item_id, media_file='media/nla.news-article226799674-24144902.jpg') +media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg') # Check that the media resource is the expected type assert media_resource['@type'] == 'o:Media' @@ -1540,6 +1600,100 @@

    OmekaAPIClien

    +
    + {% endraw %} + +
    +
    +

    Include a title for a new media item by supplying a string value to the payload parameter.

    + +
    +
    +
    + {% raw %} + +
    +
    + +
    +
    +
    media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload='This has a title')
    +
    +# The title should be saved as dcterms:title
    +assert media_resource['dcterms:title'][0]['@value'] == 'This has a title'
    +
    + +
    +
    +
    + +
    + {% endraw %} + +
    +
    +

    Include more detailed metadata with a new media item by generating a payload and supplying it using the payload parameter.

    + +
    +
    +
    + {% raw %} + +
    +
    + +
    +
    +
    media_metadata = {
    +    'schema:name': ['This is a different title'],
    +    'schema:identifier': ['myidis3']
    +}
    +
    +# Convert metadata into an Omeka payload
    +media_payload = omeka_auth.prepare_item_payload(media_metadata)
    +
    +# Add a new media file with a metadata payload to the item
    +media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload=media_payload)
    +
    +assert media_resource['schema:name'][0]['@value'] == 'This is a different title'
    +
    + +
    +
    +
    + +
    + {% endraw %} + +
    +
    +

    Use a specific resource template with the new media item by using the template_id parameter.

    + +
    +
    +
    + {% raw %} + +
    +
    + +
    +
    +
    data = omeka_auth.get_resources('resource_templates')
    +template = random.choice(data['results'])
    +template_id = template['o:id']
    +
    +# Add a new media file and assign it to a template using the `template_id` parameter
    +media_resource = omeka_auth.add_media_to_item(item_id, 'media/nla.news-article226799674-24144902.jpg', payload=media_payload, template_id=template_id)
    +
    +# Check the new media object has the correct template id
    +assert media_resource['o:resource_template']['o:id'] == template_id
    +
    + +
    +
    +
    +
    {% endraw %} @@ -1554,7 +1708,7 @@

    OmekaAPIClien
    -

    OmekaAPIClient.add_marker_to_item[source]

    OmekaAPIClient.add_marker_to_item(item_id, coords=None, terms=None, label=None, media_id=None)

    +

    OmekaAPIClient.add_marker_to_item[source]

    OmekaAPIClient.add_marker_to_item(item_id, coords=None, terms=None, label=None, media_id=None)

    Add a map marker to an item. Requires the mapping module to be installed.

    @@ -1712,7 +1866,7 @@

    Managing templates -

    OmekaAPIClient.prepare_template_payload[source]

    OmekaAPIClient.prepare_template_payload(template_file)

    +

    OmekaAPIClient.prepare_template_payload[source]

    OmekaAPIClient.prepare_template_payload(template_file)

    Insert local property, class, and vocab identifiers into a resource template exported from Omeka so that it can be uploaded to the local instance.

    @@ -1790,7 +1944,7 @@

    OmekaA
    -

    OmekaAPIClient.upload_template[source]

    OmekaAPIClient.upload_template(template_payload)

    +

    OmekaAPIClient.upload_template[source]

    OmekaAPIClient.upload_template(template_payload)

    Upload a template exported from an instance of Omeka to the current local instance.

    Parameters:

    @@ -1858,7 +2012,7 @@

    OmekaAPIClient.
    -

    OmekaAPIClient.localise_custom_vocabs[source]

    OmekaAPIClient.localise_custom_vocabs(data_types)

    +

    OmekaAPIClient.localise_custom_vocabs[source]

    OmekaAPIClient.localise_custom_vocabs(data_types)

    Check a list of data types for references to custom vocabs. If found, look for the local identifier of the custom vocab, @@ -1934,7 +2088,7 @@

    OmekaAPI
    -

    OmekaAPIClient.get_template_class_id[source]

    OmekaAPIClient.get_template_class_id(template)

    +

    OmekaAPIClient.get_template_class_id[source]

    OmekaAPIClient.get_template_class_id(template)

    Get the local id of the resource class associated with the supplied template.

    Parameters:

    @@ -1991,7 +2145,7 @@

    OmekaAPIC
    -

    OmekaAPIClient.get_template_property_id[source]

    OmekaAPIClient.get_template_property_id(template, term)

    +

    OmekaAPIClient.get_template_property_id[source]

    OmekaAPIClient.get_template_property_id(template, term)

    Get the local id of the property associated with the supplied template.

    Parameters:

    @@ -2599,21 +2753,22 @@

    Example: adding a newspa
    {'@context': 'http://timsherratt.org/collections/api-context',
    - '@id': 'http://timsherratt.org/collections/api/items/899',
    - '@type': 'o:Item',
    - 'o:id': 899,
    + '@id': 'http://timsherratt.org/collections/api/items/999',
    + '@type': ['o:Item', 'schema:Newspaper'],
    + 'o:id': 999,
      'o:is_public': True,
      'o:owner': {'@id': 'http://timsherratt.org/collections/api/users/1',
       'o:id': 1},
    - 'o:resource_class': None,
    + 'o:resource_class': {'@id': 'http://timsherratt.org/collections/api/resource_classes/161',
    +  'o:id': 161},
      'o:resource_template': {'@id': 'http://timsherratt.org/collections/api/resource_templates/5',
       'o:id': 5},
      'o:thumbnail': None,
      'o:title': 'The Bendigo Independent (Vic. : 1891 - 1918)',
      'thumbnail_display_urls': {'large': None, 'medium': None, 'square': None},
    - 'o:created': {'@value': '2022-02-14T10:39:41+00:00',
    + 'o:created': {'@value': '2022-04-03T06:44:57+00:00',
       '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},
    - 'o:modified': {'@value': '2022-02-14T10:39:41+00:00',
    + 'o:modified': {'@value': '2022-04-03T06:44:57+00:00',
       '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},
      'o:media': [],
      'o:item_set': [],
    @@ -2879,8 +3034,8 @@ 

    Example: adding a newspa '@value': "MR WRAGGE'S PREDICTION. RENEWAL OF CYCLONE FORETOLD."}], 'schema:isPartOf': [{'property_id': 736, 'type': 'resource:item', - '@id': 'http://timsherratt.org/collections/api/items/899', - 'value_resource_id': 899, + '@id': 'http://timsherratt.org/collections/api/items/999', + 'value_resource_id': 999, 'value_resource_name': 'items'}], 'schema:datePublished': [{'property_id': 928, 'type': 'numeric:timestamp', @@ -2956,26 +3111,27 @@

    Example: adding a newspa
    {'@context': 'http://timsherratt.org/collections/api-context',
    - '@id': 'http://timsherratt.org/collections/api/items/900',
    - '@type': 'o:Item',
    - 'o:id': 900,
    + '@id': 'http://timsherratt.org/collections/api/items/1000',
    + '@type': ['o:Item', 'schema:NewsArticle'],
    + 'o:id': 1000,
      'o:is_public': True,
      'o:owner': {'@id': 'http://timsherratt.org/collections/api/users/1',
       'o:id': 1},
    - 'o:resource_class': None,
    + 'o:resource_class': {'@id': 'http://timsherratt.org/collections/api/resource_classes/543',
    +  'o:id': 543},
      'o:resource_template': {'@id': 'http://timsherratt.org/collections/api/resource_templates/4',
       'o:id': 4},
      'o:thumbnail': None,
      'o:title': "MR WRAGGE'S PREDICTION. RENEWAL OF CYCLONE FORETOLD.",
    - 'thumbnail_display_urls': {'large': 'http://timsherratt.org/collections/files/large/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg',
    -  'medium': 'http://timsherratt.org/collections/files/medium/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg',
    -  'square': 'http://timsherratt.org/collections/files/square/f5ed7414ea6f98988a59b8b0e97235e678181216.jpg'},
    - 'o:created': {'@value': '2022-02-14T10:39:49+00:00',
    + 'thumbnail_display_urls': {'large': 'http://timsherratt.org/collections/files/large/4ad01b874e1d7f94c659638f681b93287b231263.jpg',
    +  'medium': 'http://timsherratt.org/collections/files/medium/4ad01b874e1d7f94c659638f681b93287b231263.jpg',
    +  'square': 'http://timsherratt.org/collections/files/square/4ad01b874e1d7f94c659638f681b93287b231263.jpg'},
    + 'o:created': {'@value': '2022-04-03T06:45:04+00:00',
       '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},
    - 'o:modified': {'@value': '2022-02-14T10:39:49+00:00',
    + 'o:modified': {'@value': '2022-04-03T06:45:04+00:00',
       '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'},
    - 'o:media': [{'@id': 'http://timsherratt.org/collections/api/media/901',
    -   'o:id': 901}],
    + 'o:media': [{'@id': 'http://timsherratt.org/collections/api/media/1001',
    +   'o:id': 1001}],
      'o:item_set': [],
      'o:site': [],
      'schema:name': [{'type': 'literal',
    @@ -2993,8 +3149,8 @@ 

    Example: adding a newspa 'property_id': 736, 'property_label': 'isPartOf', 'is_public': True, - '@id': 'http://timsherratt.org/collections/api/items/899', - 'value_resource_id': 899, + '@id': 'http://timsherratt.org/collections/api/items/999', + 'value_resource_id': 999, 'value_resource_name': 'items', 'url': None, 'display_title': 'The Bendigo Independent (Vic. : 1891 - 1918)'}], diff --git a/omeka_s_tools/__init__.py b/omeka_s_tools/__init__.py index 485f44a..d3ec452 100644 --- a/omeka_s_tools/__init__.py +++ b/omeka_s_tools/__init__.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.2.0" diff --git a/omeka_s_tools/api.py b/omeka_s_tools/api.py index 5f2c949..a3fd9ad 100644 --- a/omeka_s_tools/api.py +++ b/omeka_s_tools/api.py @@ -303,6 +303,10 @@ def add_item(self, payload, media_files=None, template_id=None, class_id=None, i ''' if template_id: payload['o:resource_template'] = self.format_resource_id(template_id, 'resource_templates') + # If class is not set explicitly, use class associated with template + if not class_id: + template = self.get_resource_by_id(template_id, 'resource_templates') + class_id = template['o:resource_class']['o:id'] if class_id: payload['o:resource_class'] = self.format_resource_id(class_id, 'resource_classes') if item_set_id: @@ -447,38 +451,47 @@ def update_resource(self, payload, resource_type='items'): response = self.s.put(f'{self.api_url}/{resource_type}/{payload["o:id"]}', json=payload, params=self.params) return response.json() - def add_media_to_item(self, item_id, media_file): + def add_media_to_item(self, item_id, media_file, payload={}, template_id=None, class_id=None): ''' Upload a media file and associate it with an existing item. Parameters: * `item_id` - the Omeka id of the item this media file should be added to - * `media_file` - the media file to be uploaded, c - - The value of `media_file` can be either: - * a path to an image/media file (filename is used as title) - * a dict containing `title` and `path` values - - The path values can either be strings or pathlib Paths. + * `media_path` - a path to an image/media file (string or pathlib Path) + * `payload` (optional) - metadata to attach to media object, either + a dict generated by `prepare_item_payload()` or `prepare_item_payload_using_template()`, + or a string which is used as the value for `dcterms:title`. + * `template_id` - internal Omeka identifier of a resource template you want to attach to this item + * `class_id` - internal Omeka identifier of a resource class you want to attach to this item Returns: * a dict providing a JSON-LD representation of the new media object ''' files = {} + # For backwards compatibility if isinstance(media_file, dict): - title = media_file['title'] - path = Path(media_file['path']) - else: - path = Path(media_file) - title = path.name + path = media_file['path'] + payload = media_file['title'] + # Make sure path is a Path object + path = Path(media_file) + if isinstance(payload, str): + payload = self.prepare_item_payload({'dcterms:title': [payload]}) + if template_id: + payload['o:resource_template'] = self.format_resource_id(template_id, 'resource_templates') + if not class_id: + template = self.get_resource_by_id(template_id, 'resource_templates') + class_id = template['o:resource_class']['o:id'] + if class_id: + payload['o:resource_class'] = self.format_resource_id(class_id, 'resource_classes') file_data = { 'o:ingester': 'upload', 'file_index': '0', + 'o:source': path.name, 'o:item': {'o:id': item_id}, - 'dcterms:title': [{'property_id': 1, '@value': title, 'type': 'literal'}] } + payload.update(file_data) files[f'file[0]'] = path.read_bytes() - files['data'] = (None, json.dumps(file_data), 'application/json') + files['data'] = (None, json.dumps(payload), 'application/json') response = self.s.post(f'{self.api_url}/media', files=files, params=self.params) return response.json() diff --git a/settings.ini b/settings.ini index 8faaffd..6de5123 100644 --- a/settings.ini +++ b/settings.ini @@ -13,7 +13,7 @@ author = Tim Sherratt author_email = tim@timsherratt.org copyright = Tim Sherratt branch = master -version = 0.1.1 +version = 0.2.0 min_python = 3.8 audience = Developers language = English