From 754e4d525128b89b6340d815a3615dcb7fa6a1ab Mon Sep 17 00:00:00 2001 From: Jamie Hardt Date: Sat, 19 Sep 2026 15:20:18 -0700 Subject: [PATCH] ruffage --- pyproject.toml | 5 ++++ reaper/Export Items as Text.py | 4 +-- src/ptulsconv/__main__.py | 13 +--------- src/ptulsconv/broadcast_timecode.py | 33 +++++++++++++----------- src/ptulsconv/commands.py | 40 ++++++++++++++--------------- 5 files changed, 45 insertions(+), 50 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d7f5feb..b29361b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"] diff --git a/reaper/Export Items as Text.py b/reaper/Export Items as Text.py index dcb81c9..904dad9 100644 --- a/reaper/Export Items as Text.py +++ b/reaper/Export Items as Text.py @@ -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 == "": diff --git a/src/ptulsconv/__main__.py b/src/ptulsconv/__main__.py index 69ca810..253d216 100644 --- a/src/ptulsconv/__main__.py +++ b/src/ptulsconv/__main__.py @@ -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() diff --git a/src/ptulsconv/broadcast_timecode.py b/src/ptulsconv/broadcast_timecode.py index a8b7f76..535ef7a 100644 --- a/src/ptulsconv/broadcast_timecode.py +++ b/src/ptulsconv/broadcast_timecode.py @@ -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}" diff --git a/src/ptulsconv/commands.py b/src/ptulsconv/commands.py index 5966cbd..6129f09 100644 --- a/src/ptulsconv/commands.py +++ b/src/ptulsconv/commands.py @@ -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))