Skip to content

Add python type hints and stubs #1900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ exclude OTIO_VERSION.json
global-exclude *.pyc
global-exclude *.so
global-exclude *.pyd
global-include *.pyi

prune maintainers
prune tsc
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ def run(self):
package_data={
'opentimelineio': [
'adapters/builtin_adapters.plugin_manifest.json',
'*.pyi',
'*/**/*.pyi',
],
},

Expand Down
1 change: 1 addition & 0 deletions src/py-opentimelineio/opentimelineio/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
UnsupportedSchemaError,
CannotComputeAvailableRangeError
)
from typing import Type

__all__ = [
'OTIOError',
Expand Down
23 changes: 12 additions & 11 deletions src/py-opentimelineio/opentimelineio/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
plugins,
core,
)
from typing import Any, Optional, Dict, List

__doc__ = """
HookScripts are plugins that run at defined points ("Hooks").
Expand Down Expand Up @@ -82,14 +83,14 @@ class HookScript(plugins.PythonPlugin):

def __init__(
self,
name=None,
filepath=None,
):
name: Optional[str] = None,
filepath: Optional[str] = None,
) -> None:
"""HookScript plugin constructor."""

super().__init__(name, filepath)

def run(self, in_timeline, argument_map={}):
def run(self, in_timeline: Any, argument_map: Optional[Dict[str, Any]] = {}) -> Any:
"""Run the hook_function associated with this plugin."""

# @TODO: should in_timeline be passed in place? or should a copy be
Expand All @@ -100,13 +101,13 @@ def run(self, in_timeline, argument_map={}):
argument_map=argument_map
)

def __str__(self):
def __str__(self) -> str:
return "HookScript({}, {})".format(
repr(self.name),
repr(self.filepath)
)

def __repr__(self):
def __repr__(self) -> str:
return (
"otio.hooks.HookScript("
"name={}, "
Expand All @@ -118,24 +119,24 @@ def __repr__(self):
)


def names():
def names() -> List[str]:
"""Return a list of all the registered hooks."""

return plugins.ActiveManifest().hooks.keys()


def available_hookscript_names():
def available_hookscript_names() -> List[str]:
"""Return the names of HookScripts that have been registered."""

return [hs.name for hs in plugins.ActiveManifest().hook_scripts]


def available_hookscripts():
def available_hookscripts() -> List[Any]:
"""Return the HookScripts objects that have been registered."""
return plugins.ActiveManifest().hook_scripts


def scripts_attached_to(hook):
def scripts_attached_to(hook: str) -> List[str]:
"""Return an editable list of all the hook scripts that are attached to
the specified hook, in execution order. Changing this list will change the
order that scripts run in, and deleting a script will remove it from
Expand All @@ -146,7 +147,7 @@ def scripts_attached_to(hook):
return plugins.ActiveManifest().hooks[hook]


