Utilities for building clean, maintainable ArcPy toolboxes
Project description
arcsmith
Utilities for building clean, maintainable ArcPy toolboxes.
arcsmith reduces the boilerplate common to ArcPy toolbox development — parameter validation, symbology application, and field management — so that toolbox code remains readable and consistent.
Installation
pip install arcsmith
Note:
arcsmithdepends onarcpy, which ships with ArcGIS Pro and is not available via pip. Ensure you are running in an environment wherearcpyis accessible.
Usage
import arcsmith
# Layer symbology
arcsmith.layer.add_w_sym("path/to/fc", "path/to/sym.lyrx", target_map)
# Parameter management (Inside of toolbox's updateParameters)
if arcsmith.param.state(parameters[0]) == 'pending':
parameters[1].value = None
Modules
arcsmith.param: Parameter state management, dropdowns, and checkbox-driven visibilityarcsmith.layer: Adding layers and applying symbologyarcsmith.fields: Field introspection, management, and mapping (coming soon)
arcsmith.param
Helpers for managing arcpy.Parameter state inside ToolValidator.
A key concept throughout this module is parameter state. Understanding whether a parameter has been changed by the user and whether it has passed through ArcPy's validation cycle is the foundation of updateParameters logic that ArcSmith simplifies.
state
Returns a string describing the combined altered / hasBeenValidated state of a parameter.
state(param: arcpy.Parameter) -> str
States
| State | .altered |
.hasBeenValidated |
Description |
|---|---|---|---|
fresh |
False |
False |
Initial, untouched state |
pending |
True |
False |
Changed, awaiting validation |
settled |
False |
True |
Validated, not changed since |
confirmed |
True |
True |
Changed and validated |
The 'pending' state is the most important to detect. It marks the moment a value was just changed, and is the right time to cascade resets or re-populate dependent controls.
Example
state = state(parameters[0])
if state == 'pending':
# parameter was just changed
...
cascade_clear
Resets downstream parameters to None when an upstream parameter is in a pending state.
cascade_clear(trigger_param, downstream_params)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
trigger_param |
arcpy.Parameter |
required | The parameter whose change triggers the cascade. |
downstream_params |
list[arcpy.Parameter] |
required | Parameters to clear when trigger_param is 'pending'. |
Safe to call unconditionally on every updateParameters pass. If trigger_param is not 'pending' the call is a no-op.
Example
# Clear workspace and layer fields whenever the geodatabase selection changes
cascade_clear(params[0], [params[1], params[2]])
drop_populate
Sets or replaces a parameter's dropdown filter list.
drop_populate(param, values, overwrite_empty=False)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
param |
arcpy.Parameter |
required | The dropdown parameter to populate. |
values |
list[str] |
required | Options to display in the dropdown. |
overwrite_empty |
bool |
False |
If True, updates the filter even when values is empty, clearing the list. |
By default, an empty values list leaves the existing filter untouched. This prevents accidentally clearing a valid dropdown when an upstream dependency hasn't been set yet.
Example
# Populate field names derived from a selected feature class
fields = [f.name for f in arcpy.ListFields(params[0].value)]
drop_populate(params[1], fields)
# Explicitly clear a dropdown
drop_populate(params[1], [], overwrite_empty=True)
checkbox_dependence
Enables or disables dependent parameters based on a controlling checkbox, assigning placeholder values when hidden to keep required parameters satisfied.
checkbox_dependence(
controlling_checkbox,
dependents,
placeholder=None,
always_show_dependents=False
)
Behaviour
| Checkbox state | Effect |
|---|---|
| Unchecked | Dependents disabled; placeholder value(s) assigned |
| Just checked | Dependents enabled; values cleared to None |
| Otherwise | No-op. Existing user input is preserved. |
Raises: ValueError if placeholder is a list whose length differs from dependents.
Examples
# Broadcast a single placeholder to all dependents
checkbox_dependence(cb, [p1, p2, p3], placeholder="N/A")
# Single dependent - no list required
checkbox_dependence(cb, p1, placeholder=0)
# Mixed types, one placeholder per dependent
checkbox_dependence(cb, [p1, p2, p3], placeholder=["N/A", 0, None])
# Keep dependents visible but disabled when unchecked
checkbox_dependence(cb, [p1, p2], placeholder="N/A", always_show_dependents=True)
dynamic_dropdown
Enables the correct group of dependent parameters based on the selected dropdown option, disabling all others.
dynamic_dropdown(controlling_dropdown, option_map, placeholder_map=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
controlling_dropdown |
arcpy.Parameter |
required | Dropdown that controls which parameter group is active. |
option_map |
dict[str, list[arcpy.Parameter]] |
required | Maps each option label to the parameters that should be enabled when that option is selected. |
placeholder_map |
dict[str, list] |
None |
Maps each option label to placeholder values assigned when the dropdown is pending. None entries skip assignment for that parameter. |
Behaviour
| Dropdown state | Effect |
|---|---|
| Any state | All managed parameters disabled first |
| Valid selection, not pending | Active group re-enabled; existing values preserved |
| Valid selection, pending | Active group cleared to placeholders (or None) and enabled |
Raises: ValueError if any placeholder_map list length differs from its option_map counterpart.
Examples
# Show different parameters depending on the input type selected
dynamic_dropdown(
params[0],
option_map={
"Shapefile": [params[1]],
"Feature Class": [params[2], params[3]],
}
)
# With placeholder values applied on change
dynamic_dropdown(
params[0],
option_map={
"Shapefile": [params[1]],
"Feature Class": [params[2], params[3]],
},
placeholder_map={
"Shapefile": [None],
"Feature Class": ["N/A", 0],
}
)
arcsmith.layer
Helpers for adding layers to a map and applying .lyrx symbology programmatically.
add_w_sym
Adds a data source to a map as a new layer and immediately applies symbology from a .lyrx file.
add_w_sym(lyr_src, lyrx_src, target_map, lyr_name=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
lyr_src |
str or Path |
required | Path to the data source (feature class, raster, etc.) to add. |
lyrx_src |
str or Path |
required | Path to the .lyrx file containing the symbology to apply. |
target_map |
arcpy.mp.Map |
required | Map object to add the layer to. |
lyr_name |
str |
None |
Display name for the layer in the TOC. Defaults to the source name. |
Returns: arcpy.mp.Layer. The newly added layer with symbology applied.
Example
# Add a feature class and apply symbology
lyr = add_w_sym("path/to/fc", "path/to/sym.lyrx", target_map)
# Add with a custom display name
lyr = add_w_sym("path/to/fc", "path/to/sym.lyrx", target_map, lyr_name="Study Area")
apply_lyrx
Applies symbology from a .lyrx file to one or more layers already present in the map TOC, matched by display name or data source path.
apply_lyrx(lyrx_src, target_map, lyr_name=None, lyr_source=None, geom_type=None)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
lyrx_src |
str or Path |
required | Path to the .lyrx file containing the symbology to apply. |
target_map |
arcpy.mp.Map |
required | Map object containing the layer(s) to update. |
lyr_name |
str |
None |
Display name to match; all layers with this name are updated. |
lyr_source |
str or Path |
None |
Data source path to match; only the first exact match is updated. |
geom_type |
'Point' | 'Polyline' | 'Polygon' | 'Multipoint' |
None |
Geometry type filter when matching by lyr_name. Case-insensitive. Ignored when matching by lyr_source. |
Returns: list[arcpy.mp.Layer]. All layers that were updated.
Raises:
ValueErrorif neither or both oflyr_nameandlyr_sourceare provided.ValueErrorif no matching layers are found in the map.
Example
# Update all layers named "rivers"
lyrs = apply_lyrx("path/to/sym.lyrx", target_map, lyr_name="rivers")
# Update only polyline "rivers" layers
lyrs = apply_lyrx("path/to/sym.lyrx", target_map, lyr_name="rivers", geom_type="Polyline")
# Update a single layer by data source path
lyrs = apply_lyrx("path/to/sym.lyrx", target_map, lyr_source="path/to/fc")
arcsmith.fields
Coming soon. This module is planned for a future release.
Utilities for field introspection, management, and mapping. These functions return copies of the input rather than modifying it in place, and accept both layer objects and path strings.
Field introspection
list_fields: Return field names for a layer or table, with optional filters for field type and to exclude system fields likeOIDandShape.unique_values: Return sorted unique values for a given field.field_exists: Check whether a named field exists, useful for defensive scripting before adds or deletes.
Field management
keep_fields: Return a copy with all fields removed except a specified list.drop_fields: Return a copy with a specified list of fields removed. Skips missing names rather than erroring.rename_field: Return a copy with a field renamed. Handled via add/calculate/delete internally since ArcPy has no native rename.
Field mapping
build_field_map: Construct aFieldMappingsobject from a layer, optionally filtered to a subset of fields, as a clean starting point for tools likeMergeorAppend.field_map_rename: Apply a rename dictionary to aFieldMappingsobject, avoiding verboseFieldMapboilerplate.align_fields: Given a source and target, build a field mapping that matches fields by name, useful forAppendwith schema mismatches.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arcsmith-0.0.2.tar.gz.
File metadata
- Download URL: arcsmith-0.0.2.tar.gz
- Upload date:
- Size: 8.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.17.0 {"ci":null,"cpu":"AMD64","implementation":{"name":"CPython","version":"3.14.5"},"installer":{"name":"hatch","version":"1.17.0"},"openssl_version":"OpenSSL 3.0.20 7 Apr 2026","python":"3.14.5","system":{"name":"Windows","release":"11"}} HTTPX2/2.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f3f3727f318c4209bfcea0e1db40d09d33a5ee85061120cd26fef83148c8988
|
|
| MD5 |
0770913b3d1bf54dfbffb12a729d04fe
|
|
| BLAKE2b-256 |
4e1ac09141d55d9c1cde892881b4d3a10e6725a3baa23582c0c4f7414ba55c73
|
File details
Details for the file arcsmith-0.0.2-py3-none-any.whl.
File metadata
- Download URL: arcsmith-0.0.2-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: Hatch/1.17.0 {"ci":null,"cpu":"AMD64","implementation":{"name":"CPython","version":"3.14.5"},"installer":{"name":"hatch","version":"1.17.0"},"openssl_version":"OpenSSL 3.0.20 7 Apr 2026","python":"3.14.5","system":{"name":"Windows","release":"11"}} HTTPX2/2.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2496af5674f5b2f5afabd258c0a360f593907699852eb81a057fcf7f470b470c
|
|
| MD5 |
b9111a3c330927c90f58573a2e74e778
|
|
| BLAKE2b-256 |
7f0fd6185fa7b8a903eb909399cfe24399a0e857db0faee2ec0965a8ecf8ba1e
|