|
18 | 18 |
|
19 | 19 | from __future__ import annotations |
20 | 20 |
|
21 | | -# Standard Library |
22 | | -import ast |
23 | | -import os.path |
24 | | -import sys |
25 | | - |
26 | 21 | # External Dependencies |
27 | 22 | import setuptools |
28 | 23 |
|
29 | | -PACKAGE_NAME = "exec_helpers" |
30 | | - |
31 | | -with open(os.path.join(os.path.dirname(__file__), PACKAGE_NAME, "__init__.py")) as f: |
32 | | - SOURCE = f.read() |
33 | | - |
34 | | -with open("requirements.txt") as f: |
35 | | - REQUIRED = f.read().splitlines() |
36 | | - |
37 | | -with open("README.rst") as f: |
38 | | - LONG_DESCRIPTION = f.read() |
39 | | - |
40 | | - |
41 | | -# noinspection PyUnresolvedReferences |
42 | | -def get_simple_vars_from_src( |
43 | | - src: str, |
44 | | -) -> dict[str, str | bytes | int | float | complex | list | set | dict | tuple | None | bool | Ellipsis]: |
45 | | - """Get simple (string/number/boolean and None) assigned values from source. |
46 | | -
|
47 | | - :param src: Source code |
48 | | - :type src: str |
49 | | - :return: OrderedDict with keys, values = variable names, values |
50 | | - :rtype: dict[str, str | bytes | int | float | complex | list | set | dict | tuple | None | bool | Ellipsis] |
51 | | -
|
52 | | - Limitations: Only defined from scratch variables. |
53 | | - Not supported by design: |
54 | | - * Imports |
55 | | - * Executable code, including string formatting and comprehensions. |
56 | | -
|
57 | | - Examples: |
58 | | - >>> string_sample = "a = '1'" |
59 | | - >>> get_simple_vars_from_src(string_sample) |
60 | | - {'a': '1'} |
61 | | -
|
62 | | - >>> int_sample = "b = 1" |
63 | | - >>> get_simple_vars_from_src(int_sample) |
64 | | - {'b': 1} |
65 | | -
|
66 | | - >>> list_sample = "c = [u'1', b'1', 1, 1.0, 1j, None]" |
67 | | - >>> result = get_simple_vars_from_src(list_sample) |
68 | | - >>> result == {'c': [u'1', b'1', 1, 1.0, 1j, None]} |
69 | | - True |
70 | | -
|
71 | | - >>> iterable_sample = "d = ([1], {1: 1}, {1})" |
72 | | - >>> get_simple_vars_from_src(iterable_sample) |
73 | | - {'d': ([1], {1: 1}, {1})} |
74 | | -
|
75 | | - >>> multiple_assign = "e = f = g = 1" |
76 | | - >>> get_simple_vars_from_src(multiple_assign) |
77 | | - {'e': 1, 'f': 1, 'g': 1} |
78 | | - """ |
79 | | - if sys.version_info[:2] < (3, 8): |
80 | | - ast_data = (ast.Str, ast.Num, ast.List, ast.Set, ast.Dict, ast.Tuple, ast.Bytes, ast.NameConstant, ast.Ellipsis) |
81 | | - else: |
82 | | - ast_data = (ast.Constant, ast.List, ast.Set, ast.Dict, ast.Tuple) |
83 | | - |
84 | | - tree = ast.parse(src) |
85 | | - |
86 | | - result = {} |
87 | | - |
88 | | - for node in ast.iter_child_nodes(tree): |
89 | | - # We parse assigns only |
90 | | - if not isinstance(node, (ast.Assign, ast.AnnAssign)) or not isinstance(node.value, ast_data): |
91 | | - continue |
92 | | - try: |
93 | | - value = ast.literal_eval(node.value) |
94 | | - except ValueError: |
95 | | - continue |
96 | | - if isinstance(node, ast.Assign): |
97 | | - for tgt in node.targets: |
98 | | - if isinstance(tgt, ast.Name) and isinstance(tgt.ctx, ast.Store): |
99 | | - result[tgt.id] = value |
100 | | - else: |
101 | | - result[node.target.id] = value |
102 | | - return result |
103 | | - |
104 | | - |
105 | | -VARIABLES = get_simple_vars_from_src(SOURCE) |
106 | | - |
107 | | -CLASSIFIERS = [ |
108 | | - "Development Status :: 5 - Production/Stable", |
109 | | - "Intended Audience :: Developers", |
110 | | - "Topic :: Software Development :: Libraries :: Python Modules", |
111 | | - "License :: OSI Approved :: Apache Software License", |
112 | | - "Programming Language :: Python :: 3", |
113 | | - "Programming Language :: Python :: 3 :: Only", |
114 | | - "Programming Language :: Python :: 3.7", |
115 | | - "Programming Language :: Python :: 3.8", |
116 | | - "Programming Language :: Python :: 3.9", |
117 | | - "Programming Language :: Python :: 3.10", |
118 | | - "Programming Language :: Python :: 3.11", |
119 | | - "Programming Language :: Python :: Implementation :: CPython", |
120 | | - "Programming Language :: Python :: Implementation :: PyPy", |
121 | | -] |
122 | | - |
123 | | -KEYWORDS = ["logging", "debugging", "development"] |
124 | | - |
125 | | -XML_DEPS = ["defusedxml"] |
126 | | -LXML_DEPS = ["lxml>=4.6.2"] |
127 | | -YAML_DEPS = ["PyYAML>=3.12"] |
128 | | - |
129 | | - |
130 | | -setuptools.setup( |
131 | | - name="exec-helpers", |
132 | | - author=VARIABLES["__author__"], |
133 | | - author_email=VARIABLES["__author_email__"], |
134 | | - maintainer=", ".join(f"{name} <{email}>" for name, email in VARIABLES["__maintainers__"].items()), |
135 | | - url=VARIABLES["__url__"], |
136 | | - license=VARIABLES["__license__"], |
137 | | - description=VARIABLES["__description__"], |
138 | | - long_description=LONG_DESCRIPTION, |
139 | | - long_description_content_type="text/x-rst", |
140 | | - classifiers=CLASSIFIERS, |
141 | | - keywords=KEYWORDS, |
142 | | - python_requires=">=3.7.0", |
143 | | - # While setuptools cannot deal with pre-installed incompatible versions, |
144 | | - # setting a lower bound is not harmful - it makes error messages cleaner. DO |
145 | | - # NOT set an upper bound on setuptools, as that will lead to uninstallable |
146 | | - # situations as progressive releases of projects are done. |
147 | | - # Blacklist setuptools 34.0.0-34.3.2 due to https://github.com/pypa/setuptools/issues/951 |
148 | | - # Blacklist setuptools 36.2.0 due to https://github.com/pypa/setuptools/issues/1086 |
149 | | - setup_requires=[ |
150 | | - "setuptools >= 21.0.0,!=24.0.0," |
151 | | - "!=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," |
152 | | - "!=36.2.0", |
153 | | - "wheel", |
154 | | - "setuptools_scm[toml]>=3.4", |
155 | | - ], |
156 | | - use_scm_version={"write_to": f"{PACKAGE_NAME}/_version.py"}, |
157 | | - install_requires=REQUIRED, |
158 | | - extras_require={ |
159 | | - "xml": XML_DEPS, |
160 | | - "lxml": LXML_DEPS, |
161 | | - "yaml": YAML_DEPS, |
162 | | - "all_formats": XML_DEPS + LXML_DEPS + YAML_DEPS, |
163 | | - "all-formats": XML_DEPS + LXML_DEPS + YAML_DEPS, |
164 | | - }, |
165 | | - package_data={PACKAGE_NAME: ["py.typed"], "": ["*.pyi"]}, |
166 | | -) |
| 24 | +setuptools.setup() |
0 commit comments