~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/urlutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-08-12 01:42:55 UTC
  • mfrom: (6055.2.12 unparsedurl)
  • Revision ID: pqm@pqm.ubuntu.com-20110812014255-y3thbw6gdn7cw6uz
(jelmer) Add a URL object for manipulating parsed URLs. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
730
730
    return osutils.pathjoin(*segments)
731
731
 
732
732
 
 
733
class URL(object):
 
734
    """Parsed URL."""
 
735
 
 
736
    def __init__(self, scheme, quoted_user, quoted_password, quoted_host,
 
737
            port, quoted_path):
 
738
        self.scheme = scheme
 
739
        self.quoted_host = quoted_host
 
740
        self.host = urllib.unquote(self.quoted_host)
 
741
        self.quoted_user = quoted_user
 
742
        if self.quoted_user is not None:
 
743
            self.user = urllib.unquote(self.quoted_user)
 
744
        else:
 
745
            self.user = None
 
746
        self.quoted_password = quoted_password
 
747
        if self.quoted_password is not None:
 
748
            self.password = urllib.unquote(self.quoted_password)
 
749
        else:
 
750
            self.password = None
 
751
        self.port = port
 
752
        self.quoted_path = quoted_path
 
753
        self.path = urllib.unquote(self.quoted_path)
 
754
 
 
755
    def __eq__(self, other):
 
756
        return (isinstance(other, self.__class__) and
 
757
                self.scheme == other.scheme and
 
758
                self.host == other.host and
 
759
                self.user == other.user and
 
760
                self.password == other.password and
 
761
                self.path == other.path)
 
762
 
 
763
    def __repr__(self):
 
764
        return "<%s(%r, %r, %r, %r, %r, %r)>" % (
 
765
            self.__class__.__name__,
 
766
            self.scheme, self.quoted_user, self.quoted_password,
 
767
            self.quoted_host, self.port, self.quoted_path)
 
768
 
 
769
    @classmethod
 
770
    def from_string(cls, url):
 
771
        """Create a URL object from a string.
 
772
 
 
773
        :param url: URL as bytestring
 
774
        """
 
775
        if isinstance(url, unicode):
 
776
            raise errors.InvalidURL('should be ascii:\n%r' % url)
 
777
        url = url.encode('utf-8')
 
778
        (scheme, netloc, path, params,
 
779
         query, fragment) = urlparse.urlparse(url, allow_fragments=False)
 
780
        user = password = host = port = None
 
781
        if '@' in netloc:
 
782
            user, host = netloc.rsplit('@', 1)
 
783
            if ':' in user:
 
784
                user, password = user.split(':', 1)
 
785
        else:
 
786
            host = netloc
 
787
 
 
788
        if ':' in host and not (host[0] == '[' and host[-1] == ']'): #there *is* port
 
789
            host, port = host.rsplit(':',1)
 
790
            try:
 
791
                port = int(port)
 
792
            except ValueError:
 
793
                raise errors.InvalidURL('invalid port number %s in url:\n%s' %
 
794
                                        (port, url))
 
795
        if host != "" and host[0] == '[' and host[-1] == ']': #IPv6
 
796
            host = host[1:-1]
 
797
 
 
798
        return cls(scheme, user, password, host, port, path)
 
799
 
733
800
 
734
801
def parse_url(url):
735
802
    """Extract the server address, the credentials and the path from the url.
738
805
    chars.
739
806
 
740
807
    :param url: an quoted url
741
 
 
742
808
    :return: (scheme, user, password, host, port, path) tuple, all fields
743
809
        are unquoted.
744
810
    """
745
 
    if isinstance(url, unicode):
746
 
        raise errors.InvalidURL('should be ascii:\n%r' % url)
747
 
    url = url.encode('utf-8')
748
 
    (scheme, netloc, path, params,
749
 
     query, fragment) = urlparse.urlparse(url, allow_fragments=False)
750
 
    user = password = host = port = None
751
 
    if '@' in netloc:
752
 
        user, host = netloc.rsplit('@', 1)
753
 
        if ':' in user:
754
 
            user, password = user.split(':', 1)
755
 
            password = urllib.unquote(password)
756
 
        user = urllib.unquote(user)
757
 
    else:
758
 
        host = netloc
759
 
 
760
 
    if ':' in host and not (host[0] == '[' and host[-1] == ']'): #there *is* port
761
 
        host, port = host.rsplit(':',1)
762
 
        try:
763
 
            port = int(port)
764
 
        except ValueError:
765
 
            raise errors.InvalidURL('invalid port number %s in url:\n%s' %
766
 
                                    (port, url))
767
 
    if host != "" and host[0] == '[' and host[-1] == ']': #IPv6
768
 
        host = host[1:-1]
769
 
 
770
 
    host = urllib.unquote(host)
771
 
    path = urllib.unquote(path)
772
 
 
773
 
    return (scheme, user, password, host, port, path)
 
811
    parsed_url = URL.from_string(url)
 
812
    return (parsed_url.scheme, parsed_url.user, parsed_url.password,
 
813
        parsed_url.host, parsed_url.port, parsed_url.path)