Rework File.spoiler to synchronise with the filename

Co-authored-by: Danny <Rapptz@users.noreply.github.com>
This commit is contained in:
Josh
2022-03-31 23:18:36 +10:00
committed by GitHub
parent 705c79df59
commit c11363f037
3 changed files with 163 additions and 15 deletions

View File

@ -23,11 +23,13 @@ DEALINGS IN THE SOFTWARE.
"""
from __future__ import annotations
from typing import Any, Dict, Optional, Union
from typing import Any, Dict, Optional, Tuple, Union
import os
import io
from .utils import MISSING
# fmt: off
__all__ = (
'File',
@ -35,6 +37,12 @@ __all__ = (
# fmt: on
def _strip_spoiler(filename: str) -> Tuple[str, bool]:
stripped = filename.lstrip('SPOILER_')
spoiler = stripped != filename
return stripped, spoiler
class File:
r"""A parameter object used for :meth:`abc.Messageable.send`
for sending file objects.
@ -58,26 +66,23 @@ class File:
To pass binary data, consider usage of ``io.BytesIO``.
filename: Optional[:class:`str`]
The filename to display when uploading to Discord.
If this is not given then it defaults to ``fp.name`` or if ``fp`` is
a string then the ``filename`` will default to the string given.
spoiler: :class:`bool`
Whether the attachment is a spoiler.
Whether the attachment is a spoiler. if left unspecified, the :attr:`~File.filename` is used
to determine if the file is a spoiler.
description: Optional[:class:`str`]
The file description to display, currently only supported for images.
.. versionadded:: 2.0
"""
__slots__ = ('fp', 'filename', 'spoiler', 'description', '_original_pos', '_owner', '_closer')
__slots__ = ('fp', '_filename', 'spoiler', 'description', '_original_pos', '_owner', '_closer')
def __init__(
self,
fp: Union[str, bytes, os.PathLike[Any], io.BufferedIOBase],
filename: Optional[str] = None,
*,
spoiler: bool = False,
spoiler: bool = MISSING,
description: Optional[str] = None,
):
if isinstance(fp, io.IOBase):
@ -100,18 +105,29 @@ class File:
if filename is None:
if isinstance(fp, str):
_, self.filename = os.path.split(fp)
_, filename = os.path.split(fp)
else:
self.filename = getattr(fp, 'name', None)
else:
self.filename: Optional[str] = filename
filename = getattr(fp, 'name', 'untitled')
if spoiler and self.filename is not None and not self.filename.startswith('SPOILER_'):
self.filename = 'SPOILER_' + self.filename
self._filename, filename_spoiler = _strip_spoiler(filename) # type: ignore # the above getattr doesn't narrow the type
if spoiler is MISSING:
spoiler = filename_spoiler
self.spoiler: bool = spoiler or (self.filename is not None and self.filename.startswith('SPOILER_'))
self.spoiler: bool = spoiler
self.description: Optional[str] = description
@property
def filename(self) -> str:
""":class:`str`: The filename to display when uploading to Discord.
If this is not given then it defaults to ``fp.name`` or if ``fp`` is
a string then the ``filename`` will default to the string given.
"""
return 'SPOILER_' + self._filename if self.spoiler else self._filename
@filename.setter
def filename(self, value: str) -> None:
self._filename, self.spoiler = _strip_spoiler(value)
def reset(self, *, seek: Union[int, bool] = True) -> None:
# The `seek` parameter is needed because
# the retry-loop is iterated over multiple times