def processor(forType): """ Create an Axiom Item type which is suitable to use as a batch processor for the given Axiom Item type. Processors created this way depend on a L{iaxiom.IScheduler} powerup on the on which store they are installed. @type forType: L{item.MetaItem} @param forType: The Axiom Item type for which to create a batch processor type. @rtype: L{item.MetaItem} @return: An Axiom Item type suitable for use as a batch processor. If such a type previously existed, it will be returned. Otherwise, a new type is created. """ MILLI = 1000 try: processor = _processors[forType] except KeyError: def __init__(self, *a, **kw): item.Item.__init__(self, *a, **kw) self.store.powerUp(self, iaxiom.IBatchProcessor) attrs = { '__name__': 'Batch_' + forType.__name__, '__module__': forType.__module__, '__init__': __init__, '__repr__': lambda self: '<Batch of %s #%d>' % (reflect.qual(self.workUnitType), self.storeID), 'schemaVersion': 2, 'workUnitType': forType, 'scheduled': attributes.timestamp(doc=""" The next time at which this processor is scheduled to run. """, default=None), # MAGIC NUMBERS AREN'T THEY WONDERFUL? 'busyInterval': attributes.integer(doc="", default=MILLI / 10), } _processors[forType] = processor = item.MetaItem( attrs['__name__'], (item.Item, _BatchProcessorMixin), attrs) registerUpgrader( upgradeProcessor1to2, _processors[forType].typeName, 1, 2) return processor
class ConcurrentItemB(item.Item): anotherAttribute = attributes.integer()
class SoonToChange(item.Item): attribute = attributes.integer()
oldCertPath = site.store.dbdir.preauthChild(certificateFile) newCertPath = site.store.newFilePath('server.pem') oldCertPath.moveTo(newCertPath) port = SSLPort( store=site.store, portNumber=oldSite.securePortNumber, certificatePath=newCertPath, factory=site) installOn(port, site.store) newSite.deleteFromStore() declareLegacyItem( WebSite.typeName, 1, dict( hitCount = integer(default=0), installedOn = reference(), portNumber = integer(default=0), securePortNumber = integer(default=0), certificateFile = bytes(default=None))) def upgradeWebSite1To6(oldSite): return _makeSiteConfiguration(1, oldSite, False) upgrade.registerUpgrader(upgradeWebSite1To6, 'mantissa_web_powerup', 1, 6) declareLegacyItem( WebSite.typeName, 2, dict( hitCount = integer(default=0), installedOn = reference(), portNumber = integer(default=0), securePortNumber = integer(default=0),
self.dispatcher.installTemporaryProcessor(sip.URL(host, localpart), uac) uac._doCall(partyA[1], fromName="Divmod") def sipServer1to2(old): ss = old.upgradeVersion(old.typeName, 1, 2) ss.portno = old.portno ss.pstn = old.pstn ss.userbase = old.store.findOrCreate(LoginSystem) return ss registerUpgrader(sipServer1to2, SIPServer.typeName, 1, 2) declareLegacyItem( SIPServer.typeName, 2, dict(portno=integer(), pstn=bytes(), scheduler=reference(), userbase=reference())) def sipServer2to3(old): ss = old.upgradeVersion(old.typeName, 2, 3) ss.portno = old.portno ss.pstn = old.pstn ss.userbase = old.userbase return ss registerUpgrader(sipServer2to3, SIPServer.typeName, 2, 3) class Registration(Item): typename = "sine_registration"
An application L{SubStore} whose default shared item should be displayed on the root web resource. If None, the default index of applications will be displayed. """, allowNone=True) def createResourceWith(self, crud): """ Create a L{_PublicFrontPage} resource wrapping this object. """ return _PublicFrontPage(self, crud) item.declareLegacyItem( FrontPage.typeName, 1, dict(publicViews = attributes.integer(), privateViews = attributes.integer(), prefixURL = attributes.text(allowNone=False))) upgrade.registerAttributeCopyingUpgrader(FrontPage, 1, 2) class PublicAthenaLivePage(_PublicPageMixin, website.MantissaLivePage): """ PublicAthenaLivePage is a publicly viewable Athena-enabled page which slots a single fragment into the center of the page. """ docFactory = ThemedDocumentFactory('shell', 'templateResolver') unsupportedBrowserLoader = ThemedDocumentFactory( 'athena-unsupported', 'templateResolver')
{'CRAM-MD5': credentials.CramMD5Credentials, 'LOGIN': imap4.LOGINCredentials, }, certOpts) if self.debug: self.factory = policies.TrafficLoggingFactory(self.factory, 'smtp') return self.factory # GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG def setServiceParent(self, parent): pass item.declareLegacyItem(typeName=MailTransferAgent.typeName, schemaVersion=2, attributes=dict(messageCount=attributes.integer(), installedOn=attributes.reference(), portNumber=attributes.integer(), securePortNumber=attributes.integer(), certificateFile=attributes.bytes(), domain=attributes.bytes())) def upgradeMailTransferAgent1to2(oldMTA): """ MailTransferAgent has been replaced with MailDeliveryAgent on B{user stores}. Delete it from user stores and create a MailDelivery agent there, but leave it alone on the site store. """ loginSystem = oldMTA.store.findUnique(userbase.LoginSystem, default=None) if loginSystem is not None: newMTA = oldMTA.upgradeVersion(
class DecimalDoodad(Item): integral = point1decimal(default=0, allowNone=False) otherMoney = money(allowNone=True) extraintegral = integer() money = money(default=0)
class Bunny(item.Item): """ A bunny in a petting zoo. """ timesPetted = attributes.integer(default=0)
class List(Item): typeName = 'list' schemaVersion = 1 length = integer(default=0) def __init__(self, *args, **kw): super(List, self).__init__(**kw) if args: self.extend(args[0]) def _queryListItems(self): return self.store.query(_ListItem, _ListItem._container == self) def _getListItem(self, index): return list( self.store.query( _ListItem, AND(_ListItem._container == self, _ListItem._index == index)))[0] def _delListItem(self, index, resetIndexes=True): for li in self.store.query( _ListItem, AND(_ListItem._container == self, _ListItem._index == index)): li.deleteFromStore(deleteObject=True) break def _fixIndex(self, index, truncate=False): """ @param truncate: If true, negative indices which go past the beginning of the list will be evaluated as zero. For example:: >>> L = List([1,2,3,4,5]) >>> len(L) 5 >>> L._fixIndex(-9, truncate=True) 0 """ assert not isinstance(index, slice), 'slices are not supported (yet)' if index < 0: index += self.length if index < 0: if not truncate: raise IndexError('stored List index out of range') else: index = 0 return index def __getitem__(self, index): index = self._fixIndex(index) return self._getListItem(index)._value def __setitem__(self, index, value): index = self._fixIndex(index) self._getListItem(index)._value = value def __add__(self, other): return list(self) + list(other) def __radd__(self, other): return list(other) + list(self) def __mul__(self, other): return list(self) * other def __rmul__(self, other): return other * list(self) def index(self, other, start=0, maximum=None): if maximum is None: maximum = len(self) for pos in range(start, maximum): if pos >= len(self): break if self[pos] == other: return pos raise ValueError('List.index(x): %r not in List' % other) def __len__(self): return self.length def __delitem__(self, index): assert not isinstance(index, slice), 'slices are not supported (yet)' self._getListItem(index).deleteFromStore() if index < self.length - 1: for item in self.store.query( _ListItem, AND(_ListItem._container == self, _ListItem._index > index)): item._index -= 1 self.length -= 1 def __contains__(self, value): return bool(self.count(value)) def append(self, value): """ @type value: L{axiom.item.Item} @param value: Must be stored in the same L{Store<axiom.store.Store>} as this L{List} instance. """ # XXX: Should List.append(unstoredItem) automatically store the item? self.insert(self.length, value) def extend(self, other): for item in iter(other): self.append(item) def insert(self, index, value): index = self._fixIndex(index, truncate=True) # If we do List(length=5).insert(50, x), we don't want # x's _ListItem._index to actually be 50. index = min(index, self.length) # This uses list() in case our contents change halfway through. # But does that _really_ work? for li in list( self.store.query( _ListItem, AND(_ListItem._container == self, _ListItem._index >= index))): # XXX: The performance of this operation probably sucks # compared to what it would be with an UPDATE. li._index += 1 _ListItem(store=self.store, _value=value, _container=self, _index=index) self.length += 1 def pop(self, index=None): if index is None: index = self.length - 1 index = self._fixIndex(index) x = self[index] del self[index] return x def remove(self, value): del self[self.index(value)] def reverse(self): # XXX: Also needs to be an atomic action. length = 0 for li in list( self.store.query(_ListItem, _ListItem._container == self, sort=_ListItem._index.desc)): li._index = length length += 1 self.length = length def sort(self, *args): # We want to sort by value, not sort by _ListItem. We could # accomplish this by having _ListItem.__cmp__ do something # with self._value, but that seemed wrong. This was easier. values = [li._value for li in self._queryListItems()] values.sort(*args) index = 0 for li in self._queryListItems(): # XXX: Well, can it? assert index < len(values), \ '_ListItems were added during a sort (can this happen?)' li._index = index li._value = values[index] index += 1 def count(self, value): return self.store.count( _ListItem, AND(_ListItem._container == self, _ListItem._value == value))
class MyItem(item.Item): typeName = 'test_deadtype_myitem' schemaVersion = 1 hello = attributes.integer()
class Factoid(Item, Plugin): classProvides(IPlugin, IEridanusPluginProvider) schemaVersion = 1 typeName = 'eridanus_plugins_factoid' dummy = integer() @usage(u'list <key>') def cmd_list(self, source, key): """ List all factoids for <key>. """ def formatFactoid(fact, n): return u'\002%d\002: %s' % (n, fact.value) factoids = factoid.getFactoids(self.store, key) factoidText = (eutil.truncate(formatFactoid(fact, i), 40) for i, fact in enumerate(factoids)) msg = u' '.join(factoidText) source.reply(msg) @usage(u'get <key> [index]') def cmd_get(self, source, key, index=None): """ Retrieve a factoid for <key>. If <index> is omitted, a random factoid for <key> is retrieved. """ if index is not None: fac = factoid.getFactoid(self.store, key, int(index)) else: factoids = list(factoid.getFactoids(self.store, key)) fac = random.sample(factoids, 1)[0] source.reply(u'%s \002is\002 %s' % (fac.key, fac.value)) @usage(u'set <key> <value>') def cmd_set(self, source, key, value): """ Replace all factoids for <key> with <value>. """ factoid.setFactoid(self.store, source.user.nickname, key, value) source.reply(u'Set factoid for "%s".' % (key, )) @usage(u'add <key> <value>') def cmd_add(self, source, key, value): """ Add a new factoid for <key>. """ factoid.createFactoid(self.store, source.user.nickname, key, value) source.reply(u'Added a factoid for "%s".' % (key, )) @usage(u'delete <key> <index>') def cmd_delete(self, source, key, index): """ Delete a factoid for <key>. If `*` is supplied for <index>, all factoids for <key> are deleted. """ if index == u'*': index = None msg = u'Deleted all factoids for "%s".' % (key, ) else: index = int(index) msg = u'Deleted %d for factoid "%s".' % (index, key) factoid.deleteFactoid(self.store, key, index) source.reply(msg) @usage(u'replace <key> <index> <value>') def cmd_replace(self, source, key, index, value): """ Replace a specific factoid for <key>. """ index = int(index) factoid.replaceFactoid(self.store, source.user.nickname, key, index, value) source.reply(u'Replaced %d for factoid "%s".' % (index, key)) @usage(u'change <key> <regexp>') def cmd_change(self, source, key, regexp): """ Change factoids for <key> based on a regular expression. <regexp> should be of the form `s/foo/bar/`, `g` and `i` flags are accepted. If <regexp> matches multiple factoids for <key>, the global (`g`) flag must be specified. """ subst = reparse.parseRegex(regexp) numChanged = factoid.changeFactoids(self.store, source.user.nickname, key, subst) source.reply(u'Changed %d factoid(s).' % (numChanged, ))
class Garment(item.Item, Enhancement): """ An enhancement for a L{Thing} representing its utility as an article of clothing. """ implements(iimaginary.IClothing, iimaginary.IDescriptionContributor, iimaginary.IMovementRestriction) powerupInterfaces = (iimaginary.IClothing, iimaginary.IDescriptionContributor, iimaginary.IMovementRestriction) thing = attributes.reference() # templated / constant stuff garmentSlots = attributes.textlist(allowNone=False) bulk = attributes.integer(allowNone=False, default=1) garmentDescription = attributes.text(doc=""" Description of this as an individual garment. """, allowNone=False) # transient / mutable stuff wearer = attributes.reference() wearLevel = attributes.integer(default=0) def contributeDescriptionFrom(self, paths): return language.ExpressString(u'This can be worn.') def expressTo(self, observer): """ Describe the garment as it looks when it is worn. The garment's normal description is C{self.thing.description} or somesuch. """ return self.garmentDescription def nowWornBy(self, wearer): """ This garment is now worn by the given wearer. As this garment is now on top, set its C{wearLevel} to be higher than any other L{Garment} related to the new C{wearer}. """ self.wearer = wearer self.wearLevel = wearer.store.query( Garment, Garment.wearer == wearer).getColumn("wearLevel").max(default=0) + 1 def noLongerWorn(self): """ This garment is no longer being worn by anyone. """ self.wearer = None self.wearLevel = None def movementImminent(self, movee, destination): """ Something is trying to move. Don't allow it if I'm currently worn. """ if self.wearer is not None and movee is self.thing: raise ActionFailure( ThatDoesntWork( # XXX I don't actually know who is performing the action # :-(. actor=self.wearer.thing, actorMessage=[ "You can't move ", language.Noun(self.thing).definiteNounPhrase(), " without removing it first." ]))
""" self.composer.redirect(fromAddress, toAddresses, self.message) class ComposeBenefactor(item.Item): endowed = attributes.integer(default=0) powerupNames = ["xquotient.compose.Composer"] registerAttributeCopyingUpgrader(ComposePreferenceCollection, 1, 2) item.declareLegacyItem(ComposePreferenceCollection.typeName, 2, dict(installedOn=attributes.reference(), preferredSmarthost=attributes.text(), smarthostUsername=attributes.text(), smarthostPassword=attributes.text(), smarthostPort=attributes.integer(), smarthostAddress=attributes.text())) def composePreferenceCollection2to3(old): """ Create an L{smtpout.FromAddress} out of the appropriate L{userbase.LoginMethod} in the store, using L{_getFromAddressFromStore}. This probably should happen in the L{Composer} 2->3 upgrader, but we also make an L{smtpout.FromAddress} item out the smarthost attributes of C{old} if they are set, and we need to do that after creating the initial L{smtpout.FromAddress}, so it gets set as the default. Copy C{old.installedOn} onto the new L{ComposePreferenceCollection} """ baseFrom = FromAddress( store=old.store, address=_getFromAddressFromStore(old.store))
Obsolete. Only present for schema compatibility. Do not use. """ powerupInterfaces = (INavigableElement,) implements(INavigableElement) schemaVersion = 2 typeName = 'administrator_application' updateInterval = integer(default=5) privateApplication = dependsOn(PrivateApplication) def getTabs(self): return [] declareLegacyItem(AdminStatsApplication, 1, dict(updateInterval=integer(default=5))) def _adminStatsApplication1to2(old): new = old.upgradeVersion(AdminStatsApplication.typeName, 1, 2, updateInterval=old.updateInterval, privateApplication=old.store.findOrCreate(PrivateApplication)) return new registerUpgrader(_adminStatsApplication1to2, AdminStatsApplication.typeName, 1, 2) class LocalUserBrowser(Item): """ XXX I am an unfortunate necessity. This class shouldn't exist, and in fact, will be destroyed at the first possible moment. It's stateless, existing only to serve as a web lookup hook for the UserInteractionFragment view class.
self.running = True self.tries += 1 d = self.sendmail() d.addCallback(self.mailSent, sch) d.addErrback(self.failureSending, sch) d.addErrback(log.err) item.declareLegacyItem(DeliveryToAddress.typeName, 2, dict(composer = attributes.reference(), message = attributes.reference(), fromAddress = attributes.reference(), toAddress = attributes.text(), tries = attributes.integer(default=0))) def deliveryToAddress2to3(old): delivery = MessageDelivery(composer=old.composer, message=old.message, store=old.store) new = old.upgradeVersion(old.typeName, 2, 3, delivery=delivery, message=old.message, fromAddress=old.fromAddress, toAddress=old.toAddress, tries=old.tries, status=UNSENT) return new
class B(Item): typeName = 'test_circular_b' a = reference() n = integer()
sort=_AlreadyAnswered.storeID.ascending): self._deliverAnswer(answer) nextmsg = self.store.findFirst(_QueuedMessage, default=None) if nextmsg is not None: delay = _RETRANSMIT_DELAY else: nextanswer = self.store.findFirst(_AlreadyAnswered, default=None) if nextanswer is not None: delay = _RETRANSMIT_DELAY if delay is not None: return IScheduler(self.store).now() + timedelta(seconds=delay) declareLegacyItem( MessageQueue.typeName, 1, dict(messageCounter=integer(default=0, allowNone=False), scheduler=reference())) def upgradeMessageQueue1to2(old): """ Copy the C{messageCounter} attribute to the upgraded MessageQueue. """ return old.upgradeVersion( MessageQueue.typeName, 1, 2, messageCounter=old.messageCounter) registerUpgrader(upgradeMessageQueue1to2, MessageQueue.typeName, 1, 2) #### High-level convenience API #### AMP_MESSAGE_TYPE = u'mantissa.amp.message'
class ThingsWithIntegers(Item): schemaVersion = 1 typeName = 'axiom_test_thing_with_integers' a = integer() b = integer()
Compatibility hack necessary to prevent the Axiom service startup mechanism from barfing. Even though this Item is no longer an IService powerup, it will still be found as one one more time and this method will be called on it. """ def pop3Listener1to2(old): p3l = old.upgradeVersion(POP3Listener.typeName, 1, 2) p3l.userbase = old.store.findOrCreate(LoginSystem) return p3l registerUpgrader(pop3Listener1to2, POP3Listener.typeName, 1, 2) declareLegacyItem( POP3Listener.typeName, 2, dict(portNumber=integer(default=6110), securePortNumber=integer(default=0), certificateFile=bytes(default=None), userbase=reference(doc="dependsOn(LoginSystem)"))) def pop3listener2to3(oldPOP3): """ Create TCPPort and SSLPort items as appropriate. """ newPOP3 = oldPOP3.upgradeVersion( POP3Listener.typeName, 2, 3, userbase=oldPOP3.userbase, certificateFile=oldPOP3.certificateFile) if oldPOP3.portNumber is not None: port = TCPPort(store=newPOP3.store, portNumber=oldPOP3.portNumber, factory=newPOP3)
def indirect(self, interface): """ Indirect the implementation of L{IWebViewer} to L{_AuthenticatedWebViewer}. """ if interface == IWebViewer: return _AuthenticatedWebViewer(self) return self PrivateApplicationV2 = declareLegacyItem( PrivateApplication.typeName, 2, dict( installedOn=reference(), preferredTheme=text(), hitCount=integer(default=0), privateKey=integer(), privateIndexPage=reference(), )) PrivateApplicationV3 = declareLegacyItem( PrivateApplication.typeName, 3, dict( preferredTheme=text(), hitCount=integer(default=0), privateKey=integer(), privateIndexPage=reference(), customizedPublicPage=reference("dependsOn(CustomizedPublicPage)"), authenticationApplication=reference( "dependsOn(AuthenticationApplication)"), preferenceAggregator=reference("dependsOn(PreferenceAggregator)"),
self.assertEquals(t.__legacy__, True) self.assertFalse(store.objectCache.has(t.storeID)) t2 = store.getItemByID(t.storeID) self.assertNotIdentical(t, t2) self.assertTrue(isinstance(t2, UpgradedItem)) class UpgradedItem(Item): """ A simple item which is the current version of L{nonUpgradedItem}. """ schemaVersion = 2 dummy = integer() nonUpgradedItem = declareLegacyItem( UpgradedItem.typeName, 1, dict(dummy=integer())) def item1to2(old): """ Upgrade an nonUpgradedItem to UpgradedItem """ return old.upgradeVersion(UpgradedItem.typeName, 1, 2, dummy=old.dummy) registerUpgrader(item1to2, UpgradedItem.typeName, 1, 2)
class PrivateApplication(Item, PrefixURLMixin): """ This is the root of a private, navigable web application. It is designed to be installed on avatar stores after installing WebSite. To plug into it, install powerups of the type INavigableElement on the user's store. Their tabs will be retrieved and items that are part of those powerups will be linked to; provide adapters for said items to either INavigableFragment or IResource. Note: IResource adapters should be used sparingly, for example, for specialized web resources which are not 'nodes' within the application; for example, that need to set a custom content/type or that should not display any navigation elements because they will be displayed only within IFRAME nodes. Do _NOT_ use IResource adapters to provide a customized look-and-feel; instead use mantissa themes. (XXX document webtheme.py more thoroughly) @ivar preferredTheme: A C{unicode} string naming the preferred theme for this application. Templates and suchlike will be looked up for this theme first. @ivar privateKey: A random integer used to deterministically but unpredictably perturb link generation to avoid being the target of XSS attacks. @ivar privateIndexPage: A reference to the Item whose IResource or INavigableFragment adapter will be displayed on login and upon viewing the 'root' page, /private/. """ implements(ISiteRootPlugin, IWebTranslator, ITemplateNameResolver, IPowerupIndirector) powerupInterfaces = (IWebTranslator, ITemplateNameResolver, IWebViewer) typeName = 'private_web_application' schemaVersion = 5 preferredTheme = text() privateKey = integer(defaultFactory=genkey) website = dependsOn(WebSite) customizedPublicPage = dependsOn(CustomizedPublicPage) authenticationApplication = dependsOn(AuthenticationApplication) preferenceAggregator = dependsOn(PreferenceAggregator) defaultPreferenceCollection = dependsOn(DefaultPreferenceCollection) searchAggregator = dependsOn(SearchAggregator) #XXX Nothing ever uses this privateIndexPage = reference() prefixURL = 'private' sessioned = True sessionless = False def getPageComponents(self): navigation = getTabs(self.store.powerupsFor(INavigableElement)) staticShellContent = IStaticShellContent(self.store, None) return _PageComponents(navigation, self.searchAggregator, staticShellContent, self.store.findFirst(PreferenceAggregator), getInstalledThemes(self.store.parent)) def _getUsername(self): """ Return a localpart@domain style string naming the owner of our store. @rtype: C{unicode} """ for (l, d) in getAccountNames(self.store): return l + u'@' + d def createResourceWith(self, webViewer): return _PrivateRootPage(self, self.getPageComponents(), self._getUsername(), webViewer) # ISiteRootPlugin def produceResource(self, req, segments, webViewer): if segments == JUST_SLASH: return self.createResourceWith(webViewer), JUST_SLASH else: return super(PrivateApplication, self).produceResource(req, segments, webViewer) # IWebTranslator def linkTo(self, obj): # currently obj must be a storeID, but other types might come eventually return '/%s/%s' % (self.prefixURL, storeIDToWebID( self.privateKey, obj)) def linkToWithActiveTab(self, childItem, parentItem): """ Return a URL which will point to the web facet of C{childItem}, with the selected nav tab being the one that represents C{parentItem} """ return self.linkTo(parentItem.storeID) + '/' + self.toWebID(childItem) def linkFrom(self, webid): return webIDToStoreID(self.privateKey, webid) def fromWebID(self, webID): storeID = self.linkFrom(webID) if storeID is None: # This is not a very good interface, but I don't want to change the # calling code right now as I'm neither confident in its test # coverage nor looking to go on a test-writing rampage through this # code for a minor fix. raise _WebIDFormatException("%r didn't look like a webID" % (webID, )) webitem = self.store.getItemByID(storeID, None) return webitem def toWebID(self, item): return storeIDToWebID(self.privateKey, item.storeID) def _preferredThemes(self): """ Return a list of themes in the order of preference that this user has selected via L{PrivateApplication.preferredTheme}. """ themes = getInstalledThemes(self.store.parent) _reorderForPreference(themes, self.preferredTheme) return themes #ITemplateNameResolver def getDocFactory(self, fragmentName, default=None): """ Retrieve a Nevow document factory for the given name. @param fragmentName: a short string that names a fragment template. @param default: value to be returned if the named template is not found. """ themes = self._preferredThemes() for t in themes: fact = t.getDocFactory(fragmentName, None) if fact is not None: return fact return default # IPowerupIndirector def indirect(self, interface): """ Indirect the implementation of L{IWebViewer} to L{_AuthenticatedWebViewer}. """ if interface == IWebViewer: return _AuthenticatedWebViewer(self) return self
class Scheduler(Item, Service, SchedulerMixin): """ Track and execute persistent timed events for a I{site} store. """ typeName = 'axiom_scheduler' schemaVersion = 1 implements(IService, IScheduler) powerupInterfaces = (IService, IScheduler) parent = inmemory() name = inmemory() timer = inmemory() # Also testing hooks callLater = inmemory() now = inmemory() # This is unused and should be upgraded away. eventsRun = integer(default=0) lastEventAt = timestamp(default=None) nextEventAt = timestamp(default=None) class running(descriptor.attribute): def get(self): return (self.parent is self.store._axiom_service and self.store._axiom_service is not None and self.store._axiom_service.running) def set(self, value): # Eh whatever pass def __repr__(self): return '<Scheduler>' def installed(self): self.setServiceParent(IService(self.store)) def activate(self): self.timer = None self.callLater = reactor.callLater self.now = Time def startService(self): """ Start calling persistent timed events whose time has come. """ super(Scheduler, self).startService() self._transientSchedule(self.now(), self.now()) def stopService(self): """ Stop calling persistent timed events. """ super(Scheduler, self).stopService() if self.timer is not None: self.timer.cancel() self.timer = None def tick(self): self.timer = None return super(Scheduler, self).tick() def _transientSchedule(self, when, now): if not self.running: return if self.timer is not None: if self.timer.getTime() < when.asPOSIXTimestamp(): return self.timer.cancel() delay = when.asPOSIXTimestamp() - now.asPOSIXTimestamp() # reactor.callLater allows only positive delay values. The scheduler # may want to have scheduled things in the past and that's OK, since we # are dealing with Time() instances it's impossible to predict what # they are relative to the current time from user code anyway. delay = max(_EPSILON, delay) self.timer = self.callLater(delay, self.tick) self.nextEventAt = when
class LocalStoreMigration(Item): """ Migration from local content store. """ implements(IMigration) powerupInterfaces = [IMigration] source = reference( allowNone=False, doc="The content store that is the source of this migration") destination = reference(allowNone=True, doc=""" The content store that is the destination of this migration. If C{None}, this is a "validation" migration. """) start = integer(allowNone=False, doc="Starting storeID") current = integer(allowNone=False, doc="Most recent storeID migrated") end = integer(allowNone=False, doc="Ending storeID") concurrency = 10 _running = inmemory() def activate(self): self._running = False @transacted def _nextObject(self): """ Obtain the next object for which migration should be attempted. """ obj = self.store.findFirst(ImmutableObject, AND(ImmutableObject.storeID > self.current, ImmutableObject.storeID <= self.end), sort=ImmutableObject.storeID.asc) if obj is None: return None self.current = obj.storeID return PendingMigration(store=self.store, parent=self, obj=obj) # IMigration def run(self): """ Perform the migration. """ if self._running: return self._running = True def _done(ign): self._running = False migrations = chain( self.store.query(PendingMigration, PendingMigration.parent == self), iter(self._nextObject, None)) it = (m.attemptMigration() for m in migrations) tasks = [cooperate(it) for _ in xrange(self.concurrency)] d = gatherResults([task.whenDone() for task in tasks]) d.addCallback(_done) return d
class WebSite(Item, SiteRootMixin): """ An IResource avatar which supports L{ISiteRootPlugin}s on user stores and a limited number of other statically defined children. """ powerupInterfaces = (IResource,) implements(*powerupInterfaces + (IPowerupIndirector,)) typeName = 'mantissa_web_powerup' schemaVersion = 6 hitCount = integer(default=0) def cleartextRoot(self, hostname=None): """ Return a string representing the HTTP URL which is at the root of this site. @param hostname: An optional unicode string which, if specified, will be used as the hostname in the resulting URL, regardless of the C{hostname} attribute of this item. """ warnings.warn( "Use ISiteURLGenerator.rootURL instead of WebSite.cleartextRoot.", category=DeprecationWarning, stacklevel=2) if self.store.parent is not None: generator = ISiteURLGenerator(self.store.parent) else: generator = ISiteURLGenerator(self.store) return generator.cleartextRoot(hostname) def encryptedRoot(self, hostname=None): """ Return a string representing the HTTPS URL which is at the root of this site. @param hostname: An optional unicode string which, if specified, will be used as the hostname in the resulting URL, regardless of the C{hostname} attribute of this item. """ warnings.warn( "Use ISiteURLGenerator.rootURL instead of WebSite.encryptedRoot.", category=DeprecationWarning, stacklevel=2) if self.store.parent is not None: generator = ISiteURLGenerator(self.store.parent) else: generator = ISiteURLGenerator(self.store) return generator.encryptedRoot(hostname) def maybeEncryptedRoot(self, hostname=None): """ Returning a string representing the HTTPS URL which is at the root of this site, falling back to HTTP if HTTPS service is not available. @param hostname: An optional unicode string which, if specified, will be used as the hostname in the resulting URL, regardless of the C{hostname} attribute of this item. """ warnings.warn( "Use ISiteURLGenerator.rootURL instead of " "WebSite.maybeEncryptedRoot", category=DeprecationWarning, stacklevel=2) if self.store.parent is not None: generator = ISiteURLGenerator(self.store.parent) else: generator = ISiteURLGenerator(self.store) root = generator.encryptedRoot(hostname) if root is None: root = generator.cleartextRoot(hostname) return root def rootURL(self, request): """ Simple utility function to provide a root URL for this website which is appropriate to use in links generated in response to the given request. @type request: L{twisted.web.http.Request} @param request: The request which is being responded to. @rtype: L{URL} @return: The location at which the root of the resource hierarchy for this website is available. """ warnings.warn( "Use ISiteURLGenerator.rootURL instead of WebSite.rootURL.", category=DeprecationWarning, stacklevel=2) if self.store.parent is not None: generator = ISiteURLGenerator(self.store.parent) else: generator = ISiteURLGenerator(self.store) return generator.rootURL(request) def rootChild_resetPassword(self, req, webViewer): """ Redirect authenticated users to their settings page (hopefully they have one) when they try to reset their password. This is the wrong way for this functionality to be implemented. See #2524. """ from xmantissa.ixmantissa import IWebTranslator, IPreferenceAggregator return URL.fromString( IWebTranslator(self.store).linkTo( IPreferenceAggregator(self.store).storeID)) def setServiceParent(self, parent): """ Compatibility hack necessary to prevent the Axiom service startup mechanism from barfing. Even though this Item is no longer an IService powerup, it will still be found as one one more time and this method will be called on it. """ def getFactory(self): """ @see L{setServiceParent}. """ return self.store.findUnique(SiteConfiguration).getFactory() def _getUsername(self): """ Return a username, suitable for creating a L{VirtualHostWrapper} with. """ return u'@'.join(getAccountNames(self.store).next())
class Actor(item.Item, Actable, _Enhancement): hitpoints = attributes.reference(doc=""" """) stamina = attributes.reference(doc=""" """) strength = attributes.reference(doc=""" """) _ephemeralIntelligence = attributes.inmemory(doc=""" Maybe the L{IEventObserver} associated with this actor, generally a L{wiring.player.Player} instance. """) _enduringIntelligence = attributes.reference(doc=""" Maybe the persistent L{IEventObserver} associated with this actor. Generally used with NPCs. """) thing = attributes.reference(doc=""" The L{IThing} that this is installed on. """) level = attributes.integer(doc=""" Don't you hate level-based games? They're so stupid. """, default=0, allowNone=False) experience = attributes.integer(doc=""" XP! Come on, you know what this is. """, default=0, allowNone=False) def __init__(self, **kw): super(Actor, self).__init__(**kw) if self.hitpoints is None: self.hitpoints = Points(store=self.store, max=100) if self.stamina is None: self.stamina = Points(store=self.store, max=100) if self.strength is None: self.strength = Points(store=self.store, max=100) def activate(self): self._ephemeralIntelligence = None def setEphemeralIntelligence(self, intelligence): """ Set the ephemeral intelligence, generally one representing a PC's user interface. """ if self._enduringIntelligence: raise ValueError("Tried setting an ephemeral intelligence %r when " "an enduring intelligence %r already existed" % (intelligence, self._enduringIntelligence)) self._ephemeralIntelligence = intelligence def setEnduringIntelligence(self, intelligence): """ Set the enduring intelligence, generally one representing an NPC's AI. """ if self._ephemeralIntelligence: raise ValueError("Tried setting an enduring intelligence %r when " "an ephemeral intelligence %r already existed" % (intelligence, self._ephemeralIntelligence)) self._enduringIntelligence = intelligence def getIntelligence(self): """ Get the current intelligence, be it ephemeral or enduring. """ if self._ephemeralIntelligence is not None: return self._ephemeralIntelligence return self._enduringIntelligence
class AttributefulItem(item.Item): schemaVersion = 1 typeName = 'test_attributeful_item' withDefault = attributes.integer(default=42) withoutDefault = attributes.integer()
class Thing(item.Item): implements(iimaginary.IThing, iimaginary.IVisible) weight = attributes.integer(doc=""" Units of weight of this object. """, default=1, allowNone=False) location = attributes.reference(doc=""" Direct reference to the location of this object """) portable = attributes.boolean(doc=""" Whether this can be picked up, pushed around, relocated, etc """, default=True, allowNone=False) name = attributes.text(doc=""" The name of this object. """, allowNone=False) description = attributes.text(doc=""" What this object looks like. """, default=u"") gender = attributes.integer(doc=""" The grammatical gender of this thing. One of L{language.Gender.MALE}, L{language.Gender.FEMALE}, or L{language.Gender.NEUTER}. """, default=language.Gender.NEUTER, allowNone=False) proper = attributes.boolean(doc=""" Whether my name is a proper noun. """, default=False, allowNone=False) def destroy(self): if self.location is not None: iimaginary.IContainer(self.location).remove(self) self.deleteFromStore() def links(self): d = {self.name.lower(): [self]} if self.location is not None: merge(d, {self.location.name: [self.location]}) for pup in self.powerupsFor(iimaginary.ILinkContributor): merge(d, pup.links()) return d thing = property(lambda self: self) _ProviderStackElement = structlike.record( 'distance stability target proxies') def findProviders(self, interface, distance): # Dictionary keyed on Thing instances used to ensure any particular # Thing is yielded at most once. seen = {} # Dictionary keyed on Thing instances used to ensure any particular # Thing only has its links inspected at most once. visited = {self: True} # Load proxies that are installed directly on this Thing as well as # location proxies on this Thing's location: if self is adaptable to # interface, use them as arguments to _applyProxies and yield a proxied # and adapted facet of self. facet = interface(self, None) initialProxies = list(self.powerupsFor(iimaginary.IProxy)) locationProxies = set() if self.location is not None: locationProxies.update( set(self.location.powerupsFor(iimaginary.ILocationProxy))) if facet is not None: seen[self] = True proxiedFacet = self._applyProxies(locationProxies, initialProxies, facet, interface) if proxiedFacet is not None: yield proxiedFacet # Toss in for the _ProviderStackElement list/stack. Ensures ordering # in the descendTo list remains consistent with a breadth-first # traversal of links (there is probably a better way to do this). stabilityHelper = 1 # Set up a stack of Things to ask for links to visit - start with just # ourself and the proxies we have found already. descendTo = [ self._ProviderStackElement(distance, 0, self, initialProxies) ] while descendTo: element = descendTo.pop() distance, target, proxies = (element.distance, element.target, element.proxies) links = target.links().items() links.sort() for (linkName, linkedThings) in links: for linkedThing in linkedThings: if distance: if linkedThing not in visited: # A Thing which was linked and has not yet been # visited. Create a new list of proxies from the # current list and any which it has and push this # state onto the stack. Also extend the total list # of location proxies with any location proxies it # has. visited[linkedThing] = True stabilityHelper += 1 locationProxies.update( set( linkedThing.powerupsFor( iimaginary.ILocationProxy))) proxies = proxies + list( linkedThing.powerupsFor(iimaginary.IProxy)) descendTo.append( self._ProviderStackElement( distance - 1, stabilityHelper, linkedThing, proxies)) # If the linked Thing hasn't been yielded before and is # adaptable to the desired interface, wrap it in the # appropriate proxies and yield it. facet = interface(linkedThing, None) if facet is not None and linkedThing not in seen: seen[linkedThing] = True proxiedFacet = self._applyProxies( locationProxies, proxies, facet, interface) if proxiedFacet is not None: yield proxiedFacet # Re-order anything we've appended so that we visit it in the right # order. descendTo.sort() def _applyProxies(self, locationProxies, proxies, obj, interface): # Extremely pathetic algorithm - loop over all location proxies we have # seen and apply any which belong to the location of the target object. # This could do with some serious optimization. for proxy in locationProxies: if iimaginary.IContainer(proxy.thing).contains( obj.thing) or proxy.thing is obj.thing: obj = proxy.proxy(obj, interface) if obj is None: return None # Loop over the other proxies and simply apply them in turn, giving up # as soon as one eliminates the object entirely. for proxy in proxies: obj = proxy.proxy(obj, interface) if obj is None: return None return obj def proxiedThing(self, thing, interface, distance): for prospectiveFacet in self.findProviders(interface, distance): if prospectiveFacet.thing is thing: return prospectiveFacet raise eimaginary.ThingNotFound(thing) def search(self, distance, interface, name): """ Retrieve game objects answering to the given name which provide the given interface and are within the given distance. @type distance: C{int} @param distance: How many steps to traverse (note: this is wrong, it will become a real distance-y thing with real game-meaning someday). @param interface: The interface which objects within the required range must be adaptable to in order to be returned. @type name: C{str} @param name: The name of the stuff. @return: An iterable of L{iimaginary.IThing} providers which are found. """ # TODO - Move this into the action system. It is about finding things # using strings, which isn't what the action system is all about, but # the action system is where we do that sort of thing now. -exarkun extras = [] container = iimaginary.IContainer(self.location, None) if container is not None: potentialExit = container.getExitNamed(name, None) if potentialExit is not None: try: potentialThing = self.proxiedThing( potentialExit.toLocation, interface, distance) except eimaginary.ThingNotFound: pass else: yield potentialThing if name == "me" or name == "self": facet = interface(self, None) if facet is not None: extras.append(self) if name == "here" and self.location is not None: facet = interface(self.location, None) if facet is not None: extras.append(self.location) for res in self.findProviders(interface, distance): if res.thing in extras: yield res elif res.thing.knownAs(name): yield res def moveTo(self, where, arrivalEventFactory=None): """ @see: L{iimaginary.IThing.moveTo}. """ if where is self.location: return oldLocation = self.location if oldLocation is not None: events.DepartureEvent(oldLocation, self).broadcast() if where is not None: where = iimaginary.IContainer(where) if oldLocation is not None and not self.portable: raise eimaginary.CannotMove(self, where) where.add(self) if arrivalEventFactory is not None: arrivalEventFactory(self).broadcast() if oldLocation is not None: iimaginary.IContainer(oldLocation).remove(self) def knownAs(self, name): """ Return C{True} if C{name} might refer to this L{Thing}, C{False} otherwise. XXX - See #2604. """ name = name.lower() mine = self.name.lower() return name == mine or name in mine.split() # IVisible def visualize(self): container = iimaginary.IContainer(self.thing, None) if container is not None: exits = list(container.getExits()) else: exits = () return language.DescriptionConcept( self.name, self.description, exits, self.powerupsFor(iimaginary.IDescriptionContributor))
class TestWorkUnit(item.Item): information = attributes.integer() def __repr__(self): return '<TestWorkUnit %d>' % (self.information, )
class HeaderRule(item.Item): implements(iquotient.IFilteringRule) headerName = attributes.text(doc=""" Name of the header to which this rule applies. """, allowNone=False) negate = attributes.boolean(doc=""" Take the opposite of the operation's result. """, default=False, allowNone=False) operation = attributes.integer(doc=""" One of EQUALS, STARTSWITH, ENDSWITH, or CONTAINS. """, allowNone=False) value = attributes.text(doc=""" Text which will be used in applying this rule. """, allowNone=False) shortCircuit = attributes.boolean(doc=""" Stop all further processing if this rule matches. """, default=False, allowNone=False) caseSensitive = attributes.boolean(doc=""" Consider case when applying this rule. """, default=False, allowNone=False) action = attributes.reference(doc=""" The L{iquotient.IFilteringAction} to take when this rule matches. """) def __repr__(self): return '<HeaderRule on %r %s%s %r (%s%s)>' % ( self.headerName, self.negate and '!' or '', _opsToNames[self.operation], self.value, self.caseSensitive and 'case-sensitive' or 'case-insensitive', self.shortCircuit and ', short-circuit' or '') def getAction(self): return self.action def applyToHeaders(self, headers): if self.caseSensitive: value = self.value else: value = self.value.lower() for hdr in headers: if self.caseSensitive: hdrval = hdr.value else: hdrval = hdr.value.lower() if _opsToFunctions[self.operation](hdrval, value): if self.negate: break else: return (True, not self.shortCircuit, None) else: if self.negate: return (True, not self.shortCircuit, None) return (False, True, None) def applyTo(self, item): return self.applyToHeaders(item.impl.getHeaders(self.headerName))
'CRAM-MD5': credentials.CramMD5Credentials, 'LOGIN': imap4.LOGINCredentials, }, certOpts) if self.debug: self.factory = policies.TrafficLoggingFactory( self.factory, 'smtp') return self.factory # GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG def setServiceParent(self, parent): pass item.declareLegacyItem(typeName=MailTransferAgent.typeName, schemaVersion=2, attributes=dict(messageCount=attributes.integer(), installedOn=attributes.reference(), portNumber=attributes.integer(), securePortNumber=attributes.integer(), certificateFile=attributes.bytes(), domain=attributes.bytes())) def upgradeMailTransferAgent1to2(oldMTA): """ MailTransferAgent has been replaced with MailDeliveryAgent on B{user stores}. Delete it from user stores and create a MailDelivery agent there, but leave it alone on the site store. """ loginSystem = oldMTA.store.findUnique(userbase.LoginSystem, default=None) if loginSystem is not None:
class MailingListRule(item.Item): implements(iquotient.IFilteringRule) matchedMessages = attributes.integer(doc=""" Keeps track of the number of messages that have been matched as mailing list posts. """, default=0) def __repr__(self): return '<MailingListRule>' def match_ecartis(self, headers): sender = headers.get('sender', [None])[0] xlist = headers.get('x-list', [None])[0] version = headers.get('x-ecartis-version', [None])[0] if sender and xlist: domain = sender.rfind('@') if domain != -1 and version is not None: return xlist + u'.' + sender[domain + 1:] def match_yahooGroups(self, headers, listExpr = re.compile(r'''list (?P<listId>[^;]+)''')): """Match messages from Yahoo Groups. It seems the groups which were eGroups match the Ecartis filter, but some groups do not. This filter matches both the Ecartis yahoogroups and the others. """ # Example header: # Mailing-List: list [email protected]; contact [email protected] # Note: # ezmlm also has a "Mailing-List" header, but it provides the "help" # contact address only, not the list address: # Mailing-List: contact [email protected]; run by ezmlm # I don't match the ezmlm lists. (For that, see svn rev 4561 # branches/glyph/ezmlm-filtering. It matches "list-post", as appears # in both ezmlm and mailman.) mlist = headers.get('mailing-list', [None])[0] if mlist is not None: m = listExpr.search(mlist) if m is not None: listId = m.group('listId') return listId.replace('@', '.') def match_mailman(self, headers, listExpr = re.compile(r'''<(?P<listId>[^>]*)>'''), versionHeader = 'x-mailman-version'): if versionHeader in headers: listId = headers.get('list-id', [None])[0] if listId is not None: m = listExpr.search(listId) if m is not None: return m.group('listId') return listId def match_majorDomo(self, headers, listExpr = re.compile(r'''<(?P<listId>[^>]*)>''')): listId = headers.get('x-mailing-list', [None])[0] if listId is not None: m = listExpr.search(listId) if m is not None: return m.group('listId').replace(u'@', u'.') return listId.replace(u'@', u'.') def match_lyris(self, headers, listExpr = re.compile(r"""<mailto:leave-(?P<listname>.*)-.*@(?P<domain>.*)>""")): msgid = headers.get('message-id', [None])[0] unsub = headers.get('list-unsubscribe', [None])[0] if msgid is not None and u"LYRIS" in msgid and unsub is not None: m = listExpr.search(unsub) if m is not None: return u"%s.%s" % (m.group('listname'), m.group('domain')) def match_requestTracker(self, headers): ticket = headers.get('rt-ticket', [None])[0] managedby = headers.get('managed-by', [None])[0] if ticket is not None and managedby is not None: if managedby.startswith(u"RT"): return u"request-tracker" def match_EZMLM(self, headers, mailtoExpr = re.compile("<mailto:(.*)>")): # Actually, this seems to be more of a 'catch-all' filter than just # ezmlm; the information in the List-Id header for mailman is # replicated (sort of: I imagine the semantics are slightly different) # in the list-post header. lp = headers.get('list-post', [None])[0] if lp is not None: postAddress = mailtoExpr.findall(lp) if postAddress: postAddress = postAddress[0] return postAddress.replace(u"@", u".") def getAction(self): return MailingListTagAction() def applyTo(self, item): headers = {} for hdr in item.impl.getAllHeaders(): headers.setdefault(hdr.name, []).append(hdr.value) matchers = reflect.prefixedMethodNames(self.__class__, 'match_') for m in matchers: tag = getattr(self, 'match_' + m)(headers) if tag is not None: self.matchedMessages += 1 assert type(tag) is unicode, "%r was not unicode, came from %r" % (tag, m) return True, True, {"mailingListName": tag} return False, True, None
_SchedulerCompatMixin.activate(self) def setServiceParent(self, parent): """ L{Scheduler} is no longer an L{IService}, but still provides this method as a no-op in case an instance which was still an L{IService} powerup is loaded (in which case it will be used like a service once). """ declareLegacyItem( Scheduler.typeName, 1, dict(eventsRun=integer(default=0), lastEventAt=timestamp(), nextEventAt=timestamp())) def scheduler1to2(old): new = old.upgradeVersion(Scheduler.typeName, 1, 2) new.store.powerDown(new, IService) new.store.powerDown(new, IScheduler) return new registerUpgrader(scheduler1to2, Scheduler.typeName, 1, 2) class _SubSchedulerParentHook(Item): schemaVersion = 4
""" Create the extra state tracking items necessary for efficiently determining distinct source addresses. """ newInbox = oldInbox.upgradeVersion( "quotient_inbox", 1, 2, installedOn=oldInbox.installedOn, uiComplexity=oldInbox.uiComplexity ) return newInbox registerUpgrader(upgradeInbox1to2, "quotient_inbox", 1, 2) declareLegacyItem( Inbox.typeName, 2, dict(installedOn=attributes.reference(), uiComplexity=attributes.integer(), catalog=attributes.reference()), ) registerAttributeCopyingUpgrader(Inbox, 2, 3) declareLegacyItem( Inbox.typeName, 3, dict( installedOn=attributes.reference(), catalog=attributes.reference(), uiComplexity=attributes.integer(), showMoreDetail=attributes.boolean(), ), )
""") def listen(self): if self._listen is not None: _listen = self._listen else: from twisted.internet import reactor _listen = reactor.listenTCP return _listen(self.portNumber, self.factory.getFactory(), interface=self.interface.encode('ascii')) declareLegacyItem( typeName=normalize(qual(TCPPort)), schemaVersion=1, attributes=dict( portNumber=integer(), factory=reference(), parent=inmemory(), _listen=inmemory(), listeningPort=inmemory())) registerAttributeCopyingUpgrader(TCPPort, 1, 2) class SSLPort(PortMixin, Item): """ An Axiom Service Item which will bind a TCP port to a protocol factory when it is started. """ schemaVersion = 2
class POP3Grabber(item.Item): """ Item for retrieving email messages from a remote POP server. """ config = attributes.reference(doc=""" The L{GrabberConfiguration} which created this grabber. """) status = attributes.reference(doc=""" The current state of this grabber. This indicates whether a grab is currently being run, if a password is incorrect, etc. """) paused = attributes.boolean(doc=""" Flag indicating whether this particular grabber will try to get scheduled to retrieve messages. """, default=False) username = attributes.text(doc=""" Username in the remote system with which to authenticate. """, allowNone=False) password = attributes.text(doc=""" Password in the remote system with which to authenticate. """, allowNone=False) domain = attributes.text(doc=""" The address of the remote system to which to connect. """, allowNone=False) port = attributes.integer(doc=""" TCP port number on the remote system to which to connect. """, default=110) ssl = attributes.boolean(doc=""" Flag indicating whether to connect using SSL (note: this does not affect whether TLS will be negotiated post-connection.) """, default=False) messageCount = attributes.integer(doc=""" The number of messages which have been retrieved by this grabber. """, default=0) running = attributes.inmemory(doc=""" Flag indicating whether an attempt to retrieve messages is currently in progress. Only one attempt is allowed outstanding at any given time. """) protocol = attributes.inmemory(doc=""" While self.running=True this attribute will point to the ControlledPOP3GrabberProtocol that is grabbing stuff for me""") connector = attributes.inmemory(doc=""" implementor of L{twisted.internet.interfaces.IConnector}, representing our connection to the POP server """) scheduled = attributes.timestamp(doc=""" When this grabber is next scheduled to run. """) debug = attributes.boolean(doc=""" Flag indicating whether to log traffic from this grabber or not. """, default=False) created = attributes.timestamp(doc=""" Creation time of this grabber. Used when deciding whether a grabbed message is old enough to automatically archive. """) _pop3uids = attributes.inmemory(doc=""" A set of strings representing all the POP3 UIDs which have already been downloaded by this grabber. """) class installedOn(descriptor.attribute): def get(self): return self.config.installedOn def __init__(self, **kw): if 'created' not in kw: kw['created'] = extime.Time() return super(POP3Grabber, self).__init__(**kw) def activate(self): self._pop3uids = None self.running = False self.protocol = None if self.status is None: self.status = Status(store=self.store, message=u'idle') def delete(self): iaxiom.IScheduler(self.store).unscheduleAll(self) if self.running: if self.protocol is not None: self.protocol.stop() self.protocol.grabber = None else: self.connector.disconnect() self.deleteFromStore() def grab(self): # Don't run concurrently, ever. if self.running: return self.running = True from twisted.internet import reactor port = self.port if self.ssl: if port is None: port = 995 connect = lambda h, p, f: reactor.connectSSL( h, p, f, ssl.ClientContextFactory()) else: if port is None: port = 110 connect = reactor.connectTCP factory = POP3GrabberFactory(self, self.ssl) if self.debug: factory = policies.TrafficLoggingFactory( factory, 'pop3client-%d-%f' % (self.storeID, time.time())) self.status.setStatus(u"Connecting to %s:%d..." % (self.domain, port)) self.connector = connect( self.domain, port, BandwidthMeasuringFactory(factory, 'pop3-grabber')) def run(self): """ Retrieve some messages from the account associated with this grabber. """ try: if not self.paused: try: self.grab() except: log.err(None, "Failure in scheduled event") finally: # XXX This is not a good way for things to work. Different, later. delay = datetime.timedelta(seconds=300) self.scheduled = extime.Time() + delay return self.scheduled def _grabberID(self): if self.ssl and self.port == 995 or not self.ssl and self.port == 110: port = 'default' else: port = self.port return '%s@%s:%s' % (self.username, self.domain, port) grabberID = property(_grabberID) def shouldRetrieve(self, uidList): """ Return a list of (index, uid) pairs from C{uidList} which have not already been grabbed. """ if self._pop3uids is None: before = time.time() # Load all the POP3 UIDs at once and put them in a set for # super-fast lookup later. self._pop3uids = set( self.store.query( POP3UID, POP3UID.grabberID == self.grabberID).getColumn("value")) after = time.time() log.msg(interface=iaxiom.IStatEvent, stat_pop3uid_load_time=after - before) log.msg(interface=iaxiom.IStatEvent, stat_pop3uid_check=len(uidList)) return [pair for pair in uidList if pair[1] not in self._pop3uids] def markSuccess(self, uid, msg): """ Mark the retrieval of a message as successful with a particular UID. This grabber will no longer retrieve the message with that UID from the server. Archive that message if its sent date indicates it was sent more than one day before this grabber was created. @param uid: a POP3 UID specified by the server @type uid: L{str} @param msg: a L{xquotient.exmess.Message} which corresponds to that UID. @return: None """ if msg.sentWhen + datetime.timedelta(days=1) < self.created: msg.archive() log.msg(interface=iaxiom.IStatEvent, stat_messages_grabbed=1, userstore=self.store) POP3UID(store=self.store, grabberID=self.grabberID, value=uid) if self._pop3uids is not None: self._pop3uids.add(uid) def markFailure(self, uid, err): POP3UID(store=self.store, grabberID=self.grabberID, value=uid, failed=True) if self._pop3uids is not None: self._pop3uids.add(uid)
def test_integer(self): self._test_typeFor(attributes.integer(), amp.Integer)
class SpambayesBenefactor(item.Item): endowed = attributes.integer(default=0) powerupNames = ["xquotient.spam.SpambayesFilter"]
" so you should be able to skip this version.") registerUpgrader(sword2to3, 'test_app_sword', 2, 3) ####### DOUBLE-LEGACY UPGRADE SPECTACULAR !! ########### # declare legacy class. from axiom.item import declareLegacyItem declareLegacyItem(typeName = 'test_app_sword', schemaVersion = 2, attributes = dict(name=text(), damagePerHit=integer(), owner=reference(), activated=inmemory())) def upgradePlayerAndSword(oldplayer): newplayer = oldplayer.upgradeVersion('test_app_player', 1, 2) newplayer.name = oldplayer.name oldsword = oldplayer.sword newsword = oldsword.upgradeVersion('test_app_sword', 1, 3, name=oldsword.name, damagePerHit=oldsword.hurtfulness * 2) invent = InventoryEntry(store=newsword.store, owner=newplayer,
class DSPAMBenefactor(item.Item): endowed = attributes.integer(default=0) powerupNames = ["xquotient.spam.DSPAMFilter"]
def _declareLegacyIndexerItem(typeClass, version): item.declareLegacyItem(typeClass.typeName, version, dict(indexCount=attributes.integer(), installedOn=attributes.reference(), indexDirectory=attributes.text()))
class LoginAccount(Item): """ I am an entry in a LoginBase. @ivar avatars: An Item which is adaptable to various cred client interfaces. Plural because it represents a collection of potentially disparate implementors, such as an IResource for web access and an IContact for SIP access. @ivar disabled: This account has been disabled. It is still database-resident but the user should not be allowed to log in. """ typeName = 'login' schemaVersion = 2 password = text() avatars = reference() # reference to a thing which can be adapted to # implementations for application-level # protocols. In general this is a reference to # a SubStore because this is optimized for # applications where per-user data is a # substantial portion of the cost. disabled = integer() def __conform__(self, interface): """ For convenience, forward adaptation to my 'avatars' attribute. """ ifa = interface(self.avatars, None) return ifa def migrateDown(self): """ Assuming that self.avatars is a SubStore which should contain *only* the LoginAccount for the user I represent, remove all LoginAccounts and LoginMethods from that store and copy all methods from the site store down into it. """ ss = self.avatars.open() def _(): oldAccounts = ss.query(LoginAccount) oldMethods = ss.query(LoginMethod) for x in list(oldAccounts) + list(oldMethods): x.deleteFromStore() self.cloneInto(ss, ss) ss.transact(_) def migrateUp(self): """ Copy this LoginAccount and all associated LoginMethods from my store (which is assumed to be a SubStore, most likely a user store) into the site store which contains it. """ siteStore = self.store.parent def _(): # No convenience method for the following because needing to do it is # *rare*. It *should* be ugly; 99% of the time if you need to do this # you're making a mistake. -glyph siteStoreSubRef = siteStore.getItemByID(self.store.idInParent) self.cloneInto(siteStore, siteStoreSubRef) siteStore.transact(_) def cloneInto(self, newStore, avatars): """ Create a copy of this LoginAccount and all associated LoginMethods in a different Store. Return the copied LoginAccount. """ la = LoginAccount(store=newStore, password=self.password, avatars=avatars, disabled=self.disabled) for siteMethod in self.store.query(LoginMethod, LoginMethod.account == self): lm = LoginMethod(store=newStore, localpart=siteMethod.localpart, domain=siteMethod.domain, internal=siteMethod.internal, protocol=siteMethod.protocol, verified=siteMethod.verified, account=la) return la def deleteLoginMethods(self): self.store.query(LoginMethod, LoginMethod.account == self).deleteFromStore() def addLoginMethod(self, localpart, domain, protocol=ANY_PROTOCOL, verified=False, internal=False): """ Add a login method to this account, propogating up or down as necessary to site store or user store to maintain consistency. """ # Out takes you west or something if self.store.parent is None: # West takes you in otherStore = self.avatars.open() peer = otherStore.findUnique(LoginAccount) else: # In takes you east otherStore = self.store.parent subStoreItem = self.store.parent.getItemByID(self.store.idInParent) peer = otherStore.findUnique(LoginAccount, LoginAccount.avatars == subStoreItem) # Up and down take you home for store, account in [(otherStore, peer), (self.store, self)]: store.findOrCreate(LoginMethod, account=account, localpart=localpart, domain=domain, protocol=protocol, verified=verified, internal=internal)
class LoginSystem(Item, LoginBase, SubStoreLoginMixin): schemaVersion = 1 typeName = 'login_system' loginCount = integer(default=0) failedLogins = integer(default=0)
class IRCBotConfig(Item): typeName = 'eridanus_ircbotconfig' schemaVersion = 5 name = text(doc=""" The name of the network this config is for. """) hostname = bytes(doc=""" The hostname of the IRC server to connect to. """) portNumber = integer(doc=""" The port to connect to the IRC server on. """) nickname = text(doc=""" The bot's nickname. """) channels = textlist(doc=""" A C{list} of channels the bot should join. """, default=[]) ignores = textlist(doc=""" A C{list} of masks to ignore. """, default=[]) modes = bytes(doc=""" A string of user modes to set after successfully connecting to C{hostname}. """, default='B') def addChannel(self, channel): if channel not in self.channels: self.channels = self.channels + [channel] def removeChannel(self, channel): channels = self.channels while channel in channels: channels.remove(channel) self.channels = channels def isIgnored(self, mask): mask = util.normalizeMask(mask) for ignore in self.ignores: ignore = util.normalizeMask(ignore) if util.hostMatches(mask, ignore): return True return False def addIgnore(self, mask): mask = util.normalizeMask(mask) if mask not in self.ignores: self.ignores = self.ignores + [mask] return mask return None def removeIgnore(self, mask): def removeIgnores(mask): for ignore in self.ignores: normalizedIgnore = util.normalizeMask(ignore) if not util.hostMatches(normalizedIgnore, mask): yield ignore mask = util.normalizeMask(mask) newIgnores = list(removeIgnores(mask)) diff = set(self.ignores) - set(newIgnores) self.ignores = newIgnores return list(diff) or None
####### DOUBLE-LEGACY UPGRADE SPECTACULAR !! ########### # declare legacy class. from axiom.item import declareLegacyItem declareLegacyItem(typeName="test_app_player", schemaVersion=2, attributes=dict(name=text(allowNone=True))) registerAttributeCopyingUpgrader(Adventurer, 2, 3) declareLegacyItem( typeName="test_app_sword", schemaVersion=2, attributes=dict(name=text(), damagePerHit=integer(), owner=reference(), activated=inmemory()), ) def upgradePlayerAndSword(oldplayer): newplayer = oldplayer.upgradeVersion("test_app_player", 1, 2) newplayer.name = oldplayer.name oldsword = oldplayer.sword newsword = oldsword.upgradeVersion( "test_app_sword", 1, 2, name=oldsword.name, damagePerHit=oldsword.hurtfulness * 2, owner=newplayer ) return newplayer, newsword
# IPowerupIndirector def indirect(self, interface): """ Indirect the implementation of L{IWebViewer} to L{_AuthenticatedWebViewer}. """ if interface == IWebViewer: return _AuthenticatedWebViewer(self) return self PrivateApplicationV2 = declareLegacyItem(PrivateApplication.typeName, 2, dict( installedOn = reference(), preferredTheme = text(), hitCount = integer(default=0), privateKey = integer(), privateIndexPage = reference(), )) PrivateApplicationV3 = declareLegacyItem(PrivateApplication.typeName, 3, dict( preferredTheme=text(), hitCount=integer(default=0), privateKey=integer(), privateIndexPage=reference(), customizedPublicPage=reference("dependsOn(CustomizedPublicPage)"), authenticationApplication=reference("dependsOn(AuthenticationApplication)"), preferenceAggregator=reference("dependsOn(PreferenceAggregator)"), defaultPreferenceCollection=reference("dependsOn(DefaultPreferenceCollection)"), searchAggregator=reference("dependsOn(SearchAggregator)"), website=reference(),