1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
3
4import imp
5import sys
6import os
7
8from . import build_root, package_name, package_root
9
10if sys.version_info < (3,):
11    getcwd = os.getcwdu
12else:
13    getcwd = os.getcwd
14
15
16def _import_from(mod, path, mod_dir=None, allow_error=False):
17    """
18    Imports a module from a specific path
19
20    :param mod:
21        A unicode string of the module name
22
23    :param path:
24        A unicode string to the directory containing the module
25
26    :param mod_dir:
27        If the sub directory of "path" is different than the "mod" name,
28        pass the sub directory as a unicode string
29
30    :param allow_error:
31        If an ImportError should be raised when the module can't be imported
32
33    :return:
34        None if not loaded, otherwise the module
35    """
36
37    if mod_dir is None:
38        mod_dir = mod.replace('.', os.sep)
39
40    if not os.path.exists(path):
41        return None
42
43    if not os.path.exists(os.path.join(path, mod_dir)) \
44            and not os.path.exists(os.path.join(path, mod_dir + '.py')):
45        return None
46
47    if os.sep in mod_dir:
48        append, mod_dir = mod_dir.rsplit(os.sep, 1)
49        path = os.path.join(path, append)
50
51    try:
52        mod_info = imp.find_module(mod_dir, [path])
53        return imp.load_module(mod, *mod_info)
54    except ImportError:
55        if allow_error:
56            raise
57        return None
58
59
60def _preload(require_oscrypto, print_info):
61    """
62    Preloads asn1crypto and optionally oscrypto from a local source checkout,
63    or from a normal install
64
65    :param require_oscrypto:
66        A bool if oscrypto needs to be preloaded
67
68    :param print_info:
69        A bool if info about asn1crypto and oscrypto should be printed
70    """
71
72    if print_info:
73        print('Working dir: ' + getcwd())
74        print('Python ' + sys.version.replace('\n', ''))
75
76    asn1crypto = None
77    oscrypto = None
78
79    if require_oscrypto:
80        # Some CI services don't use the package name for the dir
81        if package_name == 'oscrypto':
82            oscrypto_dir = package_root
83        else:
84            oscrypto_dir = os.path.join(build_root, 'oscrypto')
85        oscrypto_tests = None
86        if os.path.exists(oscrypto_dir):
87            oscrypto_tests = _import_from('oscrypto_tests', oscrypto_dir, 'tests')
88        if oscrypto_tests is None:
89            import oscrypto_tests
90        asn1crypto, oscrypto = oscrypto_tests.local_oscrypto()
91
92    else:
93        if package_name == 'asn1crypto':
94            asn1crypto_dir = package_root
95        else:
96            asn1crypto_dir = os.path.join(build_root, 'asn1crypto')
97        if os.path.exists(asn1crypto_dir):
98            asn1crypto = _import_from('asn1crypto', asn1crypto_dir)
99        if asn1crypto is None:
100            import asn1crypto
101
102    if print_info:
103        print(
104            '\nasn1crypto: %s, %s' % (
105                asn1crypto.__version__,
106                os.path.dirname(asn1crypto.__file__)
107            )
108        )
109        if require_oscrypto:
110            print(
111                'oscrypto: %s backend, %s, %s' % (
112                    oscrypto.backend(),
113                    oscrypto.__version__,
114                    os.path.dirname(oscrypto.__file__)
115                )
116            )
117