Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_helpers.py274 linesDownload Raw Back to auth
1# Copyright 2015 Google Inc.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#      http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15"""Helper functions for commonly used utilities."""16 17import base6418import calendar19import datetime20from email.message import Message21import sys22import urllib23 24from google.auth import exceptions25 26# The smallest MDS cache used by this library stores tokens until 4 minutes from27# expiry.28REFRESH_THRESHOLD = datetime.timedelta(minutes=3, seconds=45)29 30 31def copy_docstring(source_class):32    """Decorator that copies a method's docstring from another class.33 34    Args:35        source_class (type): The class that has the documented method.36 37    Returns:38        Callable: A decorator that will copy the docstring of the same39            named method in the source class to the decorated method.40    """41 42    def decorator(method):43        """Decorator implementation.44 45        Args:46            method (Callable): The method to copy the docstring to.47 48        Returns:49            Callable: the same method passed in with an updated docstring.50 51        Raises:52            google.auth.exceptions.InvalidOperation: if the method already has a docstring.53        """54        if method.__doc__:55            raise exceptions.InvalidOperation("Method already has a docstring.")56 57        source_method = getattr(source_class, method.__name__)58        method.__doc__ = source_method.__doc__59 60        return method61 62    return decorator63 64 65def parse_content_type(header_value):66    """Parse a 'content-type' header value to get just the plain media-type (without parameters).67 68    This is done using the class Message from email.message as suggested in PEP 59469        (because the cgi is now deprecated and will be removed in python 3.13,70        see https://peps.python.org/pep-0594/#cgi).71 72    Args:73        header_value (str): The value of a 'content-type' header as a string.74 75    Returns:76        str: A string with just the lowercase media-type from the parsed 'content-type' header.77            If the provided content-type is not parsable, returns 'text/plain',78            the default value for textual files.79    """80    m = Message()81    m["content-type"] = header_value82    return (83        m.get_content_type()84    )  # Despite the name, actually returns just the media-type85 86 87def utcnow():88    """Returns the current UTC datetime.89 90    Returns:91        datetime: The current time in UTC.92    """93    # We used datetime.utcnow() before, since it's deprecated from python 3.12,94    # we are using datetime.now(timezone.utc) now. "utcnow()" is offset-native95    # (no timezone info), but "now()" is offset-aware (with timezone info).96    # This will cause datetime comparison problem. For backward compatibility,97    # we need to remove the timezone info.98    now = datetime.datetime.now(datetime.timezone.utc)99    now = now.replace(tzinfo=None)100    return now101 102 103def datetime_to_secs(value):104    """Convert a datetime object to the number of seconds since the UNIX epoch.105 106    Args:107        value (datetime): The datetime to convert.108 109    Returns:110        int: The number of seconds since the UNIX epoch.111    """112    return calendar.timegm(value.utctimetuple())113 114 115def to_bytes(value, encoding="utf-8"):116    """Converts a string value to bytes, if necessary.117 118    Args:119        value (Union[str, bytes]): The value to be converted.120        encoding (str): The encoding to use to convert unicode to bytes.121            Defaults to "utf-8".122 123    Returns:124        bytes: The original value converted to bytes (if unicode) or as125            passed in if it started out as bytes.126 127    Raises:128        google.auth.exceptions.InvalidValue: If the value could not be converted to bytes.129    """130    result = value.encode(encoding) if isinstance(value, str) else value131    if isinstance(result, bytes):132        return result133    else:134        raise exceptions.InvalidValue(135            "{0!r} could not be converted to bytes".format(value)136        )137 138 139def from_bytes(value):140    """Converts bytes to a string value, if necessary.141 142    Args:143        value (Union[str, bytes]): The value to be converted.144 145    Returns:146        str: The original value converted to unicode (if bytes) or as passed in147            if it started out as unicode.148 149    Raises:150        google.auth.exceptions.InvalidValue: If the value could not be converted to unicode.151    """152    result = value.decode("utf-8") if isinstance(value, bytes) else value153    if isinstance(result, str):154        return result155    else:156        raise exceptions.InvalidValue(157            "{0!r} could not be converted to unicode".format(value)158        )159 160 161def update_query(url, params, remove=None):162    """Updates a URL's query parameters.163 164    Replaces any current values if they are already present in the URL.165 166    Args:167        url (str): The URL to update.168        params (Mapping[str, str]): A mapping of query parameter169            keys to values.170        remove (Sequence[str]): Parameters to remove from the query string.171 172    Returns:173        str: The URL with updated query parameters.174 175    Examples:176 177        >>> url = 'http://example.com?a=1'178        >>> update_query(url, {'a': '2'})179        http://example.com?a=2180        >>> update_query(url, {'b': '3'})181        http://example.com?a=1&b=3182        >> update_query(url, {'b': '3'}, remove=['a'])183        http://example.com?b=3184 185    """186    if remove is None:187        remove = []188 189    # Split the URL into parts.190    parts = urllib.parse.urlparse(url)191    # Parse the query string.192    query_params = urllib.parse.parse_qs(parts.query)193    # Update the query parameters with the new parameters.194    query_params.update(params)195    # Remove any values specified in remove.196    query_params = {197        key: value for key, value in query_params.items() if key not in remove198    }199    # Re-encoded the query string.200    new_query = urllib.parse.urlencode(query_params, doseq=True)201    # Unsplit the url.202    new_parts = parts._replace(query=new_query)203    return urllib.parse.urlunparse(new_parts)204 205 206def scopes_to_string(scopes):207    """Converts scope value to a string suitable for sending to OAuth 2.0208    authorization servers.209 210    Args:211        scopes (Sequence[str]): The sequence of scopes to convert.212 213    Returns:214        str: The scopes formatted as a single string.215    """216    return " ".join(scopes)217 218 219def string_to_scopes(scopes):220    """Converts stringifed scopes value to a list.221 222    Args:223        scopes (Union[Sequence, str]): The string of space-separated scopes224            to convert.225    Returns:226        Sequence(str): The separated scopes.227    """228    if not scopes:229        return []230 231    return scopes.split(" ")232 233 234def padded_urlsafe_b64decode(value):235    """Decodes base64 strings lacking padding characters.236 237    Google infrastructure tends to omit the base64 padding characters.238 239    Args:240        value (Union[str, bytes]): The encoded value.241 242    Returns:243        bytes: The decoded value244    """245    b64string = to_bytes(value)246    padded = b64string + b"=" * (-len(b64string) % 4)247    return base64.urlsafe_b64decode(padded)248 249 250def unpadded_urlsafe_b64encode(value):251    """Encodes base64 strings removing any padding characters.252 253    `rfc 7515`_ defines Base64url to NOT include any padding254    characters, but the stdlib doesn't do that by default.255 256    _rfc7515: https://tools.ietf.org/html/rfc7515#page-6257 258    Args:259        value (Union[str|bytes]): The bytes-like value to encode260 261    Returns:262        Union[str|bytes]: The encoded value263    """264    return base64.urlsafe_b64encode(value).rstrip(b"=")265 266 267def is_python_3():268    """Check if the Python interpreter is Python 2 or 3.269 270    Returns:271        bool: True if the Python interpreter is Python 3 and False otherwise.272    """273    return sys.version_info > (3, 0)274 
codekingpro/portable-devtools · Team Ai