Skip to content

Commit 23d02ba

Browse files
committed
Use fspath to fully support PathLike objects.
PathLike objects were already implicitly supported by `input` and by `output` when the filename was explicitly specified as a keyword argument. However, implicitly setting the output filename from a list of output streams/filename did not permit a PathLike object.
1 parent df129c7 commit 23d02ba

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

ffmpeg/_ffmpeg.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import unicode_literals
22

33
from past.builtins import basestring
4-
from ._utils import basestring
4+
from ._utils import basestring, fspath
55

66
from .nodes import (
77
filter_operator,
@@ -23,7 +23,7 @@ def input(filename, **kwargs):
2323
2424
Official documentation: `Main options <https://ffmpeg.org/ffmpeg.html#Main-options>`__
2525
"""
26-
kwargs['filename'] = filename
26+
kwargs['filename'] = fspath(filename)
2727
fmt = kwargs.pop('f', None)
2828
if fmt:
2929
if 'format' in kwargs:
@@ -79,9 +79,12 @@ def output(*streams_and_filename, **kwargs):
7979
"""
8080
streams_and_filename = list(streams_and_filename)
8181
if 'filename' not in kwargs:
82-
if not isinstance(streams_and_filename[-1], basestring):
82+
# Raise any errors without destructively modifying streams_and_filenames
83+
try:
84+
fspath(streams_and_filename[-1])
85+
except TypeError:
8386
raise ValueError('A filename must be provided')
84-
kwargs['filename'] = streams_and_filename.pop(-1)
87+
kwargs['filename'] = fspath(streams_and_filename.pop(-1))
8588
streams = streams_and_filename
8689

8790
fmt = kwargs.pop('f', None)

ffmpeg/_utils.py

+35
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,38 @@ def convert_kwargs_to_cmd_line_args(kwargs):
106106
if v is not None:
107107
args.append('{}'.format(v))
108108
return args
109+
110+
111+
if sys.version_info >= (3, 6):
112+
from os import fspath
113+
else:
114+
# This code is mostly copy-pasted from PEP 519, with (str, bytes) instance
115+
# checks converted to basestring instance checks.
116+
def fspath(path):
117+
"""Return the string representation of the path.
118+
119+
If str or bytes is passed in, it is returned unchanged. If __fspath__()
120+
returns something other than str or bytes then TypeError is raised. If
121+
this function is given something that is not str, bytes, or os.PathLike
122+
then TypeError is raised.
123+
"""
124+
if isinstance(path, basestring):
125+
return path
126+
127+
# Work from the object's type to match method resolution of other magic
128+
# methods.
129+
path_type = type(path)
130+
try:
131+
path = path_type.__fspath__(path)
132+
except AttributeError:
133+
if hasattr(path_type, '__fspath__'):
134+
raise
135+
else:
136+
if isinstance(path, basestring):
137+
return path
138+
else:
139+
raise TypeError("expected __fspath__() to return str or bytes, "
140+
"not " + type(path).__name__)
141+
142+
raise TypeError("expected str, bytes or os.PathLike object, not "
143+
+ path_type.__name__)

0 commit comments

Comments
 (0)