def run(hook, tl, extra_args=None):
def run(hook: str, tl: Any, extra_args: Optional[Dict[str, Any]] = None) -> Any:
"""Run all the scripts associated with hook, passing in tl and extra_args.

Will return the return value of the last hook script.
Expand Down
27 changes: 14 additions & 13 deletions src/py-opentimelineio/opentimelineio/media_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import os
import inspect
from typing import Any, Optional, Dict

from . import (
exceptions,
Expand Down Expand Up @@ -64,7 +65,7 @@ def from_name(name):
)


def default_media_linker():
def default_media_linker() -> str:
try:
return os.environ['OTIO_DEFAULT_MEDIA_LINKER']
except KeyError:
Expand All @@ -74,10 +75,10 @@ def default_media_linker():


def linked_media_reference(
target_clip,
media_linker_name=MediaLinkingPolicy.ForceDefaultLinker,
media_linker_argument_map=None
):
target_clip: Any,
media_linker_name: Any = MediaLinkingPolicy.ForceDefaultLinker,
media_linker_argument_map: Optional[Dict[str, Any]] = None
) -> Any:
media_linker = from_name(media_linker_name)

if not media_linker:
Expand All @@ -100,12 +101,12 @@ class MediaLinker(plugins.PythonPlugin):

def __init__(
self,
name=None,
filepath=None,
):
name: Optional[str] = None,
filepath: Optional[str] = None,
) -> None:
super().__init__(name, filepath)

def link_media_reference(self, in_clip, media_linker_argument_map=None):
def link_media_reference(self, in_clip: Any, media_linker_argument_map: Optional[Dict[str, Any]] = None) -> Any:
media_linker_argument_map = media_linker_argument_map or {}

return self._execute_function(
Expand All @@ -114,10 +115,10 @@ def link_media_reference(self, in_clip, media_linker_argument_map=None):
media_linker_argument_map=media_linker_argument_map
)

def is_default_linker(self):
def is_default_linker(self) -> bool:
return os.environ.get("OTIO_DEFAULT_MEDIA_LINKER", "") == self.name

def plugin_info_map(self):
def plugin_info_map(self) -> Dict[str, Any]:
"""Adds extra adapter-specific information to call to the parent fn."""

result = super().plugin_info_map()
Expand All @@ -133,13 +134,13 @@ def plugin_info_map(self):

return result

def __str__(self):
def __str__(self) -> str:
return "MediaLinker({}, {})".format(
repr(self.name),
repr(self.filepath)
)

def __repr__(self):
def __repr__(self) -> str:
return (
"otio.media_linker.MediaLinker("
"name={}, "
Expand Down
16 changes: 11 additions & 5 deletions src/py-opentimelineio/opentimelineio/opentime.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@
RationalTime.duration_from_start_end_time_inclusive
)

from typing import Any, Optional

def to_timecode(rt, rate=None, drop_frame=None):

def to_timecode(
rt: Any, rate: Optional[float] = None, drop_frame: Optional[bool] = None
) -> str:
"""Convert a :class:`~RationalTime` into a timecode string."""
return (
rt.to_timecode()
Expand All @@ -48,7 +52,9 @@ def to_timecode(rt, rate=None, drop_frame=None):
)


def to_nearest_timecode(rt, rate=None, drop_frame=None):
def to_nearest_timecode(
rt: Any, rate: Optional[float] = None, drop_frame: Optional[bool] = None
) -> str:
"""Convert a :class:`~RationalTime` into a timecode string."""
return (
rt.to_nearest_timecode()
Expand All @@ -57,17 +63,17 @@ def to_nearest_timecode(rt, rate=None, drop_frame=None):
)


def to_frames(rt, rate=None):
def to_frames(rt: Any, rate: Optional[float] = None) -> float:
"""Turn a :class:`~RationalTime` into a frame number."""
return rt.to_frames() if rate is None else rt.to_frames(rate)


def to_seconds(rt):
def to_seconds(rt: Any) -> float:
"""Convert a :class:`~RationalTime` into float seconds"""
return rt.to_seconds()


def to_time_string(rt):
def to_time_string(rt: Any) -> str:
"""
Convert this timecode to time as used by ffmpeg, formatted as
``hh:mm:ss`` where ss is an integer or decimal number.
Expand Down
7 changes: 4 additions & 3 deletions src/py-opentimelineio/opentimelineio/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,30 @@
"""Utility assertions for OTIO Unit tests."""

import re
from typing import Any

from . import (
adapters
)


class OTIOAssertions:
def assertJsonEqual(self, known, test_result):
def assertJsonEqual(self, known: Any, test_result: Any) -> None:
"""Convert to json and compare that (more readable)."""
self.maxDiff = None

known_str = adapters.write_to_string(known, 'otio_json')
test_str = adapters.write_to_string(test_result, 'otio_json')

def strip_trailing_decimal_zero(s):
def strip_trailing_decimal_zero(s: str) -> str:
return re.sub(r'"(value|rate)": (\d+)\.0', r'"\1": \2', s)

self.assertMultiLineEqual(
strip_trailing_decimal_zero(known_str),
strip_trailing_decimal_zero(test_str)
)

def assertIsOTIOEquivalentTo(self, known, test_result):
def assertIsOTIOEquivalentTo(self, known: Any, test_result: Any) -> None:
"""Test using the 'is equivalent to' method on SerializableObject"""

self.assertTrue(known.is_equivalent_to(test_result))
5 changes: 3 additions & 2 deletions src/py-opentimelineio/opentimelineio/url_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import urllib
from urllib import request
import pathlib
from typing import Union, Any


def url_from_filepath(fpath):
def url_from_filepath(fpath: Union[str, os.PathLike]) -> str:
"""Convert a filesystem path to an url in a portable way.

ensures that `fpath` conforms to the following pattern:
Expand Down Expand Up @@ -42,7 +43,7 @@ def url_from_filepath(fpath):
)


def filepath_from_url(urlstr):
def filepath_from_url(urlstr: str) -> str:
"""
Take an url and return a filepath.

Expand Down
5 changes: 3 additions & 2 deletions src/py-opentimelineio/opentimelineio/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
"""Tools for fetching the family->label->schema:version maps"""

import copy
from typing import Dict

from . import (
core,
plugins
)


def full_map():
def full_map() -> Dict[str, Dict[str, Dict[str, int]]]:
"""Return the full map of schema version sets, including core and plugins.
Organized as follows:

Expand Down Expand Up @@ -57,7 +58,7 @@ def full_map():
return result


def fetch_map(family, label):
def fetch_map(family: str, label: str) -> Dict[str, int]:
"""Fetch the version map for the given family and label. OpenTimelineIO
includes a built in family called "OTIO_CORE", this is compiled into the
C++ core and represents the core interchange schemas of OpenTimelineIO.
Expand Down
Loading
Loading