Skip to content
Merged
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
84 changes: 42 additions & 42 deletions pcapkit/protocols/application/ftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,48 +291,6 @@ def _make_data(cls, data: 'Data_FTP') -> 'dict[str, Any]': # type: ignore[overr
'lines': getattr(data, 'lines', ()),
}

@staticmethod
def _make_code(code: 'Enum_ReturnCode | int | str | bytes | bytearray') -> 'bytes':
"""Render a reply code as the three digits a reply line opens with.

The three digits hold ``0``--``999``, which is what the ``[0-9]{3}``
of ``FTP_RESPONSE`` reads back, so that is the range accepted rather
than the 1xx--5xx of :rfc:`959#section-4.2` alone -- 6xx is
:rfc:`2228#section-5`, and the read path accepts it.

Args:
code: Reply code, an :class:`int` (a
:class:`~pcapkit.const.ftp.return_code.ReturnCode` member is
one) or a numeric :class:`str`, :class:`bytes` or
:class:`bytearray` holding one.

Returns:
The code as three digits, a leading zero kept.

Raises:
ProtocolError: If ``code`` is of any other type, a :obj:`bool`
included, or does not fit in three digits.

"""
# NOTE: ``ReturnCode`` is an ``IntEnum``, so a member takes the ``int``
# branch. ``bool`` is an ``int`` subclass, so without the explicit check
# ``True`` would write code 001, and ``int()`` alone would raise a bare
# ValueError or TypeError rather than a ProtocolError (#2416).
value = None # type: Optional[int]
if isinstance(code, bool):
pass
elif isinstance(code, int):
value = code
elif isinstance(code, (str, bytes, bytearray)):
try:
value = int(code)
except ValueError:
pass
if value is None or not 0 <= value <= 999:
raise ProtocolError('FTP: invalid status code: must be an int in 0-999 or a '
f'numeric str, bytes or bytearray, not {code!r}')
return b'%03d' % value

@staticmethod
def _test_lines(code: 'bytes', lines: 'tuple[bytes, ...]') -> 'bool':
"""Whether ``lines`` are the rest of a multi-line reply with ``code``.
Expand Down Expand Up @@ -383,3 +341,45 @@ def _decode_args(self, args: 'Optional[bytes]') -> 'tuple[Optional[str], Optiona
except (LookupError, UnicodeError):
pass
return args.decode('latin-1'), 'latin-1'

@staticmethod
def _make_code(code: 'Enum_ReturnCode | int | str | bytes | bytearray') -> 'bytes':
"""Render a reply code as the three digits a reply line opens with.

The three digits hold ``0``--``999``, which is what the ``[0-9]{3}``
of ``FTP_RESPONSE`` reads back, so that is the range accepted rather
than the 1xx--5xx of :rfc:`959#section-4.2` alone -- 6xx is
:rfc:`2228#section-5`, and the read path accepts it.

Args:
code: Reply code, an :class:`int` (a
:class:`~pcapkit.const.ftp.return_code.ReturnCode` member is
one) or a numeric :class:`str`, :class:`bytes` or
:class:`bytearray` holding one.

Returns:
The code as three digits, a leading zero kept.

Raises:
ProtocolError: If ``code`` is of any other type, a :obj:`bool`
included, or does not fit in three digits.

"""
# NOTE: ``ReturnCode`` is an ``IntEnum``, so a member takes the ``int``
# branch. ``bool`` is an ``int`` subclass, so without the explicit check
# ``True`` would write code 001, and ``int()`` alone would raise a bare
# ValueError or TypeError rather than a ProtocolError (#2416).
value = None # type: Optional[int]
if isinstance(code, bool):
pass
elif isinstance(code, int):
value = code
elif isinstance(code, (str, bytes, bytearray)):
try:
value = int(code)
except ValueError:
pass
if value is None or not 0 <= value <= 999:
raise ProtocolError('FTP: invalid status code: must be an int in 0-999 or a '
f'numeric str, bytes or bytearray, not {code!r}')
return b'%03d' % value
Loading