Initialize the printing system.

    This determines the behavior of the :func:`ascii`, :func:`unicode`,
    and :func:`latex` functions, as well as the ``__str__`` and ``__repr__`` of
    any :class:`.Expression`.

    The routine may be called in one of two forms. First,

    ::

        init_printing(
            str_format=<str_fmt>, repr_format=<repr_fmt>,
            caching=<use_caching>, **settings)

    provides a simplified, "manual" setup with the following parameters.

    Args:
        str_format (str): Format for ``__str__`` representation of an
            :class:`.Expression`. One of 'ascii', 'unicode', 'latex', 'srepr',
            'indsrepr' ("indented `srepr`"), or 'tree'. The string
            representation will be affected by the settings for the
            corresponding print routine, e.g. :func:`unicode` for
            ``str_format='unicode'``
        repr_format (str): Like `str_format`, but for ``__repr__``. This is
            what gets displayed in an interactive (I)Python session.
        caching (bool): By default, the printing functions  (:func:`ascii`,
            :func:`unicode`, :func:`latex`) cache their result for any
            expression and sub-expression. This is both for efficiency and to
            give the ability to to supply custom strings for subexpression by
            passing a `cache` parameter to the printing functions. Initializing
            the printing system with ``caching=False`` disables this
            possibility.
        settings: Any setting understood by any of the printing routines.

    Second,

    ::

        init_printing(inifile=<path_to_file>)


    allows for more detailed settings through a config file, see the
    :ref:`notes on using an INI file <ini_file_printing>`.

    If `str_format` or `repr_format` are not given, they will be set to
    'unicode' if the current terminal is known to support an UTF8 (accordig to
    ``sys.stdout.encoding``), and 'ascii' otherwise.

    Generally, :func:`init_printing` should be called only once at the
    beginning of a script or notebook. If it is called multiple times, any
    settings accumulate. To avoid this and to reset the printing system to the
    defaults, you may pass ``reset=True``.  In a Jupyter notebook, expressions
    are rendered graphically via LaTeX, using the settings as they affect the
    :func:`latex` printer.

    The :func:`sympy.init_printing()` routine is called automatically, unless
    `init_sympy` is given as ``False``.

    See also:
        :func:`configure_printing` allows to temporarily change the printing
        system from what was configured in :func:`init_printing`.

def init_printing(*, reset=False, init_sympy=True, **kwargs):
    """Initialize the printing system.

    This determines the behavior of the :func:`ascii`, :func:`unicode`,
    and :func:`latex` functions, as well as the ``__str__`` and ``__repr__`` of
    any :class:`.Expression`.

    The routine may be called in one of two forms. First,

    ::

        init_printing(
            str_format=<str_fmt>, repr_format=<repr_fmt>,
            caching=<use_caching>, **settings)

    provides a simplified, "manual" setup with the following parameters.

    Args:
        str_format (str): Format for ``__str__`` representation of an
            :class:`.Expression`. One of 'ascii', 'unicode', 'latex', 'srepr',
            'indsrepr' ("indented `srepr`"), or 'tree'. The string
            representation will be affected by the settings for the
            corresponding print routine, e.g. :func:`unicode` for
            ``str_format='unicode'``
        repr_format (str): Like `str_format`, but for ``__repr__``. This is
            what gets displayed in an interactive (I)Python session.
        caching (bool): By default, the printing functions  (:func:`ascii`,
            :func:`unicode`, :func:`latex`) cache their result for any
            expression and sub-expression. This is both for efficiency and to
            give the ability to to supply custom strings for subexpression by
            passing a `cache` parameter to the printing functions. Initializing
            the printing system with ``caching=False`` disables this
            possibility.
        settings: Any setting understood by any of the printing routines.

    Second,

    ::

        init_printing(inifile=<path_to_file>)


    allows for more detailed settings through a config file, see the
    :ref:`notes on using an INI file <ini_file_printing>`.

    If `str_format` or `repr_format` are not given, they will be set to
    'unicode' if the current terminal is known to support an UTF8 (accordig to
    ``sys.stdout.encoding``), and 'ascii' otherwise.

    Generally, :func:`init_printing` should be called only once at the
    beginning of a script or notebook. If it is called multiple times, any
    settings accumulate. To avoid this and to reset the printing system to the
    defaults, you may pass ``reset=True``.  In a Jupyter notebook, expressions
    are rendered graphically via LaTeX, using the settings as they affect the
    :func:`latex` printer.

    The :func:`sympy.init_printing()` routine is called automatically, unless
    `init_sympy` is given as ``False``.

    See also:
        :func:`configure_printing` allows to temporarily change the printing
        system from what was configured in :func:`init_printing`.
    """
    # return either None (default) or a dict of frozen attributes if
    # ``_freeze=True`` is given as a keyword argument (internal use in
    # `configure_printing` only)
    logger = logging.getLogger(__name__)
    if reset:
        SympyPrinter._global_settings = {}
    if init_sympy:
        if kwargs.get('repr_format', '') == 'unicode':
            sympy_init_printing(use_unicode=True)
        if kwargs.get('repr_format', '') == 'ascii':
            sympy_init_printing(use_unicode=False)
        else:
            sympy_init_printing()  # let sympy decide by itself
    if 'inifile' in kwargs:
        invalid_kwargs = False
        if '_freeze' in kwargs:
            _freeze = kwargs['_freeze']
            if len(kwargs) != 2:
                invalid_kwargs = True
        else:
            _freeze = False
            if len(kwargs) != 1:
                invalid_kwargs = True
        if invalid_kwargs:
            raise TypeError(
                "The `inifile` argument cannot be combined with any "
                "other keyword arguments")
        logger.debug(
            "Initializating printing from INI file %s", kwargs['inifile'])
        return _init_printing_from_file(kwargs['inifile'], _freeze=_freeze)
    else:
        logger.debug(
            "Initializating printing with direct settings: %s", repr(kwargs))
        return _init_printing(**kwargs)