#-----------------------------------------------------------------------------# Copyright (c) Anaconda, Inc., and Bokeh Contributors.# All rights reserved.## The full license is in the file LICENSE.txt, distributed with this software.#-----------------------------------------------------------------------------''' Functions useful for string manipulations or encoding.'''#-----------------------------------------------------------------------------# Boilerplate#-----------------------------------------------------------------------------from__future__importannotationsimportlogging# isort:skiplog=logging.getLogger(__name__)#-----------------------------------------------------------------------------# Imports#-----------------------------------------------------------------------------# Standard library importsimportrefromtypingimportAny,Iterable,overloadfromurllib.parseimportquote_plus#-----------------------------------------------------------------------------# Globals and constants#-----------------------------------------------------------------------------__all__=('append_docstring','format_docstring','indent','nice_join','snakify',)#-----------------------------------------------------------------------------# General API#-----------------------------------------------------------------------------
[docs]defindent(text:str,n:int=2,ch:str=" ")->str:''' Indent all the lines in a given block of text by a specified amount. Args: text (str) : The text to indent n (int, optional) : The amount to indent each line by (default: 2) ch (char, optional) : What character to fill the indentation with (default: " ") '''padding=ch*nreturn"\n".join(padding+lineforlineintext.split("\n"))
[docs]defnice_join(seq:Iterable[str],*,sep:str=", ",conjunction:str="or")->str:''' Join together sequences of strings into English-friendly phrases using the conjunction ``or`` when appropriate. Args: seq (seq[str]) : a sequence of strings to nicely join sep (str, optional) : a sequence delimiter to use (default: ", ") conjunction (str or None, optional) : a conjunction to use for the last two items, or None to reproduce basic join behaviour (default: "or") Returns: a joined string Examples: >>> nice_join(["a", "b", "c"]) 'a, b or c' '''seq=[str(x)forxinseq]iflen(seq)<=1orconjunctionisNone:returnsep.join(seq)else:returnf"{sep.join(seq[:-1])}{conjunction}{seq[-1]}"
[docs]defsnakify(name:str,sep:str="_")->str:''' Convert CamelCase to snake_case. '''name=re.sub("([A-Z]+)([A-Z][a-z])",rf"\1{sep}\2",name)name=re.sub("([a-z\\d])([A-Z])",rf"\1{sep}\2",name)returnname.lower()
[docs]defappend_docstring(docstring:str|None,extra:str)->str|None:''' Safely append to docstrings. When Python is executed with the ``-OO`` option, doc strings are removed and replaced the value ``None``. This function guards against appending the extra content in that case. Args: docstring (str or None) : The docstring to format, or None extra (str): the content to append if docstring is not None Returns: str or None '''returnNoneifdocstringisNoneelsedocstring+extra
[docs]defformat_docstring(docstring:str|None,*args:Any,**kwargs:Any)->str|None:''' Safely format docstrings. When Python is executed with the ``-OO`` option, doc strings are removed and replaced the value ``None``. This function guards against applying the string formatting options in that case. Args: docstring (str or None) : The docstring to format, or ``None`` args (tuple) : string formatting arguments for the docsring kwargs (dict) : string formatting arguments for the docsring Returns: str or None '''returnNoneifdocstringisNoneelsedocstring.format(*args,**kwargs)
defformat_url_query_arguments(url:str,arguments:dict[str,str]|None=None)->str:''' Format a base URL with optional query arguments Args: url (str) : An base URL to append query arguments to arguments (dict or None, optional) : A mapping of key/value URL query arguments, or None (default: None) Returns: str '''ifargumentsisnotNone:items=(f"{quote_plus(key)}={quote_plus(value)}"forkey,valueinarguments.items())url+="?"+"&".join(items)returnurl#-----------------------------------------------------------------------------# Dev API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Private API#-----------------------------------------------------------------------------#-----------------------------------------------------------------------------# Code#-----------------------------------------------------------------------------