Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

154 рядки
5.1KB

  1. """Module containing the implementation of the URIReference class."""
  2. # -*- coding: utf-8 -*-
  3. # Copyright (c) 2014 Rackspace
  4. # Copyright (c) 2015 Ian Stapleton Cordasco
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  14. # implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. from collections import namedtuple
  18. from . import compat
  19. from . import misc
  20. from . import normalizers
  21. from ._mixin import URIMixin
  22. class URIReference(namedtuple('URIReference', misc.URI_COMPONENTS), URIMixin):
  23. """Immutable object representing a parsed URI Reference.
  24. .. note::
  25. This class is not intended to be directly instantiated by the user.
  26. This object exposes attributes for the following components of a
  27. URI:
  28. - scheme
  29. - authority
  30. - path
  31. - query
  32. - fragment
  33. .. attribute:: scheme
  34. The scheme that was parsed for the URI Reference. For example,
  35. ``http``, ``https``, ``smtp``, ``imap``, etc.
  36. .. attribute:: authority
  37. Component of the URI that contains the user information, host,
  38. and port sub-components. For example,
  39. ``google.com``, ``127.0.0.1:5000``, ``username@[::1]``,
  40. ``username:password@example.com:443``, etc.
  41. .. attribute:: path
  42. The path that was parsed for the given URI Reference. For example,
  43. ``/``, ``/index.php``, etc.
  44. .. attribute:: query
  45. The query component for a given URI Reference. For example, ``a=b``,
  46. ``a=b%20c``, ``a=b+c``, ``a=b,c=d,e=%20f``, etc.
  47. .. attribute:: fragment
  48. The fragment component of a URI. For example, ``section-3.1``.
  49. This class also provides extra attributes for easier access to information
  50. like the subcomponents of the authority component.
  51. .. attribute:: userinfo
  52. The user information parsed from the authority.
  53. .. attribute:: host
  54. The hostname, IPv4, or IPv6 adddres parsed from the authority.
  55. .. attribute:: port
  56. The port parsed from the authority.
  57. """
  58. slots = ()
  59. def __new__(cls, scheme, authority, path, query, fragment,
  60. encoding='utf-8'):
  61. """Create a new URIReference."""
  62. ref = super(URIReference, cls).__new__(
  63. cls,
  64. scheme or None,
  65. authority or None,
  66. path or None,
  67. query,
  68. fragment)
  69. ref.encoding = encoding
  70. return ref
  71. __hash__ = tuple.__hash__
  72. def __eq__(self, other):
  73. """Compare this reference to another."""
  74. other_ref = other
  75. if isinstance(other, tuple):
  76. other_ref = URIReference(*other)
  77. elif not isinstance(other, URIReference):
  78. try:
  79. other_ref = URIReference.from_string(other)
  80. except TypeError:
  81. raise TypeError(
  82. 'Unable to compare URIReference() to {0}()'.format(
  83. type(other).__name__))
  84. # See http://tools.ietf.org/html/rfc3986#section-6.2
  85. naive_equality = tuple(self) == tuple(other_ref)
  86. return naive_equality or self.normalized_equality(other_ref)
  87. def normalize(self):
  88. """Normalize this reference as described in Section 6.2.2.
  89. This is not an in-place normalization. Instead this creates a new
  90. URIReference.
  91. :returns: A new reference object with normalized components.
  92. :rtype: URIReference
  93. """
  94. # See http://tools.ietf.org/html/rfc3986#section-6.2.2 for logic in
  95. # this method.
  96. return URIReference(normalizers.normalize_scheme(self.scheme or ''),
  97. normalizers.normalize_authority(
  98. (self.userinfo, self.host, self.port)),
  99. normalizers.normalize_path(self.path or ''),
  100. normalizers.normalize_query(self.query),
  101. normalizers.normalize_fragment(self.fragment),
  102. self.encoding)
  103. @classmethod
  104. def from_string(cls, uri_string, encoding='utf-8'):
  105. """Parse a URI reference from the given unicode URI string.
  106. :param str uri_string: Unicode URI to be parsed into a reference.
  107. :param str encoding: The encoding of the string provided
  108. :returns: :class:`URIReference` or subclass thereof
  109. """
  110. uri_string = compat.to_str(uri_string, encoding)
  111. split_uri = misc.URI_MATCHER.match(uri_string).groupdict()
  112. return cls(
  113. split_uri['scheme'], split_uri['authority'],
  114. normalizers.encode_component(split_uri['path'], encoding),
  115. normalizers.encode_component(split_uri['query'], encoding),
  116. normalizers.encode_component(split_uri['fragment'], encoding),
  117. encoding,
  118. )