Skip to main content

Overview

The Job module provides classes for representing individual jobs (JobInfo) and collections of jobs (JobsList) with rich display and management capabilities.

JobInfo Class

Represents information about a single job with approval and management capabilities.

Constructor

from syft_job.job import JobInfo
from pathlib import Path

job = JobInfo(
    name="Data Analysis",
    datasite_owner_email="[email protected]",
    status="inbox",
    submitted_by="[email protected]",
    location=Path("/path/to/job"),
    client=client,
    current_user_email="[email protected]",
    submitted_at="2026-03-02T10:30:00+00:00"
)
name
str
required
Name of the job
datasite_owner_email
str
required
Email of the datasite owner where the job resides
status
str
required
Job status: “inbox”, “approved”, or “done”
submitted_by
str
required
Email of the user who submitted the job
location
Path
required
Path to the job directory
client
JobClient
required
JobClient instance for job operations
current_user_email
str
required
Email of the current user
submitted_at
str
ISO format timestamp of when the job was submitted

Methods

approve()

Approve a job by creating an approved marker file.
job.approve()
# Output: ✅ Job 'Data Analysis' approved successfully!
Only the datasite owner can approve jobs in their own folder.
Raises:
  • ValueError - If job is not in inbox status
  • PermissionError - If current user is not the datasite owner

accept_by_depositing_result()

Accept a job by depositing the result file or folder and marking it as done.
result_path = job.accept_by_depositing_result(
    path="/path/to/result.csv"
)

print(result_path)
# Output: /path/to/job/outputs/result.csv
path
str
required
Path to the result file or folder to deposit
return
Path
Path to the deposited result in the outputs directory
Raises:
  • ValueError - If job is not in inbox or approved status
  • FileNotFoundError - If result path doesn’t exist
Example with folder:
# Deposit an entire results folder
result_path = job.accept_by_depositing_result(
    path="/path/to/results_folder"
)
# Result folder copied to: /path/to/job/outputs/results_folder/

rerun()

Rerun a completed job by removing logs, outputs, and done marker.
job.rerun()
# Output: 🔄 Job 'Data Analysis' prepared for rerun! 
#         Removed: logs directory, outputs directory, done marker file
Raises:
  • ValueError - If job is not in done status
After calling rerun(), the job status changes to “approved” and can be executed again.

share_outputs()

Grant read access to the outputs directory for specific users.
job.share_outputs([
    "[email protected]",
    "[email protected]"
])
users
List[str]
required
List of user emails to grant access to

share_logs()

Grant read access to log files (stdout, stderr, returncode) for specific users.
job.share_logs([
    "[email protected]",
    "[email protected]"
])
users
List[str]
required
List of user emails to grant access to

Properties

output_paths

Get list of all file paths in the outputs directory.
if job.status == "done":
    for output in job.output_paths:
        print(f"Output: {output.name}")
return
List[Path]
List of Path objects for all files/directories in outputs folder. Empty list if job is not done or outputs directory doesn’t exist.

files

Get list of all files in the job folder.
for file in job.files:
    print(f"File: {file.name}")
return
List[Path]
List of Path objects for all files and directories in the job folder

stdout

Get a viewer for the stdout content of completed jobs.
# View stdout content
print(job.stdout)

# In Jupyter, displays formatted output
job.stdout
return
StdoutViewer
Viewer object that displays stdout content with rich formatting

stderr

Get a viewer for the stderr content of completed jobs.
# View stderr content
print(job.stderr)

# In Jupyter, displays formatted output
job.stderr
return
StderrViewer
Viewer object that displays stderr content with rich formatting

Display

String Representation

print(job)
# Output: 📥 Data Analysis (inbox) -> [email protected]
Status emojis:
  • 📥 inbox
  • ✅ approved
  • 🎉 done

HTML Representation (Jupyter)

In Jupyter notebooks, jobs display with rich formatting:
job  # Displays formatted table with job details

JobsList Class

A list-like container for JobInfo objects with nice display and indexing.

Constructor

from syft_job.job import JobsList

jobs_list = JobsList(
    jobs=[job1, job2, job3],
    root_email="[email protected]"
)
jobs
List[JobInfo]
required
List of JobInfo objects
root_email
str
required
Email of the root user (for display grouping)

Indexing

By Position

# Get first job
first_job = jobs[0]

# Get last job
last_job = jobs[-1]

By Name

# Get job by name
analysis_job = jobs["Data Analysis"]
Raises:
  • ValueError - If job with name not found
  • TypeError - If index is not int or str

Iteration

# Iterate over all jobs
for job in jobs:
    print(f"{job.name}: {job.status}")

# Filter jobs
inbox_jobs = [job for job in jobs if job.status == "inbox"]

# Count jobs by status
from collections import Counter
status_counts = Counter(job.status for job in jobs)
print(status_counts)
# Output: Counter({'done': 5, 'inbox': 3, 'approved': 1})

Display

String Representation

print(jobs)
Output:
Jobs for [email protected]:
  📥 Data Analysis (inbox) - submitted by: [email protected]
  ✅ Model Training (approved) - submitted by: [email protected]
  🎉 Report Generation (done) - submitted by: [email protected]

Jobs for [email protected]:
  📥 Data Export (inbox) - submitted by: [email protected]

HTML Representation (Jupyter)

jobs  # Displays formatted tables grouped by user
In Jupyter notebooks, displays separate tables for each datasite owner with:
  • Job name
  • Status with emoji
  • Submitter
  • Submission timestamp

Length

num_jobs = len(jobs)
print(f"Total jobs: {num_jobs}")

Complete Example

from syft_job import get_client

# Get client and jobs
client = get_client(
    syftbox_folder_path="~/.syftbox",
    email="[email protected]"
)

jobs = client.jobs

# Work with individual jobs
for job in jobs:
    if job.status == "inbox":
        print(f"New job: {job.name}")
        
        # Approve job
        if job.datasite_owner_email == client.config.email:
            job.approve()
    
    elif job.status == "done":
        # Check outputs
        for output in job.output_paths:
            print(f"Output: {output}")
        
        # View logs
        print(job.stdout)
        
        # Share results
        job.share_outputs(["[email protected]"])
        job.share_logs(["[email protected]"])
        
        # Rerun if needed
        if some_condition:
            job.rerun()

# Access specific job
analysis_job = jobs["Data Analysis"]
analysis_job.approve()

# Deposit results
result_path = analysis_job.accept_by_depositing_result(
    path="./results.csv"
)
print(f"Results deposited at: {result_path}")

Job Workflow

# 1. Job submitted (status: inbox)
job = jobs["New Analysis"]
print(job.status)  # "inbox"

# 2. Approve job (status: approved)
job.approve()
print(job.status)  # "approved"

# 3. Job runs (via JobRunner)
# Runner executes job and sets status to done

# 4. View results (status: done)
for output in job.output_paths:
    print(output)

print(job.stdout)  # View execution logs

# 5. Rerun if needed
job.rerun()  # Status back to "approved"

Build docs developers (and LLMs) love