This commit is contained in:
2026-09-19 15:20:18 -07:00
parent 888d9aa5d9
commit 754e4d5251
5 changed files with 45 additions and 50 deletions
+5
View File
@@ -42,6 +42,11 @@ doc = [
"sphinx-rtd-theme>=3.0.2",
]
[tool.ruff.lint]
ignore = [
"DTZ005" # datetime created without a tz
]
[tool.ruff.lint.per-file-ignores]
"reaper/Export Items as Text.py" = ["F821"]
+2 -2
View File
@@ -6,7 +6,7 @@
#
import datetime
import json
import time
from zoneinfo import ZoneInfo
item_records = []
@@ -66,7 +66,7 @@ output["project_frame_rate"], _, output["project_drop_frame"] = (
output_path, _ = RPR_GetProjectPath("", 1024)
now = datetime.datetime.now(tz=time.tzname)
now = datetime.datetime.now()
output_title = output["project_title"]
if output_title == "":
+1 -12
View File
@@ -102,7 +102,7 @@ def main():
(options, args) = parser.parse_args(sys.argv)
print_section_header_style("Startup")
print_status_style("This run started %s" % (datetime.datetime.now().isoformat()))
print_status_style(f"This run started {datetime.datetime.now().isoformat()}")
if options.show_tags:
dump_field_map()
@@ -124,17 +124,6 @@ def main():
input_file=args[1], major_mode=major_mode, warnings=options.warnings
)
except FileNotFoundError as e:
print_fatal_error("Error trying to read input file")
raise e
except Exception as e:
import traceback
print_fatal_error("Error trying to convert file")
print("\033[31m" + e.__repr__() + "\033[0m", file=sys.stderr)
print(traceback.format_exc())
if __name__ == "__main__":
main()
+18 -15
View File
@@ -2,11 +2,13 @@
Useful functions for parsing and working with timecode.
"""
from __future__ import annotations
import math
import re
from collections import namedtuple
from fractions import Fraction
from typing import Optional, SupportsFloat
from typing import SupportsFloat
class TimecodeFormat(
@@ -16,7 +18,7 @@ class TimecodeFormat(
A struct reperesenting a timecode datum.
"""
def smpte_to_seconds(self, smpte: str) -> Optional[Fraction]:
def smpte_to_seconds(self, smpte: str) -> Fraction | None:
frame_count = smpte_to_frame_count(
smpte, self.logical_fps, drop_frame_hint=self.drop_frame
)
@@ -32,7 +34,7 @@ class TimecodeFormat(
def smpte_to_frame_count(
smpte_rep_string: str, frames_per_logical_second: int, drop_frame_hint=False
) -> Optional[int]:
) -> int | None:
"""
Convert a string with a SMPTE timecode representation into a frame count.
@@ -83,7 +85,7 @@ def frame_count_to_smpte(
frame_count: int,
frames_per_logical_second: int,
drop_frame: bool = False,
fractional_frame: Optional[float] = None,
fractional_frame: float | None = None,
) -> str:
assert frames_per_logical_second in [24, 25, 30, 48, 50, 60]
assert fractional_frame is None or fractional_frame < 1.0
@@ -104,20 +106,21 @@ def frame_count_to_smpte(
ss, ff = divmod(rem, frames_per_logical_second)
hh = hh % 24
hh = int(hh)
mm = int(mm)
ss = int(ss)
ff = int(ff)
if fractional_frame is not None and fractional_frame > 0:
return "%02i:%02i:%02i%s%02i%s" % (
hh,
mm,
ss,
separator,
ff,
("%.3f" % fractional_frame)[1:],
)
fpart = "{fractional_frame:.3f}"[1:]
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}{fpart}"
else:
return "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}"
# "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
def footage_to_frame_count(footage_string) -> Optional[int]:
def footage_to_frame_count(footage_string) -> int | None:
m = re.search(r"(\d+)\+(\d+)(\.\d+)?", footage_string)
if m is None:
return None
@@ -131,4 +134,4 @@ def footage_to_frame_count(footage_string) -> Optional[int]:
def frame_count_to_footage(frame_count):
feet, frm = divmod(frame_count, 16)
return "%i+%02i" % (feet, frm)
return f"{feet}+{frm:02}"
+19 -21
View File
@@ -3,6 +3,8 @@ This module provides the main input document parsing and transform
implementation.
"""
from __future__ import annotations
import csv
import datetime
import os
@@ -11,7 +13,7 @@ from collections.abc import Iterator
from fractions import Fraction
from itertools import chain
from json import JSONEncoder
from typing import List, Optional
from zoneinfo import ZoneInfo
import ptsl
@@ -39,26 +41,25 @@ class FractionEncoder(JSONEncoder):
as a dict.
"""
force_denominator: Optional[int]
force_denominator: int | None
def default(self, o):
""" """
if isinstance(o, Fraction):
return dict(numerator=o.numerator, denominator=o.denominator)
return {"numerator": o.numerator, "denominator": o.denominator}
else:
return o.__dict__
def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
def output_adr_csv(lines: list[ADRLine], time_format: TimecodeFormat):
"""
Writes ADR lines as CSV to the current working directory. Creates
directories for each character number and name pair, and within that
directory, creates a CSV file for each reel.
"""
reels: set[str | None] = set([ln.reel for ln in lines])
reels: set[str | None] = {ln.reel for ln in lines}
for n, name in [(n.character_id, n.character_name) for n in lines]:
dir_name = "%s_%s" % (n, name)
dir_name = f"{n}_{name}"
os.makedirs(dir_name, exist_ok=True)
os.chdir(dir_name)
for reel in reels:
@@ -69,11 +70,8 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
if len(these_lines) == 0:
continue
outfile_name = "%s_%s_%s_%s.csv" % (
these_lines[0].title,
n,
these_lines[0].character_name,
reel,
outfile_name = (
f"{these_lines[0].title}_{n}_{these_lines[0].character_name}_{reel}.csv"
)
with open(outfile_name, mode="w", newline="") as outfile:
@@ -119,13 +117,13 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
os.chdir("..")
def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], title):
def generate_documents(session_tc_format, scenes, adr_lines: list[ADRLine], title):
"""
Create PDF output.
"""
print_section_header_style("Creating PDF Reports")
report_date = datetime.datetime.now()
reports_dir = "%s_%s" % (title, report_date.strftime("%Y-%m-%d_%H%M%S"))
reports_dir = f"{title}_{report_date.strftime('%Y-%m-%d_%H%M%S')}"
os.makedirs(reports_dir, exist_ok=False)
os.chdir(reports_dir)
@@ -155,7 +153,7 @@ def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], titl
def create_adr_reports(
lines: List[ADRLine], tc_display_format: TimecodeFormat, reel_list: List[str]
lines: list[ADRLine], tc_display_format: TimecodeFormat, reel_list: list[str]
):
"""
Creates a directory heirarchy and a respective set of ADR reports,
@@ -240,18 +238,18 @@ def convert(major_mode, input_file=None, output=sys.stdout, warnings=True):
)
# TODO: Breakdown by titles
titles = set([x.title for x in (generic_events + adr_lines)])
titles = {x.title for x in (generic_events + adr_lines)}
if len(titles) != 1:
print_warning(
"Multiple titles per export is not supported, "
"found multiple titles: %s Exiting." % titles
f"found multiple titles: {titles} Exiting."
)
exit(-1)
sys.exit(-1)
title = list(titles)[0]
title = next(iter(titles))
print_status_style("%i generic events found." % len(generic_events))
print_status_style("%i ADR events found." % len(adr_lines))
print_status_style(f"{len(generic_events)} generic events found.")
print_status_style(f"{len(adr_lines)} ADR events found.")
if warnings:
perform_adr_validations(iter(adr_lines))