@@ -14,27 +14,31 @@ Implement the ``Discover`` interface:
1414
1515.. code-block :: python
1616
17+ from __future__ import annotations
18+
19+ from argparse import ArgumentParser
20+
21+ from virtualenv.config.cli.parser import VirtualEnvOptions
1722 from virtualenv.discovery.discover import Discover
1823 from virtualenv.discovery.py_info import PythonInfo
1924
2025
2126 class CustomDiscovery (Discover ):
2227 @ classmethod
23- def add_parser_arguments (cls , parser ) :
28+ def add_parser_arguments (cls , parser : ArgumentParser) -> None :
2429 parser.add_argument(" --custom-opt" , help = " custom discovery option" )
2530
26- def __init__ (self , options ) :
31+ def __init__ (self , options : VirtualEnvOptions) -> None :
2732 super ().__init__ (options)
2833 self .custom_opt = options.custom_opt
2934
30- def run (self ):
35+ def run (self ) -> PythonInfo | None :
3136 # Locate Python interpreter and return PythonInfo
32- python_exe = self ._find_python()
33- return PythonInfo.from_exe(str (python_exe))
37+ return PythonInfo.from_exe(str (self ._find_python()))
3438
35- def _find_python (self ):
39+ def _find_python (self ) -> str :
3640 # Implementation-specific logic
37- pass
41+ ...
3842
3943 Register the entry point:
4044
@@ -53,19 +57,32 @@ Implement the ``Creator`` interface:
5357
5458.. code-block :: python
5559
56- from virtualenv.create.creator import Creator
60+ from __future__ import annotations
61+
62+ from argparse import ArgumentParser
63+
64+ from virtualenv.app_data.base import AppData
65+ from virtualenv.config.cli.parser import VirtualEnvOptions
66+ from virtualenv.create.creator import Creator, CreatorMeta
67+ from virtualenv.discovery.py_info import PythonInfo
5768
5869
5970 class CustomCreator (Creator ):
6071 @ classmethod
61- def add_parser_arguments (cls , parser , interpreter ):
72+ def add_parser_arguments (
73+ cls ,
74+ parser : ArgumentParser,
75+ interpreter : PythonInfo,
76+ meta : CreatorMeta,
77+ app_data : AppData,
78+ ) -> None :
6279 parser.add_argument(" --custom-creator-opt" , help = " custom creator option" )
6380
64- def __init__ (self , options , interpreter ) :
81+ def __init__ (self , options : VirtualEnvOptions , interpreter : PythonInfo) -> None :
6582 super ().__init__ (options, interpreter)
6683 self .custom_opt = options.custom_creator_opt
6784
68- def create (self ):
85+ def create (self ) -> None :
6986 # Create directory structure
7087 self .bin_dir.mkdir(parents = True , exist_ok = True )
7188 # Copy or symlink Python executable
@@ -89,29 +106,51 @@ Register the entry point using a naming pattern that matches platform and Python
89106
90107Seeder plugins install initial packages into the virtual environment. Register under ``virtualenv.seed ``.
91108
109+ Override ``cannot_seed `` to reject target interpreters the seeder does not support. The base returns ``None `` for every
110+ interpreter; return a message instead and selection rejects the seeder before creating the environment, surfacing your
111+ message to the user. A plugin can therefore serve Python versions the bundled seeders no longer ship wheels for, such as
112+ a version past its support window.
113+
92114Implement the ``Seeder `` interface:
93115
94116.. code-block :: python
95117
118+ from __future__ import annotations
119+
120+ from argparse import ArgumentParser
121+
122+ from virtualenv.app_data.base import AppData
123+ from virtualenv.config.cli.parser import VirtualEnvOptions
124+ from virtualenv.create.creator import Creator
125+ from virtualenv.discovery.py_info import PythonInfo
96126 from virtualenv.seed.seeder import Seeder
97127
98128
99129 class CustomSeeder (Seeder ):
100130 @ classmethod
101- def add_parser_arguments (cls , parser , interpreter , app_data ):
131+ def add_parser_arguments (
132+ cls , parser : ArgumentParser, interpreter : PythonInfo, app_data : AppData
133+ ) -> None :
102134 parser.add_argument(" --custom-seed-opt" , help = " custom seeder option" )
103135
104- def __init__ (self , options , enabled , app_data ):
105- super ().__init__ (options, enabled, app_data)
136+ @ classmethod
137+ def cannot_seed (cls , interpreter : PythonInfo) -> str | None :
138+ # ship wheels down to Python 3.6, for example
139+ if interpreter.version_info[:2 ] >= (3 , 6 ):
140+ return None
141+ return " custom seeder ships wheels only for Python 3.6 and later"
142+
143+ def __init__ (self , options : VirtualEnvOptions, enabled : bool ) -> None :
144+ super ().__init__ (options, enabled)
106145 self .custom_opt = options.custom_seed_opt
107146
108- def run (self , creator ) :
147+ def run (self , creator : Creator) -> None :
109148 # Install packages into creator.bin_dir / creator.script("pip")
110149 self ._install_packages(creator)
111150
112- def _install_packages (self , creator ) :
151+ def _install_packages (self , creator : Creator) -> None :
113152 # Implementation-specific logic
114- pass
153+ ...
115154
116155 Register the entry point:
117156
@@ -130,18 +169,24 @@ Implement the ``Activator`` interface:
130169
131170.. code-block :: python
132171
172+ from __future__ import annotations
173+
174+ from pathlib import Path
175+
133176 from virtualenv.activation.activator import Activator
177+ from virtualenv.create.creator import Creator
134178
135179
136180 class CustomShellActivator (Activator ):
137- def generate (self , creator ) :
181+ def generate (self , creator : Creator) -> list[Path] :
138182 # Generate activation script content
139183 script_content = self ._render_template(creator)
140184 # Write to activation directory
141185 dest = creator.bin_dir / self .script_name
142186 dest.write_text(script_content)
187+ return [dest]
143188
144- def _render_template (self , creator ) :
189+ def _render_template (self , creator : Creator) -> str :
145190 # Return activation script content
146191 return f """
147192 # Custom shell activation script
@@ -150,7 +195,7 @@ Implement the ``Activator`` interface:
150195 """
151196
152197 @ property
153- def script_name (self ):
198+ def script_name (self ) -> str :
154199 return " activate.custom"
155200
156201 Register the entry point:
0 commit comments