Mercurial > repos > rliterman > csp2
comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/setuptools/depends.py @ 68:5028fdace37b
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 16:23:26 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
67:0e9998148a16 | 68:5028fdace37b |
---|---|
1 from __future__ import annotations | |
2 | |
3 import contextlib | |
4 import dis | |
5 import marshal | |
6 import sys | |
7 | |
8 from packaging.version import Version | |
9 | |
10 from . import _imp | |
11 from ._imp import PY_COMPILED, PY_FROZEN, PY_SOURCE, find_module | |
12 | |
13 __all__ = ['Require', 'find_module'] | |
14 | |
15 | |
16 class Require: | |
17 """A prerequisite to building or installing a distribution""" | |
18 | |
19 def __init__( | |
20 self, | |
21 name, | |
22 requested_version, | |
23 module, | |
24 homepage: str = '', | |
25 attribute=None, | |
26 format=None, | |
27 ): | |
28 if format is None and requested_version is not None: | |
29 format = Version | |
30 | |
31 if format is not None: | |
32 requested_version = format(requested_version) | |
33 if attribute is None: | |
34 attribute = '__version__' | |
35 | |
36 self.__dict__.update(locals()) | |
37 del self.self | |
38 | |
39 def full_name(self): | |
40 """Return full package/distribution name, w/version""" | |
41 if self.requested_version is not None: | |
42 return '%s-%s' % (self.name, self.requested_version) | |
43 return self.name | |
44 | |
45 def version_ok(self, version): | |
46 """Is 'version' sufficiently up-to-date?""" | |
47 return ( | |
48 self.attribute is None | |
49 or self.format is None | |
50 or str(version) != "unknown" | |
51 and self.format(version) >= self.requested_version | |
52 ) | |
53 | |
54 def get_version(self, paths=None, default: str = "unknown"): | |
55 """Get version number of installed module, 'None', or 'default' | |
56 | |
57 Search 'paths' for module. If not found, return 'None'. If found, | |
58 return the extracted version attribute, or 'default' if no version | |
59 attribute was specified, or the value cannot be determined without | |
60 importing the module. The version is formatted according to the | |
61 requirement's version format (if any), unless it is 'None' or the | |
62 supplied 'default'. | |
63 """ | |
64 | |
65 if self.attribute is None: | |
66 try: | |
67 f, p, i = find_module(self.module, paths) | |
68 except ImportError: | |
69 return None | |
70 if f: | |
71 f.close() | |
72 return default | |
73 | |
74 v = get_module_constant(self.module, self.attribute, default, paths) | |
75 | |
76 if v is not None and v is not default and self.format is not None: | |
77 return self.format(v) | |
78 | |
79 return v | |
80 | |
81 def is_present(self, paths=None): | |
82 """Return true if dependency is present on 'paths'""" | |
83 return self.get_version(paths) is not None | |
84 | |
85 def is_current(self, paths=None): | |
86 """Return true if dependency is present and up-to-date on 'paths'""" | |
87 version = self.get_version(paths) | |
88 if version is None: | |
89 return False | |
90 return self.version_ok(str(version)) | |
91 | |
92 | |
93 def maybe_close(f): | |
94 @contextlib.contextmanager | |
95 def empty(): | |
96 yield | |
97 return | |
98 | |
99 if not f: | |
100 return empty() | |
101 | |
102 return contextlib.closing(f) | |
103 | |
104 | |
105 # Some objects are not available on some platforms. | |
106 # XXX it'd be better to test assertions about bytecode instead. | |
107 if not sys.platform.startswith('java') and sys.platform != 'cli': | |
108 | |
109 def get_module_constant(module, symbol, default: str | int = -1, paths=None): | |
110 """Find 'module' by searching 'paths', and extract 'symbol' | |
111 | |
112 Return 'None' if 'module' does not exist on 'paths', or it does not define | |
113 'symbol'. If the module defines 'symbol' as a constant, return the | |
114 constant. Otherwise, return 'default'.""" | |
115 | |
116 try: | |
117 f, path, (suffix, mode, kind) = info = find_module(module, paths) | |
118 except ImportError: | |
119 # Module doesn't exist | |
120 return None | |
121 | |
122 with maybe_close(f): | |
123 if kind == PY_COMPILED: | |
124 f.read(8) # skip magic & date | |
125 code = marshal.load(f) | |
126 elif kind == PY_FROZEN: | |
127 code = _imp.get_frozen_object(module, paths) | |
128 elif kind == PY_SOURCE: | |
129 code = compile(f.read(), path, 'exec') | |
130 else: | |
131 # Not something we can parse; we'll have to import it. :( | |
132 imported = _imp.get_module(module, paths, info) | |
133 return getattr(imported, symbol, None) | |
134 | |
135 return extract_constant(code, symbol, default) | |
136 | |
137 def extract_constant(code, symbol, default: str | int = -1): | |
138 """Extract the constant value of 'symbol' from 'code' | |
139 | |
140 If the name 'symbol' is bound to a constant value by the Python code | |
141 object 'code', return that value. If 'symbol' is bound to an expression, | |
142 return 'default'. Otherwise, return 'None'. | |
143 | |
144 Return value is based on the first assignment to 'symbol'. 'symbol' must | |
145 be a global, or at least a non-"fast" local in the code block. That is, | |
146 only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' | |
147 must be present in 'code.co_names'. | |
148 """ | |
149 if symbol not in code.co_names: | |
150 # name's not there, can't possibly be an assignment | |
151 return None | |
152 | |
153 name_idx = list(code.co_names).index(symbol) | |
154 | |
155 STORE_NAME = dis.opmap['STORE_NAME'] | |
156 STORE_GLOBAL = dis.opmap['STORE_GLOBAL'] | |
157 LOAD_CONST = dis.opmap['LOAD_CONST'] | |
158 | |
159 const = default | |
160 | |
161 for byte_code in dis.Bytecode(code): | |
162 op = byte_code.opcode | |
163 arg = byte_code.arg | |
164 | |
165 if op == LOAD_CONST: | |
166 const = code.co_consts[arg] | |
167 elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): | |
168 return const | |
169 else: | |
170 const = default | |
171 | |
172 return None | |
173 | |
174 __all__ += ['get_module_constant', 'extract_constant'] |