diff --git a/doc/source/conf.py b/doc/source/conf.py index 63aeb88..061266f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -13,110 +13,11 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import ast -import collections -import os.path -import sys - -PY3 = sys.version_info[:2] > (2, 7) -PY34 = sys.version_info[:2] > (3, 3) - -with open( - os.path.join( - os.path.dirname(__file__), '..', '..', - 'exec_helpers', '__init__.py' - ) -) as f: - source = f.read() - - -# noinspection PyUnresolvedReferences -def get_simple_vars_from_src(src): - """Get simple (string/number/boolean and None) assigned values from source. - - :param src: Source code - :type src: str - :returns: OrderedDict with keys, values = variable names, values - :rtype: typing.Dict[ - str, - typing.Union[ - str, bytes, - int, float, complex, - list, set, dict, tuple, - None, - ] - ] - - Limitations: Only defined from scratch variables. - Not supported by design: - * Imports - * Executable code, including string formatting and comprehensions. - - Examples: - - >>> string_sample = "a = '1'" - >>> get_simple_vars_from_src(string_sample) - OrderedDict([('a', '1')]) - - >>> int_sample = "b = 1" - >>> get_simple_vars_from_src(int_sample) - OrderedDict([('b', 1)]) - - >>> list_sample = "c = [u'1', b'1', 1, 1.0, 1j, None]" - >>> result = get_simple_vars_from_src(list_sample) - >>> result == collections.OrderedDict( - ... [('c', [u'1', b'1', 1, 1.0, 1j, None])] - ... ) - True - - >>> iterable_sample = "d = ([1], {1: 1}, {1})" - >>> get_simple_vars_from_src(iterable_sample) - OrderedDict([('d', ([1], {1: 1}, {1}))]) - - >>> multiple_assign = "e = f = g = 1" - >>> get_simple_vars_from_src(multiple_assign) - OrderedDict([('e', 1), ('f', 1), ('g', 1)]) - """ - ast_data = ( - ast.Str, ast.Num, - ast.List, ast.Set, ast.Dict, ast.Tuple - ) - if PY3: - ast_data += (ast.Bytes,) - if PY34: - ast_data += (ast.NameConstant,) - - tree = ast.parse(src) - - result = collections.OrderedDict() - - for node in ast.iter_child_nodes(tree): - if not isinstance(node, ast.Assign): # We parse assigns only - continue - try: - if isinstance(node.value, ast_data): - value = ast.literal_eval(node.value) - elif isinstance( # NameConstant in python < 3.4 - node.value, ast.Name - ) and isinstance( - node.value.ctx, ast.Load # Read constant - ): - value = ast.literal_eval(node.value) - else: - continue - except ValueError: - continue - for tgt in node.targets: - if isinstance( - tgt, ast.Name - ) and isinstance( - tgt.ctx, ast.Store - ): - result[tgt.id] = value - return result - - -variables = get_simple_vars_from_src(source) +import pkg_resources + +release = pkg_resources.get_distribution("exec-helpers").version +version = '.'.join(release.split('.')[:2]) + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -168,9 +69,8 @@ def get_simple_vars_from_src(src): # built documents. # # The short X.Y version. -version = variables['__version__'] + # The full version, including alpha/beta/rc tags. -release = variables['__version__'] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/exec_helpers/__init__.py b/exec_helpers/__init__.py index 6660310..29af91b 100644 --- a/exec_helpers/__init__.py +++ b/exec_helpers/__init__.py @@ -14,6 +14,8 @@ """Execution helpers for simplified usage of subprocess and ssh.""" +import pkg_resources + from .proc_enums import ExitCodes from .exceptions import ( @@ -51,7 +53,17 @@ "async_api", ) -__version__ = "3.1.3" +try: + __version__ = pkg_resources.get_distribution(__name__).version +except pkg_resources.DistributionNotFound: + # package is not installed, try to get from SCM + try: + import setuptools_scm # type: ignore + + __version__ = setuptools_scm.get_version() + except ImportError: + pass + __author__ = "Alexey Stepanov" __author_email__ = "penguinolog@gmail.com" __maintainers__ = { diff --git a/exec_helpers/_ssh_client_base.py b/exec_helpers/_ssh_client_base.py index 1e83378..cd3b16c 100644 --- a/exec_helpers/_ssh_client_base.py +++ b/exec_helpers/_ssh_client_base.py @@ -53,8 +53,8 @@ class RetryOnExceptions(tenacity.retry_if_exception): # type: ignore def __init__( self, - retry_on: typing.Union[typing.Type[BaseException], typing.Tuple[typing.Type[BaseException], ...]], - reraise: typing.Union[typing.Type[BaseException], typing.Tuple[typing.Type[BaseException], ...]], + retry_on: "typing.Union[typing.Type[BaseException], typing.Tuple[typing.Type[BaseException], ...]]", + reraise: "typing.Union[typing.Type[BaseException], typing.Tuple[typing.Type[BaseException], ...]]", ) -> None: """Retry on exceptions, except several types.""" super(RetryOnExceptions, self).__init__(lambda e: isinstance(e, retry_on) and not isinstance(e, reraise)) diff --git a/setup.py b/setup.py index 64d19d5..e246967 100644 --- a/setup.py +++ b/setup.py @@ -235,7 +235,6 @@ def get_simple_vars_from_src(src): "{name} <{email}>".format(name=name, email=email) for name, email in variables["__maintainers__"].items() ), url=variables["__url__"], - version=variables["__version__"], license=variables["__license__"], description=variables["__description__"], long_description=long_description, @@ -248,9 +247,13 @@ def get_simple_vars_from_src(src): # situations as progressive releases of projects are done. # Blacklist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951 # Blacklist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086 - setup_requires="setuptools >= 21.0.0,!=24.0.0," - "!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2," - "!=36.2.0", + setup_requires=[ + "setuptools >= 21.0.0,!=24.0.0," + "!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2," + "!=36.2.0", + "setuptools_scm", + ], + use_scm_version=True, install_requires=required, package_data={"exec_helpers": ["py.typed"]}, )