Skip to main content

palletjack

Release Events codecov

A library of classes and methods for automatically updating AGOL feature services with data from several different types of external sources. Client apps (sometimes called 'skids') can reuse these classes for common use cases. The code modules are oriented around each step in the extract, transform, and load process.

palletjack works with pandas DataFrames (either regular for tabular data or Esri's spatially-enabled dataframes for spatial data). The extract and transform methods return dataframes and the load methods consume dataframes as their source data.

The documentation includes a user guide along with an API description of the available classes and methods.

Pallet jack: forklift's little brother.

Dependencies

palletjack relies on the dependencies listed in pyproject.toml. These are all available on PyPI and can be installed in most environments, including Google Cloud Functions.

The arcgis library does all the heavy lifting for spatial data. If the arcpy library is not available (such as in a cloud function), it relies on shapely for its geometry engine.

Installation

  1. Activate your application's environment
  2. pip install ugrc-palletjack

Quick start

  1. Import the desired modules

  2. Use a class in extract to load a dataframe from an external source

  3. Transform your dataframe as desired with helper methods from transform

  4. Use the dataframe to update a hosted feature service using the methods in load

    from palletjack import extract, transform, load
    
    #: Load the data from a Google Sheet
    gsheet_extractor = extract.GSheetLoader(path_to_service_account_json)
    sheet_df = gsheet_extractor.load_specific_worksheet_into_dataframe(sheet_id, "title of desired sheet", by_title=True)
    
    #: Convert the data to points using lat/long fields, clean for uploading
    spatial_df = pd.DataFrame.spatial.from_xy(input_df, x_column="longitude", y_column="latitude")
    renamed_df = transform.DataCleaning.rename_dataframe_columns_for_agol(spatial_df)
    cleaned_df = transform.DataCleaning.switch_to_nullable_int(renamed_df, ["an_int_field_with_null_values"])
    
    #: Truncate the existing feature service data and load the new data
    gis = arcgis.gis.GIS("my_agol_org_url", "username", "super-duper-secure-password")
    updater = load.ServiceUpdater(gis, "feature_service_item_id")
    updates = updater.truncate_and_load(cleaned_df)
    
    #: It even works with stand-alone tables!
    table_updater = load.TableUpdater(gis, "table_service_item_id", service_type="table")
    table_updates = table_updater.truncate_and_load(cleaned_df)
    

Development

  1. Create a conda environment with Python 3.13 (use defaults channel if you won't be deploying to an environment with ArcGIS Pro installed)
    • conda create -n palletjack -c defaults python=3.13
    • activate palletjack
  2. Clone the repo
  3. Install in dev mode with development dependencies
    • pip install -e .[tests]

Troubleshooting Weird Append Errors

If a FeatureLayer.append() call (within a load.ServiceUpdater method) fails with an "Unknown Error: 500" error or something like that, you can query the results to get more info. The urllib3 debug-level logs will include the HTTP GET or POST call, something like the following: https://services1.arcgis.com:443 POST /<unique string>/arcgis/rest/services/<feature layer name>/FeatureServer/<layer id>/append/jobs/<job guid>?f=json token=<crazy long token string>. The defualt basicConfig logger includes the urllib3 logs (logging.basicConfig(level=logging.DEBUG)) and is great for development debugging, or you can add a specific logger for urllib3 in your code and set it's level to debug.

You can use this and a token from an AGOL tab to build a new job status url. To get the token, log into AGOL in a browser and open a private hosted feature layer item. Click the layer, and then open the developer console. With the Network tab of the console open, click on the "View" link for the service URL. You should see a document in the list whose name includes "?token=". Copy the name and then copy out the token string.

Now that you've got the token string, you can build the status query: https://services1.arcgis.com/<unique string>/arcgis/rest/services/<feature layer name>/FeatureServer/<layer id>/append/jobs/<job guid>?f=json&<token from agol>

Calling this URL in a browser should return a message that will hopefully give you more info as to why it failed.

Updating Docs

palletjack uses pdoc3 to generate HTML docs in docs/palletjack from the docstrings within the code itself. These are then served up via github pages.

The github pages are served from the gh-pages branch. After you make edits to the code and update the docstrings, rebase this branch onto the updated main branch. To prevent github pages from trying to generate a site from the contents of docs/palletjack with jekyll, add a .nojekyll file to docs/palletjack.

To generate the docs, run pdoc --html -o docs\ c:\palletjack\repo\src\palletjack --force. The code's docstrings should be Google-style docstrings with proper indentation to ensure the argument lists, etc are parsed and displayed correctly.

docs/README.md is included at the top package level by adding the line .. include:: ../../docs/README.md in __init__.py's docstring. This tells pdoc to insert that markdown into the HTML generated for that docstring, and the include directive can be used for more in-depth documentation anywhere else as well. Note that pdoc tries to create links for anything surrounded by backticks, which are also used for code blocks. You may need to manually edit the HTML to remove the links if they change the content of your code blocks (such as in the example import statement).

Once the contents of docs/palletjack look correct, force push the gh-pages branch to github. This will trigger the action to republish the site. The docs are then accessible at [agrc.github.io/palletjack/palletjack/index.html].

Attribution

This project was developed with the assistance of GitHub Copilot.

Metadata

Release files for ugrc-palletjack 6.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ugrc-palletjack 6.0.5
File Size Uploaded
ugrc_palletjack-6.0.5.tar.gz 87.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ugrc-palletjack 6.0.5
File Interpreter ABI Platform
ugrc_palletjack-6.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 135.7 kB

Release files / ugrc_palletjack-6.0.5.tar.gz

Download URL ugrc_palletjack-6.0.5.tar.gz
Size 87.7 kB
Tags Source
SHA-256 checksum
How to use checksums
72e6fd8a014095f5cce2b7c26e9652e6a8b1ea1fa9ef94432fa0a075fa2571ac
BLAKE2b-256 checksum
How to use checksums
c88ba8411363e9cefa0963a611d3daa748b40f79cbb0f7f63f610b965897fa1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.

Transparency log

Release files / ugrc_palletjack-6.0.5-py3-none-any.whl

Download URL ugrc_palletjack-6.0.5-py3-none-any.whl
Size 48.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
745aa84558cc0de0b1b3242e91d2e7015c5fab0729af52c81ba3d523c27f6dde
BLAKE2b-256 checksum
How to use checksums
5ab737c02006127090e4078a065a08192466b60ed030b1722653db3cab873375
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

6.0.5 This release

2 release files

6.0.4

2 release files

6.0.3

2 release files

6.0.2

2 release files

6.0.1

2 release files

6.0.0

2 release files

5.2.12

2 release files

5.2.9

2 release files

5.2.8

2 release files

5.2.7

2 release files

5.2.6

2 release files

5.2.5

2 release files

5.2.4

2 release files

5.2.3

2 release files

5.2.2

2 release files

5.2.1

2 release files

5.2.0

2 release files

5.1.2

2 release files

5.1.1

2 release files

5.1.0

2 release files

5.0.2

2 release files

5.0.1

2 release files

5.0.0

2 release files

4.4.2

2 release files

4.4.1

2 release files

4.4.0

2 release files

4.3.1

2 release files

4.3.0

2 release files

4.2.0

2 release files

4.1.0

2 release files

4.0.1

2 release files

4.0.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.7.3

2 release files

2.7.2

2 release files

2.7.1

2 release files

2.7.0

2 release files

2.6.2

2 release files

2.5.1

2 release files

2.4.1

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page