[docs]defwrap(cls,url):"""Given a url that is either a string or :class:`Link`, return a :class:`Link`. :param url: A string-like or :class:`Link` object to wrap. :returns: A :class:`Link` object wrapping the url. """ifisinstance(url,cls):returnurlelifisinstance(url,compatible_string):returncls(url)else:raiseValueError('url must be either a string or Link.')

@classmethod

[docs]defwrap_iterable(cls,url_or_urls):"""Given a string or :class:`Link` or iterable, return an iterable of :class:`Link` objects. :param url_or_urls: A string or :class:`Link` object, or iterable of string or :class:`Link` objects. :returns: A list of :class:`Link` objects. """try:return[cls.wrap(url_or_urls)]exceptValueError:passifisinstance(url_or_urls,Iterable):return[cls.wrap(url)forurlinurl_or_urls]raiseValueError('url_or_urls must be string/Link or iterable of strings/Links')

@classmethoddef_normalize(cls,filename):return'file://'+os.path.realpath(os.path.expanduser(filename))# A cache for the result of from_filename_FROM_FILENAME_CACHE=Memoizer()@classmethod

[docs]deffrom_filename(cls,filename):"""Return a :class:`Link` wrapping the local filename."""result=cls._FROM_FILENAME_CACHE.get(filename)ifresultisNone:result=cls(cls._normalize(filename))cls._FROM_FILENAME_CACHE.store(filename,result)returnresult

def__init__(self,url):"""Construct a :class:`Link` from a url. :param url: A string-like object representing a url. """purl=urlparse.urlparse(url)ifpurl.scheme=='':purl=urlparse.urlparse(self._normalize(url))self._url=purldef__ne__(self,other):returnnotself.__eq__(other)def__eq__(self,link):returnself.__class__==link.__class__andself._url==link._urldef__hash__(self):returnhash(self._url)

[docs]defjoin(self,href):"""Given a href relative to this link, return the :class:`Link` of the absolute url. :param href: A string-like path relative to this link. """returnself.wrap(urlparse.urljoin(self.url,href))

@propertydeffilename(self):"""The basename of this url."""returnposixpath.basename(self._url.path)@propertydefpath(self):"""The full path of this url with any hostname and scheme components removed."""returnself._url.path@propertydefurl(self):"""The url string to which this link points."""returnurlparse.urlunparse(self._url)@propertydeffragment(self):"""The url fragment following '#' if any."""returnself._url.fragment@propertydefscheme(self):"""The URI scheme used by this Link."""returnself._url.scheme@propertydeflocal(self):"""Is the url a local file?"""returnself._url.schemein('','file')@propertydefremote(self):"""Is the url a remote file?"""returnself._url.schemein('http','https')def__repr__(self):return'%s(%r)'%(self.__class__.__name__,self.url)