12 Commits

Author SHA1 Message Date
688402d195 some notes to myslf 2025-12-20 13:44:29 -08:00
4e81810584 ruff configuration 2025-12-18 22:07:08 -08:00
faf2596a57 ruff for linting 2025-12-18 21:45:24 -08:00
1e9fbe339c ruff for linting 2025-12-18 21:44:28 -08:00
a8d00470d4 ruff for linting 2025-12-18 21:43:12 -08:00
fe1e59e731 fix __all__ for module 2025-12-18 21:36:11 -08:00
ec8a08074d doc twiddles 2025-12-18 20:50:06 -08:00
Jamie Hardt
ef683a7683 Update pip install command for documentation 2025-12-18 20:46:33 -08:00
Jamie Hardt
d778f64230 Merge pull request #21 from iluvcapra/uv-build
PEP 621 compliance
2025-12-18 20:43:40 -08:00
1b0ccd4ef7 doc twiddles 2025-12-18 20:41:44 -08:00
498d5c8fea doc tiwddles 2025-12-18 17:24:26 -08:00
af5d937aeb doc tiwddles 2025-12-18 17:19:20 -08:00
12 changed files with 65 additions and 38 deletions

View File

@@ -1,5 +0,0 @@
[flake8]
per-file-ignores =
src/pycmx/__init__.py: F401
tests/__init__.py: F401

View File

@@ -27,11 +27,9 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev]
- name: Lint with flake8
- name: Lint with ruff
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --max-line-length=79 --statistics
ruff check src/
- name: Test with pytest
run: |
pytest

View File

@@ -13,7 +13,7 @@ build:
jobs:
install:
- pip install --upgrade pip
- pip install --group 'doc'
- pip install --group 'doc' -e .
# Build documentation in the docs/ directory with Sphinx
sphinx:

View File

@@ -37,7 +37,7 @@ The `pycmx` package parses a CMX 3600 EDL and its most most common variations.
### Opening and Parsing EDL Files
```
>>> import pycmx
>>> with open("tests/edls/TEST.edl") as f
>>> with open("tests/edls/TEST.edl") as f:
... edl = pycmx.parse_cmx3600(f)
...
>>> edl.title

View File

@@ -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
dynamically for each statement for a high level of compliance at the expense
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.
* Preserves relationship between events and individual edits/clips.
* Remark or comment fields with common recognized forms are read and

View File

@@ -2,7 +2,7 @@
name = "pycmx"
version = "1.5.0"
description = "Python CMX 3600 Edit Decision List Parser"
authors = [{name = "Jamie Hardt", email= "<jamiehardt@me.com>"}]
authors = [{name = "Jamie Hardt", email= "jamiehardt@me.com"}]
license-files = ["LICENSE"]
readme = "README.md"
keywords = [
@@ -29,11 +29,11 @@ classifiers = [
[project.optional-dependencies]
doc = [
'sphinx >= 5.3.0',
'sphinx_rtd_theme >= 1.1.1'
'sphinx_rtd_theme >= 1.1.1',
]
dev = [
'flake8',
'pytest'
'pytest',
'ruff>=0.14.10'
]
[project.urls]
@@ -43,23 +43,37 @@ Repository = "https://github.com/iluvcapra/pycmx.git"
Tracker = "https://github.com/iluvcapra/pycmx/issues"
[dependency-groups]
dev = ['ruff', 'pytest']
doc = ['sphinx', 'sphinx_rtd_theme']
[tool.pyright]
typeCheckingMode = "basic"
[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)
]
[tool.ruff]
line-length = 88
indent-width = 4
[tool.ruff.lint]
select = ["E", "F", "W"]
[tool.ruff.format]
docstring-code-line-length = 88
# [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]
requires = ["uv_build>=0.9.18,<0.10.0"]

View File

@@ -11,3 +11,5 @@ from .parse_cmx_events import parse_cmx3600
from .transition import Transition
from .event import Event
from .edit import Edit
__all__ = ("parse_cmx3600", "Transition", "Event", "Edit")

View File

@@ -35,7 +35,6 @@ class Edit:
asc_sat_statement: Optional[StmtCdlSat] = None,
frmc_statement: Optional[StmtFrmc] = None,
) -> None:
# Assigning types for the attributes explicitly
self._edit_statement: StmtEvent = edit_statement
self._audio_ext: Optional[StmtAudioExt] = audio_ext_statement
self._clip_name_statement: Optional[StmtClipName] = clip_name_statement
@@ -51,8 +50,8 @@ class Edit:
def line_number(self) -> int:
"""
Get the line number for the "standard form" statement associated with
this edit. Line numbers a zero-indexed, such that the
"TITLE:" record is line zero.
this edit. Line numbers a zero-indexed, such that the "TITLE:" record
is line zero.
"""
return self._edit_statement.line_number
@@ -180,7 +179,7 @@ class Edit:
@property
def asc_sop_raw(self) -> Optional[str]:
"""
ASC CDL Slope-Offset-Power statement raw line
ASC CDL Slope-Offset-Power statement raw line.
"""
if self._asc_sop_statement is None:
return None
@@ -190,7 +189,7 @@ class Edit:
@property
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:
return None

View File

@@ -12,7 +12,7 @@ from typing import Any, Generator
class EditList:
"""
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):

View File

@@ -31,12 +31,27 @@ class Event:
will have multiple edits when a dissolve, wipe or key transition needs
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())
clip_names = self._clip_name_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]
# 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:
start_name: Optional[StmtClipName] = None
end_name: Optional[StmtClipName] = None
@@ -54,6 +69,10 @@ class Event:
else:
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):
the_zip.append(source_files)
elif len(source_files) == 1:
@@ -61,7 +80,7 @@ class Event:
else:
the_zip.append([None] * len(edits_audio))
# attach trans name to last event
# attach effects name to last event
try:
trans_statement = self._trans_name_statements()[0]
trans_names: List[Optional[Any]] = [None] * (len(edits_audio) - 1)
@@ -69,6 +88,7 @@ class Event:
the_zip.append(trans_names)
except IndexError:
the_zip.append([None] * len(edits_audio))
return [Edit(edit_statement=e1[0],
audio_ext_statement=e1[1],
clip_name_statement=n1,

View File

@@ -5,8 +5,6 @@ from typing import Any, NamedTuple
from .cdl import AscSopComponents
# type str = str
class StmtTitle(NamedTuple):
title: str

View File

@@ -24,7 +24,7 @@ class Transition:
@property
def kind(self) -> Optional[str]:
"""
Return the kind of transition: Cut, Wipe, etc
Return the kind of transition: Cut, Wipe, etc.
"""
if self.cut:
return Transition.Cut
@@ -56,7 +56,8 @@ class Transition:
@property
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.
"""