# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

"""
loader.py

The loader has to load the signature module completely at startup,
to make sure that the functions are available when needed.
This is meanwhile necessary to make the '__doc__' attribute work correctly.

It does not mean that everything is initialized in advance. Only the modules
are loaded completely after 'import PySide6'.

This version uses both a normal directory, but has also an embedded ZIP file
as a fallback solution. The ZIP file is generated by 'embedding_generator.py'
and embedded into 'signature.cpp' as "embed/signature.inc".

Meanwhile, the ZIP file grew so much, that MSVC had problems
with it's 64k string limit, so we had to break the string up.
See 'zipped_string_sequence' in signature.cpp.
"""

import sys
import os
import traceback
import types


# name used in signature.cpp
def pyside_type_init(type_key, sig_strings):
    return parser.pyside_type_init(type_key, sig_strings)

# name used in signature.cpp
def create_signature(props, key):
    return layout.create_signature(props, key)

# name used in signature.cpp
def seterror_argument(args, func_name, info):
    return errorhandler.seterror_argument(args, func_name, info)

# name used in signature.cpp
def make_helptext(func):
    return errorhandler.make_helptext(func)

# name used in signature.cpp
def finish_import(module):
    return importhandler.finish_import(module)

# name used in signature.cpp
def feature_import(*args, **kwds):
    # don't spend a stack level here for speed and compatibility
    global feature_import
    feature_import = feature.feature_import
    return feature_import(*args, **kwds)

# name used in signature.cpp
def feature_imported(*args, **kwds):
    # don't spend a stack level here for speed and compatibility
    global feature_imported
    feature_imported = feature.feature_imported
    return feature_imported(*args, **kwds)


import builtins
import signature_bootstrap
from shibokensupport import signature, feature
signature.get_signature = signature_bootstrap.get_signature
# PYSIDE-1019: Publish the __feature__ dictionary.
feature.pyside_feature_dict = signature_bootstrap.pyside_feature_dict
builtins.__feature_import__ = signature_bootstrap.__feature_import__
del signature_bootstrap

is_pypy = hasattr(sys, "pypy_version_info")


def put_into_package(package, module, override=None):
    # take the last component of the module name
    name = (override if override else module.__spec__.name).rsplit(".", 1)[-1]
    # allow access as {package}.{name}
    if package:
        setattr(package, name, module)
    # put into sys.modules as a package to allow all import options
    fullname = f"{package.__spec__.name}.{name}" if package else name
    module.__spec__.name = fullname
    # publish new dotted name in sys.modules
    sys.modules[fullname] = module


def move_into_pyside_package():
    import shibokensupport
    import PySide6
    try:
        import PySide6.support
    except ModuleNotFoundError:
        # This can happen in the embedding case.
        put_into_package(PySide6, shibokensupport, "support")
    if not is_pypy:
        put_into_package(PySide6.support, feature)
    put_into_package(PySide6.support, signature)
    put_into_package(PySide6.support.signature, mapping)
    put_into_package(PySide6.support.signature, errorhandler)
    put_into_package(PySide6.support.signature, layout)
    put_into_package(PySide6.support.signature, lib)
    put_into_package(PySide6.support.signature, parser)
    put_into_package(PySide6.support.signature, importhandler)
    put_into_package(PySide6.support.signature.lib, enum_sig)
    put_into_package(PySide6.support.signature.lib, pyi_generator)
    put_into_package(PySide6.support.signature.lib, tool)

from shibokensupport.signature import mapping
from shibokensupport.signature import errorhandler
from shibokensupport.signature import layout
from shibokensupport.signature import lib
from shibokensupport.signature import parser
from shibokensupport.signature import importhandler
from shibokensupport.signature.lib import enum_sig
from shibokensupport.signature.lib import pyi_generator
from shibokensupport.signature.lib import tool

import enum

post_init = lambda:None     # default

if "PySide6" in sys.modules:
    # We publish everything under "PySide6.support", again.
    move_into_pyside_package()
    # PYSIDE-1502: Make sure that support can be imported.
    try:
        import PySide6.support
    except ModuleNotFoundError as e:
        print("PySide6.support could not be imported. "
              "This is a serious configuration error.", file=sys.stderr)
        raise

    def post_init():
        """
        This function needs to be called explicitly when all function pointers are set.
        Doing this during import has bad side-effects when preloading the loader.
        """
        # PYSIDE-1019: Modify `__import__` to be `__feature__` aware.
        if not is_pypy:
            # PYSIDE-535: Cannot enable __feature__ for various reasons.
            import PySide6.support.feature
            sys.modules["__feature__"] = PySide6.support.feature
            builtins.__orig_import__ = builtins.__import__
            builtins.__import__ = builtins.__feature_import__

# end of file
