Skip to content

Instantly share code, notes, and snippets.

@knu2xs
Last active December 2, 2025 01:00
Show Gist options
  • Select an option

  • Save knu2xs/eec04f383cb72e4b1b65242b79bc858f to your computer and use it in GitHub Desktop.

Select an option

Save knu2xs/eec04f383cb72e4b1b65242b79bc858f to your computer and use it in GitHub Desktop.
Publish a feature layer and ensure the layer index is zero.
from pathlib import Path
import shutil
import tempfile
from typing import Optional
import arcgis.env
from arcgis.features import GIS, Item
import arcpy
def publish_feature_layer(
layer: arcpy._mp.Layer,
gis: Optional[GIS] = None,
feature_layer_name: Optional[str] = None
) -> Item:
    """
    Publish a feature layer to ArcGIS Online ensuring the layer ID is 0.
    Args:
        layer: The ArcPy Layer object to publish.
        gis: GIS object with permissions to publish the layer.
        feature_layer_name: Optional name for the published feature layer. If not provided, uses the layer name.
    Returns:
        The published Item object.
    """
    # ensure working with a layer object
    if not isinstance(layer, arcpy._mp.Layer):
        raise TypeError("The provided layer is not an ArcPy Layer object.")
    # ensure there is a gis to work with
    if gis is None and arcgis.env.active_gis is not None:
        gis = arcgis.env.active_gis
    else:
        raise EnvironmentError(
            "Cannot access an active GIS in the environment. Please populate the gis parameter with an "
            "instantiated GIS object with permissions to publish."
        )
   
    # ensure the logged in user has publishing permissions
    if not gis.users.me.is_publisher and not gis.users.me.is_admin:
        raise PermissionError(
            f"The logged in user, {gis.users.me.username}, does not have permissions to publish content. "
            "Please use a user with Publisher or Admin privileges."
        )
    # determine the feature layer name
    if feature_layer_name is None:
        feature_layer_name = layer.name
        # slugify the name
        feature_layer_name = re.sub(r"\s+", "_", feature_layer_name.strip())
        # if the name starts with a number, prepend with letter 'f_'
        if re.match(r"^\d", feature_layer_name):
            feature_layer_name = f"f_{feature_layer_name}"
    # use tempfile to get a temporary directory
    tmp_dir = Path(tempfile.gettempdir())
    # create a new aprx project in the temporary directory
    new_aprx_path = tmp_dir / "temp_project.aprx"
    # create a new ArcGIS Pro project
    arcpy.mp.CreateProject("NEW", new_aprx_path)
    new_aprx = arcpy.mp.ArcGISProject(new_aprx_path)
    new_map = new_aprx.listMaps()[0]
    # add the layer to the new project
    new_map.addLayer(layer)
    # ensure layer is at the top (index 0) ---
    new_map.moveLayer(None, layer, "TOP")
    new_aprx.save()
    # Create sharing draft and stage service
    sharing_draft = new_map.getWebLayerSharingDraft(
server_type="HOSTING_SERVER",
service_type="FEATURE",
service_name=feature_layer_name
)
    sddraft_path = tmp_dir / f"{feature_layer_name}.sddraft"
    sharing_draft.exportToSDDraft(out_sddraft=sddraft_path)
    sd_path = tmp_dir / f"{feature_layer_name}.sd"
    arcpy.server.StageService(
in_service_definition_draft=sddraft_path,
out_service_definition=sd_path
)
    # Upload service definition using GIS object
    published_item = gis.content.add({}, sd_path)
    published_item.publish()
    logger.debug(f"Published service: {published_item.title}")
    # Verify publication and layer id
    layers = published_item.layers
    # ensure there is only one layer
    if len(layers) != 1:
        logger.warning(
            f"Published item {published_item.title} has {len(layers)} layers. Expected exactly 1 layer."
        )
    else:
        logger.debug(
            f"Published item {published_item.title} has 1 layer as expected."
        )
    # ensure the layer id is 0
    if layers[0].properties.id != 0:
        logger.warning(
            f"Published layer {layers[0].properties.name} has layer ID {layers[0].properties.id}. Expected layer ID 0."
        )
    else:
        logger.debug(
            f"Published layer {layers[0].properties.name} has layer ID 0 as expected."
        )
   
    # report item id in log
    logger.info(
        f"Published feature layer '{feature_layer_name}' to ArcGIS Online with item ID: {published_item.id} ({published_item.url})."
    )
# clean up temporary files
    shutil.rmtree(tmp_dir, ignore_errors=True)
    return published_item
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment