venvflon 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- venvflon-0.1.0/LICENSE +21 -0
- venvflon-0.1.0/PKG-INFO +45 -0
- venvflon-0.1.0/README.md +5 -0
- venvflon-0.1.0/pyproject.toml +127 -0
- venvflon-0.1.0/setup.cfg +4 -0
- venvflon-0.1.0/src/venvflon/__init__.py +0 -0
- venvflon-0.1.0/src/venvflon/flon.py +81 -0
- venvflon-0.1.0/src/venvflon/img/cannula.ico +0 -0
- venvflon-0.1.0/src/venvflon/img/cannula_512.png +0 -0
- venvflon-0.1.0/src/venvflon/img/cannula_64.png +0 -0
- venvflon-0.1.0/src/venvflon/py.typed +0 -0
- venvflon-0.1.0/src/venvflon/run.py +27 -0
- venvflon-0.1.0/src/venvflon/utils.py +80 -0
- venvflon-0.1.0/src/venvflon.egg-info/PKG-INFO +45 -0
- venvflon-0.1.0/src/venvflon.egg-info/SOURCES.txt +24 -0
- venvflon-0.1.0/src/venvflon.egg-info/dependency_links.txt +1 -0
- venvflon-0.1.0/src/venvflon.egg-info/entry_points.txt +5 -0
- venvflon-0.1.0/src/venvflon.egg-info/requires.txt +13 -0
- venvflon-0.1.0/src/venvflon.egg-info/top_level.txt +1 -0
- venvflon-0.1.0/tests/test_utils.py +31 -0
venvflon-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Michal Plichta
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
venvflon-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: venvflon
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: simple virtual environment switcher
|
|
5
|
+
Author: Michal Plichta
|
|
6
|
+
Maintainer: Michal Plichta
|
|
7
|
+
License: MIT License
|
|
8
|
+
Project-URL: Homepage, https://github.com/emcek/venvflon
|
|
9
|
+
Project-URL: Source, https://github.com/emcek/venvflon.git
|
|
10
|
+
Project-URL: Changelog, https://github.com/emcek/venvflon/blob/master/CHANGELOG.md
|
|
11
|
+
Keywords: venv,uv,virtualenv
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Environment :: Win32 (MS Windows)
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
23
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: GitPython==3.1.43; extra == "test"
|
|
30
|
+
Requires-Dist: interrogate==1.7.0; extra == "test"
|
|
31
|
+
Requires-Dist: isort==5.13.2; extra == "test"
|
|
32
|
+
Requires-Dist: lxml==5.3.0; extra == "test"
|
|
33
|
+
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
34
|
+
Requires-Dist: packaging==24.2; extra == "test"
|
|
35
|
+
Requires-Dist: pip-audit==2.7.3; extra == "test"
|
|
36
|
+
Requires-Dist: pytest==8.3.3; extra == "test"
|
|
37
|
+
Requires-Dist: pytest-randomly==3.16.0; extra == "test"
|
|
38
|
+
Requires-Dist: ruff==0.7.4; extra == "test"
|
|
39
|
+
Requires-Dist: types-pyinstaller==6.10.0.20240812; extra == "test"
|
|
40
|
+
|
|
41
|
+
# venvflon
|
|
42
|
+
simple virtual environment switcher
|
|
43
|
+
|
|
44
|
+
## name
|
|
45
|
+
Comes from polish `wenflon` or `kaniula` (eng. `cannula`)
|
venvflon-0.1.0/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ['setuptools']
|
|
3
|
+
build-backend = 'setuptools.build_meta'
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = 'venvflon'
|
|
7
|
+
authors = [{name = 'Michal Plichta'}]
|
|
8
|
+
maintainers = [{name = 'Michal Plichta'}]
|
|
9
|
+
description = 'simple virtual environment switcher'
|
|
10
|
+
license = {text = 'MIT License'}
|
|
11
|
+
requires-python = '>=3.9'
|
|
12
|
+
readme = 'README.md'
|
|
13
|
+
classifiers = [
|
|
14
|
+
'Development Status :: 4 - Beta',
|
|
15
|
+
'Environment :: Console',
|
|
16
|
+
'Environment :: Win32 (MS Windows)',
|
|
17
|
+
'License :: OSI Approved :: MIT License',
|
|
18
|
+
'Programming Language :: Python :: 3.9',
|
|
19
|
+
'Programming Language :: Python :: 3.10',
|
|
20
|
+
'Programming Language :: Python :: 3.11',
|
|
21
|
+
'Programming Language :: Python :: 3.12',
|
|
22
|
+
'Programming Language :: Python :: 3.13',
|
|
23
|
+
'Operating System :: Microsoft :: Windows',
|
|
24
|
+
'Operating System :: Microsoft :: Windows :: Windows 10',
|
|
25
|
+
'Operating System :: Microsoft :: Windows :: Windows 11',
|
|
26
|
+
'Topic :: Utilities',
|
|
27
|
+
]
|
|
28
|
+
keywords = [
|
|
29
|
+
'venv', 'uv', 'virtualenv',
|
|
30
|
+
]
|
|
31
|
+
dynamic = ['version']
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = 'https://github.com/emcek/venvflon'
|
|
35
|
+
Source = 'https://github.com/emcek/venvflon.git'
|
|
36
|
+
Changelog = 'https://github.com/emcek/venvflon/blob/master/CHANGELOG.md'
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
flon_cli = 'venvflon.run:run'
|
|
40
|
+
|
|
41
|
+
[project.gui-scripts]
|
|
42
|
+
flon = 'venvflon.run:run'
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
test = [
|
|
46
|
+
'GitPython==3.1.43',
|
|
47
|
+
'interrogate==1.7.0',
|
|
48
|
+
'isort==5.13.2',
|
|
49
|
+
'lxml==5.3.0',
|
|
50
|
+
'mypy==1.13.0',
|
|
51
|
+
'packaging==24.2',
|
|
52
|
+
'pip-audit==2.7.3',
|
|
53
|
+
'pytest==8.3.3',
|
|
54
|
+
'pytest-randomly==3.16.0',
|
|
55
|
+
'ruff==0.7.4',
|
|
56
|
+
'types-pyinstaller==6.10.0.20240812',
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.dynamic]
|
|
60
|
+
version = {attr = 'venvflon.run.__version__'}
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.packages.find]
|
|
63
|
+
where = ['src/']
|
|
64
|
+
include = ['venvflon*']
|
|
65
|
+
exclude = ['venvflon.tests*']
|
|
66
|
+
|
|
67
|
+
[tool.setuptools.package-data]
|
|
68
|
+
venvflon = [
|
|
69
|
+
'img/*',
|
|
70
|
+
'py.typed',
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[tool.pytest.ini_options]
|
|
74
|
+
addopts = ['-q']
|
|
75
|
+
pythonpath = ['src']
|
|
76
|
+
testpaths = ['tests']
|
|
77
|
+
markers = [
|
|
78
|
+
'slow: marks tests as slow',
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
[tool.interrogate]
|
|
82
|
+
ignore-init-method = false
|
|
83
|
+
ignore-init-module = true
|
|
84
|
+
ignore-magic = true
|
|
85
|
+
ignore-semiprivate = false
|
|
86
|
+
ignore-private = false
|
|
87
|
+
ignore-property-decorators = false
|
|
88
|
+
ignore-module = true
|
|
89
|
+
ignore-nested-functions = false
|
|
90
|
+
ignore-nested-classes = true
|
|
91
|
+
ignore-setters = false
|
|
92
|
+
fail-under = 90
|
|
93
|
+
verbose = 1
|
|
94
|
+
quiet = false
|
|
95
|
+
exclude = ['tests/test_*']
|
|
96
|
+
|
|
97
|
+
[tool.ruff]
|
|
98
|
+
line-length = 160
|
|
99
|
+
lint.select = ['E', 'F', 'C90', 'D', 'RUF']
|
|
100
|
+
lint.ignore = ['D100', 'D101','D104', 'D105', 'D203', 'D204', 'D212', 'RUF001', 'RUF010']
|
|
101
|
+
extend-exclude = [
|
|
102
|
+
'tests/',
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[tool.ruff.lint.mccabe]
|
|
106
|
+
max-complexity = 5
|
|
107
|
+
|
|
108
|
+
[tool.mypy]
|
|
109
|
+
#ignore_missing_imports = true
|
|
110
|
+
#no_warn_no_return = true
|
|
111
|
+
#check_untyped_defs = true
|
|
112
|
+
html_report = 'mypyhtml'
|
|
113
|
+
exclude = [
|
|
114
|
+
'tests/',
|
|
115
|
+
'generate_ver_file\.py$',
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
[tool.isort]
|
|
119
|
+
line_length = 160
|
|
120
|
+
|
|
121
|
+
[tool.uv]
|
|
122
|
+
dev-dependencies = [
|
|
123
|
+
'venvflon[test]',
|
|
124
|
+
'build',
|
|
125
|
+
'detect-test-pollution',
|
|
126
|
+
'pre-commit',
|
|
127
|
+
]
|
venvflon-0.1.0/setup.cfg
ADDED
|
File without changes
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from os import environ, getcwd
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from sys import base_prefix, executable
|
|
6
|
+
from time import sleep
|
|
7
|
+
|
|
8
|
+
from venvflon.utils import get_command_output, make_sym_link, rm_sym_link, venv_list_in
|
|
9
|
+
|
|
10
|
+
environ['TCL_LIBRARY'] = str(Path(base_prefix) / 'tcl' / 'tcl8.6')
|
|
11
|
+
environ['TK_LIBRARY'] = str(Path(base_prefix) / 'tcl' / 'tk8.6')
|
|
12
|
+
import tkinter as tk
|
|
13
|
+
|
|
14
|
+
print(executable)
|
|
15
|
+
|
|
16
|
+
class Gui(tk.Frame):
|
|
17
|
+
"""Tkinter GUI for venvflon."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, master: tk.Tk) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Tkinter GUI for venvflon.
|
|
22
|
+
|
|
23
|
+
:param master: Tkinter root
|
|
24
|
+
"""
|
|
25
|
+
super().__init__(master)
|
|
26
|
+
self.master = master
|
|
27
|
+
self.venv = tk.StringVar(value=' ')
|
|
28
|
+
self.status_txt = tk.StringVar()
|
|
29
|
+
self.cwd_entry = tk.StringVar()
|
|
30
|
+
self.cwd = Path(getcwd())
|
|
31
|
+
self.cwd_entry.set(str(self.cwd))
|
|
32
|
+
self.venv_list = venv_list_in(current_path=self.cwd)
|
|
33
|
+
new_width, new_height = len(str(self.venv_list[0])) + 300, len(self.venv_list) * 55
|
|
34
|
+
self.master.geometry(f'{new_width}x{new_height}')
|
|
35
|
+
self.master.minsize(width=new_width, height=new_height)
|
|
36
|
+
self.init_widgets()
|
|
37
|
+
self.update_status()
|
|
38
|
+
|
|
39
|
+
def init_widgets(self) -> None:
|
|
40
|
+
"""Initialize widgets."""
|
|
41
|
+
self.master.columnconfigure(index=0, weight=1)
|
|
42
|
+
cwd_label = tk.Label(self.master, text='cwd:')
|
|
43
|
+
cwd_label.grid(row=0, column=0, sticky=tk.W)
|
|
44
|
+
cwd = tk.Entry(master=self.master, textvariable=self.cwd_entry, width=len(str(self.venv_list[0])) + 2)
|
|
45
|
+
cwd.grid(row=0, column=1, sticky=tk.W)
|
|
46
|
+
cwd.bind('<Return>', self.refresh_cwd)
|
|
47
|
+
self.add_venvs()
|
|
48
|
+
|
|
49
|
+
def add_venvs(self):
|
|
50
|
+
"""Add venvs as radio buttons to the GUI."""
|
|
51
|
+
venv_label = tk.Label(self.master, text='venv:')
|
|
52
|
+
venv_label.grid(row=1, column=0, sticky=tk.W)
|
|
53
|
+
frame = tk.Frame(master=self.master, relief=tk.GROOVE, borderwidth=2)
|
|
54
|
+
frame.grid(row=1, column=1, columnspan=2, padx=2, pady=2, rowspan=len(self.venv_list))
|
|
55
|
+
for i, text in enumerate(self.venv_list, 1):
|
|
56
|
+
rb_venvs = tk.Radiobutton(master=frame, text=str(text), variable=self.venv, value=text, command=self.venv_selected)
|
|
57
|
+
rb_venvs.grid(row=i, column=1, pady=0, padx=2, sticky=tk.W)
|
|
58
|
+
status = tk.Label(master=self.master, textvariable=self.status_txt)
|
|
59
|
+
status.grid(row=len(self.venv_list) + 1, column=0, columnspan=3, sticky=tk.E)
|
|
60
|
+
|
|
61
|
+
def refresh_cwd(self, *args):
|
|
62
|
+
"""
|
|
63
|
+
Refresh the current working directory.
|
|
64
|
+
|
|
65
|
+
:param args: internal tkinter arguments
|
|
66
|
+
"""
|
|
67
|
+
self.venv_list = venv_list_in(current_path=self.cwd)
|
|
68
|
+
self.add_venvs()
|
|
69
|
+
|
|
70
|
+
def venv_selected(self):
|
|
71
|
+
"""Set the selected venv as the active one."""
|
|
72
|
+
new_venv = self.venv.get()
|
|
73
|
+
rm_sym_link(sym_link=Path(getcwd()) / '.venv')
|
|
74
|
+
make_sym_link(to_path=Path(getcwd()) / '.venv', target=Path(new_venv))
|
|
75
|
+
sleep(0.8)
|
|
76
|
+
self.update_status()
|
|
77
|
+
|
|
78
|
+
def update_status(self):
|
|
79
|
+
"""Update the status text."""
|
|
80
|
+
out = get_command_output(cmd=['python', '-V'])
|
|
81
|
+
self.status_txt.set(f'Current: {out[2].strip()}')
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from os import environ
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from sys import base_prefix
|
|
6
|
+
|
|
7
|
+
from venvflon.flon import Gui
|
|
8
|
+
|
|
9
|
+
environ['TCL_LIBRARY'] = str(Path(base_prefix) / 'tcl' / 'tcl8.6')
|
|
10
|
+
environ['TK_LIBRARY'] = str(Path(base_prefix) / 'tcl' / 'tk8.6')
|
|
11
|
+
import tkinter as tk
|
|
12
|
+
|
|
13
|
+
__version__ = '0.1.0'
|
|
14
|
+
|
|
15
|
+
def run():
|
|
16
|
+
"""Run the main GUI."""
|
|
17
|
+
root_tk = tk.Tk()
|
|
18
|
+
width, height = 300, 150
|
|
19
|
+
root_tk.title(f'venvflon - v{__version__}')
|
|
20
|
+
root_tk.geometry(f'{width}x{height}')
|
|
21
|
+
root_tk.iconphoto(False, tk.PhotoImage(file=Path(__file__).parent / 'img' / 'cannula_64.png'))
|
|
22
|
+
gui = Gui(master=root_tk)
|
|
23
|
+
gui.mainloop()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if __name__ == '__main__':
|
|
27
|
+
run()
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from os import sep, walk
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from subprocess import CalledProcessError, run
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run_command(cmd: Sequence[str], cwd: Path | None = None) -> int:
|
|
10
|
+
"""
|
|
11
|
+
Run command in shell as a subprocess.
|
|
12
|
+
|
|
13
|
+
:param cmd: The command to be executed as a sequence of strings
|
|
14
|
+
:param cwd: current working directory
|
|
15
|
+
:return: The return code of command
|
|
16
|
+
"""
|
|
17
|
+
try:
|
|
18
|
+
proc = run(cmd, check=True, shell=False, cwd=cwd)
|
|
19
|
+
return proc.returncode
|
|
20
|
+
except CalledProcessError as e:
|
|
21
|
+
print(f'Result: {e}')
|
|
22
|
+
return -1
|
|
23
|
+
|
|
24
|
+
def get_command_output(cmd: Sequence[str], cwd: Path | None = None) -> tuple[int, str, str]:
|
|
25
|
+
"""
|
|
26
|
+
Execute command and return its output.
|
|
27
|
+
|
|
28
|
+
:param cmd: The command to be executed as a sequence of strings
|
|
29
|
+
:param cwd: current working directory
|
|
30
|
+
:return: Tuple with return code, stderr and stdout
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
result = run(cmd, capture_output=True, check=True, cwd=cwd)
|
|
34
|
+
return result.returncode, result.stderr.decode('utf-8'), result.stdout.decode('utf-8')
|
|
35
|
+
except CalledProcessError as e:
|
|
36
|
+
print(f'Result: {e}')
|
|
37
|
+
return e.returncode, e.stderr.decode('utf-8'), e.stdout.decode('utf-8')
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def make_sym_link(to_path: Path, target: Path) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Make symbolic link.
|
|
43
|
+
|
|
44
|
+
:param to_path: path to symbolic link
|
|
45
|
+
:param target: target path
|
|
46
|
+
"""
|
|
47
|
+
cmd_symlink = f'"New-Item -ItemType SymbolicLink -Path \\"{to_path}\\" -Target \\"{target}\\"'
|
|
48
|
+
ps_command = f"Start-Process powershell.exe -ArgumentList '-Command {cmd_symlink}' -Verb RunAs"
|
|
49
|
+
print(f'Make symbolic link: {ps_command}')
|
|
50
|
+
run_command(cmd=['powershell.exe', '-Command', ps_command])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def rm_sym_link(sym_link: Path) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Remove symbolic link.
|
|
56
|
+
|
|
57
|
+
:param sym_link: path to symbolic link
|
|
58
|
+
"""
|
|
59
|
+
rm_symlink = f"(Get-Item '{sym_link}').Delete()"
|
|
60
|
+
ps_command = f'Start-Process powershell.exe -ArgumentList "-Command {rm_symlink}" -Verb RunAs'
|
|
61
|
+
print(f'Execute: {ps_command}')
|
|
62
|
+
run_command(cmd=['powershell.exe', '-Command', ps_command])
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def venv_list_in(current_path: Path, max_depth: int = 1) -> Sequence[Path]:
|
|
66
|
+
"""
|
|
67
|
+
Find all virtual environments in given path.
|
|
68
|
+
|
|
69
|
+
:param current_path: path to search in
|
|
70
|
+
:param max_depth: maximum depth of search
|
|
71
|
+
:return: list of paths to virtual environments
|
|
72
|
+
"""
|
|
73
|
+
result = []
|
|
74
|
+
for dirpath, dirnames, _ in walk(current_path, topdown=True):
|
|
75
|
+
for dirname in dirnames:
|
|
76
|
+
if '.venv_' in dirname:
|
|
77
|
+
result.append(Path(dirpath) / dirname)
|
|
78
|
+
if dirpath.count(sep) - str(current_path).count(sep) == max_depth - 1:
|
|
79
|
+
del dirnames[:]
|
|
80
|
+
return result
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: venvflon
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: simple virtual environment switcher
|
|
5
|
+
Author: Michal Plichta
|
|
6
|
+
Maintainer: Michal Plichta
|
|
7
|
+
License: MIT License
|
|
8
|
+
Project-URL: Homepage, https://github.com/emcek/venvflon
|
|
9
|
+
Project-URL: Source, https://github.com/emcek/venvflon.git
|
|
10
|
+
Project-URL: Changelog, https://github.com/emcek/venvflon/blob/master/CHANGELOG.md
|
|
11
|
+
Keywords: venv,uv,virtualenv
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Environment :: Win32 (MS Windows)
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
|
|
23
|
+
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: GitPython==3.1.43; extra == "test"
|
|
30
|
+
Requires-Dist: interrogate==1.7.0; extra == "test"
|
|
31
|
+
Requires-Dist: isort==5.13.2; extra == "test"
|
|
32
|
+
Requires-Dist: lxml==5.3.0; extra == "test"
|
|
33
|
+
Requires-Dist: mypy==1.13.0; extra == "test"
|
|
34
|
+
Requires-Dist: packaging==24.2; extra == "test"
|
|
35
|
+
Requires-Dist: pip-audit==2.7.3; extra == "test"
|
|
36
|
+
Requires-Dist: pytest==8.3.3; extra == "test"
|
|
37
|
+
Requires-Dist: pytest-randomly==3.16.0; extra == "test"
|
|
38
|
+
Requires-Dist: ruff==0.7.4; extra == "test"
|
|
39
|
+
Requires-Dist: types-pyinstaller==6.10.0.20240812; extra == "test"
|
|
40
|
+
|
|
41
|
+
# venvflon
|
|
42
|
+
simple virtual environment switcher
|
|
43
|
+
|
|
44
|
+
## name
|
|
45
|
+
Comes from polish `wenflon` or `kaniula` (eng. `cannula`)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/venvflon.egg-info/PKG-INFO
|
|
5
|
+
src/venvflon.egg-info/SOURCES.txt
|
|
6
|
+
src/venvflon.egg-info/dependency_links.txt
|
|
7
|
+
src/venvflon.egg-info/entry_points.txt
|
|
8
|
+
src/venvflon.egg-info/requires.txt
|
|
9
|
+
src/venvflon.egg-info/top_level.txt
|
|
10
|
+
src/venvflon/__init__.py
|
|
11
|
+
src/venvflon/flon.py
|
|
12
|
+
src/venvflon/py.typed
|
|
13
|
+
src/venvflon/run.py
|
|
14
|
+
src/venvflon/utils.py
|
|
15
|
+
src/venvflon.egg-info/PKG-INFO
|
|
16
|
+
src/venvflon.egg-info/SOURCES.txt
|
|
17
|
+
src/venvflon.egg-info/dependency_links.txt
|
|
18
|
+
src/venvflon.egg-info/entry_points.txt
|
|
19
|
+
src/venvflon.egg-info/requires.txt
|
|
20
|
+
src/venvflon.egg-info/top_level.txt
|
|
21
|
+
src/venvflon/img/cannula.ico
|
|
22
|
+
src/venvflon/img/cannula_512.png
|
|
23
|
+
src/venvflon/img/cannula_64.png
|
|
24
|
+
tests/test_utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
venvflon
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from sys import platform
|
|
3
|
+
|
|
4
|
+
from pytest import mark
|
|
5
|
+
|
|
6
|
+
from venvflon import utils
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mark.slow
|
|
10
|
+
@mark.skipif(condition=platform != 'win32', reason='Run only on Windows')
|
|
11
|
+
@mark.parametrize('cmd, result', [('Clear-Host', 0), ('bullshit', -1)])
|
|
12
|
+
def test_run_command(cmd, result):
|
|
13
|
+
rc = utils.run_command(cmd=['powershell', cmd])
|
|
14
|
+
assert rc == result
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_success_deep_1_venv_list_in(resources):
|
|
18
|
+
venvs = utils.venv_list_in(current_path=resources, max_depth=1)
|
|
19
|
+
assert len(venvs) == 3
|
|
20
|
+
assert sorted([venv.name for venv in venvs]) == ['.venv_310', '.venv_311', '.venv_312']
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_success_deep_2_venv_list_in(resources):
|
|
24
|
+
venvs = utils.venv_list_in(current_path=resources, max_depth=2)
|
|
25
|
+
assert len(venvs) == 4
|
|
26
|
+
assert sorted([venv.name for venv in venvs]) == ['.venv_310', '.venv_311', '.venv_312', '.venv_39']
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_failure_venv_list_in():
|
|
30
|
+
venvs = utils.venv_list_in(current_path=Path('..'), max_depth=1)
|
|
31
|
+
assert len(venvs) == 0
|