@@ -50,21 +50,36 @@ def wrap(cls, plugin):
5050 "The `modify_wheel` attribute of pex.build_backend.wrap plugin {plugin} must be a "
5151 "callable but given {value} of type {type}." .format (
5252 plugin = qualified_name (plugin ),
53- value = modify_sdist ,
54- type = type (modify_sdist ).__name__ ,
53+ value = modify_wheel ,
54+ type = type (modify_wheel ).__name__ ,
5555 )
5656 )
5757
58- if not modify_sdist and not modify_wheel :
58+ modify_editable = getattr (plugin , "modify_editable" , None )
59+ if modify_editable and not callable (modify_editable ):
5960 raise ConfigurationError (
60- "The pex.build_backend.wrap plugin {plugin} must define a `modify_sdist` function, "
61- "a `modify_wheel` or both; it has neither." .format (plugin = qualified_name (plugin ))
61+ "The `modify_editable` attribute of pex.build_backend.wrap plugin {plugin} must be "
62+ "a callable but given {value} of type {type}." .format (
63+ plugin = qualified_name (plugin ),
64+ value = modify_editable ,
65+ type = type (modify_editable ).__name__ ,
66+ )
6267 )
6368
64- return cls (modify_sdist = modify_sdist , modify_wheel = modify_wheel )
69+ if not modify_sdist and not modify_wheel and not modify_editable :
70+ raise ConfigurationError (
71+ "The pex.build_backend.wrap plugin {plugin} must define at least one plugin "
72+ "function: `modify_sdist`, `modify_wheel` or `modify_editable`; "
73+ "it has none." .format (plugin = qualified_name (plugin ))
74+ )
75+
76+ return cls (
77+ modify_sdist = modify_sdist , modify_wheel = modify_wheel , modify_editable = modify_editable
78+ )
6579
6680 _modify_sdist = attr .ib () # type: Optional[Callable[[Text], None]]
6781 _modify_wheel = attr .ib () # type: Optional[Callable[[Text, Text], None]]
82+ _modify_editable = attr .ib () # type: Optional[Callable[[Text, Optional[Text]], None]]
6883
6984 @property
7085 def modifies_sdists (self ):
@@ -92,6 +107,21 @@ def modify_wheel(
92107 return self ._modify_wheel (wheel_dir , dist_info_dir_relpath )
93108 return None
94109
110+ @property
111+ def modifies_editable (self ):
112+ # type: () -> bool
113+ return self ._modify_editable is not None
114+
115+ def modify_editable (
116+ self ,
117+ wheel_dir , # type: Text
118+ dist_info_dir = None , # type: Optional[Text]
119+ ):
120+ # type: (...) -> Any
121+ if self ._modify_editable :
122+ return self ._modify_editable (wheel_dir , dist_info_dir )
123+ return None
124+
95125
96126def _check_plugin (
97127 plugin , # type: Any
0 commit comments