openjd-model · PyPI Skip to main content

Open Job Description - Models For Python

pypi python license

Open Job Description is a flexible open specification for defining render jobs which are portable between studios and render management solutions. This package provides a Python implementation of the data model for Open Job Description's template schemas. It can parse, validate, create JSON/Yaml documents for the Open Job Description specification, and more. A main use-case that this library targets is interoperability by creating applications to translate a Job from Open Job Description to the render management software of your choice.

For more information about Open Job Description and our goals with it, please see the Open Job Description Wiki on GitHub.

Compatibility

This library requires:

  1. Python 3.9 or higher; and
  2. Linux, MacOS, or Windows operating system.

Versioning

This package's version follows Semantic Versioning 2.0, but is still considered to be in its initial development, thus backwards incompatible versions are denoted by minor version bumps. To help illustrate how versions will increment during this initial development stage, they are described below:

  1. The MAJOR version is currently 0, indicating initial development.
  2. The MINOR version is currently incremented when backwards incompatible changes are introduced to the public API.
  3. The PATCH version is currently incremented when bug fixes or backwards compatible changes are introduced to the public API.

Contributing

We encourage all contributions to this package. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from our community.

Please see CONTRIBUTING.md for our contributing guidelines.

Example Usage

Reading and Validating a Job Template

To validate a job template, you can read the JSON or YAML input into Python data structures and then pass the result to decode_job_template. By default, this will accept templates of any supported version number with no extensions enabled. Use decode_environment_template for environment templates.

To accept extensions in templates, provide the list of the names you support. See the Open Job Description 2023-09 specification for the list of extensions available.

from openjd.model import DocumentType, decode_job_template, document_string_to_object

# String containing the json of the job template
template_string = """specificationVersion: jobtemplate-2023-09
name: DemoJob
steps:
  - name: DemoStep
    script:
      actions:
        onRun:
          command: python
          args: ["-c", "print('Hello')"]
"""

# You can use 'json.loads' or 'yaml.safe_load' directly as well
template_object = document_string_to_object(
    document=template_string,
    document_type=DocumentType.YAML
)

# Raises a DecodeValidationError if it fails.
job_template = decode_job_template(template=template_object, supported_extensions=["TASK_CHUNKING"])

Once you have the Open Job Description model object, you can use the model_to_object function to convert it into an object suitable for converting to JSON or YAML.

import json
from openjd.model import model_to_object

obj = model_to_object(model=job_template)
print(json.dumps(obj, indent=2))

Creating Template Model Objects

As an alternative to assembling full job templates as raw data following the specification data model, you can use the library to construct model objects of components, such as for StepTemplates, and then assemble the result into a job template. The parse_model function provides a way to do this.

To call parse_model, you will need to provide the list of extensions you want to enable as the supported_extensions argument. Individual model objects can accept inputs differently depending on what extensions are requested in the job template, and the model parsing context holds that list. The functions decode_job_template and decode_environment_template create this context from top-level template fields, but when using parse_model to process interior model types you must provide it explicitly.

import json
from openjd.model import parse_model, model_to_object
from openjd.model.v2023_09 import StepTemplate

extensions_list = ["TASK_CHUNKING"]

step_template = parse_model(
    model=StepTemplate,
    obj={
        "name": "DemoStep",
        "script": {
            "actions": {"onRun": {"command": "python", "args": ["-c", "print('Hello world!')"]}}
        },
    },
    supported_extensions=extensions_list,
)

obj = model_to_object(model=step_template)
print(json.dumps(obj, indent=2))

You can also construct the individual elements of the template from the model object types. This can be more effort than using parse_model depending on how the enabled extensions affect processing. You will need to create a ModelParsingContext object to hold the extensions list, and pass it to any model object constructors that need it.

import json
from openjd.model import model_to_object
from openjd.model.v2023_09 import (
    StepTemplate,
    StepScript,
    StepActions,
    Action,
    ArgString,
    CommandString,
    ModelParsingContext,
)

context = ModelParsingContext(supported_extensions=["TASK_CHUNKING"])

step_template = StepTemplate(
    name="DemoStep",
    script=StepScript(
        actions=StepActions(
            onRun=Action(
                command=CommandString("python", context=context),
                args=[
                    ArgString("-c", context=context),
                    ArgString("print('Hello world!')", context=context),
                ],
            )
        )
    ),
)

obj = model_to_object(model=step_template)
print(json.dumps(obj, indent=2))

Creating a Job from a Job Template

import os
from pathlib import Path
from openjd.model import (
    DecodeValidationError,
    create_job,
    decode_job_template,
    preprocess_job_parameters
)

job_template_path = Path("/absolute/path/to/job/template.json")
job_template = decode_job_template(
    template={
        "name": "DemoJob",
        "specificationVersion": "jobtemplate-2023-09",
        "parameterDefinitions": [
            { "name": "Foo", "type": "INT" }
        ],
        "steps": [
            {
                "name": "DemoStep",
                "script": {
                    "actions": {
                        "onRun": { "command": "python", "args": [ "-c", "print(r'Foo={{Param.Foo}}')" ] }
                    }
                }
            }
        ]
    }
)
try:
    parameters = preprocess_job_parameters(
        job_template=job_template,
        job_parameter_values={
            "Foo": "12"
        },
        job_template_dir=job_template_path.parent,
        current_working_dir=Path(os.getcwd())
    )
    job = create_job(
        job_template=job_template,
        job_parameter_values=parameters
    )
except (DecodeValidationError, RuntimeError) as e:
    print(str(e))

If any of the job's steps declares a template-scope let that the step's script references, then this Job is not sufficient to run the step: step-level let bindings are evaluated once during instantiation and kept in the step's symbol table rather than lowered onto the script, so a session created from the Job alone has no binding for the name and the action fails with Undefined variable. Use create_job_with_symbol_tables instead and forward the step's entry from the returned step_symbol_tables to the session that runs it. The two examples below only inspect the Job at creation time, so plain create_job is correct there.

Working with Step dependencies

from openjd.model import (
    StepDependencyGraph,
    create_job,
    decode_job_template
)

job_template = decode_job_template(
    template={
        "name": "DemoJob",
        "specificationVersion": "jobtemplate-2023-09",
        "steps": [
            {
                "name": "Step1",
                "script": {
                    "actions": {
                        "onRun": { "command": "python", "args": [ "-c", "print('Step1')" ] }
                    }
                }
            },
            {
                "name": "Step2",
                "dependencies": [ { "dependsOn": "Step1" }, { "dependsOn": "Step3" }],
                "script": {
                    "actions": {
                        "onRun": { "command": "python", "args": [ "-c", "print('Step2')" ] }
                    }
                }
            },
            {
                "name": "Step3",
                "script": {
                    "actions": {
                        "onRun": { "command": "echo", "args": [ "Step3" ] }
                    }
                }
            },
        ]
    }
)
job = create_job(job_template=job_template, job_parameter_values={})
dependency_graph = StepDependencyGraph(job=job)

for step in job.steps:
    step_node = dependency_graph.step_node(stepname=step.name)
    if step_node.in_edges:
        name_list = ', '.join(edge.origin.step.name for edge in step_node.in_edges)
        print(f"Step '{step.name}' depends upon: {name_list}")
    if step_node.out_edges:
        name_list = ', '.join(edge.dependent.step.name for edge in step_node.out_edges)
        print(f"The following Steps depend upon '{step.name}': {name_list}")

print(f"\nSteps in topological order: {[step.name for step in dependency_graph.topo_sorted()]}")
# The following Steps depend upon 'Step1': Step2
# Step 'Step2' depends upon: Step1, Step3
# The following Steps depend upon 'Step3': Step2

# Steps in topological order: ['Step1', 'Step3', 'Step2']

Working with a Step's Tasks

from openjd.model import (
    StepParameterSpaceIterator,
    create_job,
    decode_job_template
)

job_template = decode_job_template(
    template={
        "name": "DemoJob",
        "specificationVersion": "jobtemplate-2023-09",
        "steps": [
            {
                "name": "DemoStep",
                "parameterSpace": {
                    "taskParameterDefinitions": [
                        { "name": "Foo", "type": "INT", "range": "1-5" },
                        { "name": "Bar", "type": "INT", "range": "1-5" }
                    ],
                    "combination": "(Foo, Bar)"
                },
                "script": {
                    "actions": {
                        "onRun": {
                            "command": "python",
                            "args": [ "-c", "print(f'Foo={{Task.Param.Foo}}, Bar={{Task.Param.Bar}}"]
                        }
                    }
                }
            },
        ]
    }
)
job = create_job(job_template=job_template, job_parameter_values={})
for step in job.steps:
    iterator = StepParameterSpaceIterator(space=step.parameterSpace)
    print(f"Step '{step.name}' has {len(iterator)} Tasks")
    for param_set in iterator:
        print(param_set)
# Step 'DemoStep' has 5 Tasks
# {'Foo': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='1'), 'Bar': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='1')}
# {'Foo': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='2'), 'Bar': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='2')}
# {'Foo': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='3'), 'Bar': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='3')}
# {'Foo': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='4'), 'Bar': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='4')}
# {'Foo': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='5'), 'Bar': ParameterValue(type=<ParameterValueType.INT: 'INT'>, value='5')}

Downloading

You can download this package from:

Verifying GitHub Releases

See Verifying GitHub Releases for more information.

Security

We take all security reports seriously. When we receive such reports, we will investigate and subsequently address any potential vulnerabilities as quickly as possible. If you discover a potential security issue in this project, please notify AWS/Amazon Security via our vulnerability reporting page or directly via email to AWS Security. Please do not create a public GitHub issue in this project.

License

This project is licensed under the Apache-2.0 License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openjd_model-0.11.10.tar.gz (267.4 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

openjd_model-0.11.10-cp39-abi3-win_arm64.whl (4.5 MB view details)

Uploaded CPython 3.9+Windows ARM64

openjd_model-0.11.10-cp39-abi3-win_amd64.whl (4.8 MB view details)

Uploaded CPython 3.9+Windows x86-64

openjd_model-0.11.10-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

openjd_model-0.11.10-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (5.3 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

openjd_model-0.11.10-cp39-abi3-macosx_11_0_arm64.whl (4.8 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

openjd_model-0.11.10-cp39-abi3-macosx_10_12_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file openjd_model-0.11.10.tar.gz.

File metadata

  • Download URL: openjd_model-0.11.10.tar.gz
  • Upload date:
  • Size: 267.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openjd_model-0.11.10.tar.gz
Algorithm Hash digest
SHA256 735749f825def6001334e2ec40317572450815b116a8188c5aceee4c51a2a4c4
MD5 aab3428948d6e2c8bb1f37ea6fac528d
BLAKE2b-256 2b2d19116e94ab2a75e67d7408ab7e4021cc391e0ed4313786e9cd2190d131d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10.tar.gz:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-win_arm64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 3fb9d07133704dab88917f0ca32d6ee994d46c0e12ac22416c5ed6e7c84a034c
MD5 14cc66423629c4a60d5481c87c925f19
BLAKE2b-256 04730012b523be98eba7f49697ac063d0962a53c1cebd402c53cf537b37a0194

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-win_arm64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 7edd42d0c74c5b5c6dd829856a3a3c00dc359c07c7f575f7a06040f14de5f423
MD5 ca9d857ebbac0aaf9143bbdabcb63a1f
BLAKE2b-256 5f3682b61e03a4f1f471177280527b2ef67ca9d605f8e9be4888cee221a5d3ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-win_amd64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 873d8873640f5af50f1f25e889b63429c8b3a20d9a2550c6ba42e4cfcf56eceb
MD5 586213cca5d463d63e5afd2feeb20265
BLAKE2b-256 93795bf995c56834ed7b43445a87fca91244357d691d43ccfc83e1a65b40e64c

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 af9990d8a8dd041cc02cd1f1340f6867408b21c65361f8862b9f499562e9b434
MD5 91f1a9b7409c01615f44dfd984d6258d
BLAKE2b-256 4861d145294dc2c06b6b693e7724c9f817ad4013f0cae0cf7995b2a821d979d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dfa67b85bde74b49dc0a1113784f6ea4c5f494a2cc77cdb36b99a15446075d97
MD5 b663f165de8425ea70ee5691394621e0
BLAKE2b-256 893d9c0d9750273802d1713292560faf9d776d6c2842dfb4b024507d8b67749e

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openjd_model-0.11.10-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.10-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 5b49ee38d735afb1b698d17963377494ded8dba8948f20ba766568685205ed47
MD5 9f26e231be06187337cd84f1eaa2e2d8
BLAKE2b-256 55ca80b20fbdfabd048695f3cf02ce98b12cd83a12bf229d3ef8fa16d3aa4bb9

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.10-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release_publish.yml on OpenJobDescription/openjd-model-for-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.11.10 This release

7 files

0.11.9

7 files

0.11.8

7 files

0.11.6

7 files

0.11.5

7 files

0.11.4

7 files

0.11.3

7 files

0.11.2

7 files

0.11.1

7 files

0.11.0

7 files

0.10.1

6 files

0.10.0

6 files

0.9.0

2 files

0.8.7

2 files

0.8.6

2 files

0.8.5

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.0.0

2 files

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