Simon Ward <simon+pyt...@bleah.co.uk> writes: > On Thu, Mar 16, 2023 at 07:45:18AM +1300, dn via Python-list wrote: >> There is a PyPi library called pluggy (not used it). I've used >> informal approaches using an ABC as a framework/reminder (see >> @George's response). > > typing.Protocol is also useful here as the plugin interface can be > defined separately not requiring inheriting from an ABC.
Thanks to all for the helpful suggestions. I realise that I don't actually need to be able to load a bunch of arbitrary plugins, but merely to be able to override one (or, perhaps later, more) piece of default behaviour. Therefore I think the following very simple scheme will work for me: $ tree -L 3 . └── myproj ├── __init__.py ├── mailer.py ├── main.py └── plugins └── normanmailer.py Where main.py is #!/usr/bin/env python3 # -*- coding: utf-8 -*- if __name__ == "__main__": try: import plugin.mailer as mailer print("Found plugin.mailer") except ModuleNotFoundError: import mailer print("Found mailer") m = mailer.Mailer('abc') m.run() mailer.py is class Mailer(): def run(self): print("This is a generic Mailer object!") and plugins/normanmailer.py is class Mailer(): def run(self): print("This is a customized Mailer object!") This then gives me $ poetry run myproj\/main.py Found mailer This is a generic Mailer object! $ mv myproj/plugins/{norman,}mailer.py $ poetry run myproj\/main.py Found plugins.mailer This is a customized Mailer object! I suspect I was using slightly incorrect/misleading terminology. I don't want to be able to load arbitrary functionality via plugins, e.g. sending an email, dumping to a database, uploading to a cloud. That would, I far as I can tell, necessitate having some mechanism to select the functionality. Instead I just want to modify the behaviour of a piece of fixed functionality. e.g. sending a mail. So am I really talking about customisation here. Cheers, Loris -- This signature is currently under constuction. -- https://mail.python.org/mailman/listinfo/python-list