Loading buildstream/plugins/sources/_downloadablefilesource.py +83 −1 Original line number Diff line number Diff line Loading @@ -5,16 +5,81 @@ import urllib.request import urllib.error import contextlib import shutil import netrc from buildstream import Source, SourceError, Consistency from buildstream import utils class NetrcFTPOpener(urllib.request.FTPHandler): def __init__(self, netrc_config): self.netrc = netrc_config def _split(self, netloc): userpass, hostport = urllib.parse.splituser(netloc) host, port = urllib.parse.splitport(hostport) if userpass: user, passwd = urllib.parse.splitpasswd(userpass) else: user = '' passwd = '' return host, port, user, passwd def _unsplit(self, host, port, user, passwd): if port: host = '{}:{}'.format(host, port) if user: if passwd: user = '{}:{}'.format(user, passwd) host = '{}@{}'.format(user, host) return host def ftp_open(self, req): host, port, user, passwd = self._split(req.host) if (not user or not passwd) and self.netrc: entry = self.netrc.authenticators(host) if entry: entry_login, _, entry_password = entry if not user: user = entry_login if not passwd: passwd = entry_password req.host = self._unsplit(host, port, user, passwd) return super().ftp_open(req) class NetrcPasswordManager: def __init__(self, netrc_config): self.netrc = netrc_config def add_password(self, realm, uri, user, passwd): pass def find_user_password(self, realm, authuri): if not self.netrc: return None, None parts = urllib.parse.urlsplit(authuri) entry = self.netrc.authenticators(parts.hostname) if not entry: return None, None else: login, _, password = entry return login, password class DownloadableFileSource(Source): # pylint: disable=attribute-defined-outside-init COMMON_CONFIG_KEYS = Source.COMMON_CONFIG_KEYS + ['url', 'ref', 'etag'] __urlopener = None def configure(self, node): self.original_url = self.node_get_member(node, str, 'url') self.ref = self.node_get_member(node, str, 'ref', None) Loading Loading @@ -118,7 +183,8 @@ class DownloadableFileSource(Source): if etag and self.get_consistency() == Consistency.CACHED: request.add_header('If-None-Match', etag) with contextlib.closing(urllib.request.urlopen(request)) as response: opener = self.__get_urlopener() with contextlib.closing(opener.open(request)) as response: info = response.info() etag = info['ETag'] if 'ETag' in info else None Loading Loading @@ -164,3 +230,19 @@ class DownloadableFileSource(Source): def _get_mirror_file(self, sha=None): return os.path.join(self._get_mirror_dir(), sha or self.ref) def __get_urlopener(self): if not DownloadableFileSource.__urlopener: try: netrc_config = netrc.netrc() except FileNotFoundError: DownloadableFileSource.__urlopener = urllib.request.build_opener() except netrc.NetrcParseError as e: self.warn('{}: While reading .netrc: {}'.format(self, e)) return urllib.request.build_opener() else: netrc_pw_mgr = NetrcPasswordManager(netrc_config) http_auth = urllib.request.HTTPBasicAuthHandler(netrc_pw_mgr) ftp_handler = NetrcFTPOpener(netrc_config) DownloadableFileSource.__urlopener = urllib.request.build_opener(http_auth, ftp_handler) return DownloadableFileSource.__urlopener Loading
buildstream/plugins/sources/_downloadablefilesource.py +83 −1 Original line number Diff line number Diff line Loading @@ -5,16 +5,81 @@ import urllib.request import urllib.error import contextlib import shutil import netrc from buildstream import Source, SourceError, Consistency from buildstream import utils class NetrcFTPOpener(urllib.request.FTPHandler): def __init__(self, netrc_config): self.netrc = netrc_config def _split(self, netloc): userpass, hostport = urllib.parse.splituser(netloc) host, port = urllib.parse.splitport(hostport) if userpass: user, passwd = urllib.parse.splitpasswd(userpass) else: user = '' passwd = '' return host, port, user, passwd def _unsplit(self, host, port, user, passwd): if port: host = '{}:{}'.format(host, port) if user: if passwd: user = '{}:{}'.format(user, passwd) host = '{}@{}'.format(user, host) return host def ftp_open(self, req): host, port, user, passwd = self._split(req.host) if (not user or not passwd) and self.netrc: entry = self.netrc.authenticators(host) if entry: entry_login, _, entry_password = entry if not user: user = entry_login if not passwd: passwd = entry_password req.host = self._unsplit(host, port, user, passwd) return super().ftp_open(req) class NetrcPasswordManager: def __init__(self, netrc_config): self.netrc = netrc_config def add_password(self, realm, uri, user, passwd): pass def find_user_password(self, realm, authuri): if not self.netrc: return None, None parts = urllib.parse.urlsplit(authuri) entry = self.netrc.authenticators(parts.hostname) if not entry: return None, None else: login, _, password = entry return login, password class DownloadableFileSource(Source): # pylint: disable=attribute-defined-outside-init COMMON_CONFIG_KEYS = Source.COMMON_CONFIG_KEYS + ['url', 'ref', 'etag'] __urlopener = None def configure(self, node): self.original_url = self.node_get_member(node, str, 'url') self.ref = self.node_get_member(node, str, 'ref', None) Loading Loading @@ -118,7 +183,8 @@ class DownloadableFileSource(Source): if etag and self.get_consistency() == Consistency.CACHED: request.add_header('If-None-Match', etag) with contextlib.closing(urllib.request.urlopen(request)) as response: opener = self.__get_urlopener() with contextlib.closing(opener.open(request)) as response: info = response.info() etag = info['ETag'] if 'ETag' in info else None Loading Loading @@ -164,3 +230,19 @@ class DownloadableFileSource(Source): def _get_mirror_file(self, sha=None): return os.path.join(self._get_mirror_dir(), sha or self.ref) def __get_urlopener(self): if not DownloadableFileSource.__urlopener: try: netrc_config = netrc.netrc() except FileNotFoundError: DownloadableFileSource.__urlopener = urllib.request.build_opener() except netrc.NetrcParseError as e: self.warn('{}: While reading .netrc: {}'.format(self, e)) return urllib.request.build_opener() else: netrc_pw_mgr = NetrcPasswordManager(netrc_config) http_auth = urllib.request.HTTPBasicAuthHandler(netrc_pw_mgr) ftp_handler = NetrcFTPOpener(netrc_config) DownloadableFileSource.__urlopener = urllib.request.build_opener(http_auth, ftp_handler) return DownloadableFileSource.__urlopener