Source code for pcapkit.vendor.ftp.command

# -*- coding: utf-8 -*-
"""FTP Command"""

import csv
import re

from pcapkit.vendor.default import Vendor

__all__ = ['Command']

#: Command type.
KIND = dict(
    a='access control',
    p='parameter setting',
    s='service execution'
)

#: Conformance requirements.
CONF = dict(
    m='mandatory to implement',
    o='optional',
    h='historic',
)

#: Command entry template.
make = lambda cmmd, feat, desc, kind, conf, rfcs, cmmt: f'''\
    # {cmmt}
    {cmmd}=Info(
        name={cmmd!r},
        feat={feat!r},
        desc={desc!r},
        type={kind!r},
        conf={conf!r},
        note={rfcs!r},
    )
'''.strip()

#: Constant template of enumerate registry from IANA CSV.
LINE = lambda NAME, DOCS, INFO, MISS: f'''\
# -*- coding: utf-8 -*-
# pylint: disable=line-too-long
"""{DOCS}"""

from pcapkit.corekit.infoclass import Info

__all__ = ['{NAME}']


class defaultInfo(Info):
    """Extended :class:`~pcapkit.corekit.infoclass.Info` with default values."""

    def __getitem__(self, key):
        """Missing keys as specified in :rfc:`3659`."""
        try:
            return super().__getitem__(key)
        except KeyError:
            return {MISS}


#: {DOCS}
{NAME} = defaultInfo(
    {INFO}
)
'''


[docs]class Command(Vendor): """FTP Command""" #: Link to registry. LINK = 'https://www.iana.org/assignments/ftp-commands-extensions/ftp-commands-extensions-2.csv'
[docs] def process(self, data): """Process CSV data. Args: data (List[str]): CSV data. Returns: List[str]: Enumeration fields. List[str]: Missing fields. """ reader = csv.reader(data) next(reader) # header info = dict() for item in reader: cmmd = item[0].strip('+') feat = item[1] or None desc = re.sub(r'{.*}', r'', item[2]).strip() or None kind = tuple(KIND.get(s) for s in item[3].split('/')) or None conf = CONF.get(item[4].split()[0]) temp = list() rfcs_temp = list() #for rfc in filter(lambda s: 'RFC' in s, re.split(r'\[|\]', item[5])): # temp.append(f'[{rfc[:3]} {rfc[3:]}]') for rfc in filter(None, map(lambda s: s.strip(), re.split(r'\[|\]', item[5]))): if 'RFC' in rfc and re.match(r'\d+', rfc[3:]): temp.append(f'[:rfc:`{rfc[3:]}`]') rfcs_temp.append(f'{rfc[:3]} {rfc[3:]}') else: temp.append(f'[{rfc}]'.replace('_', ' ')) rfcs = tuple(rfcs_temp) or None cmmt = f"{cmmd} {''.join(temp)}" if cmmd == '-N/A-': MISS = '\n'.ljust(25).join(("Info(name='%s' % key,", f'feat={feat!r},', f'desc={desc!r},', f'type={kind!r},', f'conf={conf!r},', f'note={rfcs!r})')) else: info[cmmd] = make(cmmd, feat, desc, kind, conf, rfcs, cmmt) return info, MISS
[docs] def context(self, data): """Generate constant context. Args: data (List[str]): CSV data. Returns: str: Constant context. """ info, MISS = self.process(data) INFO = ',\n '.join(map(lambda s: s.strip(), info.values())) # pylint: disable=dict-values-not-iterating return LINE(self.NAME, self.DOCS, INFO, MISS)
if __name__ == "__main__": Command()