Zásuvky a hadí vejce

27. 1. 2012 9:28 (aktualizováno) Pavel Císař

Konečně se mi podařilo vyšetřit nějaký ten čas na další vývoj PowerConsole. Už prototyp předváděný na Firebird konferenci používal pluginy pro příkazy a nápovědu, ale použitý systém byl jen taková rychlovka a už tehdy se mi moc nezamloval. Přes TurboGears se kterým v poslední době hodně pracuji jsem se blíže seznámil s modulem setuptools, který můj problém vyřešil.

Modul setuptools je nadstavba nad modulem distutils ze standardní knihovny Pythonu, takže rozšiřuje standardní systém setup.py o další metadata a funkcionalitu. Balíky spravované setuptools jsou takzvaná „vejce“ – Python Eggs (něco jako promyšlenější RPM nebo DEB). Mimo jiné řeší i závislosti (opravdu pěkně), integraci s repozitoří pypi, distribuci po internetu nebo lokální síti, propojení na Subversion a CVS repozitoře, aktualizace, vývojové a snapshot instalace a mnoho dalšího. Osobně se mi nejvíce zalíbila podpora dynamického zjišťování služeb a zásuvných modulů, tedy přesně to, co potřebuji pro svoji PowerConsoli.

Dokumentace k setuptools je velmi detailní, možná až moc. Setuptools má totiž tolik možností, že je velmi snadné pro samé detaily nevidět les, a nějaké ukázkové příklady typického použití by se určitě hodily. Ne každý má totiž čas na hledání správného postupu metodou pokus-omyl. Navíc systém dynamického zjišťování služeb není závislý jen na setuptools, ale i na balíku pkg_resources, který zajišťuje právě ono „dynamické zjišťování“.

Experimentování mě naštěstí ušetřil framework TurboGears, který jsem před pár měsíci začal používat, a který možností setuptools využívá opravdu důkladně. Po nahlédnutí do zdrojáků TurboGears bylo hned jasné, jak celý koncept použít.

V souboru setup.py balíku obsahujícím zásuvné moduly stačí doplnit parametr entry_points:

    entry_points = {'<jméno přípojného bodu>': 
['<jméno pluginu> = <modul>:<funkce nebo třída>']}

Např.:

    entry_points = {'powerconsole.commands': 
['quit = pcore.stdcmd:cmdQuit',
'help = pcore.stdcmd:cmdHelp'
]},

V kódu který pluginy používá je zapotřebí použít modul pkg_resources k načtení seznamu instalovaných zásuvných modulů pro daný přípojný bod, a vytvořit jejich instance. Např.:

   import pkg_resources
commands = []
for command in pkg_resources.iter_entry_points("powerconsole.commands"):
commands.append(command.load()(argumenty konstruktoru))

Sdílet