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))

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.4.tar.gz (261.5 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.4-cp39-abi3-win_arm64.whl (4.4 MB view details)

Uploaded CPython 3.9+Windows ARM64

openjd_model-0.11.4-cp39-abi3-win_amd64.whl (4.7 MB view details)

Uploaded CPython 3.9+Windows x86-64

openjd_model-0.11.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.1 MB view details)

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

openjd_model-0.11.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (5.2 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

openjd_model-0.11.4-cp39-abi3-macosx_11_0_arm64.whl (4.7 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

openjd_model-0.11.4-cp39-abi3-macosx_10_12_x86_64.whl (4.9 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: openjd_model-0.11.4.tar.gz
  • Upload date:
  • Size: 261.5 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.4.tar.gz
Algorithm Hash digest
SHA256 b71773b039c53008ee230368d7e3ed92b6c1c18807806086b242a801aa3660ec
MD5 a68cec455bfb19a2c5ef3a05fb902480
BLAKE2b-256 1023700d8210b5d994c0f0ff4ba8b4b923e2f02a1af617f2a2e08cb7fdc488e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4.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.4-cp39-abi3-win_arm64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 ba54bd54597141d507d680913b43278fde84824c97f263bc929b9dca4c221aa6
MD5 6f7501d173046034b76696d7efd672e9
BLAKE2b-256 db0238f41f916f504f53c169a59ab1de25c49fb173b43115c44eafe708dc862e

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.4-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5fec780235aa53d8c988968f9ad55eb84f68c5139f6b54d684b1a0760bfff9d6
MD5 4b29ac5fb927711c544c402986527b76
BLAKE2b-256 a3fcd986e7df8340260755074867aa7c04468b3b7f28c6779b4cac0ebd0adf2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 40acdd0f227300a8c209e3b336e8a3069f7fe7e73068d46ecaa1ad6ba7551525
MD5 f4d5970ed52a9f610304931a1ec75543
BLAKE2b-256 1cfe9a0d0ba750c7443de66bfbddac44f4d38246bb2880845df3cf883d9a41e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 733caa041f1860f30a68d994e87060ae9ab64027bb9add97c45faf36f41f1a76
MD5 2149c890df0584fc5921282925681fb0
BLAKE2b-256 f1cfea5028a805be57c6f1ebba42292dd27b83fe257b910b1adaa9fcdfc8f4aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.4-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e70aab3ac81c6fa473fecd0a891d44fb948cb8be2fb2751cfc835b5515b91a86
MD5 544f89d49b19295373deb9748c76a92c
BLAKE2b-256 01ac74781a0c2b2e2d42fb0a2d7b5a8c16987879623c28d57abc4ba5451d0e0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.4-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for openjd_model-0.11.4-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2abc2e2344e40841f134769f6c57e3863a18fb0687a92c6f32c50a1e621b5e52
MD5 0a2a48c0608dfc3001877104916d6719
BLAKE2b-256 c71d3aa127390487a9688456e8a9dea3e09e0637fc22bee0b78861e0410679a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for openjd_model-0.11.4-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.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page