Name | openjd-sessions JSON |
Version |
0.10.4
JSON |
| download |
home_page | None |
Summary | Provides a library that can be used to build a runtime that is able to run Jobs in a Session as defined by Open Job Description. |
upload_time | 2025-07-22 15:50:32 |
maintainer | None |
docs_url | None |
author | Amazon Web Services |
requires_python | >=3.9 |
license | None |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Open Job Description - Sessions for Python
[](https://pypi.python.org/pypi/openjd-sessions)
[](https://pypi.python.org/pypi/openjd-sessions)
[](https://github.com/OpenJobDescription/openjd-sessions/blob/mainline/LICENSE)
Open Job Description is a flexible open specification for defining render jobs which are portable
between studios and render solutions. This package provides a library that can be used to build
a runtime that is able to run Jobs in a
[Session](https://github.com/OpenJobDescription/openjd-specifications/wiki/How-Jobs-Are-Run#sessions)
as defined by Open Job Description.
For more information about Open Job Description and our goals with it, please see the
Open Job Description [Wiki on GitHub](https://github.com/OpenJobDescription/openjd-specifications/wiki).
## Compatibility
This library requires:
1. Python 3.9 or higher;
2. Linux, MacOS, or Windows operating system;
3. On Linux/MacOS:
* `sudo`
4. On Windows:
* CPython implementation of Python
## Versioning
This package's version follows [Semantic Versioning 2.0](https://semver.org/), 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](./CONTRIBUTING.md) for our contributing guidelines.
## Example Usage
### Running a Session
```python
from openjd.model import (
StepParameterSpaceIterator,
create_job,
decode_job_template,
preprocess_job_parameters
)
from openjd.sessions import (
LOG,
ActionState,
ActionStatus,
Session
)
import logging
import os
from pathlib import Path
import sys
from threading import Event
# Setup
# ========
job_template_path = Path("/absolute/path/to/job")
job_template = decode_job_template(
template={
"name": "DemoJob",
"specificationVersion": "jobtemplate-2023-09",
"parameterDefinitions": [
{ "name": "Foo", "type": "INT" }
],
"jobEnvironments": [
{
"name": "DemoJobEnv",
"script": {
"actions": {
"onEnter": { "command": "python", "args": [ "-c", "print('Entering DemoJobEnv')" ] },
"onExit": { "command": "python", "args": [ "-c", "print('Exiting DemoJobEnv')" ] }
}
}
}
],
"steps": [
{
"name": "DemoStep",
"stepEnvironments": [
{
"name": "DemoStepEnv",
"script": {
"actions": {
"onEnter": { "command": "python", "args": [ "-c", "print('Entering DemoStepEnv')" ] },
"onExit": { "command": "python", "args": [ "-c", "print('Exiting DemoStepEnv')" ] }
}
}
}
],
"parameterSpace": {
"taskParameterDefinitions": [
{ "name": "Bar", "type": "INT", "range": "1-10" }
]
},
"script": {
"actions": {
"onRun": { "command": "python", "args": [ "-c", "print(r'Foo={{Param.Foo}} Bar={{Task.Param.Bar}}')" ] }
}
}
}
]
}
)
job_parameters = preprocess_job_parameters(
job_template=job_template,
job_parameter_values={
"Foo": "12"
},
job_template_dir=job_template_path,
current_working_dir=Path(os.getcwd())
)
job = create_job(
job_template=job_template,
job_parameter_values=job_parameters
)
# stdout/stderr from the Session's running processes are sent to LOG
LOG.addHandler(logging.StreamHandler(stream=sys.stdout))
# Run the Session
# ======
action_event = Event()
last_status: ActionStatus = None
def action_complete_callback(session_id: str, status: ActionStatus) -> None:
# This function will be called by the Session when one of the processes
# that was started has experienced a status change.
# e.g. Completing as FAILED/SUCCEEDED, or an update to a progress message.
global last_status
last_status = status
if status.state != ActionState.RUNNING:
action_event.set()
# Run all tasks in the DemoStep within a Session
with Session(
session_id="demo",
job_parameter_values=job_parameters,
callback=action_complete_callback
) as session:
unwind_session: bool = False
environment_ids = list[str]()
step = job.steps[0]
try:
def run_environment(env):
global status
action_event.clear()
id = session.enter_environment(environment=env)
environment_ids.append(id)
# enter_environment is non-blocking, wait for the process to complete
action_event.wait()
if last_status.state in (ActionState.CANCELED, ActionState.FAILED):
raise RuntimeError("Abnormal exit")
# Enter each job environment
for env in job.jobEnvironments:
run_environment(env)
# Enter each step environment
for env in step.stepEnvironments:
run_environment(env)
# Run each task in the step
for task_parameters in StepParameterSpaceIterator(space=step.parameterSpace):
action_event.clear()
session.run_task(
step_script=step.script,
task_parameter_values=task_parameters
)
# run_task is non-blocking, wait for the process to complete
action_event.wait()
if last_status.state in (ActionState.CANCELED, ActionState.FAILED):
raise RuntimeError("Abnormal exit")
except RuntimeError:
pass
finally:
# Exit all environments in the reverse order that they were entered.
environment_ids.reverse()
for _id in environment_ids:
session.exit_environment(identifier=_id)
action_event.clear()
action_event.wait()
```
### Impersonating a User
This library supports running its Session Actions as a different operating system
user than the user that is running the library. In the following, we refer to the
operating system user that is running this library as the `host` user and the
user that is being impersonated to run actions as the `actions` user.
This feature exists to:
1. Provide a means to securely isolate the environment and files of the `host` user
from the environment in which the Session Actions are run. Configure your filesystem
permissions, and user groups for the `host` and `actions` users such that the `actions`
user cannot read, write, or execute any of the `host` user files that it should not be
able to.
2. Provide a way for you to permit access, on a per-Session basis, to specific local and
shared filesystem assets to the running Actions running in the Session.
#### Impersonating a User: POSIX Systems
To run an impersonated Session on POSIX Systems modify the "Running a Session" example
as follows:
```
...
from openjd.sessions import PosixSessionUser
...
user = PosixSessionUser($USERNAME$, password=$PASSWORD_OF_USERNAME$)
...
with Session(
session_id="demo",
job_parameter_values=job_parameters,
callback=action_complete_callback,
user=user
) as session:
...
```
You must ensure that the `host` user is able to run commands as the `actions` user
with passwordless `sudo` by, for example, adding a rule like follows to your
`sudoers` file or making the equivalent change in your user permissions directory:
```
host ALL=(actions) NOPASSWD: ALL
```
#### Impersonating a User: Windows Systems
To run an impersonated Session on Windows Systems modify the "Running a Session" example
as follows:
```
...
from openjd.sessions import WindowsSessionUser
...
# If you're running in an interactive logon session (e.g. cmd or powershell on your desktop)
user = WindowsSessionUser($USERNAME$, password=$PASSWORD_OF_USERNAME$)
# If you're running in a Windows Service
user = WindowsSessionUser($USERNAME$, logon_token=user_logon_token)
# Where `user_logon_token` is a token that you have created that is compatible
# with the Win32 API: CreateProcessAsUser
...
with Session(
session_id="demo",
job_parameter_values=job_parameters,
callback=action_complete_callback,
user=user
) as session:
...
```
You must ensure that the Python installation hosting this code can be run by any impersonated
user in addition to the `host` user. The library makes impersonated subprocess calls to
perform operations dependent on the impersonated user file system permissions, such as finding
files in search paths.
If running in a Windows Service, then you must ensure that:
1. The `host` user is an Administrator, LocalSystem, or LocalService user as your
security posture requires; and
2. The `host` user has the [Replace a process level token](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/replace-a-process-level-token)
privilege.
## Downloading
You can download this package from:
- [PyPI](https://pypi.org/project/openjd-sessions/)
- [GitHub releases](https://github.com/OpenJobDescription/openjd-sessions-for-python/releases)
### Verifying GitHub Releases
See [Verifying GitHub Releases](https://github.com/OpenJobDescription/openjd-sessions-for-python?tab=security-ov-file#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](http://aws.amazon.com/security/vulnerability-reporting/)
or directly via email to [AWS Security](aws-security@amazon.com). Please do not
create a public GitHub issue in this project.
## License
This project is licensed under the Apache-2.0 License.
Raw data
{
"_id": null,
"home_page": null,
"name": "openjd-sessions",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": null,
"author": "Amazon Web Services",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/a7/02/9972a0eddc7e8e3f40809efd63ebadec238f7581d26129de6713ec0b6285/openjd_sessions-0.10.4.tar.gz",
"platform": null,
"description": "# Open Job Description - Sessions for Python\n\n[](https://pypi.python.org/pypi/openjd-sessions)\n[](https://pypi.python.org/pypi/openjd-sessions)\n[](https://github.com/OpenJobDescription/openjd-sessions/blob/mainline/LICENSE)\n\nOpen Job Description is a flexible open specification for defining render jobs which are portable\nbetween studios and render solutions. This package provides a library that can be used to build\na runtime that is able to run Jobs in a\n[Session](https://github.com/OpenJobDescription/openjd-specifications/wiki/How-Jobs-Are-Run#sessions)\nas defined by Open Job Description.\n\nFor more information about Open Job Description and our goals with it, please see the\nOpen Job Description [Wiki on GitHub](https://github.com/OpenJobDescription/openjd-specifications/wiki).\n\n## Compatibility\n\nThis library requires:\n\n1. Python 3.9 or higher;\n2. Linux, MacOS, or Windows operating system;\n3. On Linux/MacOS:\n * `sudo`\n4. On Windows:\n * CPython implementation of Python\n\n## Versioning\n\nThis package's version follows [Semantic Versioning 2.0](https://semver.org/), but is still considered to be in its\ninitial development, thus backwards incompatible versions are denoted by minor version bumps. To help illustrate how\nversions will increment during this initial development stage, they are described below:\n\n1. The MAJOR version is currently 0, indicating initial development.\n2. The MINOR version is currently incremented when backwards incompatible changes are introduced to the public API.\n3. The PATCH version is currently incremented when bug fixes or backwards compatible changes are introduced to the public API.\n\n## Contributing\n\nWe encourage all contributions to this package. Whether it's a bug report, new feature, correction, or additional\ndocumentation, we greatly value feedback and contributions from our community.\n\nPlease see [CONTRIBUTING.md](./CONTRIBUTING.md) for our contributing guidelines.\n\n## Example Usage\n\n### Running a Session\n\n```python\nfrom openjd.model import (\n StepParameterSpaceIterator,\n create_job,\n decode_job_template,\n preprocess_job_parameters\n)\nfrom openjd.sessions import (\n LOG,\n ActionState,\n ActionStatus,\n Session\n)\nimport logging\nimport os\nfrom pathlib import Path\nimport sys\nfrom threading import Event\n\n# Setup\n# ========\njob_template_path = Path(\"/absolute/path/to/job\")\njob_template = decode_job_template(\n template={\n \"name\": \"DemoJob\",\n \"specificationVersion\": \"jobtemplate-2023-09\",\n \"parameterDefinitions\": [\n { \"name\": \"Foo\", \"type\": \"INT\" }\n ],\n \"jobEnvironments\": [\n {\n \"name\": \"DemoJobEnv\",\n \"script\": {\n \"actions\": {\n \"onEnter\": { \"command\": \"python\", \"args\": [ \"-c\", \"print('Entering DemoJobEnv')\" ] },\n \"onExit\": { \"command\": \"python\", \"args\": [ \"-c\", \"print('Exiting DemoJobEnv')\" ] }\n }\n }\n }\n ],\n \"steps\": [\n {\n \"name\": \"DemoStep\",\n \"stepEnvironments\": [\n {\n \"name\": \"DemoStepEnv\",\n \"script\": {\n \"actions\": {\n \"onEnter\": { \"command\": \"python\", \"args\": [ \"-c\", \"print('Entering DemoStepEnv')\" ] },\n \"onExit\": { \"command\": \"python\", \"args\": [ \"-c\", \"print('Exiting DemoStepEnv')\" ] }\n }\n }\n }\n ],\n \"parameterSpace\": {\n \"taskParameterDefinitions\": [\n { \"name\": \"Bar\", \"type\": \"INT\", \"range\": \"1-10\" }\n ]\n },\n \"script\": {\n \"actions\": {\n \"onRun\": { \"command\": \"python\", \"args\": [ \"-c\", \"print(r'Foo={{Param.Foo}} Bar={{Task.Param.Bar}}')\" ] }\n }\n }\n }\n ]\n }\n)\njob_parameters = preprocess_job_parameters(\n job_template=job_template,\n job_parameter_values={\n \"Foo\": \"12\"\n },\n job_template_dir=job_template_path,\n current_working_dir=Path(os.getcwd())\n)\njob = create_job(\n job_template=job_template,\n job_parameter_values=job_parameters\n)\n\n# stdout/stderr from the Session's running processes are sent to LOG\nLOG.addHandler(logging.StreamHandler(stream=sys.stdout))\n\n# Run the Session\n# ======\naction_event = Event()\nlast_status: ActionStatus = None\n\ndef action_complete_callback(session_id: str, status: ActionStatus) -> None:\n # This function will be called by the Session when one of the processes\n # that was started has experienced a status change.\n # e.g. Completing as FAILED/SUCCEEDED, or an update to a progress message.\n global last_status\n last_status = status\n if status.state != ActionState.RUNNING:\n action_event.set()\n\n# Run all tasks in the DemoStep within a Session\nwith Session(\n session_id=\"demo\",\n job_parameter_values=job_parameters,\n callback=action_complete_callback\n) as session:\n unwind_session: bool = False\n environment_ids = list[str]()\n step = job.steps[0]\n try:\n def run_environment(env):\n global status\n action_event.clear()\n id = session.enter_environment(environment=env)\n environment_ids.append(id)\n # enter_environment is non-blocking, wait for the process to complete\n action_event.wait()\n if last_status.state in (ActionState.CANCELED, ActionState.FAILED):\n raise RuntimeError(\"Abnormal exit\")\n # Enter each job environment\n for env in job.jobEnvironments:\n run_environment(env)\n # Enter each step environment\n for env in step.stepEnvironments:\n run_environment(env)\n # Run each task in the step\n for task_parameters in StepParameterSpaceIterator(space=step.parameterSpace):\n action_event.clear()\n session.run_task(\n step_script=step.script,\n task_parameter_values=task_parameters\n )\n # run_task is non-blocking, wait for the process to complete\n action_event.wait()\n if last_status.state in (ActionState.CANCELED, ActionState.FAILED):\n raise RuntimeError(\"Abnormal exit\")\n except RuntimeError:\n pass\n finally:\n # Exit all environments in the reverse order that they were entered.\n environment_ids.reverse()\n for _id in environment_ids:\n session.exit_environment(identifier=_id)\n action_event.clear()\n action_event.wait()\n```\n\n### Impersonating a User\n\nThis library supports running its Session Actions as a different operating system\nuser than the user that is running the library. In the following, we refer to the\noperating system user that is running this library as the `host` user and the\nuser that is being impersonated to run actions as the `actions` user.\n\nThis feature exists to:\n1. Provide a means to securely isolate the environment and files of the `host` user\n from the environment in which the Session Actions are run. Configure your filesystem\n permissions, and user groups for the `host` and `actions` users such that the `actions`\n user cannot read, write, or execute any of the `host` user files that it should not be\n able to.\n2. Provide a way for you to permit access, on a per-Session basis, to specific local and\n shared filesystem assets to the running Actions running in the Session.\n\n#### Impersonating a User: POSIX Systems\n\nTo run an impersonated Session on POSIX Systems modify the \"Running a Session\" example\nas follows:\n\n```\n...\nfrom openjd.sessions import PosixSessionUser\n...\nuser = PosixSessionUser($USERNAME$, password=$PASSWORD_OF_USERNAME$)\n...\nwith Session(\n session_id=\"demo\",\n job_parameter_values=job_parameters,\n callback=action_complete_callback,\n user=user\n) as session:\n ...\n```\n\nYou must ensure that the `host` user is able to run commands as the `actions` user\nwith passwordless `sudo` by, for example, adding a rule like follows to your\n`sudoers` file or making the equivalent change in your user permissions directory:\n\n```\nhost ALL=(actions) NOPASSWD: ALL\n```\n\n#### Impersonating a User: Windows Systems\n\nTo run an impersonated Session on Windows Systems modify the \"Running a Session\" example\nas follows:\n\n```\n...\nfrom openjd.sessions import WindowsSessionUser\n...\n# If you're running in an interactive logon session (e.g. cmd or powershell on your desktop)\nuser = WindowsSessionUser($USERNAME$, password=$PASSWORD_OF_USERNAME$)\n# If you're running in a Windows Service\nuser = WindowsSessionUser($USERNAME$, logon_token=user_logon_token)\n# Where `user_logon_token` is a token that you have created that is compatible\n# with the Win32 API: CreateProcessAsUser\n...\nwith Session(\n session_id=\"demo\",\n job_parameter_values=job_parameters,\n callback=action_complete_callback,\n user=user\n) as session:\n ...\n```\n\nYou must ensure that the Python installation hosting this code can be run by any impersonated\nuser in addition to the `host` user. The library makes impersonated subprocess calls to\nperform operations dependent on the impersonated user file system permissions, such as finding\nfiles in search paths.\n\nIf running in a Windows Service, then you must ensure that:\n1. The `host` user is an Administrator, LocalSystem, or LocalService user as your\n security posture requires; and\n2. The `host` user has the [Replace a process level token](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/replace-a-process-level-token)\n privilege.\n\n\n## Downloading\n\nYou can download this package from:\n- [PyPI](https://pypi.org/project/openjd-sessions/)\n- [GitHub releases](https://github.com/OpenJobDescription/openjd-sessions-for-python/releases)\n\n### Verifying GitHub Releases\n\nSee [Verifying GitHub Releases](https://github.com/OpenJobDescription/openjd-sessions-for-python?tab=security-ov-file#verifying-github-releases) for more information.\n\n## Security\n\nWe take all security reports seriously. When we receive such reports, we will \ninvestigate and subsequently address any potential vulnerabilities as quickly \nas possible. If you discover a potential security issue in this project, please \nnotify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/)\nor directly via email to [AWS Security](aws-security@amazon.com). Please do not \ncreate a public GitHub issue in this project.\n\n## License\n\nThis project is licensed under the Apache-2.0 License.\n",
"bugtrack_url": null,
"license": null,
"summary": "Provides a library that can be used to build a runtime that is able to run Jobs in a Session as defined by Open Job Description.",
"version": "0.10.4",
"project_urls": {
"Homepage": "https://github.com/OpenJobDescription/openjd-sessions-for-python",
"Source": "https://github.com/OpenJobDescription/openjd-sessions-for-python"
},
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "4a4f091871d5de8c2ee7627dd6c2d74fd25ed4f5354ed98d3030beda24e74641",
"md5": "ffed2b08e47ff5c5a3c48debf78f4fd8",
"sha256": "363f071e4d2a3da3f9c9496ac711365bf26f1264cedf8a49e7b38a9f26e2c666"
},
"downloads": -1,
"filename": "openjd_sessions-0.10.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ffed2b08e47ff5c5a3c48debf78f4fd8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 84468,
"upload_time": "2025-07-22T15:50:30",
"upload_time_iso_8601": "2025-07-22T15:50:30.931691Z",
"url": "https://files.pythonhosted.org/packages/4a/4f/091871d5de8c2ee7627dd6c2d74fd25ed4f5354ed98d3030beda24e74641/openjd_sessions-0.10.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "a7029972a0eddc7e8e3f40809efd63ebadec238f7581d26129de6713ec0b6285",
"md5": "0bb0364ff4b88a324abfedd135637c75",
"sha256": "7ff35f6b4503a16c0f4dde806c309afb69c2a7c2b4b1a2f5be01674762d3149e"
},
"downloads": -1,
"filename": "openjd_sessions-0.10.4.tar.gz",
"has_sig": false,
"md5_digest": "0bb0364ff4b88a324abfedd135637c75",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 71171,
"upload_time": "2025-07-22T15:50:32",
"upload_time_iso_8601": "2025-07-22T15:50:32.310070Z",
"url": "https://files.pythonhosted.org/packages/a7/02/9972a0eddc7e8e3f40809efd63ebadec238f7581d26129de6713ec0b6285/openjd_sessions-0.10.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-22 15:50:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "OpenJobDescription",
"github_project": "openjd-sessions-for-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "openjd-sessions"
}