Package urilibplus

urilibplus

A python module containing classes used to interact and manipulate uris in python in a easier and consistent manner.

Sub-modules

urilibplus.characters

characters …

urilibplus.tests

__init__

urilibplus.tools
urilibplus.typings
urilibplus.uri
urilibplus.uri_path
urilibplus.uri_query

Classes

class CharacterSets

CharacterSets

Holds the character literals and related functions for the urilibplus module.

Sources: - https://www.rfc-editor.org/rfc/rfc3986 - https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

Expand source code
class CharacterSets:
    """
    `CharacterSets`

    Holds the character literals and related functions for the `urilibplus` module.
    
    Sources:
     - https://www.rfc-editor.org/rfc/rfc3986
     - https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
    """

    HEXDIGITS: LiteralString = hexdigits
    DIGITS: LiteralString = digits
    LETTERS: LiteralString = ascii_letters

    GENERIC_DELIMITERS: LiteralString = ":/?#[]@"
    SPECIFIC_DELIMITERS: LiteralString = "!$&'()*+,;="
    PERCENT_ENCODING: LiteralString = singlify_str(HEXDIGITS,
                                                   "%")
    UNRESERVED: LiteralString = singlify_str(LETTERS,
                                             DIGITS,
                                             "-._~")
    P_CHARS: LiteralString = singlify_str(UNRESERVED,
                                          PERCENT_ENCODING,
                                          SPECIFIC_DELIMITERS,
                                          ":@")
    ALL: LiteralString = singlify_str(GENERIC_DELIMITERS,
                                      SPECIFIC_DELIMITERS,
                                      PERCENT_ENCODING,
                                      UNRESERVED)

    SEGMENT: LiteralString = P_CHARS

    SCHEME: LiteralString = cast(LiteralString, uri_scheme_chars)
    USERINFO: LiteralString = singlify_str(UNRESERVED,
                                           PERCENT_ENCODING,
                                           SPECIFIC_DELIMITERS,
                                           ":")
    HOST: LiteralString = singlify_str(DIGITS,
                                       HEXDIGITS,
                                       UNRESERVED,
                                       PERCENT_ENCODING,
                                       SPECIFIC_DELIMITERS,
                                       ".-:[]")
    PORT: LiteralString = DIGITS
    PATH: LiteralString = singlify_str(SEGMENT, "/")
    QUERY: LiteralString = singlify_str(P_CHARS, "/?")
    FRAGMENT: LiteralString = QUERY

    @staticmethod
    def invalid_check(character_set: LiteralString, *validate_all: str) -> bool:
        """
        `invalid_check`

        Checks that all the `*validate_all` strings only use
        characters from the given `character-set`

        Arguments:
            `character_set` -- The character set to check the strings with.
            `*validate_all` -- The strings to check.

        Returns:
            True if *all* `*validate_all` strings only use
            the characters in the given `character_set`.
        """

        return any(any((c not in character_set) for c in s) for s in validate_all if s != "")

Class variables

var ALL : LiteralString
var DIGITS : LiteralString
var FRAGMENT : LiteralString
var GENERIC_DELIMITERS : LiteralString
var HEXDIGITS : LiteralString
var HOST : LiteralString
var LETTERS : LiteralString
var PATH : LiteralString
var PERCENT_ENCODING : LiteralString
var PORT : LiteralString
var P_CHARS : LiteralString
var QUERY : LiteralString
var SCHEME : LiteralString
var SEGMENT : LiteralString
var SPECIFIC_DELIMITERS : LiteralString
var UNRESERVED : LiteralString
var USERINFO : LiteralString

Static methods

def invalid_check(character_set: LiteralString, *validate_all: str) ‑> bool

invalid_check

Checks that all the *validate_all strings only use characters from the given character-set

Arguments

character_set – The character set to check the strings with. *validate_all – The strings to check.

Returns

True if all *validate_all strings only use the characters in the given character_set.

class URI (contents: Union[str, ForwardRef('URI'), urllib.parse.SplitResult, Tuple[str, str, str, str, str]], default_scheme: Optional[str] = None, *, unquote: bool = False, requote: bool = False, quote_safe: str = '')

URI

A python class used to interact and manipulate with uris in python in a easier and consistent manner.

Sources: - https://www.rfc-editor.org/rfc/rfc3986 - https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

Expand source code
class URI:
    """
    `URI`

    A python class used to interact and manipulate with
    uris in python in a easier and consistent manner.
    
    Sources:
     - https://www.rfc-editor.org/rfc/rfc3986
     - https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
    """
    CHARACTER_SETS = CharacterSets

    quotestr = staticmethod(uriquote)
    unquotestr = staticmethod(uriunquote)

    @property
    def authority(self) -> str:
        """
        `authority`

        Returns:
            The authority of the uri;
            ie. the user, password, host, and port;
            formatted as required.
        """
        authority = ""
        if self.user_info != "":
            authority = f"{self.user_info}@"
        authority += f"{self.host}"
        if self.port is not None and self.port > 0:
            authority += f":{self.port}"
        return authority
    @authority.setter
    def authority(self, value: str):
        at_index = value.find("@")
        if at_index < 0:
            self.user_info = ""
        else:
            self.user_info = value[:at_index]
        value = value.replace(self.user_info, "", 1).lstrip("@")

        col_index = value.rfind(":")
        if col_index < 0:
            self.port = None
        else:
            self.port = int(value[col_index+1:])
            if self.port < 0:
                self.port = None
        if self.port is not None:
            value = value.replace(str(self.port), "", 1).rstrip(":")

        self.host = value

    @property
    def username(self) -> Union[None, str]:
        """
        `username`

        Returns:
            The username in the uri, or None if no username in included.
        """
        if self.userinfo.count(":") == 1:
            return self.userinfo[:self.userinfo.find(":")]
        else:
            return None
    @username.setter
    def username(self, value: Union[None, str]):
        if value is None:
            self.userinfo = self.userinfo[self.userinfo.find(":")+1:]
        else:
            if self.userinfo[0] != ":" and self.username is None:
                value += ":"
            self.userinfo = value + \
                self.userinfo[max(self.userinfo.find(":"), 0):]

    @property
    def password(self) -> Union[None, str]:
        """
        `password`

        Returns:
            The password in the uri, or None if no password in included.
        """
        if self.userinfo_string.count(":") == 1:
            return self.userinfo_string[self.userinfo_string.find(":")+1:]
        else:
            return None
    @password.setter
    def password(self, value: Union[None, str]):
        if value is None:
            self.userinfo_string = self.userinfo_string[:self.userinfo_string.find(
                ":")]
        else:
            if self.userinfo_string[-1] != ":" and self.password is None:
                value = ":" + value
            self.userinfo_string = self.userinfo_string[:self.userinfo_string.find(
                ":")] + value

    def __init__(self,
                 contents:Union[str, 'URI', SplitResult, Tuple[str, str, str, str, str]],
                 default_scheme: Optional[str] = None,
                 *,
                 unquote:bool = False,
                 requote:bool = False,
                 quote_safe:str = ""):
        self.scheme: str
        self.user_info: str = ""
        self.host: str = ""
        self.port: Optional[int] = None
        self.path: Optional['URIPath'] = None
        self.query: Optional['URIQuery'] = None
        self.fragment: Optional['URIQuery'] = None

        if default_scheme is None:
            default_scheme = ""

        parsed = None
        if isinstance(contents, SplitResult):
            parsed = contents
        elif isinstance(contents, tuple) and len(contents) <= 5 and len(contents) >= 1:
            parsed = SplitResult(*contents)
        else:
            if isinstance(contents, URI):
                contents = str(contents)
            contents = contents.strip()
            contents = uriunwrap(contents)
            parsed = urisplit(contents, scheme=default_scheme, allow_fragments=True)

        self.scheme = uriunquote(parsed.scheme) if unquote else parsed.scheme
        self.authority = uriunquote(parsed.netloc) if unquote else parsed.netloc
        self.path = URIPath(parsed.path.lstrip("/"), unquote=unquote)
        self.query = URIQuery(parsed.query, unquote=unquote)
        self.fragment = URIQuery(parsed.fragment, unquote=unquote)

        self.default_scheme = default_scheme
        self.requote = requote
        self.quote_safe = quote_safe

    def __repr__(self):
        return f"<URI object (url = {self.encode()}, valid = {self.validate()})>"

    def __len__(self):
        return len(self.encode())

    def __contains__(self, value:str):
        return value in self.encode()

    def __iter__(self):
        return iter(self.tupled())

    def copy(self) -> 'URI':
        """
        `copy`

        Returns:
            A complete, deep, copy of this object.
        """
        return URI(self.splitted(False),
                   default_scheme=self.default_scheme,
                   unquote=False,
                   requote=self.requote,
                   quote_safe=self.quote_safe
                  )
    __copy__ = copy
    __deepcopy__ = copy

    def tupled(self,
               quote: Optional[bool] = None,
               quote_safe:Optional[str] = None
              ) -> Tuple[str, str, str, str, str]:
        """
        `tupled`
        
        Returns this object formated as a `tuple`,
        a ordered in the commonly used order used in native python uri related functions.

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            This object as a `tuple`.
        """
        if quote is None:
            quote = self.requote

        if quote_safe is None:
            quote_safe = self.quote_safe

        return (uriquote(self.scheme, quote_safe) if quote else self.scheme,
                uriquote(self.authority, quote_safe) if quote else self.authority,
                "" if self.path is None else self.path.encode(quote, quote_safe),
                "" if self.query is None else self.query.encode(quote, quote_safe),
                "" if self.fragment is None else self.fragment.encode(quote, quote_safe)
               )

    def splitted(self,
                 quote: Optional[bool] = None,
                 quote_safe:Optional[str] = None
                ) -> SplitResult:
        """
        `splitted`
        
        Returns this object formated as a `SplitResult`,
        a native object commonly used with native python uri related functions.

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            This object as a `SplitResult`.
        """
        return SplitResult(*self.tupled(quote, quote_safe))

    def encode(self, quote: Optional[bool] = None, quote_safe:Optional[str] = None) -> str:
        """
        `encode`

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            The URI object, encoded as a string.
        """

        if quote is None:
            quote = self.requote

        if quote_safe is None:
            quote_safe = self.quote_safe

        encoded = uriunsplit(SplitResult(*self.tupled(None, None)))
        if quote is True:
            encoded = uriquote(encoded, safe = quote_safe)
        elif quote is False:
            encoded = uriunquote(encoded)
        return encoded
    __str__ = encode
    __repr__ = encode

    def stripped(self, quote: Optional[bool] = None, quote_safe:Optional[str] = None) -> str:
        """
        `stripped`

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            The URI without any fragment or query, ie. the URI with only its
            scheme and authority (host, user, password, and port) and path
        """
        if quote is None:
            quote = self.requote

        if quote_safe is None:
            quote_safe = self.quote_safe

        encoded = uriunsplit(SplitResult(*self.tupled(quote, quote_safe)[:3], "", ""))

        if quote is True:
            encoded = uriquote(encoded, safe = quote_safe)
        elif quote is False:
            encoded = uriunquote(encoded)
        return encoded

    def root(self, quote: Optional[bool] = None, quote_safe:Optional[str] = None) -> str:
        """
        `root`

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            The URI's root path, ie. the URI with only its
            scheme and authority (host, user, password, and port)
        """
        if quote is None:
            quote = self.requote

        if quote_safe is None:
            quote_safe = self.quote_safe

        encoded = uriunsplit(SplitResult(*self.tupled(quote, quote_safe)[:2], "", "", ""))

        if quote is True:
            encoded = uriquote(encoded, safe = quote_safe)
        elif quote is False:
            encoded = uriunquote(encoded)
        return encoded

    def validate(self) -> bool:
        """
        `validate`

        Returns:
            True if all characters in this object are allowed in a URI.
        """
        for char in self.scheme:
            if char not in self.CHARACTER_SETS.SCHEME:
                return False

        for char in self.user_info:
            if char not in self.CHARACTER_SETS.USERINFO:
                return False

        for char in self.host:
            if char not in self.CHARACTER_SETS.HOST:
                return False

        if not (isinstance(self.port, int) or self.port is None):
            return False

        if self.path is None:
            return False
        elif isinstance(self.path, URIPath) and not self.path.validate():
            return False
        else:
            for char in self.host:
                if char not in self.CHARACTER_SETS.PATH:
                    return False

        if isinstance(self.query, URIQuery) and not self.query.validate():
            return False
        else:
            for char in self.host:
                if char not in self.CHARACTER_SETS.QUERY:
                    return False

        for char in str(self.fragment):
            if char not in self.CHARACTER_SETS.FRAGMENT:
                return False

        # This is specifically stated as invalid in the specs
        if self.authority == "" and self.path[0] == "":
            return False
        return True

    # NOTE this doesn't test all parts fo the URI, just the required parts!
    def isempty(self) -> bool:
        """
        `isempty`

        Returns:
            True if the given url's scheme or path are blank.
        """
        return self.scheme == "" or (self.path is None or self.path.isempty())
    __bool__ = isempty

    def search(self,
               pattern:Union[str, Pattern],
               quoted: Optional[bool] = None,
               quote_safe:Optional[str] = None
              ) -> Optional[Match]:
        """
        `search`

        A simple shorcut to regex `search` this url, returning the `Match`,
        or `None` if there was no matches.

        Arguments:
            `pattern` -- The pattern to check the url with.

        Keyword Arguments:
            quoted -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            `None` if not matches where found, or a `Match` object otherwise.
        """
        if isinstance(pattern, str):
            pattern = regexcompile(pattern)

        return pattern.search(self.encode(quoted, quote_safe))

    def pathappend(self, *parts:Union[str, PathLike]):
        """
        `pathappend`
        
        A simple shorcut to append to the path directly from the this
        object, if a path is defined.
        
        Will initialise `path` if `path` is None.
        
        Arguments:
            `*parts` -- The parts to be appended to the path, in order.
        """
        if self.path is None:
            self.path = URIPath()
        self.path.append(parts)

    def __truediv__(self, value:Union[str, PathLike]) -> 'URI':
        cpy = self.copy()
        cpy.pathappend(value)
        return cpy

    def __floordiv__(self, value:Union[str, PathLike]) -> 'URI':
        cpy = self.copy()
        cpy.pathappend("", value)
        return cpy

Class variables

var CHARACTER_SETS

CharacterSets

Holds the character literals and related functions for the urilibplus module.

Sources: - https://www.rfc-editor.org/rfc/rfc3986 - https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

Static methods

def quotestr(string, safe='/', encoding=None, errors=None)

quote('abc def') -> 'abc%20def'

Each part of a URL, e.g. the path info, the query, etc., has a different set of reserved characters that must be quoted. The quote function offers a cautious (not minimal) way to quote a string for most of these parts.

RFC 3986 Uniform Resource Identifier (URI): Generic Syntax lists the following (un)reserved characters.

unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

Each of the reserved characters is reserved in some component of a URL, but not necessarily in all of them.

The quote function %-escapes all characters that are neither in the unreserved chars ("always safe") nor the additional chars set via the safe arg.

The default for the safe arg is '/'. The character is reserved, but in typical usage the quote function is being called on a path where the existing slash characters are to be preserved.

Python 3.7 updates from using RFC 2396 to RFC 3986 to quote URL strings. Now, "~" is included in the set of unreserved characters.

string and safe may be either str or bytes objects. encoding and errors must not be specified if string is a bytes object.

The optional encoding and errors parameters specify how to deal with non-ASCII characters, as accepted by the str.encode method. By default, encoding='utf-8' (characters are encoded with UTF-8), and errors='strict' (unsupported characters raise a UnicodeEncodeError).

def unquotestr(string, encoding='utf-8', errors='replace')

Replace %xx escapes by their single-character equivalent. The optional encoding and errors parameters specify how to decode percent-encoded sequences into Unicode characters, as accepted by the bytes.decode() method. By default, percent-encoded sequences are decoded with UTF-8, and invalid sequences are replaced by a placeholder character.

unquote('abc%20def') -> 'abc def'.

Instance variables

prop authority : str

authority

Returns

The authority of the uri; ie. the user, password, host, and port; formatted as required.

Expand source code
@property
def authority(self) -> str:
    """
    `authority`

    Returns:
        The authority of the uri;
        ie. the user, password, host, and port;
        formatted as required.
    """
    authority = ""
    if self.user_info != "":
        authority = f"{self.user_info}@"
    authority += f"{self.host}"
    if self.port is not None and self.port > 0:
        authority += f":{self.port}"
    return authority
prop password : Optional[str]

password

Returns

The password in the uri, or None if no password in included.

Expand source code
@property
def password(self) -> Union[None, str]:
    """
    `password`

    Returns:
        The password in the uri, or None if no password in included.
    """
    if self.userinfo_string.count(":") == 1:
        return self.userinfo_string[self.userinfo_string.find(":")+1:]
    else:
        return None
prop username : Optional[str]

username

Returns

The username in the uri, or None if no username in included.

Expand source code
@property
def username(self) -> Union[None, str]:
    """
    `username`

    Returns:
        The username in the uri, or None if no username in included.
    """
    if self.userinfo.count(":") == 1:
        return self.userinfo[:self.userinfo.find(":")]
    else:
        return None

Methods

def copy(self) ‑> URI

copy

Returns

A complete, deep, copy of this object.

def encode(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> str

encode

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

The URI object, encoded as a string.

def isempty(self) ‑> bool

isempty

Returns

True if the given url's scheme or path are blank.

def pathappend(self, *parts: Union[str, os.PathLike])

pathappend

A simple shorcut to append to the path directly from the this object, if a path is defined.

Will initialise path if path is None.

Arguments

*parts – The parts to be appended to the path, in order.

def root(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> str

root

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

The URI's root path, ie. the URI with only its scheme and authority (host, user, password, and port)

def search(self, pattern: Union[str, re.Pattern], quoted: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> Optional[re.Match]

search

A simple shorcut to regex search this url, returning the Match, or None if there was no matches.

Arguments

pattern – The pattern to check the url with.

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

None if not matches where found, or a Match object otherwise.

def splitted(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> urllib.parse.SplitResult

splitted

Returns this object formated as a SplitResult, a native object commonly used with native python uri related functions.

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

This object as a SplitResult.

def stripped(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> str

stripped

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

The URI without any fragment or query, ie. the URI with only its scheme and authority (host, user, password, and port) and path

def tupled(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> Tuple[str, str, str, str, str]

tupled

Returns this object formated as a tuple, a ordered in the commonly used order used in native python uri related functions.

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

This object as a tuple.

def validate(self) ‑> bool

validate

Returns

True if all characters in this object are allowed in a URI.

class URIPath (*path: Union[str, os.PathLike, Iterable[Union[str, os.PathLike]]], unquote: bool = False, requote: bool = False, quote_safe: str = '')

URIPath

A class used to manipulate and use a URI path in python easily.

Expand source code
class URIPath(PurePosixPath, PathLike, MutableSequenceABC[str]):
    """
    `URIPath`

    A class used to manipulate and use a URI path in python easily.
    """

    _USE_NEW_PUREPATH_INIT_METHOD:bool = version_info.major > 3 or (version_info.major == 3 and
                                                                    version_info.minor >= 12)
    _CACHEING_ANCESTORS:Tuple[type, ...] = (PurePosixPath, PurePath, PureWindowsPath)
    _CACHE_ATTR_NAMES:Iterator[LiteralString] = cast(Iterator[LiteralString],
                                                     iter_flatten(
                                                         (getattr(c, "__slots__", []) for c in _CACHEING_ANCESTORS), #pylint:disable=line-too-long
                                                         str
                                                         )
                                                     )
    @property
    def raw(self) -> List[str]:
        """
        `__raw`

        Used internally, do not modify without express intent.

        Returns:
            The internal list of strings used by `Path` types to create paths from.
        """
        return self._raw_paths
    @raw.setter
    def raw(self, value:List[str]):
        #without this, the caches parts of the path wont update when we manually change the content
        for attr in self._CACHE_ATTR_NAMES:
            if hasattr(self, attr):
                delattr(self, attr)
        self._raw_paths = value
    @raw.deleter
    def raw(self):
        # you don't just delete raw, but you can clear it...
        self.raw = []

    def __new__(cls,
                *path:Union[str, PathLike, Iterable[Union[str, PathLike]]],
                unquote: bool = False,
                requote:bool = False,
                quote_safe:str = ""
               ) -> 'URIPath':
        # don't run the inherited __new__ methods,
        # it automatically makes the path in the OS local type and confuses type checkers
        if cls._USE_NEW_PUREPATH_INIT_METHOD or TYPE_CHECKING:
            return object.__new__(cls)
        else:
            return cls._from_parts(tuple(iter_flatten(path, str)))

    def __init__(self,
                 *path:Union[str, PathLike, Iterable[Union[str, PathLike]]],
                 unquote:bool = False,
                 requote:bool = False,
                 quote_safe:str = ""
                ):
        self.unquote:bool = unquote
        self.requote:bool = requote
        self.quote_safe = quote_safe

        if self._USE_NEW_PUREPATH_INIT_METHOD:
            super().__init__(*tuple(iter_flatten(path, str)))

    def __iter__(self):
        return iter(self.parts)

    @overload
    def __getitem__(self, index:int) -> str: ...
    @overload
    def __getitem__(self, index:slice) -> List[str]: ...
    def __getitem__(self, index:Union[int, slice]) -> Union[str, List[str]]:
        return list(self.parts[index])

    def __setitem__(self,
                    index:Union[int, slice],
                    value:Union[str, PathLike, Iterable[Union[str, PathLike]]]
                   ):
        c = list(self)

        value = self.copy(value)

        if isinstance(index, int):
            c[index] = str(value)
        else:
            c[index] = list(value)

        self.raw = c

    def __delitem__(self, index:Union[int, slice]):
        c = list(self)
        del c[index]
        self.raw = c

    def __bool__(self):
        return not self.isempty()

    def __len__(self):
        return len(self.parts)

    def __truediv__(self, other:Union[str, PathLike, Iterable[Union[str, PathLike]]]): #self / other
        c = self.copy()
        c.append(other)
        return c

    @overload
    def __contains__(self,                                                     #type:ignore
                     other:Union[str, PathLike, Iterable[Union[str, PathLike]]]
                    ) -> bool: ...
    @overload
    def __contains__(self, other:object) -> NotImplementedType: ...
    def __contains__(self,
                     other:Union[str, PathLike, Iterable[Union[str, PathLike]], object]
                    ) -> Union[bool, NotImplementedType]:
        if not isinstance(other, (str, PathLike, Iterable)):
            return NotImplemented
        return all((x in list(self)) for x in self.copy(other))

    def copy(self,
             *content_override:Union[str, PathLike, Iterable[Union[str, PathLike]]]
            ) -> 'URIPath':
        """
        `copy`

        `*content_override` -- When any of these arguments are set,
            the copy will instead be initialised with these values as the path's content.

        Returns:
            A complete, deep, copy of this object; with the contents optionally overridden.
        """
        kwargs = {
            "unquote":self.unquote,
            "requote":self.requote,
            "quote_safe":self.quote_safe
        }

        return URIPath(*((self,) if len(content_override) <= 0 else content_override), **kwargs)
    __copy__ = copy
    __deepcopy__ = copy

    def append(self, value:Union[str, PathLike, Iterable[Union[str, PathLike]]]):
        appendage = []
        if isinstance(value, URIPath) :
            if all(not x.startswith("/") for x in value.raw):
                appendage = value.raw
            else:
                appendage = list(value[1:] if value[0] == "/" else value[:])
        else:
            appendage = self.copy(value).raw
        self.raw = self.raw + appendage

    def count(self, value:str) -> int:
        return list(self).count(value)

    def index(self, value:str, start:int = 0, stop:int = sys_maxsize) -> int:
        return list(self).index(value, start, stop)

    def rindex(self, value:str, start:int = 0, stop:Optional[int] = None) -> int:
        """
        `rindex`

        Similar to `index`, but searching in reverse order.

        Arguments:
            value -- The value to search for.

        Keyword Arguments:
            start -- The lower index to limit searches at, defaults to 0.
            stop -- The higher index to limit searches at, defaults to `None`,
                which equates to stopping at the end of the list.

        Returns:
            The index found.
        """
        return (len(self) - self[start:stop][-1::-1].index(value) - 1) + abs(start)

    def insert(self, index:int, value:Union[str, PathLike, Iterable[Union[str, PathLike]]]):
        value = self.copy(value).raw
        self.raw = self.raw[:index] + value + self.raw[index:]

    def remove(self, value:str):
        newraw = list(self.copy(value))
        newraw.remove(value)
        self.raw = newraw

    def isempty(self) -> bool:
        """
        `isempty`

        Returns:
            `True` if the path contains no segments, otherwise `False`.
        """
        return len(self.raw) <= 0

    def encode(self, quote: Optional[bool] = None, quote_safe:Optional[str] = None) -> str:
        """
        `encode`

        Keyword Arguments:
            quoted -- If not `None`, the path will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            quote_safe -- If quoting, these characters will be excluded when quoting.

        Returns:
            The path object, encoded as a string.
        """
        if quote is None:
            quote = self.requote

        if quote_safe is None:
            quote_safe = cast(str, self.quote_safe)

        quote_safe += "/"

        if not quote:
            return super().__str__()
        else:
            seg = tuple(uriquote(x, quote_safe) for x in self)
            if self[0] == "/": #the root slash will be consitered a part, we need to preserve that
                seg = ("/", ) + seg[1:]
            return super(URIPath, self.copy(*seg)).__str__()
    __str__ = encode
    __repr__ = encode

    def validate(self, encoded:bool = False) -> bool:
        """
        `validate`

        Returns:
            True if all characters in this object are allowed in a URI's path.
        """
        if encoded:
            return not CharacterSets.invalid_check(CharacterSets.PATH, self.encode(True))
        else:
            return not CharacterSets.invalid_check(CharacterSets.SEGMENT, *tuple(self))

    def segafter(self, value: str, last:bool = False) -> Union[str, None]:
        """
        `segafter`
        
        Retrieves the content of the after the first (or last)
        path segment matching `value`, if any; otherwise None.

        Arguments:
            value -- The exact value of a segment to find.

        Keyword Arguments:
            last -- Instead of finding the first possible segment matching `value`,
                find the last.

        Returns:
            The content of the segment comming after the found `value`,
            or `None` if `value` was not found.
        """
        if value not in self:
            return None

        ind = (self.rindex if last else self.index)(value)
        if ind >= len(self):
            return None

        return cast(str, self[ind + 1])

    def segbefore(self, value: str, last:bool = False) -> Union[str, None]:
        """
        `segbefore`
        
        Retrieves the content of the before the first (or last)
        path segment matching `value`, if any; otherwise None.

        Arguments:
            value -- The exact value of a segment to find.

        Keyword Arguments:
            last -- Instead of finding the first possible segment matching `value`,
                find the last.

        Returns:
            The content of the segment comming before the found `value`,
            or `None` if `value` was not found.
        """
        if value not in self:
            return None

        ind = (self.rindex if last else self.index)(value)
        if ind <= 0:
            return None

        return cast(str, self[ ind - 1])

    def segsearch(self,
                  pattern:Union[str, Pattern],
                  include_all:bool = False
                 ) -> Iterable[Match]:
        """
        `segsearch`

        Searches every segment in the path for the given regex `pattern`,
        returning any found as an iterable.

        Arguments:
            `pattern` -- The pattern to search for in each segment.

        Keyword Arguments:
            `include_all` -- Return every match found in a single segment, not just the first one.

        Returns:
            A iterable of found matches, in the same rough
            order of the segment they where found in.

        Yields:
            A match found.
        """
        if isinstance(pattern, str):
            pattern = regexcompile(pattern)

        for s in self:
            m = pattern.search(s)
            if include_all or m is not None:
                yield cast(Match, m)

Ancestors

  • pathlib.PurePosixPath
  • pathlib.PurePath
  • os.PathLike
  • abc.ABC
  • collections.abc.MutableSequence
  • collections.abc.Sequence
  • collections.abc.Reversible
  • collections.abc.Collection
  • collections.abc.Sized
  • collections.abc.Iterable
  • collections.abc.Container

Instance variables

prop raw : List[str]

__raw

Used internally, do not modify without express intent.

Returns

The internal list of strings used by Path types to create paths from.

Expand source code
@property
def raw(self) -> List[str]:
    """
    `__raw`

    Used internally, do not modify without express intent.

    Returns:
        The internal list of strings used by `Path` types to create paths from.
    """
    return self._raw_paths

Methods

def append(self, value: Union[str, os.PathLike, Iterable[Union[str, os.PathLike]]])

S.append(value) – append value to the end of the sequence

def copy(self, *content_override: Union[str, os.PathLike, Iterable[Union[str, os.PathLike]]]) ‑> URIPath

copy

*content_override – When any of these arguments are set, the copy will instead be initialised with these values as the path's content.

Returns

A complete, deep, copy of this object; with the contents optionally overridden.

def count(self, value: str) ‑> int

S.count(value) -> integer – return number of occurrences of value

def encode(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None) ‑> str

encode

Keyword Arguments: quoted – If not None, the path will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting.

Returns

The path object, encoded as a string.

def index(self, value: str, start: int = 0, stop: int = 9223372036854775807) ‑> int

S.index(value, [start, [stop]]) -> integer – return first index of value. Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

def insert(self, index: int, value: Union[str, os.PathLike, Iterable[Union[str, os.PathLike]]])

S.insert(index, value) – insert value before index

def isempty(self) ‑> bool

isempty

Returns

True if the path contains no segments, otherwise False.

def remove(self, value: str)

S.remove(value) – remove first occurrence of value. Raise ValueError if the value is not present.

def rindex(self, value: str, start: int = 0, stop: Optional[int] = None) ‑> int

rindex

Similar to index, but searching in reverse order.

Arguments

value – The value to search for.

Keyword Arguments: start – The lower index to limit searches at, defaults to 0. stop – The higher index to limit searches at, defaults to None, which equates to stopping at the end of the list.

Returns

The index found.

def segafter(self, value: str, last: bool = False) ‑> Optional[str]

segafter

Retrieves the content of the after the first (or last) path segment matching value, if any; otherwise None.

Arguments

value – The exact value of a segment to find.

Keyword Arguments: last – Instead of finding the first possible segment matching value, find the last.

Returns

The content of the segment comming after the found value, or None if value was not found.

def segbefore(self, value: str, last: bool = False) ‑> Optional[str]

segbefore

Retrieves the content of the before the first (or last) path segment matching value, if any; otherwise None.

Arguments

value – The exact value of a segment to find.

Keyword Arguments: last – Instead of finding the first possible segment matching value, find the last.

Returns

The content of the segment comming before the found value, or None if value was not found.

def segsearch(self, pattern: Union[str, re.Pattern], include_all: bool = False) ‑> Iterable[re.Match]

segsearch

Searches every segment in the path for the given regex pattern, returning any found as an iterable.

Arguments

pattern – The pattern to search for in each segment.

Keyword Arguments: include_all – Return every match found in a single segment, not just the first one.

Returns

A iterable of found matches, in the same rough order of the segment they where found in.

Yields

A match found.

def validate(self, encoded: bool = False) ‑> bool

validate

Returns

True if all characters in this object are allowed in a URI's path.

class URIQuery (content: Union[str, List[Tuple[str, str]], Dict[str, str], ForwardRef('URIQuery'), ForwardRef(None)] = None, *, unquote: bool = False, requote: bool = False, force_case: Literal['upper', 'lower', 'preserve'] = 'preserve', quote_safe: str = '')

URIQuery

A class used to manipulate and use a URI query in python easily.

NOTE: while this class acts and appears very similar to a tuple of dictionary items, it is not, as it allows for duplacate keys, and requires the ordering to be preserved.

Expand source code
class URIQuery(UserList):
    """
    `URIQuery`

    A class used to manipulate and use a URI query in python easily.
    
    NOTE: while this class acts and appears very similar to a tuple of dictionary items,
    it is not, as it allows for duplacate keys, and requires the ordering to be preserved.
    """

    def __parse(self, querystr:str) -> List[Tuple[str, str]]:
        parsed = uriqueryparse(querystr, keep_blank_values=True, strict_parsing = True)
        return parsed if not self.unquote else [(uriunquote(k), uriunquote(v)) for k,v in parsed]

    def __init__(self,
                 content:Union[str, List[Tuple[str, str]], Dict[str, str], 'URIQuery', None]= None,
                 *,
                 unquote:bool = False, #unquote values when unencoding strings
                 requote: bool = False, #requote values when normalizing to string
                 force_case: Literal["upper", "lower", "preserve"] = "preserve",
                 quote_safe: str = ""
                ):
        self.unquote:bool = unquote
        self.requote:bool = requote
        self.quote_safe:str = quote_safe
        self.force_case: Literal["upper", "lower", "preserve"] = force_case
        self.data:List[Tuple[str, str]]

        if isinstance(content, (dict, URIQuery)):
            content = list(content.items())
        elif isinstance(content, str):
            content = content.strip().lstrip("?").lstrip()
            if content == "":
                content = None
            else:
                if "=" not in content:
                    #normaize a nonstandard query with a empty value while still in string form
                    content += "="
                content = self.__parse(content)

        super().__init__(content)

    def __bool__(self):
        return not self.isempty()

    def __lshift__(self, count:int) -> 'URIQuery':
        c = self.copy()
        if count > 0:
            for _ in range(count):
                c.append(c.pop(0))
        else:
            for _ in range(abs(count)):
                c.insert(0, c.pop(-1))
        return c

    def __rshift__(self, count:int) -> 'URIQuery':
        return self << -count

    def __add__(self,
                other:Union[str, Tuple[str, str], Iterable[Tuple[str, str]], 'URIQuery']
               ) -> 'URIQuery':
        c = self.copy()

        if isinstance(other, str):
            other = self.__parse(other)
        elif isinstance(other, URIQuery):
            other = other.data
        elif (isinstance(other, tuple) and
              len(other) == 2 and
              isinstance(other[0], str) and
              isinstance(other[1], str)
             ):
            other = [cast(Tuple[str, str], other)]
        else:
            other = list(cast(Iterable[Tuple[str, str]], other))

        c.data += other

        return c

    def __len__(self):
        return len(self.data)

    def append(self, item:Union[str, Tuple[str, str], Iterable[Tuple[str, str]]]):
        #we can use the __add__ opperator, as this appcompishes the same thing
        self.data = list(self + item)

    def count(self, item:Union[str, Tuple[str, str]]) -> int:
        if isinstance(item, str):
            parsed = self.__parse(item)
            if len(parsed) == 1:
                item = parsed[0]
            else:
                raise TypeError(item)

        return super().count(item)

    def index(self,                                        #pylint:disable=arguments-differ
              item:Union[str, Tuple[str, str]],
              start:Union[int, SupportsIndex] = 0,
              stop:Union[int, SupportsIndex] = sys_maxsize
             ) -> int:
        if isinstance(item, str):
            parsed = self.__parse(item)
            if len(parsed) == 1:
                item = parsed[0]
            else:
                raise TypeError(item)

        return super().index(item, start, stop)

    def insert(self, i:int, item:Union[str, Tuple[str, str]]):
        if isinstance(item, str):
            parsed = self.__parse(item)
            if len(parsed) == 1:
                item = parsed[0]
            else:
                raise TypeError(item)

        super().insert(i, item)

    def remove(self, item:Union[str, Tuple[str, str]]):
        if isinstance(item, str):
            parsed = self.__parse(item)
            if len(parsed) == 1:
                item = parsed[0]
            else:
                raise TypeError(item)

        super().remove(item)

    def querykeys(self, *values:str) -> Iterable[str]:
        """
        `querykeys`

        Returns:
            An iterable with all keys of this query,
            or only the keys with one of the exact `*values` given,
            if any `*values` are given.
        """
        return (k for k,v in self if len(values) <= 0 or v in values)

    def queryvalues(self, *keys:str) -> Iterable[str]:
        """
        `queryvalues`

        Returns:
            An iterable with all values of this query,
            or only the values with one of the exact `*keys` given,
            if any `*keys` are given.
        """
        return (v for k,v in self if len(keys) <= 0 or k in keys)

    def items(self, *kvpairs:Tuple[str,str]) -> Iterable[Tuple[str, str]]:
        """
        `items`

        Returns:
            An iterable with all items of this query (formated as a tuple of `("key", "value")`),
            or only the values with one of the exact `*kvpairs` given,
            if any `*kvpairs` are given.
        """
        return (self.data if len(kvpairs) <= 0 else((k,v) for k,v in self if (k,v) in kvpairs))

    def keyindexes(self, *keys:str) -> Tuple[int, ...]:
        """
        `keyindexes`

        Returns:
            An iterable with all indexes of all entries with one of the exact `*keys` in this query.
        """
        return tuple(i for i,(k,v) in enumerate(self) if k in keys)

    def valueindexes(self, *values:str) -> Tuple[int, ...]:
        """
        `valueindexes`

        Returns:
            An iterable with all indexes of all entries
            with one of the exact `*value` in this query.
        """
        return tuple(i for i,(k,v) in enumerate(self) if v in values)

    #dictionary like methods
    def getvalues(self, key:str) -> Tuple[str, ...]:
        """
        `getvalues`

        A dictionary like get method.

        Returns:
            A tuple with all values found with the given `key`.
        """
        return tuple(self.queryvalues(key))

    #dictionary like methods
    def setvalues(self, key:str, *values:str):
        """
        `setvalues`

        A dictionary like get method.

        Sets every value in query with the key `key` to the single given value in `*values`,
        or if multiple `*values` are given,
        then it will set every key in order with a value from `*values`.
        With multiple `*values`, it's expected that the quantity of `*values`
        match the quantity of entries in the query with `key`.
        """
        inds = self.keyindexes(key)

        if len(inds) != len(values) and len(values) != 1:
            raise TypeError(values)

        for vi, qi in enumerate(inds):
            if len(values) != 1:
                value = values[vi]
            else:
                value = values[0]

            self[qi] = (key, value)

    def delkey(self, key:str):
        """
        `delkey`

        Deletes every entry in the query with key `key`.
        """
        for i in reversed(self.keyindexes(key)):
            del self[i]

    def isempty(self) -> bool:
        """
        `isempty`

        Returns:
            `True` if there are no keys or values in this query, otherwise `False`.
        """
        return len(self) <= 0

    def iskeyempty(self, key:str, all_values:bool = False) -> bool:
        """
        `iskeyempty`

        Arguments:
            `key` -- The key to check the value of.

        Keyword Arguments:
            `all_values` -- If `True`, `True` will be returned only if *all* values are empty,
                not just one.
        """
        return (all if all_values else any)(v == "" for v in self.queryvalues(key))

    def encode(self,
               quote: Optional[bool] = None,
               quote_safe:Optional[str] = None,
               force_case: Optional[Literal["upper", "lower", "preserve"]] = None
              ) -> str:
        """
        `encode`

        Keyword Arguments:
            `quoted` -- If not `None`, the URI will be quoted, if `True`; or unquoted, if `False`,
                with `None` defaulting to the objects `quote` attribute.
            `quote_safe` -- If quoting, these characters will be excluded when quoting.
            `force_case` -- If not `None`, the query's case will be converted to the given case, 
                with `None` defaulting to the objects `force_case` attribute for how case should
                be handled.

        Returns:
            This `URIQuery` object, encoded as a string.
        """
        #pylint:disable=unnecessary-lambda-assignment

        if force_case is not None and force_case not in ("upper", "lower", "preserve"):
            raise AttributeError

        if quote is None:
            quote = self.requote

        if force_case is None:
            force_case = self.force_case

        if quote_safe is None:
            quote_safe = self.quote_safe

        qmet = passthrough_first
        if quote:
            qmet = lambda s: uriquote(s, quote_safe)

        cmet = passthrough_first
        if force_case != "preserve":
            cmet = (lambda s: s.upper()) if force_case == "upper" else (lambda s: s.lower())

        quote_via=lambda *p :cmet(qmet(passthrough_first(*p)))
        #we must use items instead of the query dict to ensure that the order remains intace
        encoded = uriqueryunparse(tuple(self.items()), doseq=True, quote_via=quote_via)

        _self_tup = tuple(self.items())
        if len(_self_tup) == 1 and _self_tup[0][0] != "" and _self_tup[0][1] == "":
            #reformat a single, valueless query as just a string of the query key
            encoded = encoded.rstrip("=")

        return encoded
    __str__ = encode
    __repr__ = encode

    def validate(self, encoded:bool = False) -> bool:
        """
        `validate`

        Returns:
            True if all characters in this object are allowed in a URI query.
        """
        if encoded:
            return not CharacterSets.invalid_check(CharacterSets.QUERY, self.encode(True))
        else:
            return not CharacterSets.invalid_check(CharacterSets.QUERY,
                                                   *self.querykeys(),
                                                   *self.queryvalues()
                                                  )

    def search(self,
               keymatch:Optional[Union[str, Pattern]] = None,
               valmatch:Optional[Union[str, Pattern]] = None
              ) -> Iterable[Tuple[Optional[Match], Optional[Match]]]:
        """
        `search`

        Keyword Arguments:
            keymatch -- A optional regex pattern to match keys with.
            valmatch -- A optional regex pattern to match values with.

        Returns:
            An iterable of tuples, each with a match either for a key and/or value,
            with the format of `(Optional[Match], Optional[Match])`,
            the first being matches for keys, the second for values.
        """
        #pylint:disable=unnecessary-lambda, unnecessary-lambda-assignment
        ksch = lambda *a, **k: None
        if isinstance(keymatch, str):
            keymatch = cast(Pattern, regexcompile(keymatch))
        if keymatch is not None:
            ksch = lambda s: keymatch.search(s)

        vsch = lambda *a, **k: None
        if isinstance(valmatch, str):
            valmatch = cast(Pattern, regexcompile(valmatch))
        if valmatch is not None:
            vsch = lambda s: valmatch.search(s)

        return ((ksch(k),vsch(v)) for k,v in self if ksch(k) is not None or vsch(v) is not None)

Ancestors

  • collections.UserList
  • collections.abc.MutableSequence
  • collections.abc.Sequence
  • collections.abc.Reversible
  • collections.abc.Collection
  • collections.abc.Sized
  • collections.abc.Iterable
  • collections.abc.Container

Methods

def append(self, item: Union[str, Tuple[str, str], Iterable[Tuple[str, str]]])

S.append(value) – append value to the end of the sequence

def count(self, item: Union[str, Tuple[str, str]]) ‑> int

S.count(value) -> integer – return number of occurrences of value

def delkey(self, key: str)

delkey

Deletes every entry in the query with key key.

def encode(self, quote: Optional[bool] = None, quote_safe: Optional[str] = None, force_case: Optional[Literal['upper', 'lower', 'preserve']] = None) ‑> str

encode

Keyword Arguments: quoted – If not None, the URI will be quoted, if True; or unquoted, if False, with None defaulting to the objects quote attribute. quote_safe – If quoting, these characters will be excluded when quoting. force_case – If not None, the query's case will be converted to the given case, with None defaulting to the objects force_case attribute for how case should be handled.

Returns

This URIQuery object, encoded as a string.

def getvalues(self, key: str) ‑> Tuple[str, ...]

getvalues

A dictionary like get method.

Returns

A tuple with all values found with the given key.

def index(self, item: Union[str, Tuple[str, str]], start: Union[int, SupportsIndex] = 0, stop: Union[int, SupportsIndex] = 9223372036854775807) ‑> int

S.index(value, [start, [stop]]) -> integer – return first index of value. Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

def insert(self, i: int, item: Union[str, Tuple[str, str]])

S.insert(index, value) – insert value before index

def isempty(self) ‑> bool

isempty

Returns

True if there are no keys or values in this query, otherwise False.

def iskeyempty(self, key: str, all_values: bool = False) ‑> bool

iskeyempty

Arguments

key – The key to check the value of.

Keyword Arguments: all_values – If True, True will be returned only if all values are empty, not just one.

def items(self, *kvpairs: Tuple[str, str]) ‑> Iterable[Tuple[str, str]]

items

Returns

An iterable with all items of this query (formated as a tuple of ("key", "value")), or only the values with one of the exact *kvpairs given, if any *kvpairs are given.

def keyindexes(self, *keys: str) ‑> Tuple[int, ...]

keyindexes

Returns

An iterable with all indexes of all entries with one of the exact *keys in this query.

def querykeys(self, *values: str) ‑> Iterable[str]

querykeys

Returns

An iterable with all keys of this query, or only the keys with one of the exact *values given, if any *values are given.

def queryvalues(self, *keys: str) ‑> Iterable[str]

queryvalues

Returns

An iterable with all values of this query, or only the values with one of the exact *keys given, if any *keys are given.

def remove(self, item: Union[str, Tuple[str, str]])

S.remove(value) – remove first occurrence of value. Raise ValueError if the value is not present.

def search(self, keymatch: Union[str, re.Pattern, ForwardRef(None)] = None, valmatch: Union[str, re.Pattern, ForwardRef(None)] = None) ‑> Iterable[Tuple[Optional[re.Match], Optional[re.Match]]]

search

Keyword Arguments: keymatch – A optional regex pattern to match keys with. valmatch – A optional regex pattern to match values with.

Returns

An iterable of tuples, each with a match either for a key and/or value, with the format of (Optional[Match], Optional[Match]), the first being matches for keys, the second for values.

def setvalues(self, key: str, *values: str)

setvalues

A dictionary like get method.

Sets every value in query with the key key to the single given value in *values, or if multiple *values are given, then it will set every key in order with a value from *values. With multiple *values, it's expected that the quantity of *values match the quantity of entries in the query with key.

def validate(self, encoded: bool = False) ‑> bool

validate

Returns

True if all characters in this object are allowed in a URI query.

def valueindexes(self, *values: str) ‑> Tuple[int, ...]

valueindexes

Returns

An iterable with all indexes of all entries with one of the exact *value in this query.