mirror of
https://github.com/iluvcapra/pycmx.git
synced 2025-12-31 17:00:53 +00:00
Compare commits
23 Commits
19-unusual
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 688402d195 | |||
| 4e81810584 | |||
| faf2596a57 | |||
| 1e9fbe339c | |||
| a8d00470d4 | |||
| fe1e59e731 | |||
| ec8a08074d | |||
|
|
ef683a7683 | ||
|
|
d778f64230 | ||
| 1b0ccd4ef7 | |||
| 498d5c8fea | |||
| af5d937aeb | |||
| 637f4ab9a4 | |||
| 4cd635ff17 | |||
| 26e1e38320 | |||
| 0e97742336 | |||
| 67ea12042f | |||
| 6b910a0920 | |||
| a8f35a9ffc | |||
|
|
242f2e08d5 | ||
| 610d406e97 | |||
| 28307608fc | |||
| 9ab3804c89 |
5
.flake8
5
.flake8
@@ -1,5 +0,0 @@
|
|||||||
[flake8]
|
|
||||||
per-file-ignores =
|
|
||||||
pycmx/__init__.py: F401
|
|
||||||
tests/__init__.py: F401
|
|
||||||
|
|
||||||
11
.github/workflows/python-package.yml
vendored
11
.github/workflows/python-package.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
@@ -26,13 +26,10 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
python -m pip install flake8 pytest
|
python -m pip install -e .[dev]
|
||||||
python -m pip install -e .
|
- name: Lint with ruff
|
||||||
- name: Lint with flake8
|
|
||||||
run: |
|
run: |
|
||||||
# stop the build if there are Python syntax errors or undefined names
|
ruff check src/
|
||||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
||||||
flake8 . --count --max-line-length=79 --statistics
|
|
||||||
- name: Test with pytest
|
- name: Test with pytest
|
||||||
run: |
|
run: |
|
||||||
pytest
|
pytest
|
||||||
|
|||||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
@@ -9,11 +9,11 @@ version: 2
|
|||||||
build:
|
build:
|
||||||
os: ubuntu-20.04
|
os: ubuntu-20.04
|
||||||
tools:
|
tools:
|
||||||
python: "3.10"
|
python: "3.13"
|
||||||
# You can also specify other tool versions:
|
jobs:
|
||||||
# nodejs: "16"
|
install:
|
||||||
# rust: "1.55"
|
- pip install --upgrade pip
|
||||||
# golang: "1.17"
|
- pip install --group 'doc' -e .
|
||||||
|
|
||||||
# Build documentation in the docs/ directory with Sphinx
|
# Build documentation in the docs/ directory with Sphinx
|
||||||
sphinx:
|
sphinx:
|
||||||
@@ -28,5 +28,3 @@ python:
|
|||||||
install:
|
install:
|
||||||
- method: pip
|
- method: pip
|
||||||
path: .
|
path: .
|
||||||
extra_requirements:
|
|
||||||
- doc
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ The `pycmx` package parses a CMX 3600 EDL and its most most common variations.
|
|||||||
read. Event number field and source name field sizes are determined
|
read. Event number field and source name field sizes are determined
|
||||||
dynamically for each statement for a high level of compliance at the expense
|
dynamically for each statement for a high level of compliance at the expense
|
||||||
of strictness.
|
of strictness.
|
||||||
* An more relaxed "tolerant" mode allows parsing of an EDL file where columns
|
* A more relaxed "tolerant" mode allows parsing of an EDL file where columns
|
||||||
use non-standard widths.
|
use non-standard widths.
|
||||||
* Preserves relationship between events and individual edits/clips.
|
* Preserves relationship between events and individual edits/clips.
|
||||||
* Remark or comment fields with common recognized forms are read and
|
* Remark or comment fields with common recognized forms are read and
|
||||||
@@ -37,7 +37,7 @@ The `pycmx` package parses a CMX 3600 EDL and its most most common variations.
|
|||||||
### Opening and Parsing EDL Files
|
### Opening and Parsing EDL Files
|
||||||
```
|
```
|
||||||
>>> import pycmx
|
>>> import pycmx
|
||||||
>>> with open("tests/edls/TEST.edl") as f
|
>>> with open("tests/edls/TEST.edl") as f:
|
||||||
... edl = pycmx.parse_cmx3600(f)
|
... edl = pycmx.parse_cmx3600(f)
|
||||||
...
|
...
|
||||||
>>> edl.title
|
>>> edl.title
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ The `pycmx` package parses a CMX 3600 EDL and its most most common variations.
|
|||||||
read. Event number field and source name field sizes are determined
|
read. Event number field and source name field sizes are determined
|
||||||
dynamically for each statement for a high level of compliance at the expense
|
dynamically for each statement for a high level of compliance at the expense
|
||||||
of strictness.
|
of strictness.
|
||||||
* An more relaxed "tolerant" mode allows parsing of an EDL file where columns
|
* A more relaxed "tolerant" mode allows parsing of an EDL file where columns
|
||||||
use non-standard widths.
|
use non-standard widths.
|
||||||
* Preserves relationship between events and individual edits/clips.
|
* Preserves relationship between events and individual edits/clips.
|
||||||
* Remark or comment fields with common recognized forms are read and
|
* Remark or comment fields with common recognized forms are read and
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
[tool.poetry]
|
[project]
|
||||||
name = "pycmx"
|
name = "pycmx"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
description = "Python CMX 3600 Edit Decision List Parser"
|
description = "Python CMX 3600 Edit Decision List Parser"
|
||||||
authors = ["Jamie Hardt <jamiehardt@me.com>"]
|
authors = [{name = "Jamie Hardt", email= "jamiehardt@me.com"}]
|
||||||
license = "MIT"
|
license-files = ["LICENSE"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = [
|
keywords = [
|
||||||
'parser',
|
'parser',
|
||||||
'film',
|
'film',
|
||||||
'broadcast'
|
'broadcast'
|
||||||
]
|
]
|
||||||
|
requires-python = '>3.8'
|
||||||
classifiers = [
|
classifiers = [
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'License :: OSI Approved :: MIT License',
|
'License :: OSI Approved :: MIT License',
|
||||||
@@ -21,36 +22,59 @@ classifiers = [
|
|||||||
'Programming Language :: Python :: 3.10',
|
'Programming Language :: Python :: 3.10',
|
||||||
'Programming Language :: Python :: 3.11',
|
'Programming Language :: Python :: 3.11',
|
||||||
'Programming Language :: Python :: 3.12',
|
'Programming Language :: Python :: 3.12',
|
||||||
'Programming Language :: Python :: 3.13'
|
'Programming Language :: Python :: 3.13',
|
||||||
|
'Programming Language :: Python :: 3.14'
|
||||||
]
|
]
|
||||||
homepage = "https://github.com/iluvcapra/pycmx"
|
|
||||||
documentation = "https://pycmx.readthedocs.io/"
|
|
||||||
repository = "https://github.com/iluvcapra/pycmx.git"
|
|
||||||
urls.Tracker = "https://github.com/iluvcapra/pycmx/issues"
|
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[project.optional-dependencies]
|
||||||
|
doc = [
|
||||||
|
'sphinx >= 5.3.0',
|
||||||
|
'sphinx_rtd_theme >= 1.1.1',
|
||||||
|
]
|
||||||
|
dev = [
|
||||||
|
'pytest',
|
||||||
|
'ruff>=0.14.10'
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://github.com/iluvcapra/pycmx"
|
||||||
|
Documentation = "https://pycmx.readthedocs.io/"
|
||||||
|
Repository = "https://github.com/iluvcapra/pycmx.git"
|
||||||
|
Tracker = "https://github.com/iluvcapra/pycmx/issues"
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = ['ruff', 'pytest']
|
||||||
doc = ['sphinx', 'sphinx_rtd_theme']
|
doc = ['sphinx', 'sphinx_rtd_theme']
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
|
||||||
python = "^3.8"
|
|
||||||
sphinx = { version='>= 5.3.0', optional=true}
|
|
||||||
sphinx_rtd_theme = {version ='>= 1.1.1', optional=true}
|
|
||||||
|
|
||||||
[tool.pyright]
|
[tool.pyright]
|
||||||
typeCheckingMode = "basic"
|
typeCheckingMode = "basic"
|
||||||
|
|
||||||
[tool.pylint]
|
[tool.ruff]
|
||||||
max-line-length = 88
|
line-length = 88
|
||||||
disable = [
|
indent-width = 4
|
||||||
"C0103", # (invalid-name)
|
|
||||||
"C0114", # (missing-module-docstring)
|
[tool.ruff.lint]
|
||||||
"C0115", # (missing-class-docstring)
|
select = ["E", "F", "W"]
|
||||||
"C0116", # (missing-function-docstring)
|
|
||||||
"R0903", # (too-few-public-methods)
|
[tool.ruff.format]
|
||||||
"R0913", # (too-many-arguments)
|
docstring-code-line-length = 88
|
||||||
"W0105", # (pointless-string-statement)
|
|
||||||
]
|
# [tool.pylint]
|
||||||
|
# max-line-length = 88
|
||||||
|
# disable = [
|
||||||
|
# "C0103", # (invalid-name)
|
||||||
|
# "C0114", # (missing-module-docstring)
|
||||||
|
# "C0115", # (missing-class-docstring)
|
||||||
|
# "C0116", # (missing-function-docstring)
|
||||||
|
# "R0903", # (too-few-public-methods)
|
||||||
|
# "R0913", # (too-many-arguments)
|
||||||
|
# "W0105", # (pointless-string-statement)
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["uv_build>=0.9.18,<0.10.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "uv_build"
|
||||||
|
|||||||
@@ -11,3 +11,5 @@ from .parse_cmx_events import parse_cmx3600
|
|||||||
from .transition import Transition
|
from .transition import Transition
|
||||||
from .event import Event
|
from .event import Event
|
||||||
from .edit import Edit
|
from .edit import Edit
|
||||||
|
|
||||||
|
__all__ = ("parse_cmx3600", "Transition", "Event", "Edit")
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# pycmx
|
# pycmx
|
||||||
# (c) 2018-2025 Jamie Hardt
|
# (c) 2018-2025 Jamie Hardt
|
||||||
|
|
||||||
from pycmx.cdl import AscSopComponents, FramecountTriple
|
from .cdl import AscSopComponents, FramecountTriple
|
||||||
from pycmx.statements import (
|
from .statements import (
|
||||||
StmtCdlSat,
|
StmtCdlSat,
|
||||||
StmtCdlSop,
|
StmtCdlSop,
|
||||||
StmtFrmc,
|
StmtFrmc,
|
||||||
@@ -35,7 +35,6 @@ class Edit:
|
|||||||
asc_sat_statement: Optional[StmtCdlSat] = None,
|
asc_sat_statement: Optional[StmtCdlSat] = None,
|
||||||
frmc_statement: Optional[StmtFrmc] = None,
|
frmc_statement: Optional[StmtFrmc] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
# Assigning types for the attributes explicitly
|
|
||||||
self._edit_statement: StmtEvent = edit_statement
|
self._edit_statement: StmtEvent = edit_statement
|
||||||
self._audio_ext: Optional[StmtAudioExt] = audio_ext_statement
|
self._audio_ext: Optional[StmtAudioExt] = audio_ext_statement
|
||||||
self._clip_name_statement: Optional[StmtClipName] = clip_name_statement
|
self._clip_name_statement: Optional[StmtClipName] = clip_name_statement
|
||||||
@@ -51,8 +50,8 @@ class Edit:
|
|||||||
def line_number(self) -> int:
|
def line_number(self) -> int:
|
||||||
"""
|
"""
|
||||||
Get the line number for the "standard form" statement associated with
|
Get the line number for the "standard form" statement associated with
|
||||||
this edit. Line numbers a zero-indexed, such that the
|
this edit. Line numbers a zero-indexed, such that the "TITLE:" record
|
||||||
"TITLE:" record is line zero.
|
is line zero.
|
||||||
"""
|
"""
|
||||||
return self._edit_statement.line_number
|
return self._edit_statement.line_number
|
||||||
|
|
||||||
@@ -177,10 +176,20 @@ class Edit:
|
|||||||
|
|
||||||
return self._asc_sop_statement.cdl_sop
|
return self._asc_sop_statement.cdl_sop
|
||||||
|
|
||||||
|
@property
|
||||||
|
def asc_sop_raw(self) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
ASC CDL Slope-Offset-Power statement raw line.
|
||||||
|
"""
|
||||||
|
if self._asc_sop_statement is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self._asc_sop_statement.line
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def asc_sat(self) -> Optional[float]:
|
def asc_sat(self) -> Optional[float]:
|
||||||
"""
|
"""
|
||||||
Get ASC CDL saturation value for clip, if present
|
Get ASC CDL saturation value for clip, if present.
|
||||||
"""
|
"""
|
||||||
if self._asc_sat_statement is None:
|
if self._asc_sat_statement is None:
|
||||||
return None
|
return None
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# pycmx
|
# pycmx
|
||||||
# (c) 2018-2025 Jamie Hardt
|
# (c) 2018-2025 Jamie Hardt
|
||||||
|
|
||||||
from pycmx.statements import (StmtCorruptRemark, StmtTitle, StmtEvent,
|
from .statements import (StmtCorruptRemark, StmtTitle, StmtEvent,
|
||||||
StmtUnrecognized, StmtSourceUMID)
|
StmtUnrecognized, StmtSourceUMID)
|
||||||
from .event import Event
|
from .event import Event
|
||||||
from .channel_map import ChannelMap
|
from .channel_map import ChannelMap
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ from typing import Any, Generator
|
|||||||
class EditList:
|
class EditList:
|
||||||
"""
|
"""
|
||||||
Represents an entire edit decision list as returned by
|
Represents an entire edit decision list as returned by
|
||||||
:func:`~pycmx.parse_cmx3600()`.
|
:func:`~pycmx.parse_cmx_events.parse_cmx3600()`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, statements: list):
|
def __init__(self, statements: list):
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
# pycmx
|
# pycmx
|
||||||
# (c) 2023-2025 Jamie Hardt
|
# (c) 2023-2025 Jamie Hardt
|
||||||
|
|
||||||
from pycmx.statements import StmtFrmc
|
from .statements import (StmtFrmc, StmtEvent, StmtClipName, StmtSourceFile,
|
||||||
from .parse_cmx_statements import (
|
StmtAudioExt, StmtUnrecognized, StmtEffectsName,
|
||||||
StmtEvent, StmtClipName, StmtSourceFile, StmtAudioExt, StmtUnrecognized,
|
StmtCdlSop, StmtCdlSat)
|
||||||
StmtEffectsName, StmtCdlSop, StmtCdlSat)
|
|
||||||
from .edit import Edit
|
from .edit import Edit
|
||||||
|
|
||||||
from typing import List, Generator, Optional, Tuple, Any
|
from typing import List, Generator, Optional, Tuple, Any
|
||||||
@@ -32,12 +31,27 @@ class Event:
|
|||||||
will have multiple edits when a dissolve, wipe or key transition needs
|
will have multiple edits when a dissolve, wipe or key transition needs
|
||||||
to be performed.
|
to be performed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# FTR this is a totall bonkers way of doing this, I wrote this when
|
||||||
|
# I was still learning Python and I'm sure there's easier ways to do
|
||||||
|
# it. The job is complicated because multiple edits can occur in one
|
||||||
|
# event and then other statements can modify the event in different
|
||||||
|
# ways.
|
||||||
|
|
||||||
edits_audio = list(self._statements_with_audio_ext())
|
edits_audio = list(self._statements_with_audio_ext())
|
||||||
clip_names = self._clip_name_statements()
|
clip_names = self._clip_name_statements()
|
||||||
source_files = self._source_file_statements()
|
source_files = self._source_file_statements()
|
||||||
|
|
||||||
|
# We first get the edit events combined with their extra audio
|
||||||
|
# channel statements, if any.
|
||||||
|
|
||||||
|
# The list the_zip contains one element for each initialization
|
||||||
|
# parameter in Edit()
|
||||||
the_zip: List[List[Any]] = [edits_audio]
|
the_zip: List[List[Any]] = [edits_audio]
|
||||||
|
|
||||||
|
# If there are two Clip Name statements and two edits, we look for
|
||||||
|
# "FROM" and "TO" clip name lines. Otherwise we just look for on
|
||||||
|
# each per edit.
|
||||||
if len(edits_audio) == 2:
|
if len(edits_audio) == 2:
|
||||||
start_name: Optional[StmtClipName] = None
|
start_name: Optional[StmtClipName] = None
|
||||||
end_name: Optional[StmtClipName] = None
|
end_name: Optional[StmtClipName] = None
|
||||||
@@ -55,6 +69,10 @@ class Event:
|
|||||||
else:
|
else:
|
||||||
the_zip.append([None] * len(edits_audio))
|
the_zip.append([None] * len(edits_audio))
|
||||||
|
|
||||||
|
# if there's one source file statemnent per clip, we allocate them to
|
||||||
|
# each edit in order. Otherwise if there's only one, we assign the one
|
||||||
|
# to all the edits. If there's no source_file statements, we provide
|
||||||
|
# None.
|
||||||
if len(edits_audio) == len(source_files):
|
if len(edits_audio) == len(source_files):
|
||||||
the_zip.append(source_files)
|
the_zip.append(source_files)
|
||||||
elif len(source_files) == 1:
|
elif len(source_files) == 1:
|
||||||
@@ -62,7 +80,7 @@ class Event:
|
|||||||
else:
|
else:
|
||||||
the_zip.append([None] * len(edits_audio))
|
the_zip.append([None] * len(edits_audio))
|
||||||
|
|
||||||
# attach trans name to last event
|
# attach effects name to last event
|
||||||
try:
|
try:
|
||||||
trans_statement = self._trans_name_statements()[0]
|
trans_statement = self._trans_name_statements()[0]
|
||||||
trans_names: List[Optional[Any]] = [None] * (len(edits_audio) - 1)
|
trans_names: List[Optional[Any]] = [None] * (len(edits_audio) - 1)
|
||||||
@@ -70,6 +88,7 @@ class Event:
|
|||||||
the_zip.append(trans_names)
|
the_zip.append(trans_names)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
the_zip.append([None] * len(edits_audio))
|
the_zip.append([None] * len(edits_audio))
|
||||||
|
|
||||||
return [Edit(edit_statement=e1[0],
|
return [Edit(edit_statement=e1[0],
|
||||||
audio_ext_statement=e1[1],
|
audio_ext_statement=e1[1],
|
||||||
clip_name_statement=n1,
|
clip_name_statement=n1,
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
import re
|
import re
|
||||||
from typing import TextIO, List
|
from typing import TextIO, List
|
||||||
|
|
||||||
from pycmx.cdl import AscSopComponents, Rgb
|
from .cdl import AscSopComponents, Rgb
|
||||||
|
|
||||||
from .statements import (StmtCdlSat, StmtCdlSop, StmtCorruptRemark, StmtFrmc,
|
from .statements import (StmtCdlSat, StmtCdlSop, StmtCorruptRemark, StmtFrmc,
|
||||||
StmtRemark, StmtTitle, StmtUnrecognized, StmtFCM,
|
StmtRemark, StmtTitle, StmtUnrecognized, StmtFCM,
|
||||||
@@ -60,9 +60,8 @@ def _parse_cmx3600_line(line: str, line_number: int,
|
|||||||
source_field_len = len(line) - (event_field_len + 65)
|
source_field_len = len(line) - (event_field_len + 65)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return _parse_columns_for_standard_form(line, event_field_len,
|
return _parse_columns_for_standard_form(
|
||||||
source_field_len,
|
line, event_field_len, source_field_len, line_number)
|
||||||
line_number)
|
|
||||||
|
|
||||||
except EventFormError:
|
except EventFormError:
|
||||||
if tolerant:
|
if tolerant:
|
||||||
@@ -134,15 +133,19 @@ def _parse_remark(line, line_number) -> object:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
return StmtCdlSop(cdl_sop=AscSopComponents(
|
return StmtCdlSop(line=line,
|
||||||
slope=Rgb(red=float(v[0][0]), green=float(v[0][1]),
|
cdl_sop=AscSopComponents(
|
||||||
blue=float(v[0][2])),
|
slope=Rgb(red=float(v[0][0]),
|
||||||
offset=Rgb(red=float(v[1][0]), green=float(v[1][1]),
|
green=float(v[0][1]),
|
||||||
blue=float(v[1][2])),
|
blue=float(v[0][2])),
|
||||||
power=Rgb(red=float(v[2][0]), green=float(v[2][1]),
|
offset=Rgb(red=float(v[1][0]),
|
||||||
blue=float(v[2][2]))
|
green=float(v[1][1]),
|
||||||
),
|
blue=float(v[1][2])),
|
||||||
line_number=line_number)
|
power=Rgb(red=float(v[2][0]),
|
||||||
|
green=float(v[2][1]),
|
||||||
|
blue=float(v[2][2]))
|
||||||
|
),
|
||||||
|
line_number=line_number)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return StmtCorruptRemark('ASC_SOP', e, line_number)
|
return StmtCorruptRemark('ASC_SOP', e, line_number)
|
||||||
@@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
from typing import Any, NamedTuple
|
from typing import Any, NamedTuple
|
||||||
|
|
||||||
from pycmx.cdl import AscSopComponents
|
from .cdl import AscSopComponents
|
||||||
|
|
||||||
# type str = str
|
|
||||||
|
|
||||||
|
|
||||||
class StmtTitle(NamedTuple):
|
class StmtTitle(NamedTuple):
|
||||||
@@ -50,6 +48,7 @@ class StmtSourceFile(NamedTuple):
|
|||||||
|
|
||||||
|
|
||||||
class StmtCdlSop(NamedTuple):
|
class StmtCdlSop(NamedTuple):
|
||||||
|
line: str
|
||||||
cdl_sop: AscSopComponents[float]
|
cdl_sop: AscSopComponents[float]
|
||||||
line_number: int
|
line_number: int
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ class Transition:
|
|||||||
@property
|
@property
|
||||||
def kind(self) -> Optional[str]:
|
def kind(self) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Return the kind of transition: Cut, Wipe, etc
|
Return the kind of transition: Cut, Wipe, etc.
|
||||||
"""
|
"""
|
||||||
if self.cut:
|
if self.cut:
|
||||||
return Transition.Cut
|
return Transition.Cut
|
||||||
@@ -56,7 +56,8 @@ class Transition:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def effect_duration(self) -> int:
|
def effect_duration(self) -> int:
|
||||||
"""The duration of this transition, in frames of the record target.
|
"""
|
||||||
|
The duration of this transition, in frames of the record target.
|
||||||
|
|
||||||
In the event of a key event, this is the duration of the fade in.
|
In the event of a key event, this is the duration of the fade in.
|
||||||
"""
|
"""
|
||||||
Reference in New Issue
Block a user