"""Code related to optional dependencies."""
import os
import sys
import locale
from importlib.util import find_spec
__all__ = [
'set_url_support',
'get_config_read_mode',
]
_jsonschema = jsonvalidator = find_spec('jsonschema')
_jsonnet = find_spec('_jsonnet')
_url_validator = find_spec('validators')
_requests = find_spec('requests')
_docstring_parser = find_spec('docstring_parser')
_argcomplete = find_spec('argcomplete')
_dataclasses = find_spec('dataclasses')
jsonschema_support = False if _jsonschema is None else True
jsonnet_support = False if any(x is None for x in [_jsonnet, _jsonschema]) else True
url_support = False if any(x is None for x in [_url_validator, _requests]) else True
docstring_parser_support = False if _docstring_parser is None else True
argcomplete_support = False if _argcomplete is None else True
dataclasses_support = False if _dataclasses is None else True
_config_read_mode = 'fr'
if sys.version_info.minor > 5:
ModuleNotFound = ModuleNotFoundError
else:
class ModuleNotFound(Exception): # type: ignore
pass
if jsonschema_support:
from jsonschema.exceptions import ValidationError as jsonschemaValidationError
else:
jsonschemaValidationError = None
def import_jsonschema(importer):
try:
import jsonschema
from jsonschema import Draft7Validator as jsonvalidator
return jsonschema, jsonvalidator
except (ImportError, ModuleNotFound) as ex:
raise ImportError('jsonschema package is required by '+importer+' :: '+str(ex)) from ex
def import_jsonnet(importer):
try:
import _jsonnet
return _jsonnet
except (ImportError, ModuleNotFound) as ex:
raise ImportError('jsonnet package is required by '+importer+' :: '+str(ex)) from ex
def import_url_validator(importer):
try:
from validators.url import url as url_validator
return url_validator
except (ImportError, ModuleNotFound) as ex:
raise ImportError('validators package is required by '+importer+' :: '+str(ex)) from ex
def import_requests(importer):
try:
import requests
return requests
except (ImportError, ModuleNotFound) as ex:
raise ImportError('requests package is required by '+importer+' :: '+str(ex)) from ex
def import_docstring_parse(importer):
try:
from docstring_parser import parse as docstring_parse
return docstring_parse
except (ImportError, ModuleNotFound) as ex:
raise ImportError('docstring-parser package is required by '+importer+' :: '+str(ex)) from ex
def import_argcomplete(importer):
try:
import argcomplete
return argcomplete
except (ImportError, ModuleNotFound) as ex:
raise ImportError('argcomplete package is required by '+importer+' :: '+str(ex)) from ex
def import_dataclasses(importer):
try:
import dataclasses
return dataclasses
except (ImportError, ModuleNotFound) as ex:
raise ImportError('dataclasses package is required by '+importer+' :: '+str(ex)) from ex
[docs]def set_url_support(enabled:bool):
"""Enables/disables URL support for config read mode."""
if enabled and not url_support:
pkg = ['validators', 'requests']
missing = {pkg[n] for n, x in enumerate([_url_validator, _requests]) if x is None}
raise ImportError('Missing packages for URL support: '+str(missing))
global _config_read_mode
_config_read_mode = 'fur' if enabled else 'fr'
[docs]def get_config_read_mode() -> str:
"""Returns the current config reading mode."""
return _config_read_mode
files_completer = None
if argcomplete_support:
from argcomplete.completers import FilesCompleter
files_completer = FilesCompleter()
class FilesCompleterMethod:
"""Completer method for Action classes that should complete files."""
def completer(self, prefix, **kwargs):
return sorted(files_completer(prefix, **kwargs))
class TypeCastCompleterMethod:
"""Completer method for Action classes with a casting type."""
def completer(self, prefix, **kwargs):
if chr(int(os.environ['COMP_TYPE'])) == '?':
try:
self.type(prefix) # pylint: disable=no-member
msg = 'value already valid, '
except ValueError:
msg = 'value not yet valid, '
msg += 'expected type '+self.type.__name__ # pylint: disable=no-member
return argcomplete_warn_redraw_prompt(prefix, msg)
def argcomplete_warn_redraw_prompt(prefix, message):
argcomplete = import_argcomplete('argcomplete_warn_redraw_prompt')
if prefix != '':
argcomplete.warn(message)
try:
shell_pid = int(os.popen('ps -p %d -oppid=' % os.getppid()).read().strip())
os.kill(shell_pid, 28)
except ValueError:
pass
_ = '_' if locale.getlocale()[1] != 'UTF-8' else '\xa0'
return [_+message.replace(' ', _), '']