diff --git a/pcapkit/protocols/application/ftp.py b/pcapkit/protocols/application/ftp.py index ef955bd087..984f781798 100644 --- a/pcapkit/protocols/application/ftp.py +++ b/pcapkit/protocols/application/ftp.py @@ -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``. @@ -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