diff --git a/guide/03-the-gis/offline-cloning-backups.ipynb b/guide/03-the-gis/offline-cloning-backups.ipynb index 4dd2fe10da..62421dc3e1 100644 --- a/guide/03-the-gis/offline-cloning-backups.ipynb +++ b/guide/03-the-gis/offline-cloning-backups.ipynb @@ -1,337 +1,347 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "71c3b6a8-98ef-464c-b3fe-dcc61f8caa52", - "metadata": {}, - "source": [ - "# Cloning via Offline Backups\n", - "\n", - "Cloning items from one organization has long been an important workflow in the ArcGIS API for Python, primarily through [`clone_items()`](https://developers.arcgis.com/python/latest/guide/cloning-content/). `clone_items()` depends on having multiple active GIS connections, and items are dissected and reconstructed from scratch within each call- the `OfflineContentManager` module, introduced in version 2.4.1, takes a slightly different approach. While both can take part and reassemble items elsewhere, the `OfflineContentManager` also creates a compressed backup of the items along the way, including all dependencies of the items being cloned.\n", - "\n", - "[We can see the documentation for the module here](https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#offlinecontentmanager).\n", - "\n", - "The module is short and sweet, and can be accessed by calling `gis.content.offline` on a GIS object. It consists of 3 functions: one to export items, one to import items, and one to list the content of a compressed backup. The way it works behind the scenes is:\n", - "- In `export_items()`, an [`ItemGraph`](include link) is first assembled with all of the items and the items they need to exist\n", - "- An output folder is generated, and within that, a folder for each item is created with the necessary data and metadata. Services without an underlying feature class file are exported to either a File Geodatabase or Shapefile, as specified in the export call.\n", - "- That output folder is compressed and stored either in the specified path or in a temporary directory\n", - "- On import, the the package is decompressed, the graph is recreated in memory, and the items are created in order from least dependencies to most\n", - "\n", - "There are a few situations where it may be advantageous to use this module instead of `clone_items()`. Creating a singular backup to use from a source org can avoid repeated calls to `clone_items()` in cases where content is being brought to multiple different GIS orgs. Additionally, creating backup packages provides safety against unexpected changes to an org's content. Another notable difference between the OCM and `clone_items()` is that the `import_content()` function provides the option to skip over items that can't be reproduced, as opposed to rolling everything back like `clone_items()` does.\n", - "\n", - "Let's take a look at its basic usage, and then a couple more specific use cases." - ] - }, - { - "cell_type": "markdown", - "id": "e27ffdf0-eebd-4f8c-bd4a-bd5a9fc14438", - "metadata": {}, - "source": [ - "## Step 1: Exporting\n", - "\n", - "We'll start by showing how to create one of these offline packages in our source organization. It's as easy as just selecting the items you wish to export, and passing them into the function- a package with those items and every other item they need to exist will be assembled.\n", - "\n", - "Let's start by connecting to a GIS, and accessing the OfflineContentManager for it." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0b1df0b5-dbef-4fed-9756-09d5982088c4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from arcgis.gis import GIS\n", - "gis = GIS(profile=\"your_admin_profile\")\n", - "ocm = gis.content.offline\n", - "ocm" - ] - }, - { - "cell_type": "markdown", - "id": "7c70c162-f9d9-479a-836a-4ada1fedebae", - "metadata": {}, - "source": [ - "We'll grab the item that we want to back up and/or migrate." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "a1d32822-9ac8-4891-bce1-abc2c455afb8", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "
\n", - " \n", - " \n", - " \n", - "
\n", - "\n", - "
\n", - " Oceanic Experience\n", - " \n", - "

Web Experience by nparavicini_geosaurus\n", - "
Last Modified: November 20, 2024\n", - "
0 comments, 10 views\n", - "
\n", - "
\n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "experience = gis.content.get(\"b2136e64f7414d10b02b52b009d7c13b\")\n", - "experience" - ] - }, - { - "cell_type": "markdown", - "id": "6bf87d97-eb48-4b5f-8cc1-facb7fdab800", - "metadata": {}, - "source": [ - "When we call the `export_items()` function, there are a couple things we can dictate: where the items are exported, what the name of the package is, and whether to export hosted services as a File Geodatabase or Shapefile. If no path is specified, a package will be created in a tempfile, and that path can be used for the import." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "0df3d667-9c23-4127-b1b1-69ce59dcb56d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'/var/folders/dn/rybvglf95w710d__8w91yngc0000gn/T/tmph411_rwn/exported_content.contentexport'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "file_path = ocm.export_items([experience])\n", - "file_path" - ] - }, - { - "cell_type": "markdown", - "id": "3d6a5e05-8e29-4f0a-a889-4433ee53c017", - "metadata": {}, - "source": [ - "## Step 2: Listing Items (Optional)\n", - "\n", - "This second step is optional and is just handy for understanding what exactly was exported into your offline package. This can be helpful for a few different reasons: you're sent a package by somebody else and you'd like to know exactly what was in it, you're exporting complicated items and want to see the full scope of dependencies, or you want to understand what is in the package so you can select a subset to import.\n", - "\n", - "We'll connect to our second GIS and see what was exported by the function in our first GIS." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "fc3ca216-212c-4428-a870-b81c602009ee", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'b2136e64f7414d10b02b52b009d7c13b': {'title': 'Oceanic Experience',\n", - " 'type': 'Web Experience',\n", - " 'created': 1721117377000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'},\n", - " 'bf5a039b1947422190b5812fc34af717': {'title': 'Ugly Map',\n", - " 'type': 'Web Map',\n", - " 'created': 1720503733000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'},\n", - " 'd322ea73f27844228a2f235d9615854e': {'title': 'CA/OR Airports',\n", - " 'type': 'Feature Service',\n", - " 'created': 1720503718000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'}}" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gis2 = GIS(profile=\"another_admin_profile\")\n", - "ocm2 = gis2.content.offline\n", - "ocm2.list_items(file_path)" - ] - }, - { - "cell_type": "markdown", - "id": "9b267b6b-4a37-4ab1-b6eb-cd14095f78fb", - "metadata": {}, - "source": [ - "As we can see, more than just our initial Web Experience got exported- the map contained within the Experience, as well as the Feature Layer displayed within the map, were also exported." - ] - }, - { - "cell_type": "markdown", - "id": "6c29295e-da19-4f05-8fd6-ccc326d445ec", - "metadata": {}, - "source": [ - "## Step 3: Importing\n", - "\n", - "This is the final and most involved step. Importing the content into the target org is very straightforward, but there are a few options you as a user has to customize the process:\n", - "- Selection of which items to import from a package\n", - "- The option to roll back all item creation on failure, or skip over failed items and continue cloning the rest\n", - "- An `item_mapping` parameter (similar to `clone_items()`) that allows users to replace certain dependencies with existent items\n", - "\n", - "Let's look at a basic call, and then we'll observe the failsafe mechanisms in place when there is an issue encountered importing." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "731b43aa-076a-4345-9cbe-6bccbd00b070", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[,\n", - " ,\n", - " ,\n", - " ]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "imported = ocm2.import_content(file_path)\n", - "imported" - ] - }, - { - "cell_type": "markdown", - "id": "aed977b7-c8c2-4a24-a5f3-494fdb7178fd", - "metadata": {}, - "source": [ - "As we can see, we got one extra item compared to what we started with: a File Geodatabase. This is because we needed to story the data from the feature layer in some offline format.\n", - "\n", - "What if we're importing a larger set of items, and some of them might have issues? For anybody familiar with `clone_items()`, one notable caveat of working with the function is that if any single item gets messed up along the way, all items are rolled back and deleted, meaning a user has to start at square one or find an alternative. Luckily, this function allows users to skip by items that encounter issues. We'll show what happens when cloning a package where some of the items has been corrupted." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "0867a29f-d4e6-439e-891a-0272e3fb573a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'b13272e4cf334436b1f86ba0137a0aa8': {'title': \"Why won't this work?\",\n", - " 'type': 'StoryMap',\n", - " 'created': 1745620980000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'},\n", - " 'cb7dd4102c51495e8b4c3a346f03f612': {'title': 'Minnesota_Private_Wells',\n", - " 'type': 'Feature Service',\n", - " 'created': 1751491976000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'},\n", - " '265de67ceed6498e8cf3fc4a9f795413': {'title': 'Minnesota_Private_Wells',\n", - " 'type': 'File Geodatabase',\n", - " 'created': 1751491961000,\n", - " 'source': 'https://geosaurus.maps.arcgis.com'}}" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "fail_path = \"/Users/pythondemo/Downloads/ocm_failure.contentexport\"\n", - "ocm.list_items(fail_path)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "b3329112-adf8-4abc-8ccd-9bf3caa9c5aa", - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/pythondemo/packages/arcgis/apps/itemgraph/_migration.py:767: RuntimeWarning: Failed to import item b13272e4cf334436b1f86ba0137a0aa8 due to error: Expected object or value. Skipping...\n", - " warnings.warn(\n", - "/Users/pythondemo/packages/arcgis/apps/itemgraph/_migration.py:767: RuntimeWarning: Failed to import item cb7dd4102c51495e8b4c3a346f03f612 due to error: Trailing data. Skipping...\n", - " warnings.warn(\n" - ] - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ocm2.import_content(fail_path)" - ] - }, - { - "cell_type": "markdown", - "id": "1415d59e-96b2-4d46-acb4-8bbd8632990f", - "metadata": {}, - "source": [ - "As we can see, it skipped over importing the two failed items and gave us a warning about what happened, but carried out importing the one valid one. However, if we wanted, we could also set `failure_rollback = True`, and it wouldn't have imported anything, just like `clone_items()`." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.10" - } + "cells": [ + { + "cell_type": "markdown", + "id": "71c3b6a8-98ef-464c-b3fe-dcc61f8caa52", + "metadata": {}, + "source": [ + "# Cloning via Offline Backups\n", + "\n", + "Cloning items from one organization has long been an important workflow in the ArcGIS API for Python, primarily through [`clone_items()`](/python/latest/guide/cloning-content/). The [`clone_items()`](/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.clone_items) method depends on having multiple active GIS connections, and items are dissected and reconstructed from scratch within each call. The [`OfflineContentManager`](/python/latest/api-reference/arcgis.gis.toc.html#offlinecontentmanager) (OCM) module, introduced in version 2.4.1, takes a slightly different approach. While both can take part and reassemble items elsewhere, the `OfflineContentManager` also creates a compressed backup of the items along the way, including all dependencies of the items being cloned.\n", + "\n", + "See the the API reference documentation for the module [here](https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#offlinecontentmanager).\n", + "\n", + "The module is compact, and an object of the `OfflineContentManager` class can be accessed through the [`offline`](/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.offline) property of a [ContentManager]([GIS](/python/latest/api-reference/arcgis.gis.toc.html#contentmanager) object: `gis.content.offline`. It consists of 3 methods: \n", + "* [`export_items()`](/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.OfflineContentManager.export_items) - to export item content to a package\n", + "* [`import_content()`](/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.OfflineContentManager.import_content) - one to import package content \n", + "* [`list_items()`](/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.OfflineContentManager.list_items) - to explore the content of a compressed backup.\n", + "\n", + "The way it works behind the scenes is:\n", + "- In `export_items()`, an [`ItemGraph`](/python/latest/api-reference/arcgis.apps.itemgraph.html#itemgraph) is assembled with all of the items and the items they need to exist\n", + "- An output folder is generated, and within that, a folder for each item is created with the necessary data and metadata. Services without an underlying feature class file are exported to either a File Geodatabase or Shapefile, as specified in the export call's `service_format` argument.\n", + "- That output folder is compressed and stored either in the specified path or in a temporary directory\n", + "- On import, the the package is decompressed, the graph is recreated in memory, and the items are created in order from least dependencies to most\n", + "\n", + "There are a few situations where it may be advantageous to use this module instead of `clone_items()`. Creating a singular backup to use from a source org can avoid repeated calls to `clone_items()` in cases where content is being brought to multiple different GIS orgs. Additionally, creating backup packages provides safety against unexpected changes to an organiztion's content. Another notable difference between the OCM and `clone_items()` is that the `import_content()` method provides the option to skip over items that aren't recreated correctly, as opposed to rolling everything back like `clone_items()` does.\n", + "\n", + "Let's take a look at its basic usage, and then a couple more specific use cases." + ] + }, + { + "cell_type": "markdown", + "id": "e27ffdf0-eebd-4f8c-bd4a-bd5a9fc14438", + "metadata": {}, + "source": [ + "## Step 1: Exporting\n", + "\n", + "We'll start by showing how to create one of these offline packages in our source organization. It's as easy as just selecting the items you wish to export, and passing them into the `export_items()` method. A package with those items and every other item they need to exist will be assembled.\n", + "\n", + "Let's start by connecting to a GIS, and accessing an OfflineContentManager object." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0b1df0b5-dbef-4fed-9756-09d5982088c4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from arcgis.gis import GIS\n", + "gis = GIS(profile=\"your_admin_profile\")\n", + "ocm = gis.content.offline\n", + "ocm" + ] + }, + { + "cell_type": "markdown", + "id": "7c70c162-f9d9-479a-836a-4ada1fedebae", + "metadata": {}, + "source": [ + "We'll get the item that we want to back up and/or migrate." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a1d32822-9ac8-4891-bce1-abc2c455afb8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + " Oceanic Experience\n", + " \n", + "

Web Experience by nparavicini_geosaurus\n", + "
Last Modified: November 20, 2024\n", + "
0 comments, 10 views\n", + "
\n", + "
\n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "experience = gis.content.get(\"b2136e64f7414d10b02b52b009d7c13b\")\n", + "experience" + ] + }, + { + "cell_type": "markdown", + "id": "6bf87d97-eb48-4b5f-8cc1-facb7fdab800", + "metadata": {}, + "source": [ + "When we call the `export_items()` method, there are a couple things we can dictate: \n", + "* the location the items are exported\n", + "* the name of the output package\n", + "* whether to export hosted services as a File Geodatabase or Shapefile.\n", + "\n", + "If no path is specified, a package will be created in a temporary file path, and that path can be used for the import." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0df3d667-9c23-4127-b1b1-69ce59dcb56d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/var/folders/dn/rybvglf95w710d__8w91yngc0000gn/T/tmph411_rwn/exported_content.contentexport'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "file_path = ocm.export_items([experience])\n", + "file_path" + ] + }, + { + "cell_type": "markdown", + "id": "3d6a5e05-8e29-4f0a-a889-4433ee53c017", + "metadata": {}, + "source": [ + "## Step 2: Listing Items (Optional)\n", + "\n", + "This second step is optional and is just handy for understanding what exactly was exported into your offline package. This can be helpful for a few different reasons: you're sent a package by somebody else and you'd like to know exactly what was in it, you're exporting complicated items and want to see the full scope of dependencies, or you want to understand what is in the package so you can select a subset to import.\n", + "\n", + "We'll connect to our second GIS and see what was exported by the function in our first GIS." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "fc3ca216-212c-4428-a870-b81c602009ee", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'b2136e64f7414d10b02b52b009d7c13b': {'title': 'Oceanic Experience',\n", + " 'type': 'Web Experience',\n", + " 'created': 1721117377000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'},\n", + " 'bf5a039b1947422190b5812fc34af717': {'title': 'Ugly Map',\n", + " 'type': 'Web Map',\n", + " 'created': 1720503733000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'},\n", + " 'd322ea73f27844228a2f235d9615854e': {'title': 'CA/OR Airports',\n", + " 'type': 'Feature Service',\n", + " 'created': 1720503718000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'}}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gis2 = GIS(profile=\"another_admin_profile\")\n", + "ocm2 = gis2.content.offline\n", + "ocm2.list_items(file_path)" + ] + }, + { + "cell_type": "markdown", + "id": "9b267b6b-4a37-4ab1-b6eb-cd14095f78fb", + "metadata": {}, + "source": [ + "As we can see, more than just our initial Web Experience got exported- the map contained within the Experience, as well as the Feature Layer displayed within the map, were also exported." + ] + }, + { + "cell_type": "markdown", + "id": "6c29295e-da19-4f05-8fd6-ccc326d445ec", + "metadata": {}, + "source": [ + "## Step 3: Importing\n", + "\n", + "This is the final and most involved step. Importing the content into the target org is very straightforward, but there are a few options you have to customize the process:\n", + "- which specific items to import from a package or all of them\n", + "- whether to roll back all item creation on failure, or skip over failed items and continue cloning the rest\n", + "- whether to use an `item_mapping` parameter (similar to `clone_items()`) that allows you to replace certain dependencies with existent items\n", + "\n", + "Let's look at a basic call, and then we'll observe the failsafe mechanisms in place when there is an issue encountered importing." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "731b43aa-076a-4345-9cbe-6bccbd00b070", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[,\n", + " ,\n", + " ,\n", + " ]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "imported = ocm2.import_content(file_path)\n", + "imported" + ] + }, + { + "cell_type": "markdown", + "id": "aed977b7-c8c2-4a24-a5f3-494fdb7178fd", + "metadata": {}, + "source": [ + "As we can see, the imported content contains an extra item compared to what we started with: a File Geodatabase. We needed to store the data from the feature layer in some offline format, so that is where the file geodatabase comes from.\n", + "\n", + "What if we're importing a larger set of items, and some of them might have issues? For anybody familiar with `clone_items()`, one notable caveat of working with the function is that if any single item fails along the way, all items are rolled back and deleted, meaning a user has to start at square one or find an alternative. Fortunately the `import_content()` method allows users to skip by items that encounter issues. We'll show what happens when cloning a package where some of the items have been corrupted." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "0867a29f-d4e6-439e-891a-0272e3fb573a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'b13272e4cf334436b1f86ba0137a0aa8': {'title': \"Why won't this work?\",\n", + " 'type': 'StoryMap',\n", + " 'created': 1745620980000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'},\n", + " 'cb7dd4102c51495e8b4c3a346f03f612': {'title': 'Minnesota_Private_Wells',\n", + " 'type': 'Feature Service',\n", + " 'created': 1751491976000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'},\n", + " '265de67ceed6498e8cf3fc4a9f795413': {'title': 'Minnesota_Private_Wells',\n", + " 'type': 'File Geodatabase',\n", + " 'created': 1751491961000,\n", + " 'source': 'https://geosaurus.maps.arcgis.com'}}" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fail_path = \"/Users/pythondemo/Downloads/ocm_failure.contentexport\"\n", + "ocm.list_items(fail_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b3329112-adf8-4abc-8ccd-9bf3caa9c5aa", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/pythondemo/packages/arcgis/apps/itemgraph/_migration.py:767: RuntimeWarning: Failed to import item b13272e4cf334436b1f86ba0137a0aa8 due to error: Expected object or value. Skipping...\n", + " warnings.warn(\n", + "/Users/pythondemo/packages/arcgis/apps/itemgraph/_migration.py:767: RuntimeWarning: Failed to import item cb7dd4102c51495e8b4c3a346f03f612 due to error: Trailing data. Skipping...\n", + " warnings.warn(\n" + ] }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ocm2.import_content(fail_path)" + ] + }, + { + "cell_type": "markdown", + "id": "1415d59e-96b2-4d46-acb4-8bbd8632990f", + "metadata": {}, + "source": [ + "As we can see, it skipped over importing the two failed items and gave us a warning about what happened, but carried out importing the one valid one. However, if we wanted, we could also set `failure_rollback = True`, and it wouldn't have imported anything, just like `clone_items()`." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}