Beispiel #1
0
    def testProxyHostComps(self):
        pers_comps = BaseComponents(BASE, 'persistent', (BASE,))
        host_comps = BaseComponents(BASE, 'example.com', (BASE,))
        host_sm = HSM('example.com', 'siteman', host_comps, pers_comps)
        host_site = MockSite(host_sm)
        host_site.__name__ = host_sm.__name__
        setSite(host_site)

        new_comps = BaseComponents(BASE, 'sub_site', (pers_comps,))
        new_site = MockSite(new_comps)
        new_site.__name__ = new_comps.__name__
        interface.alsoProvides(new_site, IFoo)

        threadSiteSubscriber(new_site, None)

        cur_site = getSite()
        # It should implement the static and dynamic
        # ifaces
        assert_that(cur_site, validly_provides(IFoo))
        assert_that(cur_site, validly_provides(IMock))

        # It should have the marker property
        assert_that(cur_site.getSiteManager(),
                    has_property('host_components',
                                   host_comps))

        assert_that(ro.ro(cur_site.getSiteManager()),
                    contains(
                         # The first entry is synthesized
                         has_property('__name__', new_comps.__name__),
                         pers_comps,
                         # The host comps appear after all the bases
                         # in the ro of the new site
                         host_comps,
                         BASE))
    def changed(self, originally_changed):
        """We, or something we depend on, have changed
        """
        try:
            del self._v_attrs
        except AttributeError:
            pass

        implied = self._implied
        implied.clear()

        ancestors = ro(self)

        try:
            if Interface not in ancestors:
                ancestors.append(Interface)
        except NameError:
            pass # defining Interface itself

        self.__sro__ = tuple(ancestors)
        self.__iro__ = tuple([ancestor for ancestor in ancestors
                              if isinstance(ancestor, InterfaceClass)
                              ])

        for ancestor in ancestors:
            # We directly imply our ancestors:
            implied[ancestor] = ()

        # Now, advise our dependents of change:
        for dependent in tuple(self.dependents.keys()):
            dependent.changed(originally_changed)
Beispiel #3
0
    def changed(self, originally_changed):
        """We, or something we depend on, have changed
        """
        try:
            del self._v_attrs
        except AttributeError:
            pass

        implied = self._implied
        implied.clear()

        ancestors = ro(self)

        try:
            if Interface not in ancestors:
                ancestors.append(Interface)
        except NameError:
            pass  # defining Interface itself

        self.__sro__ = tuple(ancestors)
        self.__iro__ = tuple([
            ancestor for ancestor in ancestors
            if isinstance(ancestor, InterfaceClass)
        ])

        for ancestor in ancestors:
            # We directly imply our ancestors:
            implied[ancestor] = ()

        # Now, advise our dependents of change:
        for dependent in self.dependents.keys():
            dependent.changed(originally_changed)
Beispiel #4
0
    def _setBases(self, bases):
        """
        If subclasses need to track when ``__bases__`` changes, they
        can override this method.

        Subclasses must still call this method.
        """
        self.__dict__['__bases__'] = bases
        self.ro = ro.ro(self)
        self.changed(self)
Beispiel #5
0
            def test_ro(self, stdlib_class=stdlib_class, iface=iface):
                from zope.interface import ro
                from zope.interface import implementedBy
                from zope.interface import Interface
                self.assertEqual(tuple(ro.ro(iface, strict=True)),
                                 iface.__sro__)
                implements = implementedBy(stdlib_class)
                sro = implements.__sro__
                self.assertIs(sro[-1], Interface)

                # Check that we got the strict C3 resolution order, unless we
                # know we cannot. Note that 'Interface' is virtual base that doesn't
                # necessarily appear at the same place in the calculated SRO as in the
                # final SRO.
                strict = stdlib_class not in self.NON_STRICT_RO
                isro = ro.ro(implements, strict=strict)
                isro.remove(Interface)
                isro.append(Interface)

                self.assertEqual(tuple(isro), sro)
Beispiel #6
0
    def objectImplements(self):
        """
        All interfaces and classes implemented by an object.

        This is a KeywordIndex on the catalog.
        """
        dottednames = set()
        # Add the highest five classes in resolution order. 5 is
        # an arbitrary number; essentially, we only care about indexing
        # Zenoss classes, and our inheritance tree isn't that deep. Past
        # 5 we index a bunch of ObjectManager, Persistent, etc., which
        # we'll never use, and enact a significant performance penalty
        # when inserting keywords into the index.
        for kls in ro.ro(self._context.__class__)[:5]:
            dottednames.add('%s.%s' % (kls.__module__, kls.__name__))
        return list(dottednames)
Beispiel #7
0
    def objectImplements(self):
        """
        All interfaces and classes implemented by an object.

        This is a KeywordIndex on the catalog.
        """
        dottednames = set()
        # Add the highest five classes in resolution order. 5 is
        # an arbitrary number; essentially, we only care about indexing
        # Zenoss classes, and our inheritance tree isn't that deep. Past
        # 5 we index a bunch of ObjectManager, Persistent, etc., which
        # we'll never use, and enact a significant performance penalty
        # when inserting keywords into the index.
        for kls in ro.ro(self._context.__class__)[:5]:
            dottednames.add('%s.%s' % (kls.__module__, kls.__name__))
        return list(dottednames)
Beispiel #8
0
    def test_simple_ro(self):
        # Check that resolution order is what we think. See
        # site.py
        # This simulates the layout in the database and global
        # site manager.
        class GSM(object): pass
        # DB
        class Root(GSM): pass
        class DS(Root): pass
        # global sites
        class Base(GSM): pass
        class S1(Base): pass
        class S2(Base): pass
        # DB sites
        class PS1(S1, DS): pass
        class PS2(S2, PS1): pass

        assert_that(ro.ro(PS2),
                     is_([PS2, S2, PS1, S1, Base, DS, Root, GSM, object]))
Beispiel #9
0
def get_all_host_sites():
    """
    The order in which sites are accessed is top-down breadth-first,
    that is, the shallowest to the deepest nested sites. This allows
    you to assume that your parent sites have already been updated.

    :returns: A list of sites
    :rtype: list
    """

    sites = component.getUtility(IEtcNamespace, name='hostsites')
    sites = list(sites.values())

    # The easyiest way to go top-down is to again use the resolution order;
    # we just have to watch out for duplicates and non-persistent components
    site_to_ro = {site: ro.ro(site.getSiteManager()) for site in sites}

    # This should be a plain, directed acyclic tree (single root) that is now
    # linearized.
    # Transform from the site manager back into the site object itself
    site_to_site_ro = {}
    for site, managers in site_to_ro.items():
        site_to_site_ro[site] = [getattr(x, '__parent__', None) for x in managers]

    # Ok, now, go through the dictionary, walking from the top to the bottom,
    # one at a time, thus producing the correct order
    # (Because our datastructure looks like this:
    #   site1: [site1, ds, base, GSM]
    #   site2: [site2, site1, base, GSM]
    #   site3: [site3, ds, base, GSM])
    ordered = list()

    while site_to_site_ro:
        for site, managers in dict(site_to_site_ro).items():
            if not managers:
                site_to_site_ro.pop(site)
                continue

            base_site = managers.pop()
            if base_site in sites and base_site not in ordered:
                # Ie., it's a real one we haven't seen before
                ordered.append(base_site)
    return ordered
Beispiel #10
0
    def objectImplements(self):
        """
        All interfaces and classes implemented by an object.

        This is a KeywordIndex on the catalog.
        """
        dottednames = set()
        # Add the highest five classes in resolution order. 5 is
        # an arbitrary number; essentially, we only care about indexing
        # Zenoss classes, and our inheritance tree isn't that deep. Past
        # 5 we index a bunch of ObjectManager, Persistent, etc., which
        # we'll never use, and enact a significant performance penalty
        # when inserting keywords into the index.

        for kls in ro.ro(self._context.__class__):
            # @TODO review. had some issues with picking only the top 5
            # instead we get anything from Products or Zenpacks
            if kls.__module__.startswith("Products") or kls.__module__.startswith("ZenPacks"):
                dottednames.add('%s.%s' % (kls.__module__, kls.__name__))
        return list(dottednames)
Beispiel #11
0
    def objectImplements(self):
        """
        All interfaces and classes implemented by an object.

        This is a KeywordIndex on the catalog.
        """
        dottednames = set()
        # Add the highest five classes in resolution order. 5 is
        # an arbitrary number; essentially, we only care about indexing
        # Zenoss classes, and our inheritance tree isn't that deep. Past
        # 5 we index a bunch of ObjectManager, Persistent, etc., which
        # we'll never use, and enact a significant performance penalty
        # when inserting keywords into the index.

        for kls in ro.ro(self._context.__class__):
            # @TODO review. had some issues with picking only the top 5
            # instead we get anything from Products or Zenpacks
            if kls.__module__.startswith(
                    "Products") or kls.__module__.startswith("ZenPacks"):
                dottednames.add('%s.%s' % (kls.__module__, kls.__name__))
        return list(dottednames)
Beispiel #12
0
    def test_site_sync(self):

        for site in _SITES:
            assert_that(_find_site_components((site.__name__,)),
                         is_(not_none()))

        with mock_db_trans() as conn:
            for site in _SITES:
                assert_that(_find_site_components((site.__name__,)),
                             is_(not_none()))


            ds = conn.root()['nti.dataserver']
            assert ds is not None
            sites = ds['++etc++hostsites']
            for site in _SITES:
                assert_that(sites, does_not(has_key(site.__name__)))

            synchronize_host_policies()
            synchronize_host_policies()

            assert_that(self._events, has_length(len(_SITES)))
            # These were put in in order
            # assert_that( self._events[0][0].__parent__,
            #            has_property('__name__', EVAL.__name__))

            # XXX These two lines are cover only.
            get_host_site(DEMO.__name__)
            get_host_site('DNE', True)
            assert_that(calling(get_host_site).with_args('dne'),
                        raises(LookupError))

        with mock_db_trans() as conn:
            for site in _SITES:
                assert_that(_find_site_components((site.__name__,)),
                             is_(not_none()))

            ds = conn.root()['nti.dataserver']

            assert ds is not None
            sites = ds['++etc++hostsites']

            assert_that(sites, has_key(EVAL.__name__))
            assert_that(sites[EVAL.__name__], verifiably_provides(ISite))

            # If we ask the demoalpha persistent site for an ITestSyteSync,
            # it will find us, because it goes to the demo global site
            assert_that(sites[DEMOALPHA.__name__].getSiteManager().queryUtility(ITestSiteSync),
                         is_(ASync))

            # However, if we put something in the demo *persistent* site, it
            # will find that
            sites[DEMO.__name__].getSiteManager().registerUtility(OtherSync())
            assert_that(sites[DEMOALPHA.__name__].getSiteManager().queryUtility(ITestSiteSync),
                        is_(OtherSync))

            # Verify the resolution order too
            def _name(x):
                if x.__name__ == '++etc++site':
                    return 'P' + str(x.__parent__.__name__)
                return x.__name__
            assert_that([_name(x) for x in ro.ro(sites[DEMOALPHA.__name__].getSiteManager())],
                        is_([u'Pdemo-alpha.nextthoughttest.com',
                             u'demo-alpha.nextthoughttest.com',
                             u'Pdemo.nextthoughttest.com',
                             u'demo.nextthoughttest.com',
                             u'Peval.nextthoughttest.com',
                             u'eval.nextthoughttest.com',
                             u'Pdataserver2',
                             u'PNone',
                             'base']))

            # including if we ask to travers from top to bottom
            names = list()
            def func():
                names.append(_name(component.getSiteManager()))

            run_job_in_all_host_sites(func)
            # Note that PDemo and Peval-alpha are arbitrary, they both
            # descend from eval;
            # TODO: why aren't we maintaining alphabetical order?
            # we should be, but sometimes we don't
            assert_that(names, is_(any_of(
                [u'Peval.nextthoughttest.com',
                 u'Pdemo.nextthoughttest.com',
                 u'Peval-alpha.nextthoughttest.com',
                 u'Pdemo-alpha.nextthoughttest.com'],
                [u'Peval.nextthoughttest.com',
                 u'Peval-alpha.nextthoughttest.com',
                 u'Pdemo.nextthoughttest.com',
                 u'Pdemo-alpha.nextthoughttest.com'])))

            # And that it's what we get back if we ask for it
            assert_that(get_site_for_site_names((DEMOALPHA.__name__,)),
                         is_(same_instance(sites[DEMOALPHA.__name__])))

        # No new sites created
        assert_that(self._events, has_length(len(_SITES)))
Beispiel #13
0
    def clean(self):
        for base in self.__bases__:
            base.unsubscribe(self)
        self.__bases__ = [self.registry.get(base)
                          for base in self.spec().__bases__]
        for base in self.__bases__:
            base.subscribe(self)

        self.selfImplied, self.multImplied = adapterImplied(self.adapters)

        implied = {}

        ancestors = ro(self)

        # Collect implied data in reverse order to have more specific data
        # override less-specific data.
        ancestors.reverse()
        for ancestor in ancestors:
            
            for key, v in ancestor.selfImplied.iteritems():

                # key is specification or ('s', specification)
                subscription = isinstance(key, tuple) and key[0] == 's'
                if subscription:
                    # v is tuple of subs
                    implied[key] = implied.get(key, ()) + v
                else:
                    oldbyname = implied.get(key)
                    if not oldbyname:
                        implied[key] = oldbyname = {}
                    
                    # v is name -> object
                    oldbyname.update(v)

            for key, v in ancestor.multImplied.iteritems():
                # key is (specification, order)
                #     or ('s', specification, order)
                subscription = key[0] == 's'
                if subscription:
                    oldwithobs = implied.get(key)
                    if not oldwithobs:
                        oldwithobs = implied[key] = {}
                        
                    # v is {with -> tuple([object])}
                    for with, objects in v.iteritems():
                        oldwithobs[with] = oldwithobs.get(with, ()) + objects
                    
                else:
                    oldbyname = implied.get(key)
                    if not oldbyname:
                        implied[key] = oldbyname = {}

                    # v is {name -> {with -> ?}}
                    for name, withobs in v.iteritems():
                        oldwithobs = oldbyname.get(name)
                        if not oldwithobs:
                            oldwithobs = oldbyname[name] = {}

                        # withobs is {with -> object}
                        oldwithobs.update(withobs)

        # Now flatten with mappings to tuples
        for key, v in implied.iteritems():
            if isinstance(key, tuple):
                if key[0] == 's':
                    # subscriptions
                    if isinstance(v, dict):
                        implied[key] = v.items()
                else:
                    byname = v
                    for name, value in byname.iteritems():
                        if isinstance(value, dict):
                            # We have {with -> value}
                            # convert it to sorted [(with, value]
                            byname[name] = orderwith(value)

        self.get = implied.get
Beispiel #14
0
 def _callFUT(self, ob):
     from zope.interface.ro import ro
     return ro(ob)
Beispiel #15
0
def synchronize_host_policies():
    """
    Called within a transaction with a site being the current application
    site, find any :mod:`z3c.baseregistry` components that
    should be persistent sites, and register them in the database.

    As a prerequisite, :func:`install_sites_folder` must have been done, and
    we must be in that site.
    """

    # TODO: We will ultimately need to deal with removing and renaming
    # of these

    # Resolution order: The actual ISite __parent__ order is not
    # important, so we can keep them flat to mirror the GSM IComponents
    # registrations. What matters is the __bases__ of the site managers.
    # Now, if the global IComponents are themselves flat, then it doesn't matter;
    # however, if you have a hierarchy (and we do) then it matters critically, because
    # we need to pick up persistent utilities from these objects, as well as
    # the global components, in the right order. For example, if we have this
    # global hierarchy:
    #  GSM
    #  \
    #   S1
    #   \
    #     S2
    # and in the database we have the nti.dataserver and root persistent site managers,
    # then when we create the persistent sites for S1 and S2 (PS1 and PS2) we want
    # the resolution order to be:
    #   PS2 -> S2 -> PS1 -> S1 -> DS -> Root -> GSM
    # That is, we need to get the persistent components mixed in between the
    # global components.
    # Fortunately this is very easy to achieve. The code in zope.interface.ro handles
    # this.
    # We just need to ensure:
    #   PS1.__bases__ = (S1, DS)
    #   PS2.__bases__ = (S2, PS1)

    sites = component.getUtility(IEtcNamespace, name='hostsites')
    ds_folder = sites.__parent__
    assert IMainApplicationFolder.providedBy(ds_folder)

    ds_site_manager = ds_folder.getSiteManager()

    # Ok, find everything that is globally registered
    global_sm = component.getGlobalSiteManager()
    all_global_named_utilities = list(global_sm.getUtilitiesFor(IComponents))
    for name, comp in all_global_named_utilities:
        # The sites must be registered the same as their internal name
        assert name == comp.__name__
    all_global_utilities = [x[1] for x in all_global_named_utilities]

    # Now, get the resolution order of each site; this is an easy way
    # to do a kind of topological sort.
    site_ros = [ro.ro(x) for x in all_global_utilities]

    # Next, start creating persistent sites in the database, walking from the top
    # of the resolution order (the end of the list)
    # towards the root; the first one we put in the DB gets the DS as its
    # base, otherwise it gets the previous one we put in.

    for site_ro in site_ros:
        site_ro = reversed(site_ro)

        secondary_comps = ds_site_manager
        for comps in site_ro:
            name = comps.__name__
            logger.debug("Checking host policy for site %s", name)
            if name.endswith('base') or name.startswith('base'):
                # The GSM or the base global objects
                # TODO: better way to do this...marker interface?
                continue # pragma: no cover
            if name in sites:
                logger.debug("Host policy for %s already in place", name)
                # Ok, we've already put one in for this level.
                # We need to make it our next choice going forward
                secondary_comps = sites[name].getSiteManager()
            else:
                # Great, create the site
                logger.info("Installing site policy %s", name)

                site = HostPolicyFolder()
                # should fire object created event
                sites[name] = site

                site_policy = HostPolicySiteManager(site)
                site_policy.__bases__ = (comps, secondary_comps)
                # should fire INewLocalSite
                site.setSiteManager(site_policy)
                secondary_comps = site_policy
Beispiel #16
0
 def _setBases(self, bases):
     self.__dict__['__bases__'] = bases
     self.ro = ro.ro(self)
     self.changed(self)
 def _setBases(self, bases):
     self.__dict__['__bases__'] = bases
     self.ro = ro.ro(self)
     self.changed(self)
Beispiel #18
0
 def _callFUT(self, ob, **kwargs):
     from zope.interface.ro import ro
     return ro(ob, **kwargs)