"""Module for helper functions for parsing requirements file."""importosimportrefromtypingimportDict,Tuple,castfrompkg_resourcesimportRequirement# Adopted from requirements-parser:# https://github.com/madpah/requirements-parserVCS=['git','hg','svn','bzr',]VCS_SCHEMES=['git','git+https','git+ssh','git+git','hg+http','hg+https','hg+static-http','hg+ssh','svn','svn+svn','svn+http','svn+https','svn+ssh','bzr+http','bzr+https','bzr+ssh','bzr+sftp','bzr+ftp','bzr+lp',]URI_REGEX=re.compile(r'^(?P<scheme>https?|file|ftps?)://(?P<path>[^#]+)'r'(#(?P<fragment>\S+))?')VCS_SCHEMES_REGEX=r'|'.join([scheme.replace('+',r'\+')forschemeinVCS_SCHEMES])VCS_REGEX=re.compile(rf'^(?P<scheme>{VCS_SCHEMES_REGEX})://((?P<login>[^/@]+)@)?'r'(?P<path>[^#@]+)(@(?P<revision>[^#]+))?(#(?P<fragment>\S+))?')extras_require_search=re.compile(r'(?P<name>.+)\[(?P<extras>[^\]]+)\]')def_parse_fragment(fragment_string:str)->Dict[str,str]:"""Takes a fragment string nd returns a dict of the components :param fragment_string: a fragment string :return: a dict of components """fragment_string=fragment_string.lstrip('#')try:returndict(cast(Tuple[str,str],tuple(key_value_string.split('=')))forkey_value_stringinfragment_string.split('&'))exceptValueError:raiseValueError(f'Invalid fragment string {fragment_string}')
[docs]defparse_requirement(line:str)->'Requirement':"""Parses a Requirement from a line of a requirement file. :param line: a line of a requirement file :returns: a Requirement instance for the given line """vcs_match=VCS_REGEX.match(line)uri_match=URI_REGEX.match(line)ifvcs_matchisnotNone:groups=vcs_match.groupdict()name=os.path.basename(groups['path']).split('.')[0]egg=Noneifgroups['fragment']:fragment=_parse_fragment(groups['fragment'])egg=fragment.get('egg')line=f'{eggorname} @ {line}'elifuri_matchisnotNone:groups=uri_match.groupdict()name=os.path.basename(groups['path']).split('.')[0]egg=Noneifgroups['fragment']:fragment=_parse_fragment(groups['fragment'])egg=fragment.get('egg')line=f'{eggorname} @ {line}'returnRequirement.parse(line)