pyenv-virtualenv for Windows 1.2
A 'pyenv' plugin to manage Python virtual environments, depending on different Python versions, for various Python projects.
Loading...
Searching...
No Matches
pyenv-virtualenv-prefix.py
Go to the documentation of this file.
1##
2# @package pyenv-virtualenv-prefix
3# @file pyenv-virtualenv-prefix.py
4# @author Michael Paul Korthals
5# @date 2025-07-10
6# @version 1.0.0
7# @copyright © 2025 Michael Paul Korthals. All rights reserved.
8# See License details in the documentation.
9#
10# Utility application to output the virtual environment path prefix.
11#
12
13# --- IMPORTS ----------------------------------------------------------
14
15# Python
16import argparse
17import os
18import sys
19
20# Avoid colored output problems
21os.system('')
22
23# Community
24try:
25 import virtualenv
26except ImportError():
27 print(
28 '\x1b[101mCRITICAL %s\x1b[0m'
29 %
30 'Cannot find package "%s".'
31 %
32 'virtualenv'
33 )
34 print(
35 '\x1b[37mINFO %s\x1b[0m'
36 %
37 'Install it using "pip". Then try again.')
38 import virtualenv
39
40# My
41import lib.hlp as hlp
42import lib.log as log
43
44
45# --- RUN ---------------------------------------------------------------
46
47## Sub routine to run the application.
48#
49# @param args Given command line arguments.
50# @return RC = 0 or other values in case of error.
51def run(args: argparse.Namespace) -> int:
52 rc: int = 0
53 # noinspection PyBroadException
54 try:
55 while True:
57 'Display "real_prefix" for a Python virtual environment version.'
58 )
59 name = ''
60 try:
61 # Use the given "version" argument
62 name: str = args.name
63 name_given = True
64 except AttributeError:
65 name_given = False
66 if name_given:
67 result = ''
68 filtered_envs = hlp.getAllEnvs(
69 name,
70 as_paths=True
71 )
72 if len(filtered_envs) > 0:
73 for env in filtered_envs:
74 pl = env.split(os.sep)
75 for i in range(len(pl)):
76 item = pl[i]
77 if item == 'versions':
78 if len(result) > 0:
79 result += '\r\n'
80 result += os.sep.join(pl[:i + 2])
81 print(result)
82 else:
83 log.warning('Cannot find virtual environments like "{}".'.format(args.name))
84 log.info('Try again with another filter by name. Wildcards are implemented.')
85 else:
86 # Check if the path to Python executable
87 # passes into a virtual environment.
88 log.debug('Python executable: "{}".'.format(sys.executable))
89 pl = sys.executable.split(os.sep)
90 if (
91 ('envs' in pl)
92 and
93 ('Scripts' in pl)
94 and
95 (os.path.isfile(
96 os.path.join(
97 os.path.dirname(sys.executable),
98 '..',
99 'pyvenv.cfg'
100 )
101 ))
102 ):
103 # Virtual environment detected
104 result = ''
105 for i in range(len(pl)):
106 item = pl[i]
107 if item == 'versions':
108 result = os.sep.join(pl[:i + 2])
109 break
110 if result == '':
111 log.error('Cannot determine Python version for this virtual environment.')
112 rc = 1
113 break
114 print(result)
115 else:
116 # Not in virtual environment
117 version = sys.version.split(' ')[0]
118 log.warning("'pyenv-virtualenv': Python version {} is not a virtual environment.".format(version))
119 log.info('Executable: "{}".'.format(sys.executable))
120 log.info("Activate a virtual environment using the 'activate' command'. Then try again.")
121 rc = 5
122 break
123 # End if
124 # Go on
125 break
126 # End while
127 except:
128 log.error(sys.exc_info())
129 rc = 1
130 return rc
131
132
133# --- MAIN --------------------------------------------------------------
134
135## Parse CLI arguments for this application.<br>
136# <br>
137# Implement this as required, but don't touch the interface definition
138# for input and output.
139#
140# @return A tuple of:
141# * Namespace to read arguments in "dot" notation or None
142# in case of help or error.
143# * RC = 0 or another value in case of error.
144def parseCliArguments0() -> tuple[(argparse.Namespace, None), int]:
145 rc: int = 0
146 # noinspection PyBroadException
147 try:
148 parser = argparse.ArgumentParser(
149# --- BEGIN CHANGE -----------------------------------------------------
150 prog='pyenv virtualenv-prefix',
151 description='Display "real_prefix" for a Python virtual environment version.'
152 )
153# --- END CHANGE -------------------------------------------------------
154 return parser.parse_args(), rc
155 except SystemExit:
156 return None, 0
157 except:
158 log.error(sys.exc_info())
159 return None, 1
160
161## Parse CLI arguments for this application.<br>
162# <br>
163# Implement this as required, but don't touch the interface definition
164# for input and output.
165#
166# @return A tuple of:
167# * Namespace to read arguments in "dot" notation or None
168# in case of help or error.
169# * RC = 0 or another value in case of error.
170def parseCliArguments1() -> tuple[(argparse.Namespace, None), int]:
171 rc: int = 0
172 # noinspection PyBroadException
173 try:
174 parser = argparse.ArgumentParser(
175# --- BEGIN CHANGE -----------------------------------------------------
176 prog='pyenv virtualenv-prefix',
177 description='Display "real_prefix" for a Python virtual environment version.'
178 )
179 # Add positional str argument
180 parser.add_argument(
181 'name',
182 help='Short name of an installed Python virtual environment. Default: Empty string = analyze the CWD.'
183 )
184# --- END CHANGE -------------------------------------------------------
185 return parser.parse_args(), rc
186 except SystemExit:
187 return None, 0
188 except:
189 log.error(sys.exc_info())
190 return None, 1
191
192## Main routine of the application.
193#
194# @return RC = 0 or other values in case of error.
195def main() -> int:
196 # noinspection PyBroadException
197 try:
198 while True:
199 # Audit the operating system platform
200 rc = hlp.auditPlatform('Windows')
201 if rc != 0:
202 # Deviation: Reject unsupported platform
203 break
204 # Audit the global Python version number
206 if rc != 0:
207 # Deviation: Reject unsupported Python version
208 break
209 # Initialize the colored logging to console
211 # Audit the "pyenv" version number
212 rc = hlp.auditPyEnv('3')
213 if rc != 0:
214 # Deviation: Reject unsupported "pyenv" version
215 break
216 # Parse arguments
217 # NOTE: Sorry, this is a complicated workaround to
218 # bypass the lack of applicability of Python "ArgumentParser"
219 # class. This simple use case to set required = False for
220 # positional argument is not included and must be patched
221 # away here.
222 log.verbose('Parsing arguments ...')
223 args = None
224 args_list = sys.argv.copy() # Clone
225 # Strip program executable path
226 args_list.pop(0)
227 # Detect and remove all optional arguments,
228 # which are not related to the positional arguments
229 help_requested = False
230 for i in reversed(range(len(args_list))):
231 arg = args_list[i]
232 if arg in ['-h', '--help']:
233 help_requested = True
234 args_list.pop(i)
235 # Calculate the count of positional arguments
236 positional_count = len(args_list)
237 if (
238 help_requested
239 or
240 (positional_count not in [0, 1])
241 ):
242 text = ("""
243Usage: pyenv virtualenv-prefix [-h] [name]
244
245Display "real_prefix" for a Python virtual environment version.
246
247Positional arguments (can be omitted):
248 [name] Short name of an installed Python virtual environment.
249 Default: Empty string = analyze the CWD.
250Options:
251 -h, --help Show this help message and exit
252 """).strip()
253 print(text)
254 elif positional_count == 0:
255 # Case 1: single positional argument must be "Name"
256 args, rc = parseCliArguments0()
257 elif positional_count == 1:
258 # Case 2: duo positional arguments must be "Version" and "Name"
259 args, rc = parseCliArguments1()
260 if rc != 0:
261 break
262 if args is None: # -h, --help
263 break
264 # Run this application
265 log.verbose('Running application ...')
266 rc = run(args)
267 if rc != 0:
268 break
269 # Go on
270 break
271 # End while
272 except Exception as exc:
274 log.error(sys.exc_info())
275 else:
276 print(
277 '\x1b[91mERROR: Unexpected error "%s".\x1b[0m'
278 %
279 str(exc)
280 )
281 rc = 1
282 return rc
283
284
285if __name__ == "__main__":
286 sys.exit(main())
287
288# --- END OF CODE ------------------------------------------------------
289
int auditPyEnv(str min_ver)
Check if "pyenv" version is greater or equal the given minimal version.
Definition hlp.py:213
int auditGlobalPythonVersion(str min_ver)
Check if Python version is greater or equal the given minimal version.
Definition hlp.py:148
int auditPlatform(str name)
Check if the program in running on the required platform.
Definition hlp.py:85
list[str] getAllEnvs(str name=' *', bool as_paths=False)
Get list of installed virtual environments for a specific Python version in "pyenv".
Definition hlp.py:768
debug((str, tuple) msg)
Log debug message colored to console only.
Definition log.py:215
warning((str, tuple) msg)
Log warning message colored to console only.
Definition log.py:191
verbose((str, tuple) msg)
Log verbose message colored to console only.
Definition log.py:209
initLogging()
Initialize the logging.
Definition log.py:71
bool isInitialized()
Definition log.py:90
info((str, tuple) msg)
Log info message colored to console only.
Definition log.py:203
error((str, tuple) msg)
Log error message colored to console only.
Definition log.py:179
int run(argparse.Namespace args)
Sub routine to run the application.
tuple[(argparse.Namespace, None), int] parseCliArguments1()
Parse CLI arguments for this application.
int main()
Main routine of the application.
tuple[(argparse.Namespace, None), int] parseCliArguments0()
Parse CLI arguments for this application.