Installing (and removing) a new PlonePAS plugin

thank you, very much for sharing this; I was able to implement the skeleton of my authentication plugin with some mocks in just a few hours; now I have some comments on your code above:

first, the old style Zope 2 initialization code seems not to be needed if you use the following directives on your configure.zcml file:

<configure
    ...
    xmlns:five="http://namespaces.zope.org/five"
    xmlns:pas="http://namespaces.zope.org/pluggableauthservice"
    ...
    >

  <include package="Products.CMFCore" file="permissions.zcml" />
  <include package="Products.PlonePAS" />

  <five:registerClass
      class=".plugin.SenhaWebUsers"
      meta_type="SenhaWebUsers"
      permission="zope2.ViewManagementScreens"
      addview="add-senhaweb-users-plugin"
      />

  <pas:registerMultiPlugin meta_type="SenhaWebUsers" />

  <browser:page
      name="add-senhaweb-users-plugin"
      for="zope.browser.interfaces.IAdding"
      class="pas.plugins.senhaweb.plugin.AddForm"
      permission="zope2.ViewManagementScreens"
      />

what would be the right permission there? I can't find the equivalent of Add User Folders.

second, the post installation/uninstallation scripts are awesome and I thank you for showing me the post_handler attribute of the directive; that's just awesome.

third, the testing setup is just way too complicated without reason; I have it working with a vanilla setup and no Zope 2 black magic at all.

the test was failing because I was looking for the plugin in the acl_users object in Zope's root and not in my Plone site; this is working now:

class InstallTestCase(unittest.TestCase):
    ...
    def test_pas_plugin(self):
        acl_users = self.portal.acl_users
        self.assertIn(PLUGIN_ID, acl_users.objectIds())


class UninstallTestCase(unittest.TestCase):
    ...
    def test_pas_plugin_removed(self):
        acl_users = self.portal.acl_users
        self.assertNotIn(PLUGIN_ID, acl_users.objectIds())

I'll release the code as an example as soon as I review that no internal information is compromised.