Skill Tracer
Skills › Scientific Agent Skills › latchbio-integration › data-management.md

data-management.md

265 lines · skills/latchbio-integration/references/data-management.md at 5f2bc03

Open on GitHub
1# Latch Data and Remote Paths
2
3This reference distinguishes the two supported Python data models:
4
5- `LPath` is the modern, `pathlib`-like API for explicit remote operations.
6- `LatchFile` and `LatchDir` are the established workflow parameter types for
7 automatic task staging and output upload.
8
9Do not assume methods from one model exist on the other. In particular,
10`LatchDir.glob()` is not a current SDK API.

Latch Data and Remote Paths

This reference distinguishes the two supported Python data models:

  • LPath is the modern, pathlib-like API for explicit remote operations.
  • LatchFile and LatchDir are the established workflow parameter types for automatic task staging and output upload.

Do not assume methods from one model exist on the other. In particular, LatchDir.glob() is not a current SDK API.

Raw lines 1 to 11
12## Choosing an API
14Use `LPath` when you need to:
16- Inspect, upload, download, copy, list, or delete a remote path explicitly
17- Work from scripts, Pods, Plots, or task code
18- Avoid automatic transfer of an entire directory
19- Store an `LPath` value in Registry with SDK 2.67.22+
21Use `LatchFile` or `LatchDir` when you need to:
23- Expose a file or directory in a workflow form
24- Automatically stage an input onto a task machine
25- Automatically upload a returned task output
26- Compose with older workflows or `latch.verified` wrappers
28It is normal to accept a `LatchFile` in a workflow and construct an `LPath`
29from its `remote_path` for a targeted remote operation.

Choosing an API

Use LPath when you need to:

  • Inspect, upload, download, copy, list, or delete a remote path explicitly
  • Work from scripts, Pods, Plots, or task code
  • Avoid automatic transfer of an entire directory
  • Store an LPath value in Registry with SDK 2.67.22+

Use LatchFile or LatchDir when you need to:

  • Expose a file or directory in a workflow form
  • Automatically stage an input onto a task machine
  • Automatically upload a returned task output
  • Compose with older workflows or latch.verified wrappers

It is normal to accept a LatchFile in a workflow and construct an LPath from its remote_path for a targeted remote operation.

Raw lines 12 to 30
31## Latch URLs
33Common forms include:
35```text
36latch:///path/in/current-workspace
37latch://12345.account/path/in/workspace
38latch://shared/path/to/shared-data
39latch://67890.node
40```
42- `latch:///...` resolves relative to the active or execution workspace.
43- Account-qualified URLs avoid ambiguity across workspaces.
44- Node URLs address a Latch Data object by immutable numeric ID.
45- Shared URLs refer to data shared across accounts.
47Do not concatenate URLs with filesystem utilities that discard the URL scheme.
48`LPath` supports `/` for child paths.

Latch URLs

Common forms include:

latch:///path/in/current-workspace
latch://12345.account/path/in/workspace
latch://shared/path/to/shared-data
latch://67890.node
  • latch:///... resolves relative to the active or execution workspace.
  • Account-qualified URLs avoid ambiguity across workspaces.
  • Node URLs address a Latch Data object by immutable numeric ID.
  • Shared URLs refer to data shared across accounts.

Do not concatenate URLs with filesystem utilities that discard the URL scheme. LPath supports / for child paths.

Raw lines 31 to 49
50## `LPath`
52Import it from its actual module:
54```python
55from latch.ldata.path import LPath
56```

LPath

Import it from its actual module:

from latch.ldata.path import LPath
Raw lines 50 to 57
58### Metadata and listing
60```python
61from latch.ldata.path import LPath
63root = LPath("latch:///welcome")
65if root.exists():
66 print(root.node_id())
67 print(root.name())
68 print(root.is_dir())
69 # size_recursive() can be slow for large directory trees.
71 for child in root.iterdir():
72 print(child.path, child.content_type(), child.size(), child.modify_time())
73```
75`iterdir()` is shallow. It returns an iterator of child `LPath` objects and
76does not recursively traverse nested directories.
78`modify_time()` (added in 2.76.9) returns a `datetime` or `None`; it is not a
79content checksum. `size_recursive()` can be expensive on large directories.
80Use ordinary file sizes unless recursive totals are needed.
82Metadata is cached for the lifetime of the object after a lookup. Call
83`fetch_metadata()` after an external rename or modification when fresh values
84are required.

Metadata and listing

from latch.ldata.path import LPath

root = LPath("latch:///welcome")

if root.exists():
    print(root.node_id())
    print(root.name())
    print(root.is_dir())
    # size_recursive() can be slow for large directory trees.

    for child in root.iterdir():
        print(child.path, child.content_type(), child.size(), child.modify_time())

iterdir() is shallow. It returns an iterator of child LPath objects and does not recursively traverse nested directories.

modify_time() (added in 2.76.9) returns a datetime or None; it is not a content checksum. size_recursive() can be expensive on large directories. Use ordinary file sizes unless recursive totals are needed.

Metadata is cached for the lifetime of the object after a lookup. Call fetch_metadata() after an external rename or modification when fresh values are required.

Raw lines 58 to 85
86### Download
88Always provide an explicit destination for durable files:
90```python
91from pathlib import Path
93from latch.ldata.path import LPath
95remote = LPath("latch:///inputs/design.csv")
96local = remote.download(Path("work/design.csv"), cache=True)
97print(local.read_text(encoding="utf-8"))
98```
100Without a destination, the SDK downloads beneath `~/.latch/lpath/` and
101registers the temporary directory for cleanup when the process exits. Do not
102rely on that path after process termination.
104With `cache=True`, the SDK uses the remote version identifier and local extended
105attributes where supported. Explicit paths plus caching are especially
106important in long-lived Pods and Plots. SDK 2.77.1 removed the `pyxattr`
107dependency: on macOS it invokes the system `xattr` command; on Linux it uses
108`os.*xattr`. Use a filesystem supporting extended attributes. Setting
109`cache=False` does not disable the post-download attribute write in this release,
110so it is not a workaround for an unsupported filesystem.

Download

Always provide an explicit destination for durable files:

from pathlib import Path

from latch.ldata.path import LPath

remote = LPath("latch:///inputs/design.csv")
local = remote.download(Path("work/design.csv"), cache=True)
print(local.read_text(encoding="utf-8"))

Without a destination, the SDK downloads beneath ~/.latch/lpath/ and registers the temporary directory for cleanup when the process exits. Do not rely on that path after process termination.

With cache=True, the SDK uses the remote version identifier and local extended attributes where supported. Explicit paths plus caching are especially important in long-lived Pods and Plots. SDK 2.77.1 removed the pyxattr dependency: on macOS it invokes the system xattr command; on Linux it uses os.*xattr. Use a filesystem supporting extended attributes. Setting cache=False does not disable the post-download attribute write in this release, so it is not a workaround for an unsupported filesystem.

Raw lines 86 to 111
112### Upload
114The destination's parent must exist:
116```python
117from pathlib import Path
119from latch.ldata.path import LPath
121destination_dir = LPath("latch:///results/run-001")
122destination_dir.mkdirp()
124report = destination_dir / "report.txt"
125report.upload_from(Path("report.txt"))
126```
128`upload_from` accepts either a local file or directory. Avoid concurrent writes
129to the same destination.

Upload

The destination's parent must exist:

from pathlib import Path

from latch.ldata.path import LPath

destination_dir = LPath("latch:///results/run-001")
destination_dir.mkdirp()

report = destination_dir / "report.txt"
report.upload_from(Path("report.txt"))

upload_from accepts either a local file or directory. Avoid concurrent writes to the same destination.

Raw lines 112 to 130
131### Remote copy and delete
133```python
134from latch.ldata.path import LPath
136source = LPath("latch:///results/run-001/report.txt")
137backup = LPath("latch:///archive/run-001/report.txt")
138source.copy_to(backup)
139```
141Deletion is recursive and destructive:
143```python
144target = LPath("latch:///scratch/run-001")
145target.rmr()
146```
148Before `rmr()`:
1501. Print or otherwise surface the exact resolved path.
1512. Confirm it is not a workspace root, shared production folder, or active
152 workflow output.
1533. Obtain user confirmation unless deletion was already explicit.

Remote copy and delete

from latch.ldata.path import LPath

source = LPath("latch:///results/run-001/report.txt")
backup = LPath("latch:///archive/run-001/report.txt")
source.copy_to(backup)

Deletion is recursive and destructive:

target = LPath("latch:///scratch/run-001")
target.rmr()

Before rmr():

  1. Print or otherwise surface the exact resolved path.
  2. Confirm it is not a workspace root, shared production folder, or active workflow output.
  3. Obtain user confirmation unless deletion was already explicit.
Raw lines 131 to 154
155## `LatchFile` and `LatchDir`
157These types carry both a local execution path and an optional remote path:
159```python
160from pathlib import Path
162from latch import small_task
163from latch.types import LatchFile
166@small_task
167def summarize(input_file: LatchFile) -> LatchFile:
168 source = Path(input_file.local_path)
169 output = Path("/root/summary.txt")
170 output.write_text(
171 f"name={source.name}\nbytes={source.stat().st_size}\n",
172 encoding="utf-8",
173 )
174 return LatchFile(str(output), "latch:///results/summary.txt")
175```
177For a passed input:
179- `local_path` is the staged path on the task machine.
180- `remote_path` identifies its source in Latch Data or S3.
182For a returned value:
184- The first constructor argument is the local file or directory.
185- The second argument is the remote destination.
187Use `LatchOutputFile` and `LatchOutputDir` in workflow signatures for
188destinations that may not exist yet:
190```python
191from latch.types import LatchOutputDir, LatchOutputFile
192```

LatchFile and LatchDir

These types carry both a local execution path and an optional remote path:

from pathlib import Path

from latch import small_task
from latch.types import LatchFile


@small_task
def summarize(input_file: LatchFile) -> LatchFile:
    source = Path(input_file.local_path)
    output = Path("/root/summary.txt")
    output.write_text(
        f"name={source.name}\nbytes={source.stat().st_size}\n",
        encoding="utf-8",
    )
    return LatchFile(str(output), "latch:///results/summary.txt")

For a passed input:

  • local_path is the staged path on the task machine.
  • remote_path identifies its source in Latch Data or S3.

For a returned value:

  • The first constructor argument is the local file or directory.
  • The second argument is the remote destination.

Use LatchOutputFile and LatchOutputDir in workflow signatures for destinations that may not exist yet:

from latch.types import LatchOutputDir, LatchOutputFile
Raw lines 155 to 193
194### Directory behavior
196Returning a local `LatchDir` to an existing remote directory adds or updates
197the returned children. It does not imply deletion of unrelated remote files.
198Do not depend on this merge behavior as a synchronization or cleanup strategy.
200`LatchDir.iterdir()` lists children of a remote directory. For globbing local
201task outputs into remote `LatchFile` values, use `file_glob`:
203```python
204from latch import small_task
205from latch.types import LatchFile, file_glob
208@small_task
209def collect_fastq_outputs() -> list[LatchFile]:
210 # Run the scientific tool here; it must create outputs/*.fastq.gz.
211 return file_glob("outputs/*.fastq.gz", "latch:///results/fastq/")
212```

Directory behavior

Returning a local LatchDir to an existing remote directory adds or updates the returned children. It does not imply deletion of unrelated remote files. Do not depend on this merge behavior as a synchronization or cleanup strategy.

LatchDir.iterdir() lists children of a remote directory. For globbing local task outputs into remote LatchFile values, use file_glob:

from latch import small_task
from latch.types import LatchFile, file_glob


@small_task
def collect_fastq_outputs() -> list[LatchFile]:
    # Run the scientific tool here; it must create outputs/*.fastq.gz.
    return file_glob("outputs/*.fastq.gz", "latch:///results/fastq/")
Raw lines 194 to 213
214## Data CLI
216Inspect help for the installed version before scripting a command:
218```bash
219latch --version
220latch cp --help
221latch sync --help
222```
224Common operations:
226```bash
227# List
228latch ls latch:///inputs
230# Upload or download
231latch cp ./sample.fastq.gz latch:///inputs/sample.fastq.gz
232latch cp latch:///results/report.html ./report.html
234# Create parents
235latch mkdirp latch:///results/run-001
237# Synchronize a local tree to a remote directory
238latch sync ./results latch:///results/run-001
240# Recursive removal — confirm the target first
241latch rmr latch:///scratch/run-001
242```
244Prefer `mkdirp` and `rmr`; the older `mkdir`, `rm`, `touch`, and `open` commands
245were deprecated.

Data CLI

Inspect help for the installed version before scripting a command:

latch --version
latch cp --help
latch sync --help

Common operations:

# List
latch ls latch:///inputs

# Upload or download
latch cp ./sample.fastq.gz latch:///inputs/sample.fastq.gz
latch cp latch:///results/report.html ./report.html

# Create parents
latch mkdirp latch:///results/run-001

# Synchronize a local tree to a remote directory
latch sync ./results latch:///results/run-001

# Recursive removal — confirm the target first
latch rmr latch:///scratch/run-001

Prefer mkdirp and rmr; the older mkdir, rm, touch, and open commands were deprecated.

Raw lines 214 to 246
247## Reliability and Security
249- Never print signed download URLs or authentication headers.
250- Avoid loading a whole remote directory when only one file is needed.
251- Use unique run destinations to prevent concurrent output collisions.
252- Validate local checksums or scientific file integrity when correctness
253 depends on complete transfer.
254- Treat mounted cloud paths according to the source bucket's access policy.
255- Keep workspace IDs explicit in automation that can access several workspaces.
256- Do not call data mutations at module import time.

Reliability and Security

  • Never print signed download URLs or authentication headers.
  • Avoid loading a whole remote directory when only one file is needed.
  • Use unique run destinations to prevent concurrent output collisions.
  • Validate local checksums or scientific file integrity when correctness depends on complete transfer.
  • Treat mounted cloud paths according to the source bucket's access policy.
  • Keep workspace IDs explicit in automation that can access several workspaces.
  • Do not call data mutations at module import time.
Raw lines 247 to 257
258## Official Sources
260- Remote files (`LPath`): https://wiki.latch.bio/workflows/sdk/api/working-with-files
261- Legacy file support: https://wiki.latch.bio/workflows/sdk/python/legacy-file-support
262- Latch URLs: https://wiki.latch.bio/workflows/sdk/python/latch-urls
263- Data CLI: https://wiki.latch.bio/data/data-command-line
264- Data overview: https://wiki.latch.bio/data/overview
265- `LPath` source in the 2.77.1 release commit: https://github.com/latchbio/latch/blob/b3768e65c6d496868f6e530f11977d857ad85dc7/src/latch/ldata/path.py

Official Sources

  • Remote files (LPath): https://wiki.latch.bio/workflows/sdk/api/working-with-files
  • Legacy file support: https://wiki.latch.bio/workflows/sdk/python/legacy-file-support
  • Latch URLs: https://wiki.latch.bio/workflows/sdk/python/latch-urls
  • Data CLI: https://wiki.latch.bio/data/data-command-line
  • Data overview: https://wiki.latch.bio/data/overview
  • LPath source in the 2.77.1 release commit: https://github.com/latchbio/latch/blob/b3768e65c6d496868f6e530f11977d857ad85dc7/src/latch/ldata/path.py
Raw lines 258 to 265