divmod-dev team mailing list archive
-
divmod-dev team
-
Mailing list archive
-
Message #00595
[Merge] lp:~ashfall/divmod.org/1320678-remove-imaginary into lp:divmod.org
Ashwini Oruganti has proposed merging lp:~ashfall/divmod.org/1320678-remove-imaginary into lp:divmod.org.
Requested reviews:
Divmod-dev (divmod-dev)
Related bugs:
Bug #1320678 in Divmod: "Migrate Imaginary to Github"
https://bugs.launchpad.net/divmod.org/+bug/1320678
For more details, see:
https://code.launchpad.net/~ashfall/divmod.org/1320678-remove-imaginary/+merge/219969
Removes Imaginary from lp:divmod.org
--
The attached diff has been truncated due to its size.
https://code.launchpad.net/~ashfall/divmod.org/1320678-remove-imaginary/+merge/219969
Your team Divmod-dev is requested to review the proposed merge of lp:~ashfall/divmod.org/1320678-remove-imaginary into lp:divmod.org.
=== modified file 'Divmod.pth'
--- Divmod.pth 2013-06-27 06:02:46 +0000
+++ Divmod.pth 2014-05-18 17:55:49 +0000
@@ -1,4 +1,4 @@
-# -*- test-case-name: axiom,combinator,epsilon,xmantissa,nevow,formless,xquotient,reverend,sine,hyperbola,imaginary,examplegame -*-
+# -*- test-case-name: axiom,combinator,epsilon,xmantissa,nevow,formless,xquotient,reverend,sine,hyperbola -*-
Axiom
Combinator
Epsilon
@@ -8,6 +8,4 @@
Reverend
Sine
Hyperbola
-Imaginary
-Imaginary/ExampleGame
Prime
=== removed directory 'Imaginary'
=== removed file 'Imaginary/COMPATIBILITY.txt'
--- Imaginary/COMPATIBILITY.txt 2009-08-17 02:40:03 +0000
+++ Imaginary/COMPATIBILITY.txt 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-Imaginary provides _no_ source-level compatibility from one release to the next.
-
-Efforts will be made to provide database level compatibility (i.e. data from
-one release can be loaded with the next). However, although we will try to
-ensure that data will load, there is no guarantee that it will be meaningfully
-upgraded yet.
=== removed file 'Imaginary/DEPS.txt'
--- Imaginary/DEPS.txt 2013-07-10 00:22:10 +0000
+++ Imaginary/DEPS.txt 1970-01-01 00:00:00 +0000
@@ -1,4 +0,0 @@
-Python 2.7
-Twisted 13.1
-Epsilon SVN-Trunk
-Axiom SVN-Trunk
=== removed directory 'Imaginary/ExampleGame'
=== removed directory 'Imaginary/ExampleGame/examplegame'
=== removed file 'Imaginary/ExampleGame/examplegame/__init__.py'
=== removed file 'Imaginary/ExampleGame/examplegame/furniture.py'
--- Imaginary/ExampleGame/examplegame/furniture.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/furniture.py 1970-01-01 00:00:00 +0000
@@ -1,139 +0,0 @@
-# -*- test-case-name: examplegame.test.test_furniture -*-
-
-"""
-
- Furniture is the mass noun for the movable objects which may support the
- human body (seating furniture and beds), provide storage, or hold objects
- on horizontal surfaces above the ground.
-
- -- Wikipedia, http://en.wikipedia.org/wiki/Furniture
-
-L{imaginary.furniture} contains L{Action}s which allow players to interact with
-household objects such as chairs and tables, and L{Enhancement}s which allow
-L{Thing}s to behave as same.
-
-This has the same implementation weakness as L{examplegame.tether}, in that it
-needs to make some assumptions about who is moving what in its restrictions of
-movement; it should be moved into imaginary proper when that can be properly
-addressed. It's also a bit too draconian in terms of preventing the player
-from moving for any reason just because they're seated. However, it's a
-workable approximation for some uses, and thus useful as an example.
-"""
-
-from zope.interface import implements
-
-from axiom.item import Item
-from axiom.attributes import reference
-
-from imaginary.iimaginary import ISittable, IContainer, IMovementRestriction
-from imaginary.eimaginary import ActionFailure
-from imaginary.events import ThatDoesntWork
-from imaginary.language import Noun
-from imaginary.action import Action, TargetAction
-from imaginary.events import Success
-from imaginary.enhancement import Enhancement
-from imaginary.objects import Container
-from imaginary.pyparsing import Literal, Optional, restOfLine
-
-class Sit(TargetAction):
- """
- An action allowing a player to sit down in a chair.
- """
- expr = (Literal("sit") + Optional(Literal("on")) +
- restOfLine.setResultsName("target"))
-
- targetInterface = ISittable
-
- def do(self, player, line, target):
- """
- Do the action; sit down.
- """
- target.seat(player)
-
- actorMessage=["You sit in ",
- Noun(target.thing).definiteNounPhrase(),"."]
- otherMessage=[player.thing, " sits in ",
- Noun(target.thing).definiteNounPhrase(),"."]
- Success(actor=player.thing, location=player.thing.location,
- actorMessage=actorMessage,
- otherMessage=otherMessage).broadcast()
-
-
-class Stand(Action):
- """
- Stand up from a sitting position.
- """
- expr = (Literal("stand") + Optional(Literal("up")))
-
- def do(self, player, line):
- """
- Do the action; stand up.
- """
- # XXX This is wrong. I should be issuing an obtain() query to find
- # something that qualifies as "my location" or "the thing I'm already
- # sitting in".
- chair = ISittable(player.thing.location, None)
- if chair is None:
- raise ActionFailure(ThatDoesntWork(
- actor=player.thing,
- actorMessage=["You're already standing."]))
- chair.unseat(player)
- Success(actor=player.thing, location=player.thing.location,
- actorMessage=["You stand up."],
- otherMessage=[player.thing, " stands up."]).broadcast()
-
-
-
-class Chair(Enhancement, Item):
- """
- A chair is a thing you can sit in.
- """
-
- implements(ISittable, IMovementRestriction)
-
- powerupInterfaces = [ISittable]
-
- thing = reference()
- container = reference()
-
-
- def movementImminent(self, movee, destination):
- """
- A player tried to move while they were seated. Prevent them from doing
- so, noting that they must stand first.
-
- (Assume the player was trying to move themselves, although there's no
- way to know currently.)
- """
- raise ActionFailure(ThatDoesntWork(
- actor=movee,
- actorMessage=u"You can't do that while sitting down."))
-
-
- def applyEnhancement(self):
- """
- Apply this enhancement to this L{Chair}'s thing, creating a
- L{Container} to hold the seated player, if necessary.
- """
- super(Chair, self).applyEnhancement()
- container = IContainer(self.thing, None)
- if container is None:
- container = Container.createFor(self.thing, capacity=300)
- self.container = container
-
-
- def seat(self, player):
- """
- The player sat down on this chair; place them into it and prevent them
- from moving elsewhere until they stand up.
- """
- player.thing.moveTo(self.container)
- player.thing.powerUp(self, IMovementRestriction)
-
-
- def unseat(self, player):
- """
- The player stood up; remove them from this chair.
- """
- player.thing.powerDown(self, IMovementRestriction)
- player.thing.moveTo(self.container.thing.location)
=== removed file 'Imaginary/ExampleGame/examplegame/glass.py'
--- Imaginary/ExampleGame/examplegame/glass.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/glass.py 1970-01-01 00:00:00 +0000
@@ -1,72 +0,0 @@
-# -*- test-case-name: examplegame.test.test_glass -*-
-"""
-This example implements a transparent container that you can see, but not
-reach, the contents of.
-"""
-from zope.interface import implements
-
-from axiom.item import Item
-from axiom.attributes import reference
-
-from imaginary.iimaginary import (
- ILinkContributor, IWhyNot, IObstruction, IContainer)
-from imaginary.enhancement import Enhancement
-from imaginary.objects import ContainmentRelationship
-from imaginary.idea import Link
-
-class _CantReachThroughGlassBox(object):
- """
- This object provides an explanation for why the user cannot access a target
- that is inside a L{imaginary.objects.Thing} enhanced with a L{GlassBox}.
- """
- implements(IWhyNot)
-
- def tellMeWhyNot(self):
- """
- Return a simple message explaining that the user can't reach through
- the glass box.
- """
- return "You can't reach through the glass box."
-
-
-
-class _ObstructedByGlass(object):
- """
- This is an annotation on a link between two objects which represents a
- physical obstruction between them. It is used to annotate between a
- L{GlassBox} and its contents, so you can see them without reaching them.
- """
- implements(IObstruction)
-
- def whyNot(self):
- """
- @return: an object which explains why you can't reach through the glass
- box.
- """
- return _CantReachThroughGlassBox()
-
-
-
-class GlassBox(Item, Enhancement):
- """
- L{GlassBox} is an L{Enhancement} which modifies a container such that it is
- contained.
- """
-
- powerupInterfaces = (ILinkContributor,)
-
- thing = reference()
-
- def links(self):
- """
- If the container attached to this L{GlassBox}'s C{thing} is closed,
- yield its list of contents with each link annotated with
- L{_ObstructedByGlass}, indicating that the object cannot be reached.
- """
- container = IContainer(self.thing)
- if container.closed:
- for content in container.getContents():
- link = Link(self.thing.idea, content.idea)
- link.annotate([_ObstructedByGlass(),
- ContainmentRelationship(container)])
- yield link
=== removed file 'Imaginary/ExampleGame/examplegame/japanese.py'
--- Imaginary/ExampleGame/examplegame/japanese.py 2007-08-17 04:46:38 +0000
+++ Imaginary/ExampleGame/examplegame/japanese.py 1970-01-01 00:00:00 +0000
@@ -1,43 +0,0 @@
-"""
-Japanese language data.
-
-This module contains a dict named 'hiragana' which maps hiragana
-unicode characters to romaji pronunciations, as well as a
-'romajiToHiragana' dict which maps romaji pronunciation to *lists* of
-hiragana characters. There are multiple hiragana characters with the
-same pronunciation, thus the multiple values per romaji in the
-romajiToHiragana dict.
-
-"""
-
-
-# Hiragana.
-hiragana = {
- u'\u3042': 'A', u'\u3044': 'I', u'\u3046': 'U', u'\u3048': 'E',
- u'\u3081': 'ME', u'\u3080': 'MU', u'\u3082': 'MO', u'\u3084': 'YA',
- u'\u3086': 'YU', u'\u3089': 'RA', u'\u3088': 'YO', u'\u308b': 'RU',
- u'\u308a': 'RI', u'\u308d': 'RO', u'\u308c': 'RE', u'\u308f': 'WA',
- u'\u3091': 'WE', u'\u3090': 'WI', u'\u3093': 'N', u'\u3092': 'WO',
- u'\u304b': 'KA', u'\u304a': 'O', u'\u304d': 'KI', u'\u304c': 'GA',
- u'\u304f': 'KU', u'\u304e': 'GI', u'\u3051': 'KE', u'\u3050': 'GU',
- u'\u3053': 'KO', u'\u3052': 'GE', u'\u3055': 'SA', u'\u3054': 'GO',
- u'\u3057': 'SHI',u'\u3056': 'ZA', u'\u3059': 'SU', u'\u3058': 'JI',
- u'\u305b': 'SE', u'\u305a': 'ZU', u'\u305d': 'SO', u'\u305c': 'ZE',
- u'\u305f': 'TA', u'\u305e': 'ZO', u'\u3061': 'CHI', u'\u3060': 'DA',
- u'\u3062': 'JI', u'\u3065': 'ZU', u'\u3064': 'TSU', u'\u3067': 'DE',
- u'\u3066': 'TE', u'\u3069': 'DO', u'\u3068': 'TO', u'\u306b': 'NI',
- u'\u306a': 'NA', u'\u306d': 'NE', u'\u306c': 'NU', u'\u306f': 'HA',
- u'\u306e': 'NO', u'\u3071': 'PA', u'\u3070': 'BA', u'\u3073': 'BI',
- u'\u3072': 'HI', u'\u3075': 'FU', u'\u3074': 'PI', u'\u3077': 'PU',
- u'\u3076': 'BU', u'\u3079': 'BE', u'\u3078': 'HE', u'\u307b': 'HO',
- u'\u307a': 'PE', u'\u307d': 'PO', u'\u307c': 'BO', u'\u307f': 'MI',
- u'\u307e': 'MA'}
-
-
-romajiToHiragana = {}
-for k, v in hiragana.iteritems():
- romajiToHiragana.setdefault(v, []).append(k)
-
-# Katakana.
-# katakana = {
-# }
=== removed file 'Imaginary/ExampleGame/examplegame/mice.py'
--- Imaginary/ExampleGame/examplegame/mice.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/mice.py 1970-01-01 00:00:00 +0000
@@ -1,264 +0,0 @@
-# -*- test-case-name: examplegame.test.test_mice,examplegame.test.test_japanese -*-
-
-import random
-
-from zope.interface import implements
-
-from axiom import item, attributes
-
-from imaginary import iimaginary, events, objects, action, language
-from examplegame import japanese
-
-
-class Mouse(item.Item):
- """
- A silly mouse which squeaks when actors enter the room it is in.
-
- @ivar _callLater: The scheduling function to use. Override in unit
- tests only.
- """
-
- implements(iimaginary.IEventObserver)
-
- squeakiness = attributes.integer(doc="""
- How likely the mouse is to squeak when intruded upon (0 - 100).
-
- This mouse is so angry that he will pretty much always squeak.
- """, default=100)
-
- _callLater = attributes.inmemory()
-
- def activate(self):
- from twisted.internet import reactor
- self._callLater = reactor.callLater
-
-
- def prepare(self, concept):
- """
- An event was received. Squeak if it represents the arrival of a dude.
- """
- if isinstance(concept, events.ArrivalEvent):
- return lambda: self._callLater(0, self.squeak)
- return lambda: None
-
-
- def squeak(self):
- actor = self.store.findUnique(
- objects.Actor,
- objects.Actor._enduringIntelligence == self)
- evt = events.Success(
- actor=actor.thing,
- otherMessage=u"SQUEAK!")
- evt.broadcast()
-
-
-
-class ChallengeCollision(Exception):
- """
- Raised when a L{HiraganaMouse} is asked to start issuing challenges when it
- is already issuing challenges.
- """
-
-
-
-class ChallengeVacuum(Exception):
- """
- Raised when a L{HiraganaMouse} is asked to stop issuing challenges when it
- is already not issuing challenges.
- """
-
-
-
-class HiraganaMouse(item.Item):
- """
- A mouse which occasionally challenges those in its location to
- transliterate Hiragana.
-
- @ivar _callLater: The scheduling function to use. Defaults to the
- reactor's callLater method. This is parameterized for the sake of
- unit tests.
- """
-
- implements(iimaginary.IEventObserver)
-
- challenging = attributes.boolean(doc="""
- Whether or not this mouse is currently creating random challenges.
- """, default=False)
-
- challengeInterval = attributes.integer(doc="""
- Number of seconds between challenges.
- """, default=15, allowNone=False)
-
- _currentChallenge = attributes.text(doc="""
- The Hiragana character which the mouse has most recently issued as a
- challenge.
- """, default=None)
-
-
- _callLater = attributes.inmemory()
- _currentChallengeCall = attributes.inmemory()
-
- def activate(self):
- from twisted.internet import reactor
- self._callLater = reactor.callLater
-
- def _actor(self):
- """
- Get the h-mouse's associated actor. PRIVATE. WHY DID I DOCUMENT THIS.
- """
- return self.store.findUnique(
- objects.Actor,
- objects.Actor._enduringIntelligence == self)
-
-
- def _numDudes(self):
- """
- Get the number of actors (other than the h-mouse) in the
- h-mouse's location. PRIVATE.
- """
- actor = self._actor()
- numDudes = len([actor
- for dude
- in actor.thing.findProviders(iimaginary.IActor, 1)
- if dude is not actor])
- return numDudes
-
-
- def maybeChallenge(self):
- """
- Start challenging if there is anyone around to challenge (and
- this h-mouse isn't already challenging).
- """
- if not self.challenging and self._numDudes() >= 1:
- self.startChallenging()
-
-
- def prepare(self, concept):
- """
- An event was received. Start or stop challenging as
- appropriate, based on whether there is anyone to challenge.
- """
- if isinstance(concept, events.ArrivalEvent):
- self.maybeChallenge()
- elif isinstance(concept, events.DepartureEvent) and self._numDudes() == 0:
- self.stopChallenging()
- elif isinstance(concept, events.SpeechEvent) and concept.speaker is not self._actor().thing:
- self.responseReceived(concept.speaker, concept.text)
- return lambda: None
-
-
- def startChallenging(self):
- """
- Start shouting hiragana in the hope that someone knows what it means.
-
- @raises ChallengeCollision: If this h-mouse is already challenging.
- """
- if self.challenging:
- raise ChallengeCollision()
-
- self.challenging = True
- self._scheduleChallenge()
-
-
- def _scheduleChallenge(self):
- """
- Schedule a challenge to happen in the number of seconds set in
- the instance attribute 'challengeInterval'.
- """
- self._currentChallengeCall = self._callLater(self.challengeInterval,
- self._challengeAndRepeat)
-
-
- def stopChallenging(self):
- """
- Stop shouting hiragana.
-
- @raises ChallengeVacuum: If this h-mouse is not currently challenging.
- """
- if not self.challenging:
- raise ChallengeVacuum()
-
- self.challenging = False
-
- self._currentChallenge = None
- self._currentChallengeCall.cancel()
- self._currentChallengeCall = None
-
-
- def _challengeAndRepeat(self):
- """
- Shout a challenge and then schedule another one.
- """
- self.challenge()
- self._scheduleChallenge()
-
-
- def getCurrentChallenge(self):
- """
- Return the Hiragana character which is this mouse's current challenge,
- if it has one.
-
- @rtype: C{unicode} or C{None}
- """
- return self._currentChallenge
-
-
- def vetteChallengeResponse(self, romajiResponse):
- """
- Return True if the given response matches the current challenge, False
- otherwise.
- """
- hiragana = japanese.romajiToHiragana.get(romajiResponse.upper(), None)
- return hiragana is not None and self.getCurrentChallenge() in hiragana
-
-
- def responseReceived(self, responder, romajiResponse):
- """
- Called when some speech is observed.
- """
- me = self._actor().thing
- if self.vetteChallengeResponse(romajiResponse):
- self._currentChallenge = None
- verb = u"salute"
- else:
- verb = u"bite"
- evt = events.Success(
- actor=me,
- target=responder,
- actorMessage=language.Sentence(["You ", verb, " ", responder, "."]),
- targetMessage=language.Sentence([language.Noun(me).shortName(), " ", verb, "s you!"]),
- otherMessage=language.Sentence([me, " ", verb, "s ", responder, "."]))
- # Fuck the reactor, Fuck scheduling, why does responseReceived
- # need to be concerned with these stupid scheduling details
- # when all it wants to do is respond basically-immediately.
- self._callLater(0, evt.broadcast)
-
-
- def challenge(self, character=None):
- """
- Say only a single random hiragana character.
- """
- if character is None:
- character = random.choice(japanese.hiragana.keys())
- self._currentChallenge = character
- actor = self._actor()
- action.Say().do(actor, None, character)
-
-
-
-def createMouseCreator(mouseIntelligenceFactory):
- """
- Create a createMouse function, which can be called to create a
- mouse object. Used for the 'Create' command plugin system.
- """
- def createMouse(**kw):
- store = kw['store']
- mouse = objects.Thing(**kw)
- mouseActor = objects.Actor.createFor(mouse)
- mousehood = mouseIntelligenceFactory(store=store)
- mouseActor.setEnduringIntelligence(mousehood)
- return mouse
- return createMouse
-
-createMouse = createMouseCreator(Mouse)
-createHiraganaMouse = createMouseCreator(HiraganaMouse)
=== removed file 'Imaginary/ExampleGame/examplegame/quiche.py'
--- Imaginary/ExampleGame/examplegame/quiche.py 2009-06-29 04:03:17 +0000
+++ Imaginary/ExampleGame/examplegame/quiche.py 1970-01-01 00:00:00 +0000
@@ -1,116 +0,0 @@
-# -*- test-case-name: examplegame.test.test_quiche -*-
-
-"""
-This module is a mid-level proof of concept of various features in Imaginary.
-
-Currently its implementation is a bit messy and it assumes lots of things about
-the reader's knowledge, but we are working on more thoroughly documenting it
-and making it into a good example of how to build functionality that interacts
-with multiple systems (currency, containment, object creation) in Imaginary.
-
-"""
-
-from zope.interface import implements, Interface
-
-from axiom import item, attributes
-
-from imaginary import iimaginary, objects, events, language
-from imaginary.enhancement import Enhancement
-
-from imaginary.creation import createCreator
-
-
-class ICoin(Interface):
- """
- Something small and probably flat and round and which probably serves as
- some form of currency.
- """
-
-
-
-class Coinage(object):
- implements(ICoin)
- powerupInterfaces = (ICoin,)
-
-
-
-class Quarter(item.Item, Coinage, Enhancement):
- thing = attributes.reference(doc="""
- The object this coin powers up.
- """)
-
-
-
-class VendingMachine(item.Item, objects.Containment, Enhancement):
- implements(iimaginary.IContainer)
-
- capacity = attributes.integer(doc="""
- Units of weight which can be contained.
- """, allowNone=False, default=1)
-
- closed = attributes.boolean(doc="""
- Indicates whether the container is currently closed or open.
- """, allowNone=False, default=True)
-
- thing = attributes.reference(doc="""
- The object this container powers up.
- """)
-
- _currencyCounter = attributes.integer(doc="""
- The number of coins which have been added to this vending machine since it
- last ejected an item.
- """, allowNone=False, default=0)
-
- def coinAdded(self, coin):
- """
- Called when a coin is added to this thing.
-
- @type coin: C{ICoin} provider
- """
- self._currencyCounter += 1
- if self._currencyCounter >= 5 and self.getContents():
- self._currencyCounter = 0
- try:
- obj = iter(self.getContents()).next()
- except StopIteration:
- evt = events.Success(
- actor=self.thing,
- target=obj,
- otherMessage=language.Sentence([self.thing, " thumps loudly."]))
- else:
- evt = events.Success(
- actor=self.thing,
- target=obj,
- otherMessage=language.Sentence([
- language.Noun(self.thing).definiteNounPhrase(),
- " thumps loudly and spits out ", obj,
- " onto the ground."]))
- state = self.closed
- self.closed = False
- try:
- obj.moveTo(self.thing.location)
- finally:
- self.closed = state
- evt.broadcast()
-
-
- def add(self, obj):
- coin = ICoin(obj, None)
- if coin is not None:
- self.coinAdded(coin)
- else:
- return super(VendingMachine, self).add(obj)
-
-
-
-def createVendingMachine(store, name, description=u""):
- o = objects.Thing(store=store, name=name, description=description)
- VendingMachine.createFor(o)
- return o
-
-
-
-createCoin = createCreator((Quarter, {}))
-createVendingMachine = createCreator((VendingMachine, {}))
-createQuiche = createCreator()
-
=== removed file 'Imaginary/ExampleGame/examplegame/squeaky.py'
--- Imaginary/ExampleGame/examplegame/squeaky.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/squeaky.py 1970-01-01 00:00:00 +0000
@@ -1,42 +0,0 @@
-# -*- test-case-name: examplegame.test.test_squeaky -*-
-
-"""
-This module implements an L{ILinkAnnotator} which causes an object to squeak
-when it is moved. It should serve as a simple example for overriding what
-happens when an action is executed (in this case, 'take' and 'drop').
-"""
-
-from zope.interface import implements
-
-from axiom.item import Item
-from axiom.attributes import reference
-
-from imaginary.iimaginary import IMovementRestriction, IConcept
-from imaginary.events import Success
-from imaginary.enhancement import Enhancement
-from imaginary.objects import Thing
-
-
-class Squeaker(Item, Enhancement):
- """
- This is an L{Enhancement} which, when installed on a L{Thing}, causes that
- L{Thing} to squeak when you pick it up.
- """
-
- implements(IMovementRestriction)
-
- powerupInterfaces = [IMovementRestriction]
-
- thing = reference(allowNone=False,
- whenDeleted=reference.CASCADE,
- reftype=Thing)
-
-
- def movementImminent(self, movee, destination):
- """
- The object enhanced by this L{Squeaker} is about to move - emit a
- L{Success} event which describes its squeak.
- """
- Success(otherMessage=(IConcept(self.thing).capitalizeConcept(),
- " emits a faint squeak."),
- location=self.thing.location).broadcast()
=== removed directory 'Imaginary/ExampleGame/examplegame/test'
=== removed file 'Imaginary/ExampleGame/examplegame/test/__init__.py'
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_furniture.py'
--- Imaginary/ExampleGame/examplegame/test/test_furniture.py 2013-07-03 23:55:37 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_furniture.py 1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
-
-"""
-This module contains tests for the examplegame.furniture module.
-"""
-
-from twisted.trial.unittest import TestCase
-
-from imaginary.test.commandutils import CommandTestCaseMixin, E, createLocation
-
-from imaginary.objects import Thing, Exit
-from examplegame.furniture import Chair
-
-class SitAndStandTests(CommandTestCaseMixin, TestCase):
- """
- Tests for the 'sit' and 'stand' actions.
- """
-
- def setUp(self):
- """
- Create a room, with a dude in it, and a chair he can sit in.
- """
- CommandTestCaseMixin.setUp(self)
- self.chairThing = Thing(store=self.store, name=u"chair")
- self.chairThing.moveTo(self.location)
- self.chair = Chair.createFor(self.chairThing)
-
-
- def test_sitDown(self):
- """
- Sitting in a chair should move your location to that chair.
- """
- self.assertCommandOutput(
- "sit chair",
- ["You sit in the chair."],
- ["Test Player sits in the chair."])
- self.assertEquals(self.player.location, self.chair.thing)
-
-
- def test_standWhenStanding(self):
- """
- You can't stand up - you're already standing up.
- """
- self.assertCommandOutput(
- "stand up",
- ["You're already standing."])
-
-
- def test_standWhenSitting(self):
- """
- If a player stands up when sitting in a chair, they should be seen to
- stand up, and they should be placed back into the room where the chair
- is located.
- """
- self.test_sitDown()
- self.assertCommandOutput(
- "stand up",
- ["You stand up."],
- ["Test Player stands up."])
- self.assertEquals(self.player.location, self.location)
-
-
- def test_takeWhenSitting(self):
- """
- When a player is seated, they should still be able to take objects on
- the floor around them.
- """
- self.test_sitDown()
- self.ball = Thing(store=self.store, name=u'ball')
- self.ball.moveTo(self.location)
- self.assertCommandOutput(
- "take ball",
- ["You take a ball."],
- ["Test Player takes a ball."])
-
-
- def test_moveWhenSitting(self):
- """
- A player who is sitting shouldn't be able to move without standing up
- first.
- """
- self.test_sitDown()
- otherRoom = createLocation(self.store, u"elsewhere", None).thing
- Exit.link(self.location, otherRoom, u'north')
- self.assertCommandOutput(
- "go north",
- ["You can't do that while sitting down."])
- self.assertCommandOutput(
- "go south",
- ["You can't go that way."])
-
-
- def test_lookWhenSitting(self):
- """
- Looking around when sitting should display the description of the room.
- """
- self.test_sitDown()
- self.assertCommandOutput(
- "look",
- # I'd like to add ', in the chair' to this test, but there's
- # currently no way to modify the name of the object being looked
- # at.
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player and a chair."])
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_glass.py'
--- Imaginary/ExampleGame/examplegame/test/test_glass.py 2013-07-03 23:55:37 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_glass.py 1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
-
-"""
-Tests for L{examplegame.glass}
-"""
-
-from twisted.trial.unittest import TestCase
-
-from imaginary.test.commandutils import CommandTestCaseMixin, E
-
-from imaginary.objects import Thing, Container
-
-from examplegame.glass import GlassBox
-
-class GlassBoxTests(CommandTestCaseMixin, TestCase):
- """
- Tests for L{GlassBox}
- """
-
- def setUp(self):
- """
- Create a room with a L{GlassBox} in it, which itself contains a ball.
- """
- CommandTestCaseMixin.setUp(self)
- self.box = Thing(store=self.store, name=u'box',
- description=u'The system under test.')
- self.ball = Thing(store=self.store, name=u'ball',
- description=u'an interesting object')
- self.container = Container.createFor(self.box)
- GlassBox.createFor(self.box)
- self.ball.moveTo(self.box)
- self.box.moveTo(self.location)
- self.container.closed = True
-
-
- def test_lookThrough(self):
- """
- You can see items within a glass box by looking at them directly.
- """
- self.assertCommandOutput(
- "look at ball",
- [E("[ ball ]"),
- "an interesting object"])
-
-
- def test_lookAt(self):
- """
- You can see the contents within a glass box by looking at the box.
- """
- self.assertCommandOutput(
- "look at box",
- [E("[ box ]"),
- "The system under test.",
- "It contains a ball."])
-
-
- def test_take(self):
- """
- You can't take items within a glass box.
- """
- self.assertCommandOutput(
- "get ball",
- ["You can't reach through the glass box."])
-
-
- def test_openTake(self):
- """
- Taking items from a glass box should work if it's open.
- """
- self.container.closed = False
- self.assertCommandOutput(
- "get ball",
- ["You take a ball."],
- ["Test Player takes a ball."])
-
-
- def test_put(self):
- """
- You can't put items into a glass box.
- """
- self.container.closed = False
- self.ball.moveTo(self.location)
- self.container.closed = True
- self.assertCommandOutput(
- "put ball in box",
- ["The box is closed."])
-
-
- def test_whyNot(self):
- """
- A regression test; there was a bug where glass boxes would interfere
- with normal target-acquisition error reporting.
- """
- self.assertCommandOutput(
- "get foobar",
- ["Nothing like that around here."])
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_japanese.py'
--- Imaginary/ExampleGame/examplegame/test/test_japanese.py 2013-07-03 23:55:37 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_japanese.py 1970-01-01 00:00:00 +0000
@@ -1,474 +0,0 @@
-import weakref
-
-from twisted.internet import task
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import iimaginary, objects, events, action
-
-from imaginary.test import commandutils
-
-from examplegame import mice
-from examplegame import japanese
-
-class MouseChallengeMixin(object):
- """
- A mixin meant to be used in TestCases which want to assert things
- about mouse challenges.
-
- The subclass must be sure to provide a C{player} instance
- attribute, which is the L{IThing<iimaginary.IThing>} provider of
- the player which observes the mouse, and a C{mouseName} attribute
- which should be the mouse's name.
- """
- def assertChallenge(self, concept):
- """
- Assert that the given concept is a challenge from the mouse
- named self.mouseName, as observed by self.player.
- """
- said = commandutils.flatten(concept.plaintext(self.player))
- self.failUnless(said.startswith(u"A %s says, '" % (self.mouseName,)), repr(said))
- self.failUnlessIn(said[-3], japanese.hiragana)
- self.failUnless(said.endswith("'\n"), repr(said))
-
-
-
-class HiraganaMouseTestCase(MouseChallengeMixin, unittest.TestCase):
- """
- Test that there is a mouse that says hiragana and stuff
- """
-
- def setUp(self):
- self.store = store.Store()
-
- self.clock = objects.Thing(store=self.store, name=u"Clock")
- self.clockContainer = objects.Container.createFor(self.clock, capacity=10)
-
- self.mouseName = u"\N{KATAKANA LETTER PI}\N{KATAKANA LETTER SMALL YU}"
- self.mouse = mice.createHiraganaMouse(
- store=self.store,
- name=self.mouseName)
- self.mouseActor = iimaginary.IActor(self.mouse)
- self.mousehood = self.mouseActor.getIntelligence()
- self.mouse.moveTo(self.clock)
-
- (self.player,
- self.playerActor,
- self.playerIntelligence) = commandutils.createPlayer(self.store,
- u"Mean Old Man")
-
-
- self.player.moveTo(self.clock)
-
- self.reactorTime = task.Clock()
- self.mousehood._callLater = self.reactorTime.callLater
-
-
- def test_mouseCanSqueak(self):
- """
- When explicitly told to challenge with a given romaji syllable, the
- mouse should say a hiragana letter.
- """
- events.runEventTransaction(
- self.store,
- self.mousehood.challenge,
- character=u"\N{HIRAGANA LETTER A}")
-
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- event = self.playerIntelligence.concepts[0]
- self.assertEquals(
- commandutils.flatten(event.otherMessage.plaintext(self.player)),
- u"A %s says, '\N{HIRAGANA LETTER A}'" % (self.mouseName,))
-
-
- def test_randomHiragana(self):
- """
- When explicitly told to challenge without specifying a syllable, the
- mouse should say a random one.
- """
- events.runEventTransaction(self.store, self.mousehood.challenge)
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- event = self.playerIntelligence.concepts[0]
- self.assertChallenge(event)
-
-
- def test_ji(self):
- """
- Two hiragana characters map to the romaji 'ji'. Test that we do the
- right thing for them.
- """
- self.mousehood.challenge(character=u"\N{HIRAGANA LETTER DI}")
- self.failUnless(self.mousehood.vetteChallengeResponse(u"ji"))
- self.mousehood.challenge(character=u"\N{HIRAGANA LETTER ZI}")
- self.failUnless(self.mousehood.vetteChallengeResponse(u"ji"))
-
-
- def test_zu(self):
- """
- Two hiragana characters map to the romaji 'zu'. Test that we do the
- right thing for them.
- """
- self.mousehood.challenge(character=u"\N{HIRAGANA LETTER DU}")
- self.failUnless(self.mousehood.vetteChallengeResponse(u"zu"))
- self.mousehood.challenge(character=u"\N{HIRAGANA LETTER ZU}")
- self.failUnless(self.mousehood.vetteChallengeResponse(u"zu"))
-
-
- def test_mouseStartsChallengingWhenPlayersArrive(self):
- """
- When a player arrives, the mouse should go into the 'I am
- challenging' state.
- """
- # Whitebox
- self.assertEquals(self.mousehood.challenging, False)
-
- evt = events.ArrivalEvent(actor=self.player)
- self.mouseActor.send(evt)
-
- self.assertEquals(self.mousehood.challenging, True)
-
-
- def test_mouseSchedulesChallenges(self):
- """
- After telling a mouse to start challenging, it should schedule timed
- events to say challenges.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
- concepts = self.playerIntelligence.concepts
- self.assertEquals(len(concepts), 1)
- self.assertChallenge(concepts[0])
-
-
- def test_mouseStopsChallengingWhenPlayersLeave(self):
- """
- When the 'last' player leaves, the mouse stops challenging.
- """
- # Whitebox
- self.mousehood.startChallenging()
-
- evt = events.DepartureEvent(location=self.clock,
- actor=self.player)
- self.player.moveTo(None)
- self.mouseActor.send(evt)
-
- self.assertEquals(self.mousehood.challenging, False)
-
-
- def test_mouseStopsSchedulingChallenges(self):
- """
- When a mouse is told to stop challenging, it should cancel any
- challenges it had scheduled.
- """
- self.mousehood.startChallenging()
- self.mousehood.stopChallenging()
-
- self.reactorTime.advance(self.mousehood.challengeInterval)
- self.assertEquals(self.playerIntelligence.concepts, [])
-
-
- def test_stopChallengingWhenNotChallengingFails(self):
- """
- Don't stop challenging when you're not challenging.
- """
- self.assertRaises(mice.ChallengeVacuum, self.mousehood.stopChallenging)
-
-
- def test_startChallengingTwiceFails(self):
- """
- Don't start challenging twice.
- """
- self.mousehood.startChallenging()
- self.assertRaises(mice.ChallengeCollision, self.mousehood.startChallenging)
-
-
- def test_challengeRecurrence(self):
- """
- After a challenge is issued another one should be issued later.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- self.assertIn(self.mousehood.getCurrentChallenge(), japanese.hiragana)
-
- self.mousehood._currentChallenge = None # Clear his challenge evilly
-
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- self.assertIn(self.mousehood.getCurrentChallenge(), japanese.hiragana)
-
-
- def test_twoMenEnter(self):
- """
- Test that when *TWO* players join, the mouse doesn't schedule too many
- challenges.
- """
- otherPlayer = commandutils.createPlayer(self.store,
- u"Polite Young Man")[0]
-
- # Send an arrival event because setUp doesn't
- firstEvent = events.ArrivalEvent(actor=self.player)
-
- self.mouseActor.send(firstEvent)
- otherPlayer.moveTo(self.clock, arrivalEventFactory=events.MovementArrivalEvent)
-
- self.playerIntelligence.concepts = []
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- self.assertChallenge(self.playerIntelligence.concepts[0])
-
-
- def test_twoMenLeave(self):
- """
- Test that when two players are near the mouse, the mouse doesn't
- unschedule its challenge until they both leave.
- """
- otherPlayer = commandutils.createPlayer(self.store,
- u"Polite Young Man")[0]
- otherPlayer.moveTo(self.clock)
-
- self.mousehood.startChallenging()
-
- firstEvent = events.DepartureEvent(location=self.clock,
- actor=self.player)
- secondEvent = events.DepartureEvent(location=self.clock,
- actor=otherPlayer)
-
- otherPlayer.moveTo(None)
- self.mouseActor.send(secondEvent)
-
- self.playerIntelligence.concepts = []
-
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- self.assertChallenge(self.playerIntelligence.concepts[0])
-
- self.player.moveTo(None)
- self.mouseActor.send(firstEvent)
-
- self.failIf(self.mousehood.challenging)
-
-
- def test_getCurrentChallenge(self):
- """
- Test that we can introspect the current challenge of a mouse.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
- self.failUnlessIn(self.mousehood.getCurrentChallenge(), japanese.hiragana)
-
- self.mousehood.stopChallenging()
- self.assertIdentical(self.mousehood.getCurrentChallenge(), None)
-
-
- def test_vetteChallengeResponse(self):
- """
- Test that the correct response to the current challenge is accepted by
- the mouse.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- romaji = japanese.hiragana[self.mousehood.getCurrentChallenge()]
- self.failUnless(self.mousehood.vetteChallengeResponse(romaji))
-
- for romaji in japanese.hiragana.values():
- if romaji != japanese.hiragana[self.mousehood.getCurrentChallenge()]:
- self.failIf(self.mousehood.vetteChallengeResponse(romaji))
-
-
- def test_respondToChallengeCorrectly(self):
- """
- Test that when a correct response is received, the current challenge is
- expired and the mouse salutes you.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- correctResponse = japanese.hiragana[
- self.mousehood.getCurrentChallenge()]
-
- self.mousehood.responseReceived(self.player, correctResponse)
- self.reactorTime.advance(0)
-
- self.assertIdentical(self.mousehood.getCurrentChallenge(), None)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 2)
- c = self.playerIntelligence.concepts[1]
- self.assertEquals(
- commandutils.flatten(c.plaintext(self.player)),
- u"%s salutes you!\n" % (self.mouseName,))
-
-
- def test_respondToChallengeInorrectly(self):
- """
- Test that when an incorrect response is received, the current challenge
- is not expired and the mouse bites you.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- correctResponse = japanese.hiragana[
- self.mousehood.getCurrentChallenge()]
-
- for ch in japanese.hiragana.values():
- if ch != correctResponse:
- self.mousehood.responseReceived(self.player, ch)
- break
- else:
- self.fail("Buggy test")
-
- self.reactorTime.advance(0)
-
- self.assertIn(self.mousehood.getCurrentChallenge(),
- japanese.romajiToHiragana[correctResponse])
-
- self.assertEquals(len(self.playerIntelligence.concepts), 2)
- c = self.playerIntelligence.concepts[1]
- self.assertEquals(
- commandutils.flatten(c.plaintext(self.player)),
- u"%s bites you!\n" % (self.mouseName,))
-
-
- def test_playerSaysCorrectThing(self):
- """
- Test that when someone gives voice to the correct response to a mouse's
- current challenge, the mouse acknowledges this with a salute.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
- action.Say().do(
- # http://divmod.org/trac/ticket/2917
- iimaginary.IActor(self.player),
- None,
- japanese.hiragana[self.mousehood.getCurrentChallenge()])
-
- self.assertIdentical(self.mousehood.getCurrentChallenge(), None)
- self.reactorTime.advance(0)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 3)
- c = self.playerIntelligence.concepts[2]
- self.assertEquals(
- commandutils.flatten(c.plaintext(self.player)),
- u"%s salutes you!\n" % (self.mouseName,))
-
-
- def test_playerSaysIncorrectThing(self):
- """
- Test that when someone gives voice to the correct response to a mouse's
- current challenge, the mouse acknowledges this with a salute.
- """
- self.mousehood.startChallenging()
- self.reactorTime.advance(self.mousehood.challengeInterval)
-
- action.Say().do(
- # http://divmod.org/trac/ticket/2917
- iimaginary.IActor(self.player), None, u"lolololo pew")
-
- self.failIfIdentical(self.mousehood.getCurrentChallenge(), None)
- self.reactorTime.advance(0)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 3)
- c = self.playerIntelligence.concepts[2]
- self.assertEquals(
- commandutils.flatten(c.plaintext(self.player)),
- u"%s bites you!\n" % (self.mouseName,))
-
-
- def test_activationUsesReactorScheduling(self):
- """
- Test that the default scheduler of the mouse is the Twisted
- reactor, since that is the scheduler that needs to be used
- with the actual Imaginary server.
- """
- deletions = []
- ref = weakref.ref(self.mousehood, deletions.append)
- # This is a hack to reload the mouse since it gets its
- # _callLater set in setUp.
- del self.mouse
- del self.mouseActor
- del self.mousehood
- self.assertEquals(deletions, [ref])
- mousehood = self.store.findUnique(mice.HiraganaMouse)
- from twisted.internet import reactor
- self.assertEquals(mousehood._callLater, reactor.callLater)
-
-
-
-class HiraganaMouseCommandTestCase(commandutils.CommandTestCaseMixin, unittest.TestCase):
- """
- H-mouse tests which use the command system.
- """
-
- mouseName = u"\N{KATAKANA LETTER PI}\N{KATAKANA LETTER SMALL YU}"
- hiraganaCharacterPattern = u"'[" + u''.join(japanese.hiragana.keys()) + u"]'"
- speechPattern = mouseName + u" says, " + hiraganaCharacterPattern
-
- def test_oneManEnters(self):
- """
- Test that when a fellow jaunts into a venue inhabited by a mouse of the
- Nipponese persuasion, a hiragana allocution follows.
- """
- clock = task.Clock()
-
- closetContainer = commandutils.createLocation(
- self.store, u"Closet", None)
- closet = closetContainer.thing
-
- mouse = mice.createHiraganaMouse(
- store=self.store,
- name=self.mouseName,
- proper=True)
- mouseActor = iimaginary.IActor(mouse)
- mousehood = mouseActor.getIntelligence()
- mousehood._callLater = clock.callLater
- mouse.moveTo(closet)
-
- objects.Exit.link(self.location, closet, u"north")
-
- self._test(
- "north",
- [commandutils.E("[ Closet ]"),
- commandutils.E("( south )"),
- commandutils.E(u"Here, you see " + self.mouseName + u".")],
- ["Test Player leaves north."])
-
- clock.advance(mousehood.challengeInterval)
-
- self._test(None, [self.speechPattern])
-
-
- def test_creation(self):
- """
- Test the creation of a hiragana-speaking mouse using the thing creation
- plugin system.
- """
- self._test(
- u"create the 'hiragana mouse' named " + self.mouseName,
- [commandutils.E(u"You create " + self.mouseName + u".")],
- [commandutils.E(u"Test Player creates %s." % (self.mouseName,))])
-
- for thing in self.location.findProviders(iimaginary.IThing, 0):
- if thing.name == self.mouseName:
- break
- else:
- self.fail("Could not find the mouse! Test bug.")
-
- clock = task.Clock()
- jimhood = iimaginary.IActor(thing).getIntelligence()
- jimhood._callLater = clock.callLater
-
- self._test(
- u"drop " + self.mouseName,
- [commandutils.E(u"You drop %s." % (self.mouseName,))],
- [commandutils.E(u"Test Player drops %s." % (self.mouseName,))])
-
- clock.advance(jimhood.challengeInterval)
-
- self._test(
- None,
- [self.speechPattern],
- [self.speechPattern])
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_mice.py'
--- Imaginary/ExampleGame/examplegame/test/test_mice.py 2013-07-03 23:50:20 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_mice.py 1970-01-01 00:00:00 +0000
@@ -1,155 +0,0 @@
-
-from twisted.trial import unittest
-from twisted.internet import task
-
-from axiom import store
-
-from imaginary import iimaginary, events, objects
-from imaginary.test import commandutils
-
-from examplegame import mice
-
-
-class IntelligenceTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
- self.locationContainer = commandutils.createLocation(
- self.store, u"Place", None)
- self.location = self.locationContainer.thing
-
- self.alice = objects.Thing(store=self.store, name=u"Alice")
- self.actor = objects.Actor.createFor(self.alice)
-
- self.alice.moveTo(self.location)
-
- self.intelligence = commandutils.MockIntelligence(store=self.store)
- self.actor.setEnduringIntelligence(self.intelligence)
-
-
- def test_intelligenceReceivesEvent(self):
- """
- Enduring intelligences should receive events.
- """
- evt = events.Success(
- location=self.location,
- otherMessage=u"Hello, how are you?")
-
- self.actor.send(evt)
- self.assertEquals(self.intelligence.concepts, [evt])
-
-
- def test_persistentIntelligence(self):
- """
- Whitebox test that enduring intelligencii are actually persistent.
- """
- # TB <---- THAT MEANS IT'S TRANSLUCENT
- self.assertIdentical(
- self.store.findUnique(
- objects.Actor,
- objects.Actor._enduringIntelligence == self.intelligence),
- self.actor)
-
-
-
-class MouseTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
- self.clock = objects.Thing(store=self.store, name=u"Clock")
- self.clockContainer = objects.Container.createFor(self.clock, capacity=10)
-
- self.mouse = mice.createMouse(store=self.store, name=u"Squeaker McSqueakenson")
- self.mouseActor = iimaginary.IActor(self.mouse)
- self.mousehood = self.mouseActor.getIntelligence()
- self.mouse.moveTo(self.clock)
-
- self.player = objects.Thing(store=self.store, name=u"Mean Old Man")
- self.playerActor = objects.Actor.createFor(self.player)
- self.playerIntelligence = commandutils.MockIntelligence(
- store=self.store)
- self.playerActor.setEnduringIntelligence(self.playerIntelligence)
-
- self.player.moveTo(self.clock)
-
-
- def test_mouseSqueaksAtIntruders(self):
- """
- When a mean old man walks into the mouse's clock, the mouse will squeak
- ruthlessly.
- """
- clock = task.Clock()
- self.mousehood._callLater = clock.callLater
- evt = events.ArrivalEvent(actor=self.player)
- self.mouseActor.send(evt)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 0)
- clock.advance(0)
-
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- event = self.playerIntelligence.concepts[0]
- self.assertEquals(
- commandutils.flatten(event.otherMessage.plaintext(self.player)),
- u"SQUEAK!")
-
-
- def test_mouseCanSqueak(self):
- events.runEventTransaction(self.store, self.mousehood.squeak)
- self.assertEquals(len(self.playerIntelligence.concepts), 1)
- event = self.playerIntelligence.concepts[0]
- self.assertEquals(
- commandutils.flatten(event.otherMessage.plaintext(self.player)),
- u"SQUEAK!")
-
-
- def test_mouseActivation(self):
- """
- Activating a mouse should set the scheduling mechanism to the
- reactor's.
- """
- from twisted.internet import reactor
- self.assertEquals(self.mousehood._callLater, reactor.callLater)
-
-
-
-class MouseReactionTestCase(commandutils.CommandTestCaseMixin,
- unittest.TestCase):
- def testCreation(self):
- """
- Test that a mouse can be created with the create command.
- """
- self._test(
- "create the mouse named squeaker",
- ['You create squeaker.'],
- ['Test Player creates squeaker.'])
-
- [mouse] = list(self.playerContainer.getContents())
- self.failUnless(isinstance(iimaginary.IActor(mouse).getIntelligence(), mice.Mouse))
-
-
- def testSqueak(self):
- """
- Test that when someone walks into a room with a mouse, the mouse
- squeaks and the person who walked in hears it.
- """
- mouse = mice.createMouse(store=self.store, name=u"squeaker")
- clock = task.Clock()
- intelligence = iimaginary.IActor(mouse).getIntelligence()
- intelligence._callLater = clock.callLater
-
- elsewhere = commandutils.createLocation(
- self.store, u"Mouse Hole", None).thing
-
- objects.Exit.link(self.location, elsewhere, u"south")
-
- mouse.moveTo(elsewhere)
-
- self._test(
- "south",
- [commandutils.E("[ Mouse Hole ]"),
- commandutils.E("( north )"),
- commandutils.E("Here, you see a squeaker.")],
- ['Test Player leaves south.'])
-
- clock.advance(0)
- self._test(None, ["SQUEAK!"])
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_quiche.py'
--- Imaginary/ExampleGame/examplegame/test/test_quiche.py 2009-06-29 04:03:17 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_quiche.py 1970-01-01 00:00:00 +0000
@@ -1,93 +0,0 @@
-from twisted.trial import unittest
-
-from imaginary import objects, iimaginary
-from imaginary.test import commandutils
-
-from examplegame import quiche
-
-
-class VendingTest(commandutils.CommandTestCaseMixin, unittest.TestCase):
- def testTheyExist(self):
- self._test("create the 'vending machine' named vendy",
- ["You create vendy."],
- ["Test Player creates vendy."])
-
-
- def testPopulateVendingMachine(self):
- self._test("create the 'vending machine' named vendy",
- ["You create vendy."],
- ["Test Player creates vendy."])
-
- self._test("create a quiche named quiche",
- ["You create a quiche."],
- ["Test Player creates a quiche."])
-
- self._test("open vendy",
- ["You open vendy."],
- ["Test Player opens vendy."])
-
- self._test("put quiche in vendy",
- ["You put the quiche in vendy."],
- ["Test Player puts a quiche in vendy."])
-
-
- def testBuyingQuiche(self):
- self._test("create the 'vending machine' named vendy",
- ["You create vendy."],
- ["Test Player creates vendy."])
-
- self._test("drop vendy",
- ["You drop vendy."],
- ["Test Player drops vendy."])
-
- self._test("create a quiche named quiche",
- ["You create a quiche."],
- ["Test Player creates a quiche."])
-
- self._test("open vendy",
- ["You open vendy."],
- ["Test Player opens vendy."])
-
- self._test("put quiche in vendy",
- ["You put the quiche in vendy."],
- ["Test Player puts a quiche in vendy."])
-
- for i in range(5):
- self._test("create the quarter named quarter%s " % i,
- ["You create quarter%s." % i],
- ["Test Player creates quarter%s." % i])
-
- for i in range(4):
- self._test("put quarter%i in vendy" % i,
- ["You put quarter%s in vendy." % i],
- ["Test Player puts quarter%s in vendy." % i])
-
- self._test("put quarter4 in vendy",
- ["You put quarter4 in vendy.",
- "Vendy thumps loudly and spits out a quiche onto the ground."],
- ["Test Player puts quarter4 in vendy.",
- "Vendy thumps loudly and spits out a quiche onto the ground."])
-
-
- def testProgrammaticQuichePurchase(self):
- location = objects.Thing(store=self.store, name=u"room")
- icloc = objects.Container.createFor(location, capacity=500)
-
- vm = quiche.createVendingMachine(store=self.store, name=u"Vendy", description=u"VEEEENDYYYYY")
- vm.moveTo(location)
-
- icvm = iimaginary.IContainer(vm)
- icvm.closed = False
- theQuiche = quiche.createQuiche(store=self.store, name=u"quiche")
- icvm.add(theQuiche)
- icvm.closed = True
-
- for i in range(4):
- quarter = quiche.createCoin(store=self.store, name=u"quarter%s" % (i,))
- icvm.add(quarter)
-
- quarter = quiche.createCoin(store=self.store, name=u"quarter4")
- icvm.add(quarter)
-
- self.failUnless(icloc.contains(theQuiche))
-
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_squeaky.py'
--- Imaginary/ExampleGame/examplegame/test/test_squeaky.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_squeaky.py 1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-
-from twisted.trial.unittest import TestCase
-
-from imaginary.test.commandutils import CommandTestCaseMixin
-
-from imaginary.objects import Thing, Container
-
-from examplegame.squeaky import Squeaker
-
-class SqueakTest(CommandTestCaseMixin, TestCase):
- """
- Squeak Test.
- """
-
- def setUp(self):
- """
- Set Up.
- """
- CommandTestCaseMixin.setUp(self)
- self.squeaker = Thing(store=self.store, name=u"squeaker")
- self.squeaker.moveTo(self.location)
- self.squeakification = Squeaker.createFor(self.squeaker)
-
-
- def test_itSqueaks(self):
- """
- Picking up a squeaky thing makes it emit a squeak.
- """
- self.assertCommandOutput(
- "take squeaker",
- ["You take a squeaker.",
- "A squeaker emits a faint squeak."],
- ["Test Player takes a squeaker.",
- "A squeaker emits a faint squeak."])
-
-
- def test_squeakyContainer(self):
- """
- If a container is squeaky, that shouldn't interfere with its function
- as a container. (i.e. let's make sure that links keep working even
- though we're using an annotator here.)
- """
- cont = Container.createFor(self.squeaker)
-
- mcguffin = Thing(store=self.store, name=u"mcguffin")
- mcguffin.moveTo(cont)
-
- self.assertCommandOutput(
- "take mcguffin from squeaker",
- ["You take a mcguffin from the squeaker."],
- ["Test Player takes a mcguffin from the squeaker."])
=== removed file 'Imaginary/ExampleGame/examplegame/test/test_tether.py'
--- Imaginary/ExampleGame/examplegame/test/test_tether.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/test/test_tether.py 1970-01-01 00:00:00 +0000
@@ -1,96 +0,0 @@
-
-from twisted.trial.unittest import TestCase
-
-from imaginary.test.commandutils import CommandTestCaseMixin, E
-
-from imaginary.objects import Thing, Container, Exit
-from imaginary.garments import Garment
-
-from examplegame.furniture import Chair
-from examplegame.tether import Tether
-
-class TetherTest(CommandTestCaseMixin, TestCase):
- """
- A test for tethering an item to its location, such that a player who picks
- it up can't leave until they drop it.
- """
-
- def setUp(self):
- """
- Tether a ball to the room.
- """
- CommandTestCaseMixin.setUp(self)
- self.ball = Thing(store=self.store, name=u'ball')
- self.ball.moveTo(self.location)
- self.tether = Tether.createFor(self.ball, to=self.location)
- self.otherPlace = Thing(store=self.store, name=u'elsewhere')
- Container.createFor(self.otherPlace, capacity=1000)
- Exit.link(self.location, self.otherPlace, u'north')
-
-
- def test_takeAndLeave(self):
- """
- You can't leave the room if you're holding the ball that's tied to it.
- """
- self.assertCommandOutput(
- "take ball",
- ["You take a ball."],
- ["Test Player takes a ball."])
- self.assertCommandOutput(
- "go north",
- ["You can't move, you're still holding a ball."],
- ["Test Player struggles with a ball."])
- self.assertCommandOutput(
- "drop ball",
- ["You drop the ball."],
- ["Test Player drops a ball."])
- self.assertCommandOutput(
- "go north",
- [E("[ elsewhere ]"),
- E("( south )"),
- ""],
- ["Test Player leaves north."])
-
-
- def test_allTiedUp(self):
- """
- If you're tied to a chair, you can't leave.
- """
- chairThing = Thing(store=self.store, name=u'chair')
- chairThing.moveTo(self.location)
- chair = Chair.createFor(chairThing)
- self.assertCommandOutput("sit chair",
- ["You sit in the chair."],
- ["Test Player sits in the chair."])
- Tether.createFor(self.player, to=chairThing)
- self.assertCommandOutput(
- "stand up",
- ["You can't move, you're tied to a chair."],
- ["Test Player struggles."])
-
-
- def test_tetheredClothing(self):
- """
- Clothing that is tethered will also prevent movement if you wear it.
-
- This isn't just simply a test for clothing; it's an example of
- integrating with a foreign system which doesn't know about tethering,
- but can move objects itself.
-
- Tethering should I{not} have any custom logic related to clothing to
- make this test pass; if it does get custom clothing code for some
- reason, more tests should be added to deal with other systems that do
- not take tethering into account (and vice versa).
- """
- Garment.createFor(self.ball, garmentDescription=u"A lovely ball.",
- garmentSlots=[u"head"])
- self.assertCommandOutput(
- "wear ball",
- ["You put on the ball."],
- ["Test Player puts on a ball."])
- self.assertCommandOutput(
- "go north",
- ["You can't move, you're still holding a ball."],
- ["Test Player struggles with a ball."])
-
-
=== removed file 'Imaginary/ExampleGame/examplegame/tether.py'
--- Imaginary/ExampleGame/examplegame/tether.py 2009-08-17 02:40:03 +0000
+++ Imaginary/ExampleGame/examplegame/tether.py 1970-01-01 00:00:00 +0000
@@ -1,121 +0,0 @@
-# -*- test-case-name: examplegame.test.test_tether -*-
-
-"""
-A simplistic implementation of tethering, which demonstrates how to prevent
-someone from moving around.
-
-This implementation is somewhat limited, as it assumes that tethered objects
-can only be located in players' inventories and on the ground. It also makes
-several assumptions about who is actually doing the moving in moveTo; in order
-to be really correct, the implementation of movement needs to relay more
-information about what is moving and how.
-"""
-
-from zope.interface import implements
-
-from axiom.item import Item
-from axiom.attributes import reference
-
-from imaginary.iimaginary import IMovementRestriction, IActor
-from imaginary.eimaginary import ActionFailure
-from imaginary.events import ThatDoesntWork
-from imaginary.enhancement import Enhancement
-from imaginary.objects import Thing
-
-
-class Tether(Item, Enhancement):
- """
- I am a force that binds two objects together.
-
- Right now this force isn't symmetric; the idea is that the thing that we
- are tethered 'to' is immovable for some other reason. This is why we're in
- the example rather than a real robust piece of game-library functionality
- in imaginary proper.
-
- The C{thing} that we are installed on is prevented from moving more than a
- certain distance away from the thing it is tethered C{to}.
-
- This is accomplished by preventing movement of the object's container;
- i.e. if you pick up a ball that is tied to the ground, you can't move until
- you drop it.
- """
-
- thing = reference(reftype=Thing,
- whenDeleted=reference.CASCADE,
- allowNone=False)
-
- # XXX 'thing' and 'to' should be treated more consistently, or at least the
- # differences between them explained officially.
- to = reference(reftype=Thing,
- whenDeleted=reference.CASCADE,
- allowNone=False)
-
- implements(IMovementRestriction)
-
- powerupInterfaces = [IMovementRestriction]
-
- def movementImminent(self, movee, destination):
- """
- The object which is tethered is trying to move somewhere. If it has an
- IActor, assume that it's a player trying to move on its own, and emit
- an appropriate message.
-
- Otherwise, assume that it is moving *to* an actor, and install a
- L{MovementBlocker} on that actor.
- """
- # There isn't enough information provided to moveTo just yet; we need
- # to know who is doing the moving. In the meanwhile, if you have an
- # actor, we'll assume you're a player.
- if IActor(movee, None) is not None:
- raise ActionFailure(
- ThatDoesntWork(
- actor=self.thing,
- actorMessage=[u"You can't move, you're tied to ",
- self.to,
- "."],
- otherMessage=[self.thing, u' struggles.']))
- MovementBlocker.destroyFor(self.thing.location)
- if self.to != destination:
- MovementBlocker.createFor(destination, tether=self)
-
- return False
-
-
-class MovementBlocker(Item, Enhancement):
- """
- A L{MovementBlocker} is an L{Enhancement} which prevents the movement of a
- player holding a tethered object.
- """
- implements(IMovementRestriction)
-
- powerupInterfaces = [IMovementRestriction]
-
- thing = reference(
- doc="""
- The L{Thing} whose movement is blocked.
- """, reftype=Thing, allowNone=False,
- whenDeleted=reference.CASCADE)
-
- tether = reference(
- doc="""
- The L{Tether} ultimely responsible for blocking movement.
- """,
- reftype=Tether, allowNone=False,
- whenDeleted=reference.CASCADE)
-
-
- def movementImminent(self, movee, destination):
- """
- The player this blocker is installed on is trying to move. Assume that
- they are trying to move themselves (via a 'go' action) and prevent it
- by raising an L{ActionFailure} with an appropriate error message for
- the player.
- """
- raise ActionFailure(
- ThatDoesntWork(
- actor=self.thing,
- actorMessage=
- [u"You can't move, you're still holding ",
- self.tether.thing,u'.'],
- otherMessage=
- [self.thing, u' struggles with ', self.tether.thing,u'.']))
=== removed directory 'Imaginary/ExampleGame/imaginary'
=== removed directory 'Imaginary/ExampleGame/imaginary/plugins'
=== removed file 'Imaginary/ExampleGame/imaginary/plugins/monsters.py'
--- Imaginary/ExampleGame/imaginary/plugins/monsters.py 2007-08-17 04:46:38 +0000
+++ Imaginary/ExampleGame/imaginary/plugins/monsters.py 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-
-from imaginary.creation import CreationPluginHelper
-from examplegame.mice import createMouse, createHiraganaMouse
-
-mouse = CreationPluginHelper(u'mouse', createMouse)
-hiraganaMouse = CreationPluginHelper(u'hiragana mouse', createHiraganaMouse)
=== removed file 'Imaginary/ExampleGame/imaginary/plugins/quiche.py'
--- Imaginary/ExampleGame/imaginary/plugins/quiche.py 2007-08-17 04:46:38 +0000
+++ Imaginary/ExampleGame/imaginary/plugins/quiche.py 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-# -*- test-case-name: examplegame.test.test_vending -*-
-
-from imaginary.creation import CreationPluginHelper
-from examplegame.quiche import createQuiche, createCoin, createVendingMachine
-
-quichePlugin = CreationPluginHelper('quiche', createQuiche)
-vendingPlugin = CreationPluginHelper('vending machine', createVendingMachine)
-quarterPlugin = CreationPluginHelper('quarter', createCoin)
-
=== removed file 'Imaginary/LICENSE'
--- Imaginary/LICENSE 2006-02-26 02:37:39 +0000
+++ Imaginary/LICENSE 1970-01-01 00:00:00 +0000
@@ -1,20 +0,0 @@
-Copyright (c) 2005 Divmod Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
=== removed file 'Imaginary/MANIFEST.in'
--- Imaginary/MANIFEST.in 2008-07-16 19:12:33 +0000
+++ Imaginary/MANIFEST.in 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-include NAME.txt
-include DEPS.txt
-include NEWS.txt
-include LICENSE
-graft imaginary
-graft axiom
=== removed file 'Imaginary/NAME.txt'
--- Imaginary/NAME.txt 2006-02-26 02:37:39 +0000
+++ Imaginary/NAME.txt 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-
-See: http://achewood.com/index.php?date=04272005
-
-Imaginary numbers are so named not because they are fictitious, but because
-they are along a different axis from real numbers.
-
-Divmod Imaginary is a simulationists take on the realm of role playing,
-interactive fiction, and multiplayer dungeons. It incorporates gameplay
-features from each area while attempting to provide a richer environment
-than is generally available from existing systems.
=== removed file 'Imaginary/NEWS.txt'
--- Imaginary/NEWS.txt 2009-11-30 01:08:55 +0000
+++ Imaginary/NEWS.txt 1970-01-01 00:00:00 +0000
@@ -1,36 +0,0 @@
-0.0.5 (2009-11-25):
- - Remove the dead imaginary.objects.Thing.locate method
- - Introduce an interface intended to be provided by administrative actors
- and require it for the "illuminate" command.
- - Remove the custom SSH server and instead plug in to the Mantissa SSH
- application server.
- - Remove all uses of "axiom.dependency.installOn".
- - Fix a bug which caused newly created avatars to not be announced when
- they arrived at the starting location.
- - When presenting an ambiguity error to an actor, enumerate the possible
- resolutions.
- - Fix certain terminal handling issues with east asian characters.
-
-0.0.4 (2008-08-12):
-
- - A "plain" Thing type has now been added and is available to the
- "create" command.
- - "scrutinize" now works when the target is not a container.
- - a "list thing types" command has been added, to allow viewing
- types of things that can be created.
- - "create" now allows users to specify if a thing is considered a
- common or proper noun.
- - Improved grammar in action text for various verbs.
- - Added a "set" action for changing thing attributes.
- - Changed noun resolution to match substrings and to match
- case-insensitively.
-
-0.0.3 (2007-01-23):
- - Work with Axiom dependency api
-
-0.0.2 (2006-09-20):
- - Some changes
-
-0.0.1 (2006-06-16):
- - Imported from Pottery repository
- - Imported from Imagination repository
=== removed file 'Imaginary/README.txt'
--- Imaginary/README.txt 2009-06-26 20:38:23 +0000
+++ Imaginary/README.txt 1970-01-01 00:00:00 +0000
@@ -1,98 +0,0 @@
-
-Imaginary is an experimental simulation-construction toolkit.
-
-Be warned! We aren't kidding when we say "experimental". Many features are
-not implemented yet and documentation is incomplete. We think there are some
-pretty cool ideas here, but if you are intending to use this system, be
-prepared to participate heavily in its development.
-
-This document is mainly concerned with getting an Imaginary server up and
-running, to the point where you can edit the code and see things change. Some
-familiarity with Python, Twisted, Nevow, Axiom, and Mantissa are all helpful,
-but we will try to make sure they aren't really required just to get started.
-
-While we have tried to make it possible to get a taste of what is possible
-here, if you want to make any serious progress, you will want to join the IRC
-channel "#imagination" on chat.freenode.net and start asking questions. If you
-are curious about what needs to be done, have a look here:
-
- http://tinyurl.com/2tuo9o
-
-The first step in configuring a new installation of Imaginary will normally be
-creating a new Mantissa database.
-
-(This is assuming you have already set up Combinator, installed Twisted, and
-all necessary Divmod dependencies. If not, see
-http://divmod.org/trac/wiki/CombinatorTutorial for more information.)
-
-First run the following command:
-
- axiomatic mantissa
-
-And answer the prompts appropriately. Please take note of the new password you
-enter for the "admin" user, as you will need it in a few steps.
-
-This should create a directory called "mantissa.axiom", containing the server
-for a web interface that will allow you to install "offerings" (plugins for
-Mantissa, in this case, Imaginary), create users, and grant them
-privileges. You can start this webserver with the following command: (the -n
-option will run it in the foreground on the current terminal)
-
- axiomatic start -n
-
-You should now be able to access this server at http://localhost:8080 in your
-web browser.
-
-Click the "Sign In" link in the upper right hand corner, and log in as "admin"
-with the password you chose previously while configuring Mantissa.
-
-If you logged in successfully, you should now be presented with a list of
-"offerings" that can be installed. Click on "Imaginary" to install it.
-
-Next, mouse over the "Admin" menu at the upper left of the screen and then
-click on the "Products" sub-menu.
-
-In the "Installable Powerups" section, check the box corresponding to
-"Imaginary Game". Then click the "Installable Powerups" button below. You
-will hopefully be presented with a green confirmation dialog to confirm your
-success. This creates a "product" which can be given to users.
-
-Mouse over the "Admin" menu again and click "Local Users". You should be
-presented with a page including a table of users - probably with only the
-"admin" user in it. Click the word "Endow" in the "Actions" column of that
-table, then select the product with "ImaginaryApp" in it (again, this is
-probably the only one presented) and click the "Installproducton
-admin@localhost" button. You should again be presented with a green
-confirmation dialog. Hooray!
-
-Ideally, you will now be able to ssh into your Imaginary server. In a new
-terminal, ssh to localhost on the Mantissa server's SSH port (by default, this
-is 8022). For example:
-
- ssh -p 8022 admin@localhost@localhost
-
-Note the odd username/host specifier - "admin@localhost" is the user, and the
-last "localhost" specifies the host to connect to.
-
-Log in with the same password you used to log in to the web interface. You
-should be presented with a screen including several options, one of which is
-"imaginary". Use tab to highlight that option (the highlighted option should
-appear red), then hit enter to select it.
-
-At the Imaginary character prompt, choose to create a new character; enter a
-new username (e.g. not "admin"). You will then join the game as that new
-character.
-
-Once in the game, you should see a row of dashes along the bottom of the
-display. To confirm your new MUDness, try typing "look" and hit enter; You
-should see some indication of the generic place that you are in, the available
-exits, and other players in the area, though initially you won't see much more
-than "[The Place]".
-
-You can enter "actions" for a list of actions, and use "help" along with one of
-them ("help dig") for specific information on how to use them. You can even log
-in via other telnet windows, create additional accounts, and interact with your
-initial user (for example, beating them to death with "hit").
-
-When you've tired of self-abuse, you can stop your Imaginary server by hitting
-control-c in the terminal where you ran "axiomatic start -n".
=== removed directory 'Imaginary/axiom'
=== removed directory 'Imaginary/axiom/plugins'
=== removed file 'Imaginary/axiom/plugins/imaginaryversion.py'
--- Imaginary/axiom/plugins/imaginaryversion.py 2008-07-16 19:12:33 +0000
+++ Imaginary/axiom/plugins/imaginaryversion.py 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-# Copyright 2008 Divmod, Inc.
-# See LICENSE file for details
-
-"""
-Register an Axiom version plugin for Imaginary.
-"""
-
-from zope.interface import directlyProvides
-from twisted.plugin import IPlugin
-from axiom.iaxiom import IVersion
-from imaginary import version
-directlyProvides(version, IPlugin, IVersion)
=== removed directory 'Imaginary/imaginary'
=== removed file 'Imaginary/imaginary/__init__.py'
--- Imaginary/imaginary/__init__.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,19 +0,0 @@
-# -*- test-case-name: imaginary,examplegame -*-
-
-"""
-Virtual simulation framework.
-"""
-
-from imaginary._version import version
-version # exported
-
-# Verbs are only registered when they are imported, and important verbs are
-# found in the following modules:
-from imaginary import action, creation
-action # exported
-creation # exported
-
-
-# Ideally there would be a nice, passive way to register verbs which would only
-# load them as necessary rather than forcing the entire package to get
-# imported, but this will work okay for now.
=== removed file 'Imaginary/imaginary/_version.py'
--- Imaginary/imaginary/_version.py 2009-11-30 01:08:55 +0000
+++ Imaginary/imaginary/_version.py 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-# This is an auto-generated file. Use Epsilon/bin/release-divmod to update.
-from twisted.python import versions
-version = versions.Version(__name__[:__name__.rfind('.')], 0, 0, 5)
=== removed file 'Imaginary/imaginary/action.py'
--- Imaginary/imaginary/action.py 2013-09-22 10:01:56 +0000
+++ Imaginary/imaginary/action.py 1970-01-01 00:00:00 +0000
@@ -1,1299 +0,0 @@
-# -*- test-case-name: imaginary.test.test_actions -*-
-
-import time, random, operator
-import pprint
-
-from zope.interface import implements
-
-from twisted.python import log, filepath
-from twisted.internet import defer
-
-from axiom import iaxiom
-from axiom.attributes import AND
-
-import imaginary.plugins
-from imaginary import (iimaginary, eimaginary, iterutils, events,
- objects, text as T, language, pyparsing)
-from imaginary.world import ImaginaryWorld
-from imaginary.idea import (
- CanSee, Proximity, ProviderOf, Named, Traversability)
-
-## Hacks because pyparsing doesn't have fantastic unicode support
-_quoteRemovingQuotedString = pyparsing.quotedString.copy()
-_quoteRemovingQuotedString.setParseAction(pyparsing.removeQuotes)
-
-class UnicodeWord(pyparsing.Token):
- def parseImpl(self, instring, loc, doActions=True):
- maxLoc = len(instring)
- while loc < maxLoc and instring[loc].isspace():
- loc += 1
- start = loc
- while loc < maxLoc and not instring[loc].isspace():
- loc += 1
- end = loc
- return end, instring[start:end]
-
-
-
-class _ActionType(type):
- actions = []
- def __new__(cls, name, bases, attrs):
- infrastructure = attrs.pop('infrastructure', False)
- t = super(_ActionType, cls).__new__(cls, name, bases, attrs)
- if not infrastructure:
- cls.actions.append(t)
- return t
-
-
- def parse(self, player, line):
- """
- Parse an action.
- """
- for eachActionType in self.actions:
- try:
- match = eachActionType.match(player, line)
- except pyparsing.ParseException:
- pass
- else:
- if match is not None:
- match = dict(match)
- for k,v in match.items():
- if isinstance(v, pyparsing.ParseResults):
- match[k] = v[0]
-
- return eachActionType().runEventTransaction(player, line, match)
- return defer.fail(eimaginary.NoSuchCommand(line))
-
-
-
-class Action(object):
- """
- An L{Action} represents an intention of a player to do something.
- """
- __metaclass__ = _ActionType
- infrastructure = True
-
- actorInterface = iimaginary.IActor
-
- def runEventTransaction(self, player, line, match):
- """
- Take a player, input, and dictionary of parse results, resolve those
- parse results into implementations of appropriate interfaces in the
- game world, and execute the actual Action implementation (contained in
- the 'do' method) in an event transaction.
-
- This is the top level of action invocation.
-
- @param player: A L{Thing} representing the actor's body.
-
- @param line: A unicode string containing the original input
-
- @param match: A dictionary containing some parse results to pass
- through to this L{Action}'s C{do} method as keyword arguments.
-
- @raise eimaginary.AmbiguousArgument: if multiple valid targets are
- found for an argument.
- """
- def thunk():
- begin = time.time()
- try:
- actor = self.actorInterface(player)
- for (k, v) in match.items():
- try:
- objs = self.resolve(player, k, v)
- except NotImplementedError:
- pass
- else:
- if len(objs) == 1:
- match[k] = objs[0]
- elif len(objs) == 0:
- self.cantFind(player, actor, k, v)
- else:
- raise eimaginary.AmbiguousArgument(self, k, v, objs)
- return self.do(actor, line, **match)
- finally:
- end = time.time()
- log.msg(interface=iaxiom.IStatEvent,
- stat_actionDuration=end - begin,
- stat_actionExecuted=1)
- events.runEventTransaction(player.store, thunk)
-
-
- def cantFind(self, player, actor, slot, name):
- """
- This hook is invoked when a target cannot be found.
-
- This will delegate to a method like C{self.cantFind_<slot>(actor,
- name)} if one exists, to determine the error message to show to the
- actor. It will then raise L{eimaginary.ActionFailure} to stop
- processing of this action.
-
- @param player: The L{Thing} doing the searching.
-
- @type player: L{IThing}
-
- @param actor: The L{IActor} doing the searching.
-
- @type actor: L{IActor}
-
- @param slot: The slot in question.
-
- @type slot: C{str}
-
- @param name: The name of the object being searched for.
-
- @type name: C{unicode}
-
- @raise eimaginary.ActionFailure: always.
- """
- func = getattr(self, "cantFind_"+slot, None)
- if func:
- msg = func(actor, name)
- else:
- msg = "Who's that?"
- raise eimaginary.ActionFailure(
- events.ThatDoesntWork(
- actorMessage=msg,
- actor=player))
-
-
- @classmethod
- def match(cls, player, line):
- """
- Parse the given C{line} using this L{Action} type's pyparsing C{expr}
- attribute. A C{pyparsing.LineEnd} is appended to C{expr} to avoid
- accidentally matching a prefix instead of the whole line.
-
- @return: a list of 2-tuples of all the results of parsing, or None if
- the expression does not match the given line.
-
- @param line: a line of user input to be interpreted as an action.
-
- @see: L{imaginary.pyparsing}
- """
- return (cls.expr + pyparsing.LineEnd()).parseString(line)
-
-
- def do(self, player, line, **slots):
- """
- Subclasses override this method to actually perform the action.
-
- This method is performed in an event transaction, by 'run'.
-
- NB: The suggested implementation strategy for a 'do' method is to do
- action-specific setup but then delegate the bulk of the actual logic to
- a method on a target/tool interface. The 'do' method's job is to
- select the appropriate methods to invoke.
-
- @param player: a provider of this L{Action}'s C{actorInterface}.
-
- @param line: the input string that created this action.
-
- @param slots: The results of calling C{self.resolve} on each parsing
- result (described by a setResultsName in C{self.expr}).
- """
- raise NotImplementedError("'do' method not implemented")
-
-
- def resolve(self, player, name, value):
- """
- Resolve a given parsed value to a valid action parameter by calling a
- 'resolve_<name>' method on this L{Action} with the given C{player} and
- C{value}.
-
- @param player: the L{Thing} attempting to perform this action.
-
- @type player: L{Thing}
-
- @param name: the name of the slot being filled. For example, 'target'.
-
- @type name: L{str}
-
- @param value: a string representing the value that was parsed. For
- example, if the user typed 'get fish', this would be 'fish'.
-
- @return: a value which will be passed as the 'name' parameter to this
- L{Action}'s C{do} method.
- """
- resolver = getattr(self, 'resolve_%s' % (name,), None)
- if resolver is None:
- raise NotImplementedError(
- "Don't know how to resolve %r (%r)" % (name, value))
- return resolver(player, value)
-
-
-
-def targetString(name):
- return (
- _quoteRemovingQuotedString ^
- UnicodeWord()).setResultsName(name)
-
-
-
-class TargetAction(Action):
- """
- Subclass L{TargetAction} to implement an action that acts on a target, like
- 'take foo' or 'eat foo' where 'foo' is the target.
-
- @cvar targetInterface: the interface which the 'target' parameter to 'do'
- must provide.
- """
-
- infrastructure = True
-
- targetInterface = iimaginary.IThing
-
- def targetRadius(self, player):
- return 2
-
- def resolve_target(self, player, targetName):
- return _getIt(player, targetName,
- self.targetInterface, self.targetRadius(player))
-
-
-
-class ToolAction(TargetAction):
- """
- Subclass L{ToolAction} to implement an action that acts on a target by
- using a tool, like 'unlock door with key', where 'door' is the target and
- 'key' is the tool.
-
- @cvar toolInterface: the L{zope.interface.Interface} which the 'tool'
- parameter to 'do' must provide.
- """
- infrastructure = True
-
- toolInterface = iimaginary.IThing
-
- def toolRadius(self, player):
- return 2
-
- def resolve_tool(self, player, toolName):
- return _getIt(player, toolName,
- self.toolInterface, self.toolRadius(player))
-
-
-
-def _getIt(player, thingName, iface, radius):
- return list(player.search(radius, iface, thingName))
-
-
-
-class LookAround(Action):
- actionName = "look"
- expr = pyparsing.Literal("look") + pyparsing.StringEnd()
-
- def do(self, player, line):
- ultimateLocation = player.thing.location
- while ultimateLocation.location is not None:
- ultimateLocation = ultimateLocation.location
- for visible in player.thing.findProviders(iimaginary.IVisible, 1):
- # XXX what if my location is furniture? I want to see '( Foo,
- # sitting in the Bar )', not '( Bar )'.
- if visible.isViewOf(ultimateLocation):
- concept = visible.visualize()
- break
- else:
- concept = u"You are floating in an empty, formless void."
- events.Success(actor=player.thing,
- actorMessage=concept).broadcast()
-
-
-
-class LookAt(TargetAction):
- actionName = "look"
- expr = (pyparsing.Literal("look") +
- pyparsing.Optional(pyparsing.White() +
- pyparsing.Literal("at")) +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("target"))
-
- targetInterface = iimaginary.IVisible
-
- def resolve_target(self, player, targetName):
- """
- Resolve the target to look at by looking for a named, visible object in
- a proximity of 3 meters from the player.
-
- @param player: The player doing the looking.
-
- @type player: L{IThing}
-
- @param targetName: The name of the object we are looking for.
-
- @type targetName: C{unicode}
-
- @return: A list of visible objects.
-
- @rtype: C{list} of L{IVisible}
-
- @raise eimaginary.ActionFailure: with an appropriate message if the
- target cannot be resolved for an identifiable reason. See
- L{imaginary.objects.Thing.obtainOrReportWhyNot} for a description
- of how such reasons may be identified.
- """
- return player.obtainOrReportWhyNot(
- Proximity(3.0, Named(targetName,
- CanSee(ProviderOf(iimaginary.IVisible)),
- player)))
-
-
- def cantFind_target(self, player, name):
- return "You don't see that."
-
- def targetRadius(self, player):
- return 3
-
- def do(self, player, line, target):
- if player.thing is not target:
- evt = events.Success(
- actor=player.thing,
- target=target,
- actorMessage=target.visualize(),
- targetMessage=(player.thing, " looks at you."))
- else:
- evt = events.Success(
- actor=player.thing,
- actorMessage=target.visualize())
- evt.broadcast()
-
-
-
-class Illuminate(Action):
- """
- Change the ambient light level at the location of the actor. Since this is
- an administrative action that directly manipulates the environment, the
- actor must be a L{iimaginary.IManipulator}.
-
- The argument taken by this action is an integer which specifies the light
- level in U{candelas<http://en.wikipedia.org/wiki/Candela>}.
- """
-
- actorInterface = iimaginary.IManipulator
-
- expr = (pyparsing.Literal("illuminate") +
- pyparsing.White() +
- pyparsing.Word("0123456789").setResultsName("candelas"))
-
-
- def do(self, player, line, candelas):
- """
- Attempt to change the illumination of the player's surroundings.
-
- @param player: a manipulator that can change the illumination of its
- room.
- @type player: L{IManipulator}
-
- @param line: the text being parsed
- @type line: L{str}
-
- @param candelas: the number of candelas to change the ambient
- illumination to.
- @type candelas: L{str}
- """
- candelas = int(candelas)
- oldCandelas = player.setIllumination(candelas)
- otherMessage = None
- if oldCandelas == candelas:
- actorMessage = u"You do it. Swell."
- elif candelas == 0:
- actorMessage = (
- u"Your environs fade to black due to Ineffable Spooky Magic.")
- otherMessage = actorMessage
- elif oldCandelas == 0:
- actorMessage = u"Your environs are suddenly alight."
- otherMessage = actorMessage
- elif candelas < oldCandelas:
- actorMessage = u"Your environs seem slightly dimmer."
- otherMessage = actorMessage
- elif candelas > oldCandelas:
- actorMessage = u"Your environs seem slightly brighter."
- otherMessage = actorMessage
- events.Success(actor=player.thing,
- actorMessage=actorMessage,
- otherMessage=otherMessage).broadcast()
-
-
-
-class Describe(TargetAction):
- expr = (pyparsing.Literal("describe") +
- pyparsing.White() +
- targetString("target") +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("description"))
-
- def targetRadius(self, player):
- return 3
-
- def do(self, player, line, target, description):
- target.description = description
- evt = events.Success(
- actor=player.thing,
- actorMessage=("You change ", target, "'s description."),
- otherMessage=(player.thing, " changes ", target, "'s description."))
- evt.broadcast()
-
-
-class Name(TargetAction):
- expr = (pyparsing.Literal("name") +
- pyparsing.White() +
- targetString("target") +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("name"))
-
- def targetRadius(self, player):
- return 3
-
- def do(self, player, line, target, name):
- evt = events.Success(
- actor=player.thing,
- actorMessage=("You change ", target, "'s name."),
- otherMessage=language.Sentence([player.thing, " changes ", target, "'s name to ", name, "."]))
- evt.broadcast()
- target.name = name
-
-
-
-class Open(TargetAction):
- expr = (pyparsing.Literal("open") +
- pyparsing.White() +
- targetString("target"))
-
- targetInterface = iimaginary.IContainer
-
- def do(self, player, line, target):
- dnf = language.Noun(target.thing).definiteNounPhrase()
- if not target.closed:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player.thing,
- target=target.thing,
- actorMessage=language.Sentence([dnf, " is already open."])))
-
- target.closed = False
- evt = events.Success(
- actor=player.thing,
- target=target.thing,
- actorMessage=("You open ", dnf, "."),
- targetMessage=language.Sentence([player.thing, " opens you."]),
- otherMessage=language.Sentence([player.thing, " opens ", target.thing, "."]))
- evt.broadcast()
-
-
-
-class Close(TargetAction):
- expr = (pyparsing.Literal("close") +
- pyparsing.White() +
- targetString("target"))
-
- targetInterface = iimaginary.IContainer
-
- def do(self, player, line, target):
- dnf = language.Noun(target.thing).definiteNounPhrase()
- if target.closed:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player.thing,
- target=target.thing,
- actorMessage=language.Sentence([dnf, " is already closed."])))
-
- target.closed = True
- evt = events.Success(
- actor=player.thing,
- target=target.thing,
- actorMessage=("You close ", dnf, "."),
- targetMessage=language.Sentence([player.thing, " closes you."]),
- otherMessage=language.Sentence([player.thing, " closes ", target.thing, "."]))
- evt.broadcast()
-
-
-
-def tooHeavy(player, target):
- return eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player, target=target,
- actorMessage=(target, " is too heavy to pick up."),
- otherMessage=(player, " struggles to lift ", target, ", but fails."),
- targetMessage=(player, " tries to pick you up, but fails.")))
-
-
-
-def targetTaken(player, target, container=None):
- if container is None:
- return events.Success(
- actor=player, target=target,
- actorMessage=("You take ", target, "."),
- targetMessage=(player, " takes you."),
- otherMessage=(player, " takes ", target, "."))
- idop = language.Noun(container).definiteNounPhrase()
- return events.Success(
- actor=player,
- target=target,
- tool=container,
- actorMessage=("You take ", target, " from ", idop, "."),
- targetMessage=(player, " takes you from ", idop, "."),
- toolMessage=(player, " takes ", target, " from you."),
- otherMessage=(player, " takes ", target, " from ", idop, "."))
-
-
-
-class Remove(TargetAction):
- expr = ((pyparsing.Literal("remove") |
- pyparsing.Literal("take off")) +
- pyparsing.White() +
- targetString("target"))
-
- targetInterface = iimaginary.IClothing
- actorInterface = iimaginary.IClothingWearer
-
- def do(self, player, line, target):
- from imaginary import garments
- try:
- player.takeOff(target)
- except garments.InaccessibleGarment, e:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player.thing,
- target=target.thing,
- actorMessage=(u"You cannot take off ",
- language.Noun(target.thing).definiteNounPhrase(),
- u" because you are wearing ",
- e.obscuringGarment.thing, u"."),
- otherMessage=language.Sentence([
- player.thing,
- u" gets a dumb look on ",
- language.Noun(player.thing).hisHer(),
- u" face."])))
-
- evt = events.Success(
- actor=player.thing,
- target=target.thing,
- actorMessage=(u"You take off ",
- language.Noun(target.thing).definiteNounPhrase(),
- u"."),
- otherMessage=language.Sentence([
- player.thing, u" takes off ", target.thing, u"."]))
- evt.broadcast()
-
-
-
-class Wear(TargetAction):
- expr = (pyparsing.Literal("wear") +
- pyparsing.White() +
- targetString("target"))
-
- targetInterface = iimaginary.IClothing
- actorInterface = iimaginary.IClothingWearer
-
- def do(self, player, line, target):
- from imaginary import garments
- try:
- player.putOn(target)
- except garments.TooBulky, e:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player.thing,
- target=target.thing,
- actorMessage=language.Sentence([
- language.Noun(e.wornGarment.thing).definiteNounPhrase(),
- u" you are already wearing is too bulky for you to do"
- u" that."]),
- otherMessage=language.Sentence([
- player.thing,
- u" wrestles with basic personal problems."])))
-
- evt = events.Success(
- actor=player.thing,
- target=target.thing,
- actorMessage=(u"You put on ",
- language.Noun(target.thing).definiteNounPhrase(),
- "."),
- otherMessage=language.Sentence([
- player.thing, " puts on ", target.thing, "."]))
- evt.broadcast()
-
-
-
-class Equipment(Action):
- expr = pyparsing.Literal("equipment")
-
- actorInterface = iimaginary.IClothingWearer
-
- def do(self, player, line):
- from imaginary import garments
- equipment = list(player.store.query(
- objects.Thing,
- AND(
- garments.Garment.thing == objects.Thing.storeID,
- garments.Garment.wearer == player),
- sort=objects.Thing.name.ascending))
- if equipment:
- evt = events.Success(
- actor=player.thing,
- actorMessage=[
- u"You are wearing ",
- language.ItemizedList(equipment),
- u"."])
- else:
- evt = events.Success(
- actor=player.thing,
- actorMessage=language.ExpressString(
- u"You aren't wearing any equipment."))
- evt.broadcast()
-
-
-
-class TakeFrom(ToolAction):
- actionName = "take"
-
- expr = ((pyparsing.Literal("get") ^ pyparsing.Literal("take")) +
- pyparsing.White() +
- targetString("target") +
- pyparsing.Optional(pyparsing.White() +
- pyparsing.Literal("from")) +
- pyparsing.White() +
- targetString("tool"))
-
- def cantFind_target(self, player, targetName):
- return "Nothing like that around here."
- cantFind_tool = cantFind_target
-
- def do(self, player, line, target, tool):
- # XXX Make sure target is in tool
- targetTaken(player.thing, target, tool).broadcast()
- try:
- target.moveTo(player.thing)
- except eimaginary.DoesntFit:
- raise tooHeavy(player.thing, target)
-
-
-
-class PutIn(ToolAction):
-
- toolInterface = iimaginary.IThing
- targetInterface = iimaginary.IContainer
-
- def cantFind_target(self, player, targetName):
- return "That doesn't work."
-
- expr = (pyparsing.Literal("put") +
- pyparsing.White() +
- targetString("tool") +
- pyparsing.Optional(pyparsing.White() +
- pyparsing.Literal("in")) +
- pyparsing.White() +
- targetString("target"))
-
- def do(self, player, line, tool, target):
- ctool = iimaginary.IContainer(tool, None)
- targetObject = target.thing
- if ctool is not None and (ctool.contains(targetObject) or ctool is target):
- raise eimaginary.ActionFailure(
- events.ThatDoesntWork(
- actor=player.thing,
- target=targetObject,
- tool=tool,
- actorMessage="A thing cannot contain itself in euclidean space."))
-
- dnf = language.Noun(targetObject).definiteNounPhrase()
- evt = events.Success(
- actor=player.thing,
- target=targetObject,
- tool=tool,
- actorMessage=("You put ",
- language.Noun(tool).definiteNounPhrase(),
- " in ", dnf, "."),
- targetMessage=language.Sentence([player.thing, " puts ", " tool in you."]),
- toolMessage=language.Sentence([player.thing, " puts you in ", targetObject, "."]),
- otherMessage=language.Sentence([player.thing, " puts ", tool, " in ", targetObject, "."]))
- evt.broadcast()
-
- try:
- tool.moveTo(target)
- except eimaginary.DoesntFit:
- # <allexpro> dash: put me in a tent and give it to moshez!
- raise eimaginary.ActionFailure(
- events.ThatDoesntWork(
- actor=player.thing,
- target=targetObject,
- tool=tool,
- actorMessage=language.Sentence([
- language.Noun(tool).definiteNounPhrase(),
- u" does not fit in ", dnf, u"."])))
- except eimaginary.Closed:
- raise eimaginary.ActionFailure(
- events.ThatDoesntWork(
- actor=player.thing,
- target=targetObject,
- tool=tool,
- actorMessage=language.Sentence([dnf, " is closed."])))
-
-
-
-class Take(TargetAction):
- expr = ((pyparsing.Literal("get") ^ pyparsing.Literal("take")) +
- pyparsing.White() +
- targetString("target"))
-
- def cantFind_target(self, player, targetName):
- return u"Nothing like that around here."
-
- def targetRadius(self, player):
- return 1
-
- def do(self, player, line, target):
- if target in (player.thing, player.thing.location) or target.location is player.thing:
- raise eimaginary.ActionFailure(events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage=("You cannot take ", target, ".")))
-
- targetTaken(player.thing, target).broadcast()
- try:
- target.moveTo(player.thing)
- except eimaginary.DoesntFit:
- raise tooHeavy(player.thing, target)
-
-
-
-def insufficientSpace(player):
- return eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player,
- actorMessage="There's not enough space for that."))
-
-
-
-class Drop(TargetAction):
- expr = (pyparsing.Literal("drop") +
- pyparsing.White() +
- targetString("target"))
-
- def cantFind_target(self, player, targetName):
- return "Nothing like that around here."
-
- def targetRadius(self, player):
- return 1
-
- def do(self, player, line, target):
- if target.location is not player.thing:
- raise eimaginary.ActionFailure(
- events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage="You can't drop that."))
-
- try:
- target.moveTo(
- player.thing.location,
- arrivalEventFactory=lambda target: events.ArrivalEvent(
- actor=player.thing,
- actorMessage=("You drop ",
- language.Noun(target).definiteNounPhrase(),
- "."),
- target=target,
- targetMessage=(player.thing, " drops you."),
- otherMessage=(player.thing, " drops ", target, ".")))
- except eimaginary.DoesntFit:
- raise insufficientSpace(player.thing)
-
-
-
-_directionNames = objects.OPPOSITE_DIRECTIONS.keys()
-_directionNames.extend(objects.DIRECTION_ALIASES.keys())
-
-DIRECTION_LITERAL = reduce(
- operator.xor, [
- pyparsing.Literal(d)
- for d in _directionNames]).setResultsName("direction")
-
-
-
-def expandDirection(direction):
- """
- Expand direction aliases into the names of the directions they refer to.
- """
- return objects.DIRECTION_ALIASES.get(direction, direction)
-
-
-
-class Dig(Action):
- expr = (pyparsing.Literal("dig") +
- pyparsing.White() +
- DIRECTION_LITERAL +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("name"))
-
- def do(self, player, line, direction, name):
- direction = expandDirection(direction)
- if iimaginary.IContainer(player.thing.location).getExitNamed(direction, None) is not None:
- raise eimaginary.ActionFailure(events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage="There is already an exit in that direction."))
-
- room = objects.Thing(store=player.store, name=name)
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(player.thing.location, room, direction)
-
- evt = events.Success(
- actor=player.thing,
- actorMessage="You create an exit.",
- otherMessage=language.Sentence([player.thing, " created an exit to the ", direction, "."]))
- evt.broadcast()
-
- # XXX Right now there can't possibly be anyone in the
- # destination room, but someday there could be. When there
- # could be, broadcast this to them too.
-
-
-
-class Bury(Action):
- expr = (pyparsing.Literal("bury") +
- pyparsing.White() +
- DIRECTION_LITERAL)
-
- def do(self, player, line, direction):
- direction = expandDirection(direction)
- for exit in iimaginary.IContainer(player.thing.location).getExits():
- if exit.name == direction:
- if exit.sibling is not None:
- evt = events.Success(
- location=exit.toLocation,
- otherMessage=language.Sentence([
- exit.sibling, " crumbles and disappears."]))
- evt.broadcast()
-
- evt = events.Success(
- actor=player.thing,
- actorMessage="It's gone.",
- otherMessage=language.Sentence([
- language.Noun(player.thing).nounPhrase(),
- " destroyed ", exit, "."]))
- evt.broadcast()
- exit.destroy()
- return
-
- raise eimaginary.ActionFailure(events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage="There isn't an exit in that direction."))
-
-
-
-class Go(Action):
- expr = (
- (pyparsing.Literal("go") + pyparsing.White() +
- targetString("direction")) |
- (pyparsing.Literal("enter") + pyparsing.White() +
- targetString("direction")) |
- (pyparsing.Literal("exit") + pyparsing.White() +
- targetString("direction")) |
- DIRECTION_LITERAL)
-
- actorInterface = iimaginary.IThing
-
- def resolve_direction(self, player, directionName):
- """
- Identify a direction by having the player search for L{IExit}
- providers that they can see and reach.
- """
- directionName = expandDirection(directionName)
- return player.obtainOrReportWhyNot(
- Proximity(
- 3.0,
- Traversability(
- Named(directionName,
- CanSee(ProviderOf(iimaginary.IExit)), player))))
-
-
- def cantFind_direction(self, actor, directionName):
- """
- Explain to the user that they can't go in a direction that they can't
- locate.
- """
- return u"You can't go that way."
-
-
- def do(self, player, line, direction):
- location = player.location
-
- evt = events.Success(
- location=location,
- actor=player,
- otherMessage=(player, " leaves ", direction.name, "."))
- evt.broadcast()
-
- try:
- direction.traverse(player)
- except eimaginary.DoesntFit:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=player,
- actorMessage=language.ExpressString(
- u"There's no room for you there.")))
-
- # This is subtly incorrect: see http://divmod.org/trac/ticket/2917
- lookAroundActor = iimaginary.IActor(player)
- LookAround().do(lookAroundActor, "look")
-
-
-
-class Restore(TargetAction):
- expr = (pyparsing.Literal("restore") +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("target"))
-
- targetInterface = iimaginary.IActor
-
- def cantFind_target(self, player, targetName):
- for thing in player.thing.search(self.targetRadius(player),
- iimaginary.IThing, targetName):
- return (language.Noun(thing).nounPhrase().plaintext(player),
- " cannot be restored.")
- return "Who's that?"
-
- def targetRadius(self, player):
- return 3
-
-
- def do(self, player, line, target):
- target.hitpoints.current = target.hitpoints.max
- target.stamina.current = target.stamina.max
-
- if player is target:
- evt = events.Success(
- actor=player.thing,
- actorMessage="You have fully restored yourself.")
- evt.broadcast()
- else:
- evt = events.Success(
- actor=player.thing,
- actorMessage=("You have restored ", target.thing, " to full health."),
- target=target.thing,
- targetMessage=(player.thing, " has restored you to full health."),
- otherMessage=(player.thing, " has restored ", target.thing, " to full health."))
- evt.broadcast()
-
-
-
-class Hit(TargetAction):
- expr = ((pyparsing.Literal("hit") ^
- pyparsing.Literal("attack") ^
- pyparsing.Literal("kill")) +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("target"))
-
- targetInterface = iimaginary.IActor
-
- def targetRadius(self, player):
- return 3
-
- def do(self, player, line, target):
- if target is player:
- raise eimaginary.ActionFailure(
- events.ThatDoesntMakeSense(u"Hit yourself? Stupid.",
- actor=player.thing))
-
- cost = random.randrange(1, 5)
- if player.stamina < cost:
- raise eimaginary.ActionFailure(
- events.ThatDoesntWork(u"You're too tired!",
- actor=player.thing))
-
- damage = random.randrange(1, 5)
- player.stamina.decrease(cost)
- thp = target.hitpoints.decrease(damage)
- events.Success(
- actor=player.thing,
- target=target.thing,
- targetMessage=language.Sentence([player.thing, " hits you for ", damage, " hitpoints."]),
- actorMessage=language.Sentence(["You hit ", language.Noun(target.thing).definiteNounPhrase(), " for ", damage, " hitpoints."]),
- otherMessage=language.Sentence([player.thing, " hits ", target.thing, "."])).broadcast()
-
- if thp <= 0:
- xp = target.experience / 2 + 1
- player.gainExperience(xp) # I LOVE IT
- targetIsDead = [target.thing, " is dead!", "\n"]
- events.Success(
- actor=player.thing, target=target.thing,
- actorMessage=["\n", targetIsDead, "You gain ", xp, " experience"],
- targetMessage=["You are dead!"],
- otherMessage=targetIsDead).broadcast()
- target.thing.destroy()
-
-
-
-class Say(Action):
- expr = (((pyparsing.Literal("say") + pyparsing.White()) ^
- pyparsing.Literal("'")) +
- pyparsing.restOfLine.setResultsName("text"))
-
- def do(self, player, line, text):
- evt = events.SpeechEvent(speaker=player.thing, text=text)
- evt.broadcast()
-
-
-
-class Emote(Action):
- expr = (((pyparsing.Literal("emote") + pyparsing.White()) ^
- pyparsing.Literal(":")) +
- pyparsing.restOfLine.setResultsName("text"))
-
- def do(self, player, line, text):
- evt = events.Success(actor=player.thing,
- actorMessage=[player.thing, " ", text],
- otherMessage=[player.thing, " ", text])
- evt.broadcast()
-
-
-
-class Actions(Action):
- expr = pyparsing.Literal("actions")
-
- def do(self, player, line):
- cmds = dict.fromkeys(
- getattr(cmd, 'actionName', cmd.__name__.lower())
- for cmd
- in self.__class__.actions).keys()
- cmds.sort()
- player.send((iterutils.interlace(" ", cmds), "\n"))
-
-
-
-class Commands(Action):
- """
- The I{commands} action provides a pointer to inexperienced players that
- they should be thinking in terms of I{actions} instead.
-
- This has no world side-effects; it just provides some user-interface
- information to the player.
- """
- expr = pyparsing.Literal("commands")
-
- def do(self, player, line):
- player.send("Try 'actions' instead.")
-
-
-
-class Search(Action):
- expr = (pyparsing.Literal("search") +
- targetString("name"))
-
- def do(self, player, line, name):
- srch = player.thing.search(2, iimaginary.IVisible, name)
- evt = events.Success(
- actor=player.thing,
- actorMessage=language.ExpressList(
- list(iterutils.interlace('\n',
- (o.visualize()
- for o
- in srch)))))
- evt.broadcast()
-
-
-
-class Score(Action):
- expr = pyparsing.Literal("score")
-
- scoreFormat = (
- '/----------------------------------------------------------------------------\\\n'
- '| Level: %20d Experience: %10d\n'
- '| Hitpoints: %16s\n'
- '| Stamina: %18s\n'
- '\\----------------------------------------------------------------------------/\n')
-
- def do(self, player, line):
- events.Success(
- actor=player.thing,
- actorMessage=self.scoreFormat % (player.level, player.experience, player.hitpoints, player.stamina)).broadcast()
-
-
-
-class ExpressWho(language.BaseExpress):
- header = (u"/============ Currently Playing ===========\\")
- footer = (u"\\================ Total %(playerCount)03d ===============/")
-
- def vt102(self, observer):
- players = self.original.connected
-
- return [[T.bold, self.header], u'\n',
- [[language.Noun(p).shortName().vt102(observer), u'\n']
- for p in players],
- [T.bold, self.footer % {'playerCount': len(players)}], u'\n']
-
-
-
-class Who(Action):
- expr = pyparsing.Literal("who")
-
- def do(self, player, line):
- player.send(ExpressWho(player.store.findUnique(ImaginaryWorld)))
-
-
-
-class Scrutinize(TargetAction):
- """
- Show detailed information about the model structure of a game object.
- """
- expr = (pyparsing.Literal("scrutinize") +
- pyparsing.White() +
- targetString("target"))
-
- def targetRadius(self, player):
- return 3
-
- def do(self, player, line, target):
- v = dict((k, getattr(target, k))
- for (k, ign)
- in target.getSchema()
- if hasattr(target, k))
-
- targetContainer = iimaginary.IContainer(target, None)
- if targetContainer is not None:
- v['contents'] = list(targetContainer.getContents())
- exits = list(targetContainer.getExits())
- if exits:
- v['exits'] = exits
- s = pprint.pformat((target.__class__.__name__, v))
- # XXX FIXME Send a real Concept
- player.send(s, '\n')
-
-
-
-class ExpressInventory(language.BaseExpress):
- implements(iimaginary.IConcept)
-
- def __init__(self, original):
- self.original = original
-
- def vt102(self, observer):
- return [[T.fg.yellow, "Inventory:\n"],
- [T.fg.green,
- [(language.Noun(o).shortName().vt102(observer), '\n')
- for o
- in iimaginary.IContainer(self.original).getContents()]]]
-
-
-
-class Inventory(Action):
- expr = pyparsing.Literal("inventory")
-
- def do(self, player, line):
- events.Success(actor=player.thing,
- actorMessage=ExpressInventory(player.thing)).broadcast()
-
-
-
-class Set(TargetAction):
- """
- Direct model-level state manipulation command.
- """
- expr = (
- pyparsing.Literal("set") + pyparsing.White() +
- targetString("attribute") + pyparsing.White() +
- pyparsing.Literal("of") + pyparsing.White() +
- targetString("target") + pyparsing.White() +
- pyparsing.Literal("to") + pyparsing.White() +
- targetString("value"))
-
- def do(self, player, line, attribute, target, value):
- """
- Dispatch handling to an attribute-specific method.
-
- @type attribute: C{unicode}
- @param attribute: The model-level attribute of which to manipulate
- the value. Handling of each attribute will be dispatched to a
- C{set_}-prefixed method for that attribute based on this value.
-
- @type target: L{Thing}
- @param target: The model object to manipulate.
-
- @type value: C{unicode}
- @param value: The new value for the specified attribute.
- """
- try:
- method = getattr(self, "set_" + attribute.upper())
- except AttributeError:
- raise eimaginary.ActionFailure(
- events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage="You cannot set that."))
- else:
- method(player, line, target, value)
-
-
- def set_GENDER(self, player, line, target, value):
- """
- Attempt to change the gender of a thing.
-
- @param target: The thing to change the gender of.
- @param value: A string naming a gender on L{language.Gender}.
- """
- try:
- target.gender = getattr(language.Gender, value.upper())
- except AttributeError:
- gender = {language.Gender.MALE: "male",
- language.Gender.FEMALE: "female",
- language.Gender.NEUTER: "neuter"}.get(target.gender)
- raise eimaginary.ActionFailure(events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage=("Only male, female, and neuter are valid "
- "genders. You remain ", gender, ".")))
- else:
- if player.thing is target:
- # XXX Why can't I do something with Noun to collapse these
- # cases?
- event = events.Success(
- actor=player.thing,
- actorMessage=(u"You set your gender to ", value, "."))
- else:
- event = events.Success(
- actor=player.thing,
- target=target,
- actorMessage=("You set ", language.Noun(target).hisHer(),
- " gender to ", value, "."),
- targetMessage=(player.thing, " set your gender to ",
- value, "."))
- event.broadcast()
-
-
- def set_PROPER(self, player, line, target, value):
- """
- Attempt to change the name of a thing from a proper noun to a common
- noun or the other way around.
-
- @param target: The thing to change.
- @param value: The string C{"true"} or C{"false"}.
- """
- if value == "true":
- target.proper = True
- phrase = '" a proper noun.'
- elif value == "false":
- target.proper = False
- phrase = '" a common noun.'
- else:
- raise eimaginary.ActionFailure(
- events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage=("Only true and false are valid settings "
- "for proper.")))
- events.Success(
- actor=player.thing,
- actorMessage=('You make the name of "',
- language.Noun(target).shortName(),
- phrase)).broadcast()
-
-
-
-class Help(Action):
- """
- A command for looking up help files.
-
- @cvar helpContentPath: The path in which to search for files.
- @type helpContentPath: L{filepath.FilePath}
- """
- expr = (pyparsing.Literal("help") +
- pyparsing.White() +
- pyparsing.restOfLine.setResultsName("topic"))
-
- helpContentPath = filepath.FilePath(imaginary.__file__).sibling(
- "resources").child("help")
-
- def do(self, player, line, topic):
- topic = topic.lower().strip()
- try:
- helpFile = self.helpContentPath.child(topic).open()
- except (OSError, IOError, filepath.InsecurePath):
- player.send("No help available on ", topic, ".", "\n")
- else:
- player.send(helpFile.read(), '\n')
=== removed file 'Imaginary/imaginary/copyright.py'
--- Imaginary/imaginary/copyright.py 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/copyright.py 1970-01-01 00:00:00 +0000
@@ -1,22 +0,0 @@
-
-# <major> <minor> <patch> <alpha | pre | final | zzz> <iteration>
-version_info = (0, 1, 0, 'alpha', 0)
-
-# Sortable version information. This will always only
-# increase from an older version to a newer version.
-hexversion = (version_info[0] << 24 |
- version_info[1] << 16 |
- version_info[2] << 8 |
- ['alpha', 'pre', 'final', 'zzz'].index(version_info[3]) << 4 |
- version_info[4])
-
-# Human-readable format
-if version_info[3] == 'final':
- version = '%d.%d.%d%s' % version_info[:-1]
-elif version_info[3] != 'zzz':
- version = '%d.%d.%d%s%d' % version_info
-else:
- version = "SVN-trunk"
-
-# Longer human-readable format
-longversion= "Imaginary " + version
=== removed file 'Imaginary/imaginary/creation.py'
--- Imaginary/imaginary/creation.py 2009-08-17 02:40:03 +0000
+++ Imaginary/imaginary/creation.py 1970-01-01 00:00:00 +0000
@@ -1,179 +0,0 @@
-# -*- test-case-name: imaginary.test.test_create -*-
-"""
-This module contains code associated with creating objects in game.
-"""
-
-from zope.interface import implements
-
-from twisted import plugin
-
-import imaginary.plugins
-
-from imaginary import objects
-from imaginary import events
-from imaginary import language
-
-from imaginary.iimaginary import IThingType
-from imaginary.eimaginary import ActionFailure, DoesntFit
-
-from imaginary.action import Action, insufficientSpace
-from imaginary.action import targetString
-
-from imaginary.pyparsing import Literal, White, Optional, restOfLine
-
-
-def getPlugins(iface, package):
- """
- Get plugins. See L{twisted.plugin.getPlugins}.
-
- This is in place only so the tests specifically for creation can replace
- it. Please use L{twisted.plugin.getPlugins} instead.
- """
- # XXX the tests should not need to do that, make it per-instance or
- # something...
- return plugin.getPlugins(iface, package)
-
-
-def createCreator(*enhancements):
- """
- Create and return a function which can create objects in the game world.
-
- This is a utility function to make it easy to define factories for certain
- configurations of power-ups to be used with Imaginary. It doesn't do
- anything magical; you can replicate its effects simply by writing a
- function that calls L{Enhancement.createFor} on the set of L{Enhancement}s.
- L{createCreator} exists because you will frequently need to do that, and it
- can be tedious.
-
- @param enhancements: The arguments to this function are a list of 2-tuples
- of (L{Enhancement}-subclass, keyword arguments to that class's
- constructor).
-
- @return: a function which takes keyword arguments that will be passed on to
- L{objects.Thing}'s constructor, and will return a L{Thing} with an
- instance of each class in C{enhancements} installed, via C{createFor},
- on it.
-
- @rtype: L{Thing}
- """
- def create(**kw):
- o = objects.Thing(**kw)
- for enhancementClass, enhancementKeywords in enhancements:
- enhancementClass.createFor(o, **(enhancementKeywords or {}))
- return o
- return create
-
-
-class CreationPluginHelper(object):
- """
- A helper for creating plugins for the 'Create' command.
-
- Create will search for L{IThingType} plugins and allow users to
- instantiate a new L{objects.Thing} using the one with the name which
- matches what was supplied to the action.
- """
-
- implements(plugin.IPlugin, IThingType)
-
- def __init__(self, typeName, typeObject):
- """
- @type typeName: C{unicode}
- @param typeName: A short string describing the kind of object this
- plugin will create.
-
- @param typeObject: A factory for creating instances of
- L{objects.Thing}. This will be invoked with four keyword arguments:
- store, name, description, and proper. See attributes of
- L{objects.Thing} for documentation of these arguments.
- """
- self.type = typeName
- self.typeObject = typeObject
-
-
- def getType(self):
- return self.typeObject
-
-
-
-def creationSuccess(player, creation):
- """
- Create and return an event describing that an object was successfully
- created.
- """
- phrase = language.Noun(creation).nounPhrase()
- return events.Success(
- actor=player,
- target=creation,
- actorMessage=language.Sentence(["You create ", phrase, "."]),
- targetMessage=language.Sentence([player, " creates you."]),
- otherMessage=language.Sentence([player, " creates ", phrase, "."]))
-
-
-class Create(Action):
- """
- An action which can create items by looking at the L{IThingType} plugin
- registry.
- """
- expr = (Literal("create") +
- Optional(White() +
- (Literal("an") | Literal("a") | Literal("the")).setResultsName("article")) +
- White() +
- targetString("typeName") +
- White() +
- Literal("named") +
- White() +
- targetString("name") +
- Optional(White() +
- restOfLine.setResultsName("description")))
-
- def do(self, player, line, typeName, name, description=None, article=None):
- """
- Create an item, and notify everyone present that it now exists.
- """
- if not description:
- description = u'an undescribed object'
- for plug in getPlugins(IThingType, imaginary.plugins):
- if plug.type == typeName:
- proper = (article == "the")
- o = plug.getType()(store=player.store, name=name,
- description=description, proper=proper)
- break
- else:
- raise ActionFailure(
- events.ThatDoesntMakeSense(
- actor=player.thing,
- actorMessage=language.ExpressString(
- u"Can't find " + typeName + u".")))
-
- creationSuccess(player.thing, o).broadcast()
- try:
- o.moveTo(player.thing)
- except DoesntFit:
- raise insufficientSpace(player.thing)
-
-
-
-
-def listThingTypes():
- """
- Return a list of C{unicode} strings each of which gives the name of a type
- which can be created with the create command.
- """
- return sorted([type.type for type in getPlugins(IThingType, imaginary.plugins)])
-
-
-
-class ListThingTypes(Action):
- """
- An action which tells the invoker what thing types exist to be created with
- the L{Create} command.
- """
- expr = Literal("list thing types")
-
- def do(self, player, line):
- """
- Tell the player the thing types which exist.
- """
- events.Success(
- actor=player.thing,
- actorMessage=[(t, "\n") for t in listThingTypes()]).broadcast()
=== removed file 'Imaginary/imaginary/eimaginary.py'
--- Imaginary/imaginary/eimaginary.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/eimaginary.py 1970-01-01 00:00:00 +0000
@@ -1,90 +0,0 @@
-
-from twisted.cred import error
-
-# Authentication errors
-class BadPassword(error.UnauthorizedLogin):
- pass
-
-class NoSuchUser(error.UnauthorizedLogin):
- pass
-
-
-# Base Imaginary error
-class ImaginaryError(Exception):
- pass
-
-
-# Input handling errors
-class NoSuchCommand(ImaginaryError):
- """
- There is no command like the one you tried to execute.
- """
-
-class AmbiguousArgument(ImaginaryError):
- """
- One or more of the inputs specified can not be narrowed down to
- just one thing. This can be due to the presence of multiple
- things with similar names, or due to the absence of anything named
- similarly to the given input.
-
- @ivar action: The action which was being processed when an ambiguity was
- found.
-
- @type part: C{str}
- @ivar part: The part of the command which was ambiguous.
- Typically something like 'target' or 'tool'.
-
- @type partValue: C{str}
- @ivar partValue: The string which was supplied by the user for the indicated part.
-
- @type objects: C{list} of C{IThing}
- @ivar objects: The objects which were involved in the ambiguity.
- """
-
- def __init__(self, action, part, partValue, objects):
- ImaginaryError.__init__(self, action, part, partValue, objects)
- self.action = action
- self.part = part
- self.partValue = partValue
- self.objects = objects
-
-
-
-class ActionFailure(ImaginaryError):
- """
- Wrapper exception for an Event that caused an action to fail (such that the
- transaction in which it was running should be reverted).
- """
- def __init__(self, event):
- ImaginaryError.__init__(self)
- self.event = event
-
-
- def __repr__(self):
- return '<Action Failure: %r>' % (self.event,)
-
-
-
-class ThingNotFound(ImaginaryError):
- """
- Resolving a Thing by identity failed.
- """
-
-
-# Game logic errors
-class DoesntFit(ImaginaryError):
- """
- An object tried to go into a container, but the container was full.
- """
-
-
-class Closed(ImaginaryError):
- """
- An object tried to go into a container, but the container was closed.
- """
-
-
-class CannotMove(ImaginaryError):
- """
- An object tried to move but it was not portable so it couldn't.
- """
=== removed file 'Imaginary/imaginary/enhancement.py'
--- Imaginary/imaginary/enhancement.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/enhancement.py 1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
-# -*- test-case-name: imaginary.test.test_enhancement -*-
-
-"""
-This module contains objects for application code to use to implement behaviors
-that attach to objects in a simulation.
-"""
-
-class Enhancement(object):
- """
- An L{Enhancement} is an object attached to a L{imaginary.objects.Thing}
- that provides some additional functionality.
-
- This class is a mixin; it expects to be mixed in to an L{Item} subclass,
- since it passes itself as an argument to L{Item.powerUp}.
-
- Note that an L{Enhancement} embodies the behavior, but not the physical
- attributes, of the object in question.
-
- For example, let's say you wanted to implement a cell phone in Imaginary.
- You would make an L{Enhancement} called C{CellPhone} which had various
- attributes, for example C{phoneNumber}. Then you would do C{phoneBody =
- Thing(...)} to create a physical 'phone' object in a world. Next, you
- would do C{cellPhone = CellPhone.createFor(phoneBody, ...)}, which would
- create a C{CellPhone} object that endowed your physical 'phone' with the
- properties of being an actual phone, like having a phone number, ringing
- when dialed, etc.
-
- Note that it is not enough to simply create your C{CellPhone}, as it will
- not have a physical body, and therefore not exist in the world.
-
- @ivar thing: a L{imaginary.objects.Thing} powered up with this
- L{Enhancement}. All subclasses which mix in L{Item} should declare
- this as an L{attributes.reference} attribute. Unless your
- L{Enhancement} subclass is specifically designed to exist
- independently of its L{Thing}, or to accept other types for this
- attribute, it should also be declared as C{(allowNone=False,
- reftype=Thing, whenDeleted=CASCADE)}.
- """
-
- def installed(self):
- """
- Override the C{installed()} hook that C{axiom.dependency} provides.
- When L{Enhancement} was called C{ThingMixin}, the suggested mechanism
- to install simulation components was to use the dependency system,
- which was wrong, c.f. U{http://divmod.org/trac/ticket/2558}.
-
- @raise RuntimeError: to indicate that you shouldn't use this
- functionality.
- """
- raise RuntimeError("Use Enhancement.createFor, not installOn(), "
- "to apply an Enhancement to a Thing.")
-
-
- def applyEnhancement(self):
- """
- Apply this L{Enhancement} to its C{thing} attribute, by powering it up.
- """
- self.thing.powerUp(self)
-
-
- def removeEnhancement(self):
- """
- Remove this L{Enhancement} from its C{thing} attribute, by powering it
- down.
- """
- self.thing.powerDown(self)
-
-
- @classmethod
- def createFor(cls, thing, **kw):
- """
- Create an L{Enhancement} of this type for the given
- L{imaginary.objects.Thing}, in the given L{imaginary.objects.Thing}'s
- store.
- """
- self = cls(store=thing.store, thing=thing, **kw)
- self.applyEnhancement()
- return self
-
-
- @classmethod
- def destroyFor(cls, thing):
- """
- Destroy the L{Enhancement}s of the given subclass associated with the
- given L{Thing}, if one exists.
-
- @param thing: A L{Thing} which may be the value of the C{thing}
- attribute of an instance of the given L{Enhancement} subclass.
-
- @type thing: L{Thing}
- """
- it = thing.store.findUnique(cls, cls.thing == thing, default=None)
- if it is not None:
- it.removeEnhancement()
- it.deleteFromStore()
=== removed file 'Imaginary/imaginary/events.py'
--- Imaginary/imaginary/events.py 2009-08-18 00:20:31 +0000
+++ Imaginary/imaginary/events.py 1970-01-01 00:00:00 +0000
@@ -1,284 +0,0 @@
-# -*- test-case-name: imaginary.test.test_actions.TargetActionTests.test_resolveTargetCaseInsensitively -*-
-
-from zope.interface import implements
-
-from twisted.python import context
-
-from imaginary import iimaginary, language, eimaginary
-from imaginary.idea import Proximity, ProviderOf
-
-
-class Event(language.BaseExpress):
- implements(iimaginary.IConcept)
-
- actorMessage = targetMessage = toolMessage = otherMessage = None
-
- def __init__(self,
- location=None, actor=None, target=None, tool=None,
- actorMessage=None, targetMessage=None, toolMessage=None,
- otherMessage=None):
-
- if location is None and actor is not None:
- location = actor.location
-
- self.location = location
- self.actor = actor
- self.target = target
- self.tool = tool
- if actorMessage is not None:
- self.actorMessage = iimaginary.IConcept(actorMessage)
- if targetMessage is not None:
- self.targetMessage = iimaginary.IConcept(targetMessage)
- if toolMessage is not None:
- self.toolMessage = iimaginary.IConcept(toolMessage)
- if otherMessage is not None:
- self.otherMessage = iimaginary.IConcept(otherMessage)
-
-
- def conceptFor(self, observer):
- """
- Retrieve the appropriate L{IConcept} provider for a given observer. If
- the observer is this L{Event}'s C{actor}, it will return the
- C{actorMessage} for this event, and so on for the tool and the target.
- If it doesn't match a L{Thing} known to this event, it will return
- C{otherMessage}.
- """
- if observer is self.actor:
- msg = self.actorMessage
- elif observer is self.target:
- msg = self.targetMessage
- elif observer is self.tool:
- msg = self.toolMessage
- else:
- msg = self.otherMessage
- return msg
-
-
- def reify(self):
- """
- Determine which objects should receive this event and return a callable
- object which will deliver it to them.
-
- Note that this occurs during event propagation, and you probably don't
- need to call it directly.
-
- @see: L{iimaginary.IEventObserver.prepare} and
- L{TransactionalEventBroadcaster} for a more thorough description of
- how this method is used to interact with transactions.
-
- @return: a 0-arg callable object which, when called, will call the
- results of all L{IEventObserver}s which were contained within this
- L{Event}'s location when this method, L{Event.reify}, was called.
- """
- L = []
- for observer in (self.location.idea.obtain(
- Proximity(0.5, ProviderOf(iimaginary.IEventObserver)))):
- sender = observer.prepare(self)
- if not callable(sender):
- raise TypeError("Senders must be callable", sender)
- L.append(sender)
- return lambda: map(apply, L)
-
-
- def vt102(self, observer):
- c = self.conceptFor(observer)
- if c is not None:
- return [c.vt102(observer), '\n']
- return u''
-
-
-
-class TransactionalEventBroadcaster(object):
- """
- Collect a bunch of output events as a transaction is being executed, then
- distribute them when it has completed.
-
- Events can be added normally or as revert events. Normal events are
- broadcast after the transaction is successfully committed. Revert events
- are broadcast if the transaction failed somehow and was been reverted.
- """
- implements(iimaginary.ITransactionalEventBroadcaster)
-
- def __init__(self):
- self._events = []
- self._revertEvents = []
-
-
- def addEvent(self, event):
- """
- Add a normal event.
-
- @param event: A no-argument callable to be invoked when this
- transaction has been committed.
- """
- if not callable(event):
- raise ValueError("Events must be callable", event)
- self._events.append(event)
-
-
- def addRevertEvent(self, event):
- """
- Add a revert event.
-
- @param event: A no-argument callable to be invoked when this
- transaction has been reverted.
- """
- if not callable(event):
- raise ValueError("Events must be callable", event)
- self._revertEvents.append(event)
-
-
- def broadcastEvents(self):
- """
- Send all normal events.
- """
- events = self._events
- self._events = self._revertEvents = None
- map(apply, events)
-
-
- def broadcastRevertEvents(self):
- """
- Send all revert events.
- """
- events = self._revertEvents
- self._events = self._revertEvents = None
- map(apply, events)
-
-
-
-def runEventTransaction(store, func, *args, **kwargs):
- """
- This takes responsibility for setting up the transactional event
- broadcasting junk, handling action errors, and broadcasting commit or
- revert events.
- """
- broadcaster = TransactionalEventBroadcaster()
- def runHelper():
- # Set up event context for the duration of the action
- # run. Additionally, handle raised ActionFailures by
- # adding their events to the revert event list and
- # re-raising them so they will revert the transaction.
- try:
- return context.call(
- {iimaginary.ITransactionalEventBroadcaster: broadcaster},
- func, *args, **kwargs)
- except eimaginary.ActionFailure, e:
- broadcaster.addRevertEvent(e.event.reify())
- raise
- try:
- result = store.transact(runHelper)
- except eimaginary.ActionFailure:
- broadcaster.broadcastRevertEvents()
- return None
- else:
- broadcaster.broadcastEvents()
- return result
-
-
-
-class ThatDoesntMakeSense(Event):
- """
- An action was attempted which is logically impossible.
- """
- def __init__(self, actorMessage="That doesn't make sense.", **kw):
- super(ThatDoesntMakeSense, self).__init__(actorMessage=actorMessage, **kw)
-
-
-class ThatDoesntWork(Event):
- """
- An action was attempted which is phyically impossible.
- """
- def __init__(self, actorMessage="That doesn't work.", **kw):
- super(ThatDoesntWork, self).__init__(actorMessage=actorMessage, **kw)
-
-
-class Success(Event):
- """
- You do it. Swell.
- """
-
- def broadcast(self):
- """
- Don't really broadcast. Add this event to the events which will be
- sent when the action (or whatever) execution transaction is committed
- successfully.
- """
- broadcaster = context.get(iimaginary.ITransactionalEventBroadcaster)
- if broadcaster is not None:
- broadcaster.addEvent(self.reify())
- else:
- self.reify()()
-
-
-
-class ArrivalEvent(Success):
- """
- An event representing the arrival of an object.
- """
-
-
-
-class MovementArrivalEvent(ArrivalEvent):
- """
- An event representing the arrival of an object at a location from an
- origin.
- """
- def __init__(self, thing, origin=None, direction=None):
- self.thing = thing
- self.origin = origin
- self.direction = direction
- self.location = self.thing.location
-
-
- def conceptFor(self, observer):
- if observer is self.thing:
- return None
- if self.origin is not None:
- msg = [" arrives from ", self.origin, "."]
- elif self.direction is not None:
- msg = [" arrives from the ", self.direction, "."]
- else:
- msg = [" arrives."]
- msg.insert(0, self.thing)
- return language.Sentence(msg)
-
-
-
-class DepartureEvent(Success):
- """
- An event representing the departure of an object at a location to a
- destination.
- """
- def __init__(self, location, actor, **kw):
- """
- @type location: L{iimaginary.IThing} provider.
- @param location: The location that the actor is leaving.
- @type actor: L{iimaginary.IThing} provider.
- @param actor: The actor that is leaving.
- """
- super(DepartureEvent, self).__init__(location, actor, **kw)
-
-
-class SpeechEvent(Success):
- """
- An event representing something somebody said.
-
- @ivar speaker: The Thing which spoke.
- @ivar text: The text which was spoken.
- """
- def __init__(self, speaker, text):
- """
- @type speaker: L{iimaginary.IThing} provider.
- @param speaker: The actor emitting this speech.
- @type text: C{unicode}
- @param text: The text that the actor said.
- """
- self.speaker = speaker
- self.text = text
- Success.__init__(
- self,
- location=speaker.location,
- actor=speaker,
- actorMessage=["You say, '", text, "'"],
- otherMessage=language.Sentence([speaker, " says, '", text, "'"]))
=== removed file 'Imaginary/imaginary/garments.py'
--- Imaginary/imaginary/garments.py 2011-09-16 18:52:54 +0000
+++ Imaginary/imaginary/garments.py 1970-01-01 00:00:00 +0000
@@ -1,370 +0,0 @@
-# -*- test-case-name: imaginary.test.test_garments -*-
-
-"""
-
-Layered clothing.
-
-"""
-
-from zope.interface import implements
-
-from axiom import item, attributes
-
-from imaginary import iimaginary, language, objects
-from imaginary.eimaginary import ActionFailure
-from imaginary.events import ThatDoesntWork
-from imaginary.idea import Link
-from imaginary.creation import createCreator
-from imaginary.enhancement import Enhancement
-
-
-class Unwearable(Exception):
- pass
-
-class TooBulky(Unwearable):
- def __init__(self, wornGarment, newGarment):
- self.wornGarment = wornGarment
- self.newGarment = newGarment
- Unwearable.__init__(self, wornGarment, newGarment)
-
-
-
-class InaccessibleGarment(Exception):
- """The garment is covered by another, therefore it cannot be removed.
- """
- def __init__(self, wearer, garment, obscuringGarment):
- self.wearer = wearer
- self.garment = garment
- self.obscuringGarment = obscuringGarment
-
-
- def __str__(self):
- return "%s tried taking off %s which was covered by %s" % (
- self.wearer, self.garment, self.obscuringGarment)
-
-
-
-GARMENT_SLOTS = [
- u"crown",
- u"left eye",
- u"right eye",
- u"left ear",
- u"right ear",
-
- u"neck",
- u"chest",
- u"back",
-
- u"left arm",
- u"right arm",
- u"left wrist",
- u"right wrist",
- u"left hand",
- u"right hand",
- u"left fingers",
- u"right fingers",
-
- u"waist",
- u"left leg",
- u"right leg",
- u"left ankle",
- u"right ankle",
- u"left foot",
- u"right foot"
- ]
-
-class GarmentSlot:
- pass
-
-for gslot in GARMENT_SLOTS:
- gslotname = gslot.upper().replace(" ", "_").encode('ascii')
- setattr(GarmentSlot, gslotname, gslot)
-
-
-
-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 conceptualize(self):
- 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."]))
-
-
-
-def _orderTopClothingByGlobalSlotList(tempClothes):
- """
- This function orders a dict as returned by getGarmentDict in the order that
- they should be shown to the user.
-
- @param tempClothes: {clothingSlot: list of clothing objects (top last)}
- @type tempClothes: dict
- """
- if not tempClothes:
- return None
- yetDescribed = []
- for universalSlot in GARMENT_SLOTS:
- slotlist = tempClothes.pop(universalSlot, ())
- if slotlist:
- topGarment = slotlist[-1]
- if topGarment not in yetDescribed:
- yetDescribed.append(topGarment)
-
- # if somebody decided to make a wacky slot that is not in the universal
- # slots list, just describe it last.
- for k in tempClothes.keys():
- x = tempClothes.pop(k)
- if x:
- topGarment = x[-1]
- if topGarment not in yetDescribed:
- yetDescribed.append(topGarment)
-
- assert tempClothes == {}, (
- "tempClothes not empty after all clothes eliminated: " +
- repr(tempClothes))
-
- return yetDescribed
-
-
-
-class Wearer(item.Item, Enhancement):
- """
- The clothing-wearing component of an object that can wear clothing; e.g. a
- person or mannequin.
- """
-
- _interfaces = (iimaginary.IClothingWearer,
- iimaginary.IDescriptionContributor,
- iimaginary.ILinkContributor,
- iimaginary.ILinkAnnotator,
- )
-
- implements(*_interfaces)
-
- powerupInterfaces = _interfaces
-
-
- thing = attributes.reference()
-
-
- def getGarmentDict(self):
- c = {}
- for garment in self.store.query(Garment, Garment.wearer == self,
- sort=Garment.wearLevel.ascending):
- for usedSlot in garment.garmentSlots:
- c.setdefault(usedSlot, []).append(garment)
- return c
-
-
- def putOn(self, newGarment):
- """
- Wear a new L{Garment} on this L{Wearer}, first moving it to this
- L{Wearer}'s C{thing} if it is not already there.
-
- @param newGarment: the article of clothing to wear.
-
- @type newGarment: L{Garment}
-
- @raise TooBulky: if the bulk of any of the slots occupied by
- C{newGarment} is greater than the bulk of any other clothing
- already in that slot. (For example, if you tried to wear a T-shirt
- over a heavy coat.)
- """
- c = self.getGarmentDict()
- for garmentSlot in newGarment.garmentSlots:
- if garmentSlot in c:
- currentTopOfSlot = c[garmentSlot][-1]
- if currentTopOfSlot.bulk >= newGarment.bulk:
- raise TooBulky(currentTopOfSlot, newGarment)
-
- newGarment.thing.moveTo(self.thing)
- newGarment.nowWornBy(self)
-
-
- def takeOff(self, garment):
- """
- Remove a garment which this player is wearing.
-
- (Note: no error checking is currently performed to see if this garment
- is actually already worn by this L{Wearer}.)
-
- @param garment: the article of clothing to remove.
-
- @type garment: L{Garment}
-
- @raise InaccessibleGarment: if the garment is obscured by any other
- clothing, and is therefore not in the top slot for any of the slots
- it occupies. For example, if you put on an undershirt, then a
- turtleneck, you can't remove the undershirt without removing the
- turtleneck first.
- """
- gdict = self.getGarmentDict()
- for slot in garment.garmentSlots:
- if gdict[slot][-1] is not garment:
- raise InaccessibleGarment(self, garment, gdict[slot][-1])
- garment.noLongerWorn()
-
-
- # IDescriptionContributor
- def conceptualize(self):
- """
- Describe the list of clothing.
- """
- return ExpressClothing(self.thing, self.getGarmentDict())
-
-
- # ILinkContributor
- def links(self):
- for garmentThing in self.store.query(objects.Thing,
- attributes.AND(
- Garment.thing == objects.Thing.storeID,
- Garment.wearer == self)):
- yield Link(self.thing.idea, garmentThing.idea)
-
-
- # ILinkAnnotator
- def annotationsFor(self, link, idea):
- """
- Tell the containment system to disregard containment relationships for
- which I will generate a link.
- """
- if list(link.of(iimaginary.IContainmentRelationship)):
- if link.source.delegate is self.thing:
- clothing = iimaginary.IClothing(link.target.delegate, None)
- if clothing is not None:
- if clothing.wearer is self:
- yield _DisregardYourWearingIt()
-
-
-
-class _DisregardYourWearingIt(object):
- """
- This is an annotation, produced by L{Wearer} for containment relationships
- between people (who are containers) and the clothing that they're wearing.
- A hopefully temporary workaround for the fact that clothing is rendered in
- its own way and therefor shouldn't show up in the list of a person's
- contents.
- """
- implements(iimaginary.IElectromagneticMedium)
-
- def isOpaque(self):
- """
- I am opaque, so that clothing will show up only once (in your "wearing"
- list, rather than there and in your "contained" list), and obscured
- clothing won't show up at all.
- """
- return True
-
-
-
-class ExpressClothing(language.BaseExpress):
- def __init__(self, thing, garments):
- self.thing = thing
- self.garments = garments
-
-
- def vt102(self, observer):
- heshe = language.Noun(self.thing).heShe()
- L = _orderTopClothingByGlobalSlotList(self.garments)
- if L is None:
- return language.Sentence([heshe, u' is naked.']).vt102(observer)
- return language.Sentence([
- heshe,
- u' is wearing ',
- language.ItemizedList([language.Noun(g.thing).nounPhrase()
- for g in L]),
- u'.']).vt102(observer)
-
-
-
-createShirt = createCreator(
- (Garment, dict(garmentDescription=u'an undescribed shirt',
- bulk=2,
- garmentSlots=[GarmentSlot.CHEST,
- GarmentSlot.BACK,
- GarmentSlot.RIGHT_ARM,
- GarmentSlot.LEFT_ARM])))
-
-
-createUnderwear = createCreator(
- (Garment, dict(garmentDescription=u'an undescribed pair of underwear',
- bulk=1,
- garmentSlots=[GarmentSlot.WAIST])))
-
-createPants = createCreator(
- (Garment, dict(garmentDescription=u'an undescribed pair of pants',
- bulk=2,
- garmentSlots=[GarmentSlot.RIGHT_LEG,
- GarmentSlot.LEFT_LEG,
- GarmentSlot.WAIST,
- GarmentSlot.LEFT_ANKLE,
- GarmentSlot.RIGHT_ANKLE])))
=== removed file 'Imaginary/imaginary/idea.py'
--- Imaginary/imaginary/idea.py 2010-04-24 18:00:14 +0000
+++ Imaginary/imaginary/idea.py 1970-01-01 00:00:00 +0000
@@ -1,625 +0,0 @@
-# -*- test-case-name: imaginary -*-
-
-"""
-This module implements a highly abstract graph-traversal system for actions and
-events to locate the objects which can respond to them. The top-level
-entry-point to this system is L{Idea.obtain}.
-
-It also implements several basic retrievers related to visibility and physical
-reachability.
-"""
-
-from zope.interface import implements
-from epsilon.structlike import record
-
-from imaginary.iimaginary import (
- INameable, ILitLink, IThing, IObstruction, IElectromagneticMedium,
- IDistance, IRetriever, IExit)
-
-
-
-class Link(record("source target")):
- """
- A L{Link} is a connection between two L{Idea}s in a L{Path}.
-
- @ivar source: the idea that this L{Link} originated from.
- @type source: L{Idea}
-
- @ivar target: the idea that this L{Link} refers to.
- @type target: L{Idea}
- """
-
- def __init__(self, *a, **k):
- super(Link, self).__init__(*a, **k)
- self.annotations = []
-
-
- def annotate(self, annotations):
- """
- Annotate this link with a list of annotations.
- """
- self.annotations.extend(annotations)
-
-
- def of(self, interface):
- """
- Yield all annotations on this link which provide the given interface.
- """
- for annotation in self.annotations:
- provider = interface(annotation, None)
- if provider is not None:
- yield provider
-
-
-
-class Path(record('links')):
- """
- A list of L{Link}s.
- """
-
- def of(self, interface):
- """
- @return: an iterator of providers of interfaces, adapted from each link
- in this path.
- """
- for link in self.links:
- for annotation in link.of(interface):
- yield annotation
-
-
- def eachTargetAs(self, interface):
- """
- @return: an iterable of all non-None results of each L{Link.targetAs}
- method in this L{Path}'s C{links} attribute.
- """
- for link in self.links:
- provider = interface(link.target.delegate, None)
- if provider is not None:
- yield provider
-
-
- def targetAs(self, interface):
- """
- Retrieve the target of the last link of this path, its final
- destination, as a given interface.
-
- @param interface: the interface to retrieve.
- @type interface: L{zope.interface.interfaces.IInterface}
-
- @return: the last link's target, adapted to the given interface, or
- C{None} if no appropriate adapter or component exists.
- @rtype: C{interface} or C{NoneType}
- """
- return interface(self.links[-1].target.delegate, None)
-
-
- def isCyclic(self):
- """
- Determine if this path is cyclic, to avoid descending down infinite
- loops.
-
- @return: a boolean indicating whether this L{Path} is cyclic or not,
- i.e. whether the L{Idea} its last link points at is the source of
- any of its links.
- """
- if len(self.links) < 2:
- return False
- return (self.links[-1].target in (x.source for x in self.links))
-
-
- def to(self, link):
- """
- Create a new path, extending this one by one new link.
- """
- return Path(self.links + [link])
-
-
- def __repr__(self):
- """
- @return: an expanded pretty-printed representation of this Path,
- suitable for debugging.
- """
- s = 'Path('
- for link in self.links:
- dlgt = link.target.delegate
- src = link.source.delegate
- s += "\n\t"
- s += repr(getattr(src, 'name', src))
- s += " => "
- s += repr(getattr(dlgt, 'name', dlgt))
- s += " "
- s += repr(link.annotations)
- s += ')'
- return s
-
-
-
-class Idea(record("delegate linkers annotators")):
- """
- Consider a person's activities with the world around them as having two
- layers. One is a physical layer, out in the world, composed of matter and
- energy. The other is a cognitive layer, internal to the person, composed
- of ideas about that matter and energy.
-
- For example, when a person wants to sit in a wooden chair, they must first
- visually locate the arrangement of wood in question, make the determination
- of that it is a "chair" based on its properties, and then perform the
- appropriate actions to sit upon it.
-
- However, a person may also interact with symbolic abstractions rather than
- physical objects. They may read a word, or point at a window on a computer
- screen. An L{Idea} is a representation of the common unit that can be
- referred to in this way.
-
- Both physical and cognitive layers are present in Imaginary. The cognitive
- layer is modeled by L{imaginary.idea}. The physical layer is modeled by a
- rudimentary point-of-interest simulation in L{imaginary.objects}. An
- L{imaginary.thing.Thing} is a physical object; an L{Idea} is a node in a
- non-physical graph, related by links that are annotated to describe the
- nature of the relationship between it and other L{Idea}s.
-
- L{Idea} is the most abstract unit of simulation. It does not have any
- behavior or simulation semantics of its own; it merely ties together
- different related systems.
-
- An L{Idea} is composed of a C{delegate}, which is an object that implements
- simulation-defined interfaces; a list of L{ILinkContributor}s, which
- produce L{Link}s to other L{Idea}s, an a set of C{ILinkAnnotator}s, which
- apply annotations (which themselves implement simulation-defined
- link-annotation interfaces) to those links.
-
- Each L{imaginary.thing.Thing} has a corresponding L{Idea} to represent it
- in the simulation. The physical simulation defines only a few types of
- links: objects have links to their containers, containers have links to
- their contents, rooms have links to their exits, exits have links to their
- destinations. Any L{imaginary.thing.Thing} can have a powerup applied to
- it which adds to the list of linkers or annotators for its L{Idea},
- however, which allows users to create arbitrary objects.
-
- For example, the target of the "look" action must implement
- L{imaginary.iimaginary.IVisible}, but need not be a
- L{iimaginary.objects.Thing}. A simulation might want to provide a piece of
- graffiti that you could look at, but would not be a physical object, in the
- sense that you couldn't pick it up, weigh it, push it, etc. Such an object
- could be implemented as a powerup for both
- L{imaginary.iimaginary.IDescriptionContributor}, which would impart some
- short flavor text to the room, and L{imaginary.iimaginary.IVisible}, which
- would be an acceptable target of 'look'. The
- L{imaginary.iimaginary.IVisible} implementation could even be an in-memory
- object, not stored in the database at all; and there could be different
- implementations for different observers, depending on their level of
- knowledge about the in-world graffiti.
-
- @ivar delegate: this object is the object which may be adaptable to a set
- of interfaces. This L{Idea} delegates all adaptation to its delegate.
- In many cases (when referring to a physical object), this will be an
- L{imaginary.thing.Thing}, but not necessarily.
-
- @ivar linkers: a L{list} of L{ILinkContributor}s which are used to gather
- L{Link}s from this L{Idea} during L{Idea.obtain} traversal.
-
- @ivar annotators: a L{list} of L{ILinkAnnotator}s which are used to annotate
- L{Link}s gathered from this L{Idea} via the C{linkers} list.
- """
-
- def __init__(self, delegate):
- super(Idea, self).__init__(delegate, [], [])
-
-
- def _allLinks(self):
- """
- Return an iterator of all L{Links} away from this idea.
- """
- for linker in self.linkers:
- for link in linker.links():
- yield link
-
-
- def _applyAnnotators(self, linkiter):
- """
- Apply my list of annotators to each link in the given iterable.
- """
- for link in linkiter:
- self._annotateOneLink(link)
- yield link
-
-
- def _annotateOneLink(self, link):
- """
- Apply all L{ILinkAnnotator}s in this L{Idea}'s C{annotators} list.
- """
- allAnnotations = []
- for annotator in self.annotators:
- # XXX important to test: annotators shouldn't mutate the links.
- # The annotators show up in a non-deterministic order, so in order
- # to facilitate a consistent view of the link in annotationsFor(),
- # all annotations are applied at the end.
- allAnnotations.extend(annotator.annotationsFor(link, self))
- link.annotate(allAnnotations)
-
-
- def obtain(self, retriever):
- """
- Traverse the graph of L{Idea}s, starting with C{self}, looking for
- objects which the given L{IRetriever} can retrieve.
-
- The graph will be traversed by looking at all the links generated by
- this L{Idea}'s C{linkers}, only continuing down those links for which
- the given L{IRetriever}'s C{shouldKeepGoing} returns L{True}.
-
- @param retriever: an object which will be passed each L{Path} in turn,
- discovered during traversal of the L{Idea} graph. If any
- invocation of L{IRetriever.retrieve} on this parameter should
- succeed, that will be yielded as a result from this method.
- @type retriever: L{IRetriever}
-
- @return: a generator which yields the results of C{retriever.retrieve}
- which are not L{None}.
- """
- return ObtainResult(self, retriever)
-
-
- def _doObtain(self, retriever, path, reasonsWhyNot):
- """
- A generator that implements the logic for obtain()
- """
- if path is None:
- # Special case: we only get a self->self link if we are the
- # beginning _and_ the end.
- path = Path([])
- selfLink = Link(self, self)
- self._annotateOneLink(selfLink)
- finalPath = path.to(selfLink)
- else:
- finalPath = Path(path.links[:])
- self._annotateOneLink(finalPath.links[-1])
-
- result = retriever.retrieve(finalPath)
- objections = set(retriever.objectionsTo(finalPath, result))
- reasonsWhyNot |= objections
- if result is not None:
- if not objections:
- yield result
-
- for link in self._applyAnnotators(self._allLinks()):
- subpath = path.to(link)
- if subpath.isCyclic():
- continue
- if retriever.shouldKeepGoing(subpath):
- for obtained in link.target._doObtain(retriever, subpath, reasonsWhyNot):
- yield obtained
-
-
-
-class ObtainResult(record("idea retriever")):
- """
- The result of L{Idea.obtain}, this provides an iterable of results.
-
- @ivar reasonsWhyNot: If this iterator has already been exhausted, this will
- be a C{set} of L{IWhyNot} objects explaining possible reasons why there
- were no results. For example, if the room where the player attempted
- to obtain targets is dark, this may contain an L{IWhyNot} provider.
- However, until this iterator has been exhausted, it will be C{None}.
- @type reasonsWhyNot: C{set} of L{IWhyNot}, or C{NoneType}
-
- @ivar idea: the L{Idea} that L{Idea.obtain} was invoked on.
- @type idea: L{Idea}
-
- @ivar retriever: The L{IRetriever} that L{Idea.obtain} was invoked with.
- @type retriever: L{IRetriever}
- """
-
- reasonsWhyNot = None
-
- def __iter__(self):
- """
- A generator which yields each result of the query, then sets
- C{reasonsWhyNot}.
- """
- reasonsWhyNot = set()
- for result in self.idea._doObtain(self.retriever, None, reasonsWhyNot):
- yield result
- self.reasonsWhyNot = reasonsWhyNot
-
-
-
-class DelegatingRetriever(object):
- """
- A delegating retriever, so that retrievers can be easily composed.
-
- See the various methods marked for overriding.
-
- @ivar retriever: A retriever to delegate most operations to.
- @type retriever: L{IRetriever}
- """
-
- implements(IRetriever)
-
- def __init__(self, retriever):
- """
- Create a delegator with a retriever to delegate to.
- """
- self.retriever = retriever
-
-
- def moreObjectionsTo(self, path, result):
- """
- Override in subclasses to yield objections to add to this
- L{DelegatingRetriever}'s C{retriever}'s C{objectionsTo}.
-
- By default, offer no additional objections.
- """
- return []
-
-
- def objectionsTo(self, path, result):
- """
- Concatenate C{self.moreObjectionsTo} with C{self.moreObjectionsTo}.
- """
- for objection in self.retriever.objectionsTo(path, result):
- yield objection
- for objection in self.moreObjectionsTo(path, result):
- yield objection
-
-
- def shouldStillKeepGoing(self, path):
- """
- Override in subclasses to halt traversal via a C{False} return value for
- C{shouldKeepGoing} if this L{DelegatingRetriever}'s C{retriever}'s
- C{shouldKeepGoing} returns C{True}.
-
- By default, return C{True} to keep going.
- """
- return True
-
-
- def shouldKeepGoing(self, path):
- """
- If this L{DelegatingRetriever}'s C{retriever}'s C{shouldKeepGoing}
- returns C{False} for the given path, return C{False} and stop
- traversing. Otherwise, delegate to C{shouldStillKeepGoing}.
- """
- return (self.retriever.shouldKeepGoing(path) and
- self.shouldStillKeepGoing(path))
-
-
- def resultRetrieved(self, path, retrievedResult):
- """
- A result was retrieved. Post-process it if desired.
-
- Override this in subclasses to modify (non-None) results returned from
- this L{DelegatingRetriever}'s C{retriever}'s C{retrieve} method.
-
- By default, simply return the result retrieved.
- """
- return retrievedResult
-
-
- def retrieve(self, path):
- """
- Delegate to this L{DelegatingRetriever}'s C{retriever}'s C{retrieve}
- method, then post-process it with C{resultRetrieved}.
- """
- subResult = self.retriever.retrieve(path)
- if subResult is None:
- return None
- return self.resultRetrieved(path, subResult)
-
-
-
-class Proximity(DelegatingRetriever):
- """
- L{Proximity} is a retriever which will continue traversing any path which
- is shorter than its proscribed distance, but not any longer.
-
- @ivar distance: the distance, in meters, to query for.
-
- @type distance: L{float}
- """
-
- def __init__(self, distance, retriever):
- DelegatingRetriever.__init__(self, retriever)
- self.distance = distance
-
-
- def shouldStillKeepGoing(self, path):
- """
- Implement L{IRetriever.shouldKeepGoing} to stop for paths whose sum of
- L{IDistance} annotations is greater than L{Proximity.distance}.
- """
- dist = sum(vector.distance for vector in path.of(IDistance))
- ok = (self.distance >= dist)
- return ok
-
-
-
-class Reachable(DelegatingRetriever):
- """
- L{Reachable} is a navivator which will object to any path with an
- L{IObstruction} annotation on it.
- """
-
- def moreObjectionsTo(self, path, result):
- """
- Yield an objection from each L{IObstruction.whyNot} method annotating
- the given path.
- """
- if result is not None:
- for obstruction in path.of(IObstruction):
- yield obstruction.whyNot()
-
-
-
-class Traversability(DelegatingRetriever):
- """
- A path is only traversible if it terminates in *one* exit. Once you've
- gotten to an exit, you have to stop, because the player needs to go through
- that exit to get to the next one.
- """
-
- def shouldStillKeepGoing(self, path):
- """
- Stop at the first exit that you find.
- """
- for index, target in enumerate(path.eachTargetAs(IExit)):
- if index > 0:
- return False
- return True
-
-
-
-class Vector(record('distance direction')):
- """
- A L{Vector} is a link annotation which remembers a distance and a
- direction; for example, a link through a 'north' exit between rooms will
- have a direction of 'north' and a distance specified by that
- L{imaginary.objects.Exit} (defaulting to 1 meter).
- """
-
- implements(IDistance)
-
-
-
-class ProviderOf(record("interface")):
- """
- L{ProviderOf} is a retriever which will retrieve the facet which provides
- its C{interface}, if any exists at the terminus of the path.
-
- @ivar interface: The interface which defines the type of values returned by
- the C{retrieve} method.
- @type interface: L{zope.interface.interfaces.IInterface}
- """
-
- implements(IRetriever)
-
- def retrieve(self, path):
- """
- Retrieve the target of the path, as it provides the interface specified
- by this L{ProviderOf}.
-
- @return: the target of the path, adapted to this retriever's interface,
- as defined by L{Path.targetAs}.
-
- @rtype: L{ProviderOf.interface}
- """
- return path.targetAs(self.interface)
-
-
- def objectionsTo(self, path, result):
- """
- Implement L{IRetriever.objectionsTo} to yield no objections.
- """
- return []
-
-
- def shouldKeepGoing(self, path):
- """
- Implement L{IRetriever.shouldKeepGoing} to always return C{True}.
- """
- return True
-
-
-
-class AlsoKnownAs(record('name')):
- """
- L{AlsoKnownAs} is an annotation that indicates that the link it annotates
- is known as a particular name.
-
- @ivar name: The name that this L{AlsoKnownAs}'s link's target is also known
- as.
- @type name: C{unicode}
- """
-
- implements(INameable)
-
- def knownTo(self, observer, name):
- """
- An L{AlsoKnownAs} is known to all observers as its C{name} attribute.
- """
- return (self.name == name)
-
-
-
-class Named(DelegatingRetriever):
- """
- A retriever which wraps another retriever, but yields only results known to
- a particular observer by a particular name.
-
- @ivar name: the name to search for.
-
- @ivar observer: the observer who should identify the target by the name
- this L{Named} is searching for.
- @type observer: L{Thing}
- """
-
- def __init__(self, name, retriever, observer):
- DelegatingRetriever.__init__(self, retriever)
- self.name = name
- self.observer = observer
-
-
- def resultRetrieved(self, path, subResult):
- """
- Invoke C{retrieve} on the L{IRetriever} which we wrap, but only return
- it if the L{INameable} target of the given path is known as this
- L{Named}'s C{name}.
- """
- named = path.targetAs(INameable)
- allAliases = list(path.links[-1].of(INameable))
- if named is not None:
- allAliases += [named]
- for alias in allAliases:
- if alias.knownTo(self.observer, self.name):
- return subResult
- return None
-
-
-
-class CanSee(DelegatingRetriever):
- """
- Wrap a L{ProviderOf}, yielding the results that it would yield, but
- applying lighting to the ultimate target based on the last L{IThing} the
- path.
-
- @ivar retriever: The lowest-level retriever being wrapped.
-
- @type retriever: L{ProviderOf} (Note: it might be a good idea to add an
- 'interface' attribute to L{IRetriever} so this no longer depends on a
- more specific type than other L{DelegatingRetriever}s, to make the
- order of composition more flexible.)
- """
-
- def resultRetrieved(self, path, subResult):
- """
- Post-process retrieved results by determining if lighting applies to
- them.
- """
- litlinks = list(path.of(ILitLink))
- if not litlinks:
- return subResult
- # XXX what if there aren't any IThings on the path?
- litThing = list(path.eachTargetAs(IThing))[-1]
- # you need to be able to look from a light room to a dark room, so only
- # apply the most "recent" lighting properties.
- return litlinks[-1].applyLighting(
- litThing, subResult, self.retriever.interface)
-
-
- def shouldStillKeepGoing(self, path):
- """
- Don't keep going through links that are opaque to the observer.
- """
- for opacity in path.of(IElectromagneticMedium):
- if opacity.isOpaque():
- return False
- return True
-
-
- def moreObjectionsTo(self, path, result):
- """
- Object to paths which have L{ILitLink} annotations which are not lit.
- """
- for lighting in path.of(ILitLink):
- if not lighting.isItLit(path, result):
- tmwn = lighting.whyNotLit()
- yield tmwn
=== removed file 'Imaginary/imaginary/iimaginary.py'
--- Imaginary/imaginary/iimaginary.py 2013-08-23 09:41:28 +0000
+++ Imaginary/imaginary/iimaginary.py 1970-01-01 00:00:00 +0000
@@ -1,707 +0,0 @@
-# -*- test-case-name: imaginary -*-
-
-
-from zope.interface import Interface, Attribute
-
-
-
-class IThingType(Interface):
- """
- Plugin interface for kinds of objects which can be created in the realm.
- """
- type = Attribute("Name of this type of object.")
-
- def getType():
- """
- Return a two-argument callable which will be invoked with C{name},
- C{description} to create a new instance of this type. Should return an
- L{IThing} provider.
- """
-
-
-class ILinkContributor(Interface):
- """
- A powerup interface which can add more connections between objects in the
- world graph.
-
- All L{ILinkContributors} which are powered up on a particular
- L{imaginary.objects.Thing} will be appended to that
- L{imaginary.objects.Thing}'s value.
- """
-
- def links():
- """
- @return: an iterable of L{imaginary.idea.Link}s.
- """
-
-
-
-class IDescriptionContributor(Interface):
- """
- A powerup interface which can add text to the description of an object.
-
- All IDescriptionContributors which are powered up on a particular Object
- will be given a chance to add to the output of its C{conceptualize} method.
- """
-
- def conceptualize():
- """
- Return an IConcept provider.
- """
-
-
-class INameable(Interface):
- """
- A provider of L{INameable} is an object which can be identified by an
- imaginary actor by a name.
- """
-
- def knownTo(observer, name):
- """
- Is this L{INameable} known to the given C{observer} by the given
- C{name}?
-
- @param name: the name to test for
-
- @type name: L{unicode}
-
- @param observer: the thing which is observing this namable.
-
- @type observer: L{IThing}
-
- @rtype: L{bool}
-
- @return: L{True} if C{name} identifies this L{INameable}, L{False}
- otherwise.
- """
-
-
-class ILitLink(Interface):
- """
- This interface is an annotation interface for L{imaginary.idea.Link}
- objects, for indicating that the link can apply lighting.
- """
-
- def applyLighting(litThing, eventualTarget, requestedInterface):
- """
- Apply a transformation to an object that an
- L{imaginary.idea.Idea.obtain} is requesting, based on the light level
- of this link and its surroundings.
-
- @param litThing: The L{IThing} to apply lighting to.
-
- @type litThing: L{IThing}
-
- @param eventualTarget: The eventual, ultimate target of the path in
- question.
-
- @type eventualTarget: C{requestedInterface}
-
- @param requestedInterface: The interface requested by the query that
- resulted in this path; this is the interface which
- C{eventualTarget} should implement.
-
- @type requestedInterface: L{Interface}
-
- @return: C{eventualTarget}, or, if this L{ILitLink} knows how to deal
- with lighting specifically for C{requestedInterface}, a modified
- version thereof which still implements C{requestedInterface}. If
- insufficient lighting results in the player being unable to access
- the desired object at all, C{None} will be returned.
-
- @rtype: C{NoneType}, or C{requestedInterface}
- """
-
-
-
-
-class IThing(Interface):
- """
- A thing in the world. It has a location and and might be relocateable.
- """
- location = Attribute("An IThing which contains this IThing")
-
- proper = Attribute(
- "A boolean indicating the definiteness of this thing's pronoun.")
-
- name = Attribute(
- "A unicode string, the name of this Thing.")
-
-
- def moveTo(where, arrivalEventFactory=None):
- """
- Change this things location to the new location, if possible.
-
- @type where: L{IThing} provider.
- @param where: The new location to be moved to.
-
- @type arrivalEventFactory: A callable which takes a single
- argument, the thing being moved, and returns an event.
- @param arrivalEventFactory: Will be called to produce the
- event to be broadcast to the new location upon arrival of this
- thing. If not specified (or None), no event will be broadcast.
- """
-
- def findProviders(interface, distance):
- """
- Retrieve all game objects which provide C{interface} within C{distance}.
-
- @return: A generator of providers of C{interface}.
- """
-
-
-
-class IMovementRestriction(Interface):
- """
- A L{MovementRestriction} is a powerup that can respond to a L{Thing}'s
- movement before it occurs, and thereby restrict it.
-
- Powerups of this type are consulted on L{Thing} before movement is allowed
- to complete.
- """
-
- def movementImminent(movee, destination):
- """
- An object is about to move. Implementations can raise an exception if
- they wish to to prevent it.
-
- @param movee: the object that is moving.
-
- @type movee: L{Thing}
-
- @param destination: The L{Thing} of the container that C{movee} will be
- moving to.
-
- @type destination: L{IThing}
-
- @raise Exception: if the movement is to be prevented.
- """
-
-
-
-class IActor(Interface):
- hitpoints = Attribute("L{Points} instance representing hit points")
- experience = Attribute("C{int} representing experience")
- level = Attribute("C{int} representing player's level")
- thing = Attribute("L{IThing} which represents the actor's physical body.")
-
- def send(event):
- """Describe something to the actor.
-
- @type event: L{IConcept} provider
- @param event: Something that will be described to the actor.
- """
-
-
- def getIntelligence():
- """
- Return the current intelligence associated with this actor, be it
- ephemeral or enduring.
-
- @rtype: L{IEventObserver}.
- """
-
-
- def setEphemeralIntelligence(intelligence):
- """
- Set the intelligence for this actor to an ephemeral L{IEventObserver}.
-
- @type intelligence: L{IEventObserver} provider.
- """
-
-
- def setEnduringIntelligence(intelligence):
- """
- Set the intelligence for this actor to a persistent L{IEventObserver}.
-
- @type intelligence: L{IEventObserver} provider.
- """
-
-
-
-class IManipulator(Interface):
- """
- An L{IManipulator} provider is an actor who can perform direct
- manipulations of a world's environment (or at least, try to).
- """
-
- def setIllumination(candelas):
- """
- Attempt to set the ambient illumination this L{IManipulator}'s
- location.
-
- @param candelas: the desired ambient illumination value of the location
- in candelas.
-
- @type candelas: L{int}
-
- @return: The previous ambient light level (in candelas)
-
- @raise imaginary.eimaginary.ActionFailure: if the action cannot be
- completed (for example, if this L{IManipulator} doesn't have
- permission to change the lighting in its location).
- """
-
-
-
-class IEventObserver(Interface):
- def prepare(concept):
- """
- Capture the given concept in a callable which will describe something
- to this observer.
-
- The callable will be invoked when it is entirely certain that the
- concept is congruent with game reality. For example, a concept for an
- arrow striking its target might be prepared but the resulting callable
- will not be invoked until the combat game system decides the arrow
- really is striking its target.
-
- This two-phase process is also used to deal with events occurring
- during transactions. While the event will be prepared immediately
- during the execution of an action, the callable resulting from the
- preparation will not be invoked until the transaction has completed.
- If the transaction fails with an exception, then the callables will not
- be invoked.
-
- @type concept: L{IConcept} provider
- @param concept: Something that will be described to the actor.
-
- @return: a 0-argument callable which will deliver the given concept to
- this observer.
- """
-
-
-
-class ITransactionalEventBroadcaster(Interface):
- """
- A thing which mediates the deadly side-effects of event broadcast by
- holding things back until a transaction has been successfully committed or
- is being reverted.
- """
- def addEvent(event):
- """
- Add an event which will be broadcast when the transaction is committed
- successfully.
- """
-
-
- def addRevertEvent(event):
- """
- Add an event which will be broadcast when the transaction is reverted.
- """
-
-
-
-class IExit(Interface):
- """
- An interface representing one direction that a player may move in. While
- L{IExit} only represents one half of a passageway, it is not necessarily
- one-way; in most cases, a parallel exit will exist on the other side.
- (However, it I{may} be one-way; there is no guarantee that you will be able
- to traverse it backwards, or even indeed that it will take you somewhere at
- all!)
- """
-
- name = Attribute(
- """
- The name of this exit. This must be something adaptable to
- L{IConcept}, to display to players.
- """)
-
- def traverse(thing):
- """
- Attempt to move the given L{IThing} through this L{IExit} to the other
- side. (Note that this may not necessarily result in actual movement,
- if the exit does something tricky like disorienting you or hurting
- you.)
-
- @param thing: Something which is passing through this exit.
-
- @type thing: L{IThing}
- """
-
-
-
-
-class IObstruction(Interface):
- """
- An L{IObstruction} is a link annotation indicating that there is a physical
- obstruction preventing solid objects from reaching between the two ends of
- the link. For example, a closed door might annotate its link to its
- destination with an L{IObstruction}.
- """
-
- def whyNot():
- """
- @return: a reason why this is obstructed.
-
- @rtype: L{IWhyNot}
- """
-
-
-
-class IContainer(Interface):
- """
- An object which can contain other objects.
- """
- capacity = Attribute(
- """
- The maximum weight this container is capable of holding.
- """)
-
- closed = Attribute(
- """
- A boolean indicating whether this container is closed.
- """)
-
-
- def add(object):
- """
- Place the given object into this container.
-
- @type object: L{IThing}
- @param object: The world object to be added to this container. Its
- C{location} attribute will be updated if it is successfully added.
-
- @raise DoesntFit: If there is no room for C{object} in this container.
- @raise Closed: If this container is not currently open.
- """
-
-
- def remove(object):
- """
- Remove the given object from this container.
-
- @type object: L{IThing}
-
- @param object: The world object which is currently in this container
- which is to be removed. If it is successfully removed, its C{location}
- attribute will be set to C{None}.
-
- @raise ValueError: If C{object} is not within this container.
- @raise Closed: If this container is not currently open.
- """
-
-
- def contains(other):
- """
- @returns: True if other is in me. And by 'in', I mean 'IN'! (And
- by 'IN' he means to any arbitrarily deeply nested distance)
- """
-
-
- def getContents():
- """
- @returns: An iterable of the direct contents of this container.
- """
-
-
- def getExits():
- """
- @return: an L{axiom.store.ItemQuery} of the exits leading out of this
- container.
- """
-
-
- def getExitNames():
- """
- @return: an L{axiom.store.AttributeQuery} of the names of the exits
- leading out of this container.
- """
-
-
- def getExitNamed(name, default=None):
- """
- @return: The L{imaginary.objects.Exit} with the given name, or default
- if none is found.
-
- @raise KeyError: When an exit with the given name is not found and no
- default was passed.
- """
-
-
-
-class IConcept(Interface):
- """
- This represents a concept which can be expressed in English.
- """
-
- def plaintext(observer):
- """
- @param observer: the IThing provider who is asking to learn about this
- concept, or None. This comes from the argument to 'express'.
- """
-
-
- def capitalizeConcept():
- """
- Make this concept CAPITALISERD!
-
- Oh man this is retarded.
-
- XXX fix it or something pleeeeeeeaaaaaaaaaasssssssssseeeeeeeeee
- deletedeletedletedletledeltetledleltellxceltedlelt
- """
-
-
-
-class ILinkAnnotator(Interface):
- """
- An L{ILinkAnnotator} provides annotations for links from one
- L{imaginary.idea.Idea} to another.
- """
-
- def annotationsFor(link, idea):
- """
- Produce an iterator of annotations to be applied to a link whose source
- or target is the L{Idea} that this L{ILinkAnnotator} has been applied
- to.
- """
-
-
-
-class ILocationLinkAnnotator(Interface):
- """
- L{ILocationLinkAnnotator} is a powerup interface to allow powerups for a
- L{Thing} to act as L{ILinkAnnotator}s for every L{Thing} contained within
- it. This allows area-effect link annotators to be implemented simply,
- without needing to monitor movement.
- """
-
- def annotationsFor(link, idea):
- """
- Produce an iterator of annotations to be applied to a link whose source
- or target is an L{Idea} of a L{Thing} contained in the L{Thing} that
- this L{ILocationLinkAnnotator} has been applied to.
- """
-
-
-
-class IRetriever(Interface):
- """
- An L{IRetriever} examines a L{Path} and retrieves a desirable object from
- it to yield from L{Idea.obtain}, if the L{Path} is suitable.
-
- Every L{IRetriever} has a different definition of suitability; you should
- examine some of their implementations for more detail.
- """
-
- def retrieve(path):
- """
- Return the suitable object described by C{path}, or None if the path is
- unsuitable for this retriever's purposes.
- """
-
- def shouldKeepGoing(path):
- """
- Inspect a L{Path}. True if it should be searched, False if not.
- """
-
-
- def objectionsTo(path, result):
- """
- @return: an iterator of IWhyNot, if you object to this result being
- yielded.
- """
-
-
-
-class IContainmentRelationship(Interface):
- """
- Indicate the containment of one idea within another, via a link.
-
- This is an annotation interface, used to annotate L{iimaginary.idea.Link}s
- to specify that the relationship between linked objects is one of
- containment. In other words, the presence of an
- L{IContainmentRelationship} annotation on a L{iimaginary.idea.Link}
- indicates that the target of that link is contained by the source of that
- link.
- """
-
- containedBy = Attribute(
- """
- A reference to the L{IContainer} which contains the target of the link
- that this L{IContainmentRelationship} annotates.
- """)
-
-
-
-class IVisible(Interface):
- """
- A thing which can be seen.
- """
-
- def visualize():
- """
- Return an IConcept which represents the visible aspects of this
- visible thing.
- """
-
-
- def isViewOf(thing):
- """
- Is this L{IVisible} a view of a given L{Thing}?
-
- @rtype: L{bool}
- """
-
-
-
-
-class ILightSource(Interface):
- """
- Powerup interface for things which emit photons in measurable quantities.
- """
- candelas = Attribute("""
- The luminous intensity in candelas.
-
- See U{http://en.wikipedia.org/wiki/Candela}.
- """)
-
-
-
-####### Below here is new, experimental stuff, which doesn't really work yet.
-
-
-class IThingPowerUp(Interface):
- """
- Utility super-interface of all interfaces which are designed to be used as
- arguments to powerUp for Thing.
-
- Objects which provide this interface must also provide IItem, obviously, as
- only Items can be Powerups.
- """
-
-
-class IClothingWearer(IThingPowerUp):
- """
- A person who can wear clothing.
- """
-
- def putOn(garment):
- """
- Put on an article of clothing.
-
- @param garment: An article of clothing.
- @type garment: L{IClothing} provider
-
- @raise: L{TooBulky}, if the new article of clothing will not fit
- because this wearer is already wearing a bulkier article of clothing in
- that slot.
- """
-
-
- def takeOff(garment):
- """
- Remove an article of clothing.
-
- @param garment: An article of clothing that this wearer is wearing.
-
- @raise: L{InaccessibleGarment}: if the article of clothing is either
- not being worn, or is being worn beneath another article of clothing
- which must be removed first.
- """
-
-
-
-class IClothing(IThingPowerUp):
- """
- A piece of clothing which can be worn by an L{IClothingWearer}.
- """
-
- garmentSlots = Attribute(
- """
- A list of unicode strings that describe the parts of the body where
- this article of clothing can be worn, taken from the list of constants
- in L{imaginary.garments.GARMENT_SLOTS}.
- """)
-
- bulk = Attribute(
- """
- An integer, 1 or greater, abstractly describing how thick this garment
- is. A bulkier garment cannot be worn over a less bulky one.
- """)
-
-
- def nowWornBy(wearer):
- """
- This article of clothing is now being worn by C{wearer}.
-
- @param wearer: The wearer of the clothing.
-
- @type wearer: L{IClothingWearer}
- """
-
-
- def noLongerWorn():
- """
- This article of clothing is no longer being worn.
- """
-
-
-
-class ISittable(Interface):
- """
- Something you can sit on.
- """
-
- def seat(sitterThing):
- """
- @param sitterThing: The person sitting down on this sittable surface.
-
- @type sitterThing: L{imaginary.objects.Thing}
- """
-
-
-
-class IDescriptor(IThingPowerUp):
- """
- I provide a portion of a Thing's description.
-
- Install IDescribable powerUps on Thing to influence how it will be shown to
- the user.
- """
-
- def conceptualize():
- """
- Return an object adaptable to the IConcept for the language of an
- observer.
- """
-
-
-class IWhyNot(Interface):
- """
- This interface is an idea link annotation interface, designed to be applied
- by L{ILinkAnnotator}s, that indicates a reason why a given path cannot
- yield a provider. This is respected by L{imaginary.idea.ProviderOf}.
- """
-
- def tellMeWhyNot():
- """
- Return something adaptable to L{IConcept}, that explains why this link
- is unsuitable for producing results. For example, the string "It's too
- dark in here."
- """
-
-
-
-class IDistance(Interface):
- """
- A link annotation that provides a distance.
- """
-
- distance = Attribute("floating point, distance in meters")
-
-
-
-class IElectromagneticMedium(Interface):
- """
- A medium through which electromagnetic radiation may or may not pass; used
- as a link annotation.
- """
-
- def isOpaque():
- """
- Will this propagate radiation the visible spectrum?
- """
-
=== removed file 'Imaginary/imaginary/iterutils.py'
--- Imaginary/imaginary/iterutils.py 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/iterutils.py 1970-01-01 00:00:00 +0000
@@ -1,15 +0,0 @@
-
-"""Utilities for dealing with iterators and such.
-"""
-
-def interlace(x, i):
- """interlace(x, i) -> i0, x, i1, x, ..., x, iN
- """
- i = iter(i)
- try:
- yield i.next()
- except StopIteration:
- return
- for e in i:
- yield x
- yield e
=== removed file 'Imaginary/imaginary/language.py'
--- Imaginary/imaginary/language.py 2013-07-24 22:10:49 +0000
+++ Imaginary/imaginary/language.py 1970-01-01 00:00:00 +0000
@@ -1,389 +0,0 @@
-# -*- test-case-name: imaginary.test.test_concept -*-
-
-"""
-
-Textual formatting for game objects.
-
-"""
-import types
-from string import Formatter
-
-from zope.interface import implements, implementer
-
-from twisted.python.components import registerAdapter
-
-from epsilon import structlike
-
-from imaginary import iimaginary, iterutils, text as T
-
-
-class Gender(object):
- """
- enum!
- """
- MALE = 1
- FEMALE = 2
- NEUTER = 3
-
-
-
-class Noun(object):
- """
- This is a language wrapper around a Thing.
-
- It is separated into its own class for two reasons:
-
- - You should try to keep your game-logic self-contained and avoid
- polluting it with lots of constant strings, so that porting to new
- interfaces (text prototype -> isometric final implementation) is easy.
- It's easier to read the code that way and make changes to the logic even
- if you don't want to move to a different interface.
-
-
- - It would be nice if text games could be internationalized by separating
- the formatting logic from the game logic. In an extreme case, it would
- be SUPER-COOL if people could be playing the same game in french and
- english on the same server, simply by changing a setting on their
- client.
- """
-
-
- def __init__(self, thing):
- self.thing = thing
-
-
- def shortName(self):
- return ExpressString(self.thing.name)
-
-
- def nounPhrase(self):
- if self.thing.proper:
- return self.shortName()
- return ExpressList([self.indefiniteArticle(), self.shortName()])
-
-
- def definiteNounPhrase(self):
- if self.thing.proper:
- return self.shortName()
- return ExpressList([self.definiteArticle(), self.shortName()])
-
-
- def indefiniteArticle(self):
- # XXX TODO FIXME: YTTRIUM
- if self.thing.name[0].lower() in u'aeiou':
- return u'an '
- return u'a '
-
-
- def definiteArticle(self):
- return u'the '
-
-
- def heShe(self):
- """
- Return the personal pronoun for the wrapped thing.
- """
- x = {Gender.MALE: u'he',
- Gender.FEMALE: u'she'
- }.get(self.thing.gender, u'it')
- return ExpressString(x)
-
-
- def himHer(self):
- """
- Return the objective pronoun for the wrapped thing.
- """
- x = {Gender.MALE: u'him',
- Gender.FEMALE: u'her'
- }.get(self.thing.gender, u'it')
- return ExpressString(x)
-
-
- def hisHer(self):
- """
- Return a possessive pronoun that cannot be used after 'is'.
- """
- x = {Gender.MALE: u'his',
- Gender.FEMALE: u'her' # <-- OMG! hers!
- }.get(self.thing.gender, u'its')
- return ExpressString(x)
-
-
- #FIXME: add his/hers LATER
-
-
-
-def flattenWithoutColors(vt102):
- return T.flatten(vt102, useColors=False)
-
-
-@implementer(iimaginary.IConcept)
-class BaseExpress(object):
-
- def __init__(self, original):
- self.original = original
-
-
- def plaintext(self, observer):
- return flattenWithoutColors(self.vt102(observer))
-
-
-
-class DescriptionConcept(structlike.record('name description exits others',
- description=u"", exits=(), others=())):
- """
- A concept which is expressed as the description of a Thing as well as
- any concepts which power up that thing for IDescriptionContributor.
-
- Concepts will be ordered by the C{preferredOrder} class attribute.
- Concepts not named in this list will appear last in an unpredictable
- order.
-
- @ivar name: The name of the thing being described.
-
- @ivar description: A basic description of the thing being described, the
- first thing to show up.
-
- @ivar exits: An iterable of L{IExit}, to be listed as exits in the
- description.
-
- @ivar others: An iterable of L{IDescriptionContributor} that will
- supplement the description.
- """
- implements(iimaginary.IConcept)
-
- # This may not be the most awesome solution to the ordering problem, but
- # it is the best I can think of right now. This is strictly a
- # user-interface level problem. Only the ordering in the string output
- # send to the user should depend on this; nothing in the world should be
- # affected.
- preferredOrder = ['ExpressCondition',
- 'ExpressClothing',
- 'ExpressSurroundings',
- ]
-
- def plaintext(self, observer):
- return flattenWithoutColors(self.vt102(observer))
-
-
- def vt102(self, observer):
- exits = u''
- if self.exits:
- exits = [T.bold, T.fg.green, u'( ',
- [T.fg.normal, T.fg.yellow,
- iterutils.interlace(u' ',
- (exit.name for exit in self.exits))],
- u' )', u'\n']
-
- description = self.description or u""
- if description:
- description = (T.fg.green, self.description, u'\n')
-
- descriptionConcepts = []
-
- for pup in self.others:
- descriptionConcepts.append(pup.conceptualize())
-
- def index(c):
- try:
- return self.preferredOrder.index(c.__class__.__name__)
- except ValueError:
- # Anything unrecognized goes after anything recognized.
- return len(self.preferredOrder)
-
- descriptionConcepts.sort(key=index)
-
- descriptionComponents = []
- for c in descriptionConcepts:
- s = c.vt102(observer)
- if s:
- descriptionComponents.extend([s, u'\n'])
-
- if descriptionComponents:
- descriptionComponents.pop()
-
- return [
- [T.bold, T.fg.green, u'[ ', [T.fg.normal, self.name], u' ]\n'],
- exits,
- description,
- descriptionComponents]
-
-
-
-class ExpressNumber(BaseExpress):
- implements(iimaginary.IConcept)
-
- def vt102(self, observer):
- return str(self.original)
-
-
-
-class ExpressString(BaseExpress):
- implements(iimaginary.IConcept)
-
- def __init__(self, original, capitalized=False):
- self.original = original
- self._cap = capitalized
-
-
- def vt102(self, observer):
- if self._cap:
- return self.original[:1].upper() + self.original[1:]
- return self.original
-
-
- def capitalizeConcept(self):
- return ExpressString(self.original, True)
-
-
-
-class ExpressList(BaseExpress):
- implements(iimaginary.IConcept)
-
- def concepts(self, observer):
- return map(iimaginary.IConcept, self.original)
-
- def vt102(self, observer):
- return [x.vt102(observer) for x in self.concepts(observer)]
-
- def capitalizeConcept(self):
- return Sentence(self.original)
-
-
-
-
-class Sentence(ExpressList):
- def vt102(self, observer):
- o = self.concepts(observer)
- if o:
- o[0] = o[0].capitalizeConcept()
- return [x.vt102(observer) for x in o]
-
-
- def capitalizeConcept(self):
- return self
-
-
-
-registerAdapter(ExpressNumber, int, iimaginary.IConcept)
-registerAdapter(ExpressNumber, long, iimaginary.IConcept)
-registerAdapter(ExpressString, str, iimaginary.IConcept)
-registerAdapter(ExpressString, unicode, iimaginary.IConcept)
-registerAdapter(ExpressList, list, iimaginary.IConcept)
-registerAdapter(ExpressList, tuple, iimaginary.IConcept)
-registerAdapter(ExpressList, types.GeneratorType, iimaginary.IConcept)
-
-
-class ItemizedList(BaseExpress):
- implements(iimaginary.IConcept)
-
- def __init__(self, listOfConcepts):
- self.listOfConcepts = listOfConcepts
-
-
- def concepts(self, observer):
- return self.listOfConcepts
-
-
- def vt102(self, observer):
- return ExpressList(
- itemizedStringList(self.concepts(observer))).vt102(observer)
-
-
- def capitalizeConcept(self):
- listOfConcepts = self.listOfConcepts[:]
- if listOfConcepts:
- listOfConcepts[0] = iimaginary.IConcept(listOfConcepts[0]).capitalizeConcept()
- return ItemizedList(listOfConcepts)
-
-
-
-def itemizedStringList(desc):
- if len(desc) == 1:
- yield desc[0]
- elif len(desc) == 2:
- yield desc[0]
- yield u' and '
- yield desc[1]
- elif len(desc) > 2:
- for ele in desc[:-1]:
- yield ele
- yield u', '
- yield u'and '
- yield desc[-1]
-
-
-
-class ConceptTemplate(object):
- """
- A L{ConceptTemplate} wraps a text template which may intersperse literal
- strings with markers for substitution.
-
- Substitution markers follow U{the syntax for str.format<http://docs.python.org/2/library/string.html#format-string-syntax>}.
-
- Values for field names are supplied to the L{expand} method.
- """
- def __init__(self, templateText):
- """
- @param templateText: The text of the template. For example,
- C{u"Hello, {target:name}."}.
- @type templateText: L{unicode}
- """
- self.templateText = templateText
-
-
- def expand(self, values):
- """
- Generate concepts based on the template.
-
- @param values: A L{dict} mapping substitution markers to application
- objects from which to take values for those substitutions. For
- example, a key might be C{u"target"}. The associated value will be
- sustituted each place C{u"{target}"} appears in the template
- string. Or, the value's name will be substituted each place
- C{u"{target:name}"} appears in the template string.
- @type values: L{dict} mapping L{unicode} to L{object}
-
- @return: An iterator the combined elements of which represent the
- result of expansion of the template. The elements are adaptable to
- L{IConcept}.
- """
- parts = Formatter().parse(self.templateText)
- for (literalText, fieldName, formatSpec, conversion) in parts:
- if literalText:
- yield ExpressString(literalText)
- if fieldName:
- try:
- target = values[fieldName.lower()]
- except KeyError:
- extra = u""
- if formatSpec:
- extra = u" '%s'" % (formatSpec,)
- yield u"<missing target '%s' for%s expansion>" % (
- fieldName, extra)
- else:
- if formatSpec:
- # A nice enhancement would be to delegate this logic to target
- try:
- expander = getattr(self, '_expand_' + formatSpec.upper())
- except AttributeError:
- yield u"<'%s' unsupported by target '%s'>" % (
- formatSpec, fieldName)
- else:
- yield expander(target)
- else:
- yield target
-
-
- def _expand_NAME(self, target):
- """
- Get the name of a L{Thing}.
- """
- return target.name
-
-
- def _expand_PRONOUN(self, target):
- """
- Get the personal pronoun of a L{Thing}.
- """
- return Noun(target).heShe()
=== removed file 'Imaginary/imaginary/manipulation.py'
--- Imaginary/imaginary/manipulation.py 2009-01-14 05:21:23 +0000
+++ Imaginary/imaginary/manipulation.py 1970-01-01 00:00:00 +0000
@@ -1,82 +0,0 @@
-# Copyright 2009 Divmod, Inc. See LICENSE for details
-# -*- test-case-name: imaginary.test.test_illumination -*-
-"""
-This module contains code that administrators can invoke to directly manipulate
-Things.
-
-@see: L{imaginary.iimaginary.IManipulator}, the interface which this module
- provides implementations of.
-"""
-
-from zope.interface import implements
-
-from twisted.python.components import registerAdapter
-
-from epsilon.structlike import record
-
-from axiom.item import Item
-from axiom.attributes import reference
-
-from imaginary.iimaginary import IManipulator, IThing
-from imaginary.objects import LocationLighting, Thing
-
-from imaginary.eimaginary import ActionFailure
-from imaginary.events import ThatDoesntWork
-
-
-
-class NonManipulator(record("thing")):
- """
- A L{NonManipulator} is the ephemeral actor, implementing the responses that
- normal users will see when they attempt to perform administrative actions.
- """
-
- implements(IManipulator)
-
- def setIllumination(self, candelas):
- """
- Don't actually set the illumination of the manipulator.
- """
- raise ActionFailure(ThatDoesntWork(
- actor=self.thing,
- actorMessage=
- "You are insufficiently brilliant to do that directly."))
-
-
-registerAdapter(NonManipulator, IThing, IManipulator)
-
-
-
-class Manipulator(Item):
- """
- A L{Manipulator} is the actor for actions which can directly change the
- properties of objects in an Imaginary world.
- """
- implements(IManipulator)
-
- powerupInterfaces = [IManipulator]
-
- thing = reference(allowNone=False,
- doc="""
- The L{IThing} for the underlying actor.
- """,
- reftype=Thing, whenDeleted=reference.CASCADE)
-
- def setIllumination(self, candelas):
- """
- Set the ambient illumination of this L{Manipulator}'s C{thing}'s
- location.
-
- @return: the location's previous ambient illumination in candelas.
- """
- ll = self.thing.store.findOrCreate(
- LocationLighting,
- lambda ll: self.thing.location.powerUp(ll),
- thing=self.thing.location)
- oldCandelas = ll.candelas
- otherMessage = None
- ll.candelas = candelas
- return oldCandelas
-
-
-
=== removed file 'Imaginary/imaginary/objects.py'
--- Imaginary/imaginary/objects.py 2013-08-23 13:42:36 +0000
+++ Imaginary/imaginary/objects.py 1970-01-01 00:00:00 +0000
@@ -1,1288 +0,0 @@
-# -*- test-case-name: imaginary.test.test_objects,imaginary.test.test_actions -*-
-
-"""
-This module contains the core, basic objects in Imaginary.
-
-L{imaginary.objects} contains the physical simulation (L{Thing}), objects
-associated with scoring (L{Points}), and the basic actor interface which allows
-the user to perform simple actions (L{Actor}).
-"""
-
-from __future__ import division
-
-import math
-
-from zope.interface import implements
-
-from twisted.python import reflect, components
-
-from epsilon import structlike
-from epsilon.remember import remembered
-
-from axiom import item, attributes
-
-from imaginary import iimaginary, eimaginary, text as T, events, language
-
-from imaginary.enhancement import Enhancement as _Enhancement
-
-from imaginary.idea import (
- Idea, Link, Proximity, Reachable, ProviderOf, Named, AlsoKnownAs, CanSee,
- Vector, DelegatingRetriever)
-
-
-class Points(item.Item):
- max = attributes.integer(doc="""
- Maximum number of points.
- """, allowNone=False)
-
- current = attributes.integer(doc="""
- Current number of points.
- """, allowNone=False)
-
- def __init__(self, **kw):
- if 'max' in kw and 'current' not in kw:
- kw['current'] = kw['max']
- super(Points, self).__init__(**kw)
-
- def __cmp__(self, other):
- return cmp(self.current, other)
-
- def __str__(self):
- return '%d/%d' % (self.current, self.max)
-
- def __repr__(self):
- d = {'class': reflect.qual(self.__class__),
- 'current': self.current,
- 'max': self.max}
- return '%(class)s(%(max)d, %(current)d)' % d
-
- def increase(self, amount):
- return self.modify(amount)
-
- def decrease(self, amount):
- return self.modify(-amount)
-
- def modify(self, amount):
- self.current = max(min(self.current + amount, self.max), 0)
- return self.current
-
-
-
-class Thing(item.Item):
- """
- A L{Thing} is a physically located object in the game world.
-
- While a game object in Imaginary is composed of many different Python
- objects, the L{Thing} is the central object that most game objects will
- share. It's central for several reasons.
-
- First, a L{Thing} is connected to the point-of-interest simulation that
- makes up the environment of an Imaginary game. A L{Thing} has a location,
- and a L{Container} can list the L{Thing}s located within it, which is how
- you can see the objects in your surroundings or a container.
-
- Each L{Thing} has an associated L{Idea}, which provides the graph that can
- be traversed to find other L{Thing}s to be the target for actions or
- events.
-
- A L{Thing} is also the object which serves as the persistent nexus of
- powerups that define behavior. An L{_Enhancement} is a powerup for a
- L{Thing}. L{Thing}s can be powered up for a number of different interfaces:
-
- - L{iimaginary.IMovementRestriction}, for preventing the L{Thing} from
- moving around,
-
- - L{iimaginary.ILinkContributor}, which can provide links from the
- L{Thing}'s L{Idea} to other L{Idea}s,
-
- - L{iimaginary.ILinkAnnotator}, which can provide annotations on links
- incoming to or outgoing from the L{Thing}'s L{Idea},
-
- - L{iimaginary.ILocationLinkAnnotator}, which can provide annotations on
- links to or from any L{Thing}'s L{Idea} which is ultimately located
- within the powered-up L{Thing}.
-
- - L{iimaginary.IDescriptionContributor}, which provide components of
- the L{Thing}'s description when viewed with the L{Look} action.
-
- - and finally, any interface used as a target for an action or event.
-
- The way this all fits together is as follows: if you wanted to make a
- shirt, for example, you would make a L{Thing}, give it an appropriate name
- and description, make a new L{Enhancement} class which implements
- L{IMovementRestriction} to prevent the shirt from moving around unless it
- is correctly in the un-worn state, and then power up that L{Enhancement} on
- the L{Thing}. This particular example is implemented in
- L{imaginary.garments}, but almost any game-logic implementation will follow
- this general pattern.
- """
-
- implements(iimaginary.IThing, iimaginary.IVisible, iimaginary.INameable,
- iimaginary.ILinkAnnotator, iimaginary.ILinkContributor)
-
- 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):
- """
- Implement L{ILinkContributor.links()} by offering a link to this
- L{Thing}'s C{location} (if it has one).
- """
- # since my link contribution is to go up (out), put this last, since
- # containment (i.e. going down (in)) is a powerup. we want to explore
- # contained items first.
- for pup in self.powerupsFor(iimaginary.ILinkContributor):
- for link in pup.links():
- # wooo composition
- yield link
- if self.location is not None:
- l = Link(self.idea, self.location.idea)
- # XXX this incorrectly identifies any container with an object in
- # it as 'here', since it doesn't distinguish the observer; however,
- # cycle detection will prevent these links from being considered in
- # any case I can think of. However, 'here' is ambiguous in the
- # case where you are present inside a container, and that should
- # probably be dealt with.
- l.annotate([AlsoKnownAs('here')])
- yield l
-
-
- def allAnnotators(self):
- """
- A generator which yields all L{iimaginary.ILinkAnnotator} providers
- that should affect this L{Thing}'s L{Idea}. This includes:
-
- - all L{iimaginary.ILocationLinkAnnotator} powerups on all
- L{Thing}s which contain this L{Thing} (the container it's in, the
- room its container is in, etc)
-
- - all L{iimaginary.ILinkAnnotator} powerups on this L{Thing}.
- """
- loc = self
- while loc is not None:
- # TODO Test the loc is None case
- if loc is not None:
- for pup in loc.powerupsFor(iimaginary.ILocationLinkAnnotator):
- yield pup
- loc = loc.location
- for pup in self.powerupsFor(iimaginary.ILinkAnnotator):
- yield pup
-
-
- def annotationsFor(self, link, idea):
- """
- Implement L{ILinkAnnotator.annotationsFor} to consult each
- L{ILinkAnnotator} for this L{Thing}, as defined by
- L{Thing.allAnnotators}, and yield each annotation for the given L{Link}
- and L{Idea}.
- """
- for annotator in self.allAnnotators():
- for annotation in annotator.annotationsFor(link, idea):
- yield annotation
-
-
- @remembered
- def idea(self):
- """
- An L{Idea} which represents this L{Thing}.
- """
- idea = Idea(self)
- idea.linkers.append(self)
- idea.annotators.append(self)
- return idea
-
-
- def findProviders(self, interface, distance):
- """
- Temporary emulation of the old way of doing things so that I can
- surgically replace findProviders.
- """
- return self.idea.obtain(
- Proximity(distance, CanSee(ProviderOf(interface))))
-
-
- def obtainOrReportWhyNot(self, retriever):
- """
- Invoke L{Idea.obtain} on C{self.idea} with the given C{retriever}.
-
- If no results are yielded, then investigate the reasons why no results
- have been yielded, and raise an exception describing one of them.
-
- Objections may be registered by:
-
- - an L{iimaginary.IWhyNot} annotation on any link traversed in the
- attempt to discover results, or,
-
- - an L{iimaginary.IWhyNot} yielded by the given C{retriever}'s
- L{iimaginary.IRetriever.objectionsTo} method.
-
- @return: a list of objects returned by C{retriever.retrieve}
-
- @rtype: C{list}
-
- @raise eimaginary.ActionFailure: if no results are available, and an
- objection has been registered.
- """
- obt = self.idea.obtain(retriever)
- results = list(obt)
- if not results:
- reasons = list(obt.reasonsWhyNot)
- if reasons:
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=self,
- actorMessage=reasons[0].tellMeWhyNot()))
- return results
-
-
- 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.
-
- @param distance: How many steps to traverse (note: this is wrong, it
- will become a real distance-y thing with real game-meaning
- someday).
- @type distance: C{float}
-
- @param interface: The interface which objects within the required range
- must be adaptable to in order to be returned.
-
- @param name: The name of the stuff.
- @type name: C{str}
-
- @return: An iterable of L{iimaginary.IThing} providers which are found.
- """
- return self.obtainOrReportWhyNot(
- Proximity(
- distance,
- Reachable(Named(name, CanSee(ProviderOf(interface)), self))))
-
-
- def moveTo(self, where, arrivalEventFactory=None):
- """
- Implement L{iimaginary.IThing.moveTo} to change the C{location} of this
- L{Thing} to a new L{Thing}, broadcasting an L{events.DepartureEvent} to
- note this object's departure from its current C{location}.
-
- Before moving it, invoke each L{IMovementRestriction} powerup on this
- L{Thing} to allow them to prevent this movement.
- """
- whereContainer = iimaginary.IContainer(where, None)
- if (whereContainer is
- iimaginary.IContainer(self.location, None)):
- # Early out if I'm being moved to the same location that I was
- # already in.
- return
- if whereContainer is None:
- whereThing = None
- else:
- whereThing = whereContainer.thing
- if whereThing is not None and whereThing.location is self:
- # XXX should be checked against _all_ locations of whereThing, not
- # just the proximate one.
-
- # XXX actor= here is wrong, who knows who is moving this thing.
- raise eimaginary.ActionFailure(events.ThatDoesntWork(
- actor=self,
- actorMessage=[
- language.Noun(where.thing).definiteNounPhrase()
- .capitalizeConcept(),
- " won't fit inside itself."]))
-
- oldLocation = self.location
- for restriction in self.powerupsFor(iimaginary.IMovementRestriction):
- restriction.movementImminent(self, where)
- 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 knownTo(self, observer, name):
- """
- Implement L{INameable.knownTo} to compare the name to L{Thing.name} as
- well as few constant values based on the relationship of the observer
- to this L{Thing}, such as 'me', 'self', and 'here'.
-
- @param observer: an L{IThing} provider.
- """
-
- mine = self.name.lower()
- name = name.lower()
- if name == mine or name in mine.split():
- return True
- if observer == self:
- if name in ('me', 'self'):
- return True
- return False
-
-
- # IVisible
- def visualize(self):
- """
- Implement L{IVisible.visualize} to return a
- L{language.DescriptionConcept} that describes this L{Thing}, including
- all its L{iimaginary.IDescriptionContributor} powerups.
- """
- container = iimaginary.IContainer(self, None)
- if container is not None:
- exits = list(container.getExits())
- else:
- exits = ()
-
- return language.DescriptionConcept(
- self.name,
- self.description,
- exits,
- # Maybe we should listify this or something; see
- # http://divmod.org/trac/ticket/2905
- self.powerupsFor(iimaginary.IDescriptionContributor))
-
-
- def isViewOf(self, thing):
- """
- Implement L{IVisible.isViewOf} to return C{True} if its argument is
- C{self}. In other words, this L{Thing} is only a view of itself.
- """
- return (thing is self)
-
-components.registerAdapter(lambda thing: language.Noun(thing).nounPhrase(),
- Thing,
- iimaginary.IConcept)
-
-
-def _eventuallyContains(containerThing, containeeThing):
- """
- Does a container, or any containers within it (or any containers within any
- of those, etc etc) contain some object?
-
- @param containeeThing: The L{Thing} which may be contained.
-
- @param containerThing: The L{Thing} which may have a L{Container} that
- contains C{containeeThing}.
-
- @return: L{True} if the containee is contained by the container.
- """
- while containeeThing is not None:
- if containeeThing is containerThing:
- return True
- containeeThing = containeeThing.location
- return False
-
-
-
-
-OPPOSITE_DIRECTIONS = {
- u"north": u"south",
- u"west": u"east",
- u"northwest": u"southeast",
- u"northeast": u"southwest"}
-
-
-def _populateOpposite():
- """
- Populate L{OPPOSITE_DIRECTIONS} with inverse directions.
-
- (Without leaking any loop locals into the global scope, thank you very
- much.)
- """
- for (k, v) in OPPOSITE_DIRECTIONS.items():
- OPPOSITE_DIRECTIONS[v] = k
-
-_populateOpposite()
-
-
-
-DIRECTION_ALIASES = {
- u"n": u"north",
- u"s": u"south",
- u"w": u"west",
- u"e": u"east",
- u"nw": u"northwest",
- u"se": u"southeast",
- u"ne": u"northeast",
- u"sw": u"southwest"}
-
-
-
-class Exit(item.Item):
- """
- An L{Exit} is an oriented pathway between two L{Thing}s which each
- represent a room.
- """
-
- implements(iimaginary.INameable, iimaginary.IExit)
-
- fromLocation = attributes.reference(
- doc="""
- Where this exit leads from.
- """, allowNone=False,
- whenDeleted=attributes.reference.CASCADE, reftype=Thing)
-
- toLocation = attributes.reference(
- doc="""
- Where this exit leads to.
- """, allowNone=False,
- whenDeleted=attributes.reference.CASCADE, reftype=Thing)
-
- name = attributes.text(doc="""
- What this exit is called/which direction it is in.
- """, allowNone=False)
-
- sibling = attributes.reference(doc="""
- The reverse exit object, if one exists.
- """)
-
- distance = attributes.ieee754_double(
- doc="""
- How far, in meters, does a user have to travel to traverse this exit?
- """, allowNone=False, default=1.0)
-
- def knownTo(self, observer, name):
- """
- Implement L{iimaginary.INameable.knownTo} to identify this L{Exit} as
- its C{name} attribute.
- """
- return name == self.name
-
-
- def traverse(self, thing):
- """
- Implement L{iimaginary.IExit} to move the given L{Thing} to this
- L{Exit}'s C{toLocation}.
- """
- if self.sibling is not None:
- arriveDirection = self.sibling.name
- else:
- arriveDirection = OPPOSITE_DIRECTIONS.get(self.name)
-
- thing.moveTo(
- self.toLocation,
- arrivalEventFactory=lambda player: events.MovementArrivalEvent(
- thing=thing,
- origin=None,
- direction=arriveDirection))
-
-
- # XXX This really needs to be renamed now that links are a thing.
- @classmethod
- def link(cls, a, b, forwardName, backwardName=None, distance=1.0):
- """
- Create two L{Exit}s connecting two rooms.
-
- @param a: The first room.
-
- @type a: L{Thing}
-
- @param b: The second room.
-
- @type b: L{Thing}
-
- @param forwardName: The name of the link going from C{a} to C{b}. For
- example, u'east'.
-
- @type forwardName: L{unicode}
-
- @param backwardName: the name of the link going from C{b} to C{a}. For
- example, u'west'. If not provided or L{None}, this will be
- computed based on L{OPPOSITE_DIRECTIONS}.
-
- @type backwardName: L{unicode}
- """
- if backwardName is None:
- backwardName = OPPOSITE_DIRECTIONS[forwardName]
- forward = cls(store=a.store, fromLocation=a, toLocation=b,
- name=forwardName, distance=distance)
- backward = cls(store=b.store, fromLocation=b, toLocation=a,
- name=backwardName, distance=distance)
- forward.sibling = backward
- backward.sibling = forward
-
-
- def destroy(self):
- if self.sibling is not None:
- self.sibling.deleteFromStore()
- self.deleteFromStore()
-
-
- @remembered
- def exitIdea(self):
- """
- This property is the L{Idea} representing this L{Exit}; this is a
- fairly simple L{Idea} that will link only to the L{Exit.toLocation}
- pointed to by this L{Exit}, with a distance annotation indicating the
- distance traversed to go through this L{Exit}.
- """
- x = Idea(self)
- x.linkers.append(self)
- return x
-
-
- def links(self):
- """
- Generate a link to the location that this exit points at.
-
- @return: an iterator which yields a single L{Link}, annotated with a
- L{Vector} that indicates a distance of 1.0 (a temporary measure,
- since L{Exit}s don't have distances yet) and a direction of this
- exit's C{name}.
- """
- l = Link(self.exitIdea, self.toLocation.idea)
- l.annotate([Vector(self.distance, self.name),
- # We annotate this link with ourselves because the 'Named'
- # retriever will use the last link in the path to determine
- # if an object has any aliases. We want this direction
- # name to be an alias for the room itself as well as the
- # exit, so we want to annotate the link with an INameable.
- # This also has an effect of annotating the link with an
- # IExit, and possibly one day an IItem as well (if such a
- # thing ever comes to exist), so perhaps we eventually want
- # a wrapper which elides all references here except
- # INameable since that's what we want. proxyForInterface
- # perhaps? However, for the moment, the extra annotations
- # do no harm, so we'll leave them there.
- self])
- yield l
-
-
- def conceptualize(self):
- return language.ExpressList(
- [u'the exit to ', language.Noun(self.toLocation).nounPhrase()])
-
-components.registerAdapter(lambda exit: exit.conceptualize(),
- Exit, iimaginary.IConcept)
-
-
-
-class ContainmentRelationship(structlike.record("containedBy")):
- """
- Implementation of L{iimaginary.IContainmentRelationship}. The interface
- specifies no methods or attributes. See its documentation for more
- information.
- """
- implements(iimaginary.IContainmentRelationship)
-
-
-
-class Containment(object):
- """
- Functionality for containment to be used as a mixin in Powerups.
- """
-
- implements(iimaginary.IContainer, iimaginary.IDescriptionContributor,
- iimaginary.ILinkContributor)
- powerupInterfaces = (iimaginary.IContainer,
- iimaginary.ILinkContributor,
- iimaginary.IDescriptionContributor)
-
- # Units of weight which can be contained
- capacity = None
-
- # Boolean indicating whether the container is currently closed or open.
- closed = False
-
- # IContainer
- def contains(self, other):
- for child in self.getContents():
- if other is child:
- return True
- cchild = iimaginary.IContainer(child, None)
- if cchild is not None and cchild.contains(other):
- return True
- return False
-
-
- def getContents(self):
- if self.thing is None:
- return []
- return self.store.query(Thing, Thing.location == self.thing)
-
-
- def add(self, obj):
- if self.closed:
- raise eimaginary.Closed(self, obj)
- containedWeight = self.getContents().getColumn("weight").sum()
- if containedWeight + obj.weight > self.capacity:
- raise eimaginary.DoesntFit(self, obj)
- assert self.thing is not None
- obj.location = self.thing
-
-
- def remove(self, obj):
- if self.closed:
- raise eimaginary.Closed(self, obj)
- if obj.location is self.thing:
- obj.location = None
-
-
- def getExits(self):
- return self.store.query(Exit, Exit.fromLocation == self.thing)
-
-
- def getExitNames(self):
- return self.getExits().getColumn("name")
-
-
- _marker = object()
- def getExitNamed(self, name, default=_marker):
- result = self.store.findUnique(
- Exit,
- attributes.AND(Exit.fromLocation == self.thing,
- Exit.name == name),
- default=default)
- if result is self._marker:
- raise KeyError(name)
- return result
-
-
- # ILinkContributor
- def links(self):
- """
- Implement L{ILinkContributor} to contribute L{Link}s to all contents of
- this container, as well as all of its exits, and its entrance from its
- location.
- """
- if not self.closed:
- for ob in self.getContents():
- content = Link(self.thing.idea, ob.idea)
- content.annotate([ContainmentRelationship(self)])
- yield content
- yield Link(self.thing.idea, self._entranceIdea)
- yield Link(self.thing.idea, self._exitIdea)
- for exit in self.getExits():
- yield Link(self.thing.idea, exit.exitIdea)
-
-
- @remembered
- def _entranceIdea(self):
- """
- Return an L{Idea} that reflects the implicit entrance from this
- container's location to the interior of the container.
- """
- return Idea(delegate=_ContainerEntrance(self))
-
-
- @remembered
- def _exitIdea(self):
- """
- Return an L{Idea} that reflects the implicit exit from this container
- to its location.
- """
- return Idea(delegate=_ContainerExit(self))
-
-
- # IDescriptionContributor
- def conceptualize(self):
- """
- Implement L{IDescriptionContributor} to enumerate the contents of this
- containment.
-
- @return: an L{ExpressSurroundings} with an iterable of all visible
- contents of this container.
- """
- return ExpressContents(self)
-
-
-
-class _ContainedBy(DelegatingRetriever):
- """
- An L{iimaginary.IRetriever} which discovers only things present in a given
- container. Currently used only for discovering the list of things to list
- in a container's description.
-
- @ivar retriever: a retriever to delegate to.
-
- @type retriever: L{iimaginary.IRetriever}
-
- @ivar container: the container to test containment by
-
- @type container: L{IThing}
- """
-
- implements(iimaginary.IRetriever)
-
- def __init__(self, retriever, container):
- DelegatingRetriever.__init__(self, retriever)
- self.container = container
-
-
- def resultRetrieved(self, path, result):
- """
- If this L{_ContainedBy}'s container contains the last L{IThing} target
- of the given path, return the result of this L{_ContainedBy}'s
- retriever retrieving from the given C{path}, otherwise C{None}.
- """
- containments = list(path.of(iimaginary.IContainmentRelationship))
- if containments:
- if containments[-1].containedBy is self.container:
- return result
-
-
-
-class _ContainerEntrance(structlike.record('container')):
- """
- A L{_ContainerEntrance} is the implicit entrance to a container from its
- location. If a container is open, and big enough, it can be entered.
-
- @ivar container: the container that this L{_ContainerEntrance} points to.
-
- @type container: L{Containment}
- """
-
- implements(iimaginary.IExit, iimaginary.INameable)
-
- @property
- def name(self):
- """
- Implement L{iimaginary.IExit.name} to return a descriptive name for the
- inward exit of this specific container.
- """
- return 'into ', language.Noun(self.container.thing).definiteNounPhrase()
-
-
- def traverse(self, thing):
- """
- Implement L{iimaginary.IExit.traverse} to move the thing in transit to
- the container specified.
- """
- thing.moveTo(self.container)
-
-
- def knownTo(self, observer, name):
- """
- Delegate L{iimaginary.INameable.knownTo} to this
- L{_ContainerEntrance}'s container's thing.
- """
- return self.container.thing.knownTo(observer, name)
-
-
-
-class _ContainerExit(structlike.record('container')):
- """
- A L{_ContainerExit} is the exit from a container, or specifically, a
- L{Containment}; an exit by which actors may move to the container's
- container.
-
- @ivar container: the container that this L{_ContainerExit} points out from.
-
- @type container: L{Containment}
- """
-
- implements(iimaginary.IExit, iimaginary.INameable)
-
- @property
- def name(self):
- """
- Implement L{iimaginary.IExit.name} to return a descriptive name for the
- outward exit of this specific container.
- """
- return 'out of ', language.Noun(self.container.thing).definiteNounPhrase()
-
-
- def traverse(self, thing):
- """
- Implement L{iimaginary.IExit.traverse} to move the thing in transit to
- the container specified.
- """
- thing.moveTo(self.container.thing.location)
-
-
- def knownTo(self, observer, name):
- """
- This L{_ContainerExit} is known to observers inside it as 'out'
- (i.e. 'go out', 'look out'), but otherwise it has no known description.
- """
- return (observer.location == self.container.thing) and (name == 'out')
-
-
-
-class ExpressSurroundings(language.ItemizedList):
- def concepts(self, observer):
- return [iimaginary.IConcept(o)
- for o in super(ExpressSurroundings, self).concepts(observer)
- if o is not observer]
-
-
-
-class Container(item.Item, Containment, _Enhancement):
- """
- A generic L{_Enhancement} that implements containment.
- """
- contentsTemplate = attributes.text(
- doc="""
- Define how the contents of this container are presented to observers.
- Certain substrings will be given special treatment.
-
- @see: L{imaginary.language.ConceptTemplate}
- """,
- allowNone=True, default=None)
-
- capacity = attributes.integer(
- doc="""
- Units of weight which can be contained.
- """, allowNone=False, default=1)
-
- closed = attributes.boolean(
- doc="""
- Indicates whether the container is currently closed or open.
- """, allowNone=False, default=False)
-
- thing = attributes.reference(
- doc="""
- The object this container powers up.
- """)
-
-
-
-class ExpressContents(language.Sentence):
- """
- A concept representing the things contained by another thing - excluding
- the observer of the concept.
- """
- _CONDITION = CanSee(ProviderOf(iimaginary.IThing))
-
- def _contentConcepts(self, observer):
- """
- Get concepts for the contents of the thing wrapped by this concept.
-
- @param observer: The L{objects.Thing} which will observe these
- concepts.
-
- @return: A L{list} of the contents of C{self.original}, excluding
- C{observer}.
- """
- container = self.original
- idea = container.thing.idea
- return [
- concept
- for concept
- in idea.obtain(_ContainedBy(self._CONDITION, container))
- if concept is not observer]
-
-
- @property
- def template(self):
- """
- This is the template string which is used to construct the overall
- concept, indicating what the container is and what its contents are.
- """
- template = self.original.contentsTemplate
- if template is None:
- template = u"{subject:pronoun} contains {contents}."
- return template
-
-
- def expand(self, template, observer):
- """
- Expand the given template using the wrapped container's L{Thing} as the
- subject.
-
- C{u"contents"} is also available for substitution with the contents of
- the container.
-
- @return: An iterator of concepts derived from the given template.
- """
- return language.ConceptTemplate(template).expand(dict(
- subject=self.original.thing,
- contents=language.ItemizedList(self._contentConcepts(observer))))
-
-
- def concepts(self, observer):
- """
- Return a L{list} of L{IConcept} providers which express the contents of
- the wrapped container.
- """
- if self._contentConcepts(observer):
- return list(self.expand(self.template, observer))
- return []
-
-
-
-class ExpressCondition(language.BaseExpress):
- implements(iimaginary.IConcept)
-
- def vt102(self, observer):
- return [
- [T.bold, T.fg.yellow, language.Noun(
- self.original.thing).shortName().plaintext(observer)],
- u" is ",
- [T.bold, T.fg.red, self.original._condition(), u"."]]
-
-
-class Actable(object):
- implements(iimaginary.IActor, iimaginary.IEventObserver)
-
- powerupInterfaces = (iimaginary.IActor, iimaginary.IEventObserver,
- iimaginary.IDescriptionContributor)
-
- # Yay, experience!
- experience = 0
- level = 0
-
- CONDITIONS = (
- 'dead',
- 'dying',
- 'incapacitated',
- 'mortally wounded',
- 'injured',
- 'bleeding',
- 'shaken up',
- 'fine',
- 'chipper',
- 'great')
-
-
- # IDescriptionContributor
- def conceptualize(self):
- return ExpressCondition(self)
-
-
- def _condition(self):
- if self.hitpoints.current == 0:
- return self.CONDITIONS[0]
- ratio = self.hitpoints.current / self.hitpoints.max
- idx = int(ratio * (len(self.CONDITIONS) - 2))
- return self.CONDITIONS[idx + 1]
-
-
- # IActor
- def send(self, *event):
- if len(event) != 1 or isinstance(event[0], (str, tuple)):
- event = events.Success(
- actor=self.thing,
- actorMessage=event)
- else:
- event = event[0]
- self.prepare(event)()
-
-
- # IEventObserver
- def prepare(self, concept):
- """
- Implement L{iimaginary.IEventObserver.prepare} to prepare C{concept}
- with this L{Actable}'s C{intelligence}, if it has one; otherwise,
- return a callable that does nothing.
- """
- intelligence = self.getIntelligence()
- if intelligence is not None:
- return intelligence.prepare(concept)
- return lambda: None
-
-
- def gainExperience(self, amount):
- experience = self.experience + amount
- level = int(math.log(experience) / math.log(2))
- evt = None
- if level > self.level:
- evt = events.Success(
- actor=self.thing,
- actorMessage=("You gain ", level - self.level, " levels!\n"))
- elif level < self.level:
- evt = events.Success(
- actor=self.thing,
- actorMessage=("You lose ", self.level - level, " levels!\n"))
- self.level = level
- self.experience = experience
- if evt is not None:
- self.send(evt)
-
-
-
-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 LocationLighting(item.Item, _Enhancement):
- """
- A L{LocationLighting} is an enhancement for a location which allows the
- location's description and behavior to depend on its lighting. While
- L{LocationLighting} includes its own ambient lighting number, it is not
- really a light source, it's just a location which is I{affected by} light
- sources; for lighting, you should use L{LightSource}.
-
- By default, in Imaginary, rooms are considered by to be lit to an
- acceptable level that actors can see and interact with both the room and
- everything in it without worrying about light. By contrast, any room that
- can be dark needs to have a L{LocationLighting} installed. A room affected
- by a L{LocationLighting} which is lit will behave like a normal room, but a
- room affected by a L{LocationLighting} with no available light sources will
- prevent players from performing actions which require targets that need to
- be seen, and seeing the room's description.
- """
-
- implements(iimaginary.ILocationLinkAnnotator)
- powerupInterfaces = (iimaginary.ILocationLinkAnnotator,)
-
- candelas = attributes.integer(
- doc="""
- The ambient luminous intensity in candelas.
-
- See U{http://en.wikipedia.org/wiki/Candela}.
- """, default=100, allowNone=False)
-
- thing = attributes.reference(
- doc="""
- The location being affected by lighting.
- """,
- reftype=Thing,
- allowNone=False,
- whenDeleted=attributes.reference.CASCADE)
-
- def getCandelas(self):
- """
- Sum the candelas of all light sources within a limited distance from
- the location this is installed on and return the result.
- """
- sum = self.candelas
- for candle in self.thing.idea.obtain(
- Proximity(1, ProviderOf(iimaginary.ILightSource))):
- sum += candle.candelas
- return sum
-
-
- def annotationsFor(self, link, idea):
- """
- Yield a L{_PossiblyDark} annotation for all links pointing to objects
- located in the C{thing} attribute of this L{LocationLighting}.
- """
- if link.target is idea:
- yield _PossiblyDark(self)
-
-
-
-class _DarkLocationProxy(structlike.record('thing')):
- """
- An L{IVisible} implementation for darkened locations.
- """
-
- implements(iimaginary.IVisible)
-
- def visualize(self):
- """
- Return a L{DescriptionConcept} that tells the player they can't see.
- """
- return language.DescriptionConcept(
- u"Blackness",
- u"You cannot see anything because it is very dark.")
-
-
- def isViewOf(self, thing):
- """
- Implement L{IVisible.isViewOf} to delegate to this
- L{_DarkLocationProxy}'s L{Thing}'s L{IVisible.isViewOf}.
-
- In other words, this L{_DarkLocationProxy} C{isViewOf} its C{thing}.
- """
- return self.thing.isViewOf(thing)
-
-
-
-class LightSource(item.Item, _Enhancement):
- """
- A simple implementation of L{ILightSource} which provides a fixed number of
- candelas of luminous intensity, assumed to be emitted uniformly in all
- directions.
- """
-
- implements(iimaginary.ILightSource)
- powerupInterfaces = (iimaginary.ILightSource,)
-
- candelas = attributes.integer(
- doc="""
- The luminous intensity in candelas.
-
- See U{http://en.wikipedia.org/wiki/Candela}.
- """, default=1, allowNone=False)
-
- thing = attributes.reference(
- doc="""
- The physical body emitting the light.
- """,
- reftype=Thing,
- allowNone=False,
- whenDeleted=attributes.reference.CASCADE)
-
-
-
-class _PossiblyDark(structlike.record("lighting")):
- """
- A L{_PossiblyDark} is a link annotation which specifies that the target of
- the link may be affected by lighting.
-
- @ivar lighting: the lighting for a particular location.
-
- @type lighting: L{LocationLighting}
- """
-
- implements(iimaginary.IWhyNot, iimaginary.ILitLink)
-
- def tellMeWhyNot(self):
- """
- Return a helpful message explaining why something may not be accessible
- due to poor lighting.
- """
- return "It's too dark to see."
-
-
- def isItLit(self, path, result):
- """
- Determine if the given result, viewed via the given path, appears to be
- lit.
-
- @return: L{True} if the result should be lit, L{False} if it is dark.
-
- @rtype: C{bool}
- """
- # XXX wrong, we need to examine this exactly the same way applyLighting
- # does. CanSee and Visibility *are* the same object now so it is
- # possible to do.
- if self.lighting.getCandelas():
- return True
- litThing = list(path.eachTargetAs(iimaginary.IThing))[-1]
- if _eventuallyContains(self.lighting.thing, litThing):
- val = litThing is self.lighting.thing
- #print 'checking if', litThing, 'is lit:', val
- return val
- else:
- return True
-
-
- def whyNotLit(self):
- """
- Return an L{iimaginary.IWhyNot} provider explaining why the target of
- this link is not lit. (Return 'self', since L{_PossiblyDark} is an
- L{iimaginary.IWhyNot} provider itself.)
- """
- return self
-
-
- def applyLighting(self, litThing, eventualTarget, requestedInterface):
- """
- Implement L{iimaginary.ILitLink.applyLighting} to return a
- L{_DarkLocationProxy} for the room lit by this
- L{_PossiblyDark.lighting}, C{None} for any items in that room, or
- C{eventualTarget} if the target is in a different place.
- """
- if self.lighting.getCandelas():
- return eventualTarget
- elif (eventualTarget is self.lighting.thing and
- requestedInterface is iimaginary.IVisible):
- return _DarkLocationProxy(self.lighting.thing)
- elif _eventuallyContains(self.lighting.thing, litThing):
- return None
- else:
- return eventualTarget
=== removed directory 'Imaginary/imaginary/plugins'
=== removed file 'Imaginary/imaginary/plugins/__init__.py'
--- Imaginary/imaginary/plugins/__init__.py 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/plugins/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-
-import os, sys
-__path__ = [os.path.abspath(os.path.join(x, *__name__.split('.'))) for x in sys.path]
-
-__all__ = [] # nothing to see here, move along, move along
=== removed file 'Imaginary/imaginary/plugins/clothes.py'
--- Imaginary/imaginary/plugins/clothes.py 2007-08-17 04:46:38 +0000
+++ Imaginary/imaginary/plugins/clothes.py 1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-# -*- test-case-name: imaginary.test.test_garments -*-
-
-from imaginary.creation import CreationPluginHelper
-from imaginary.garments import (createShirt, createPants, createUnderwear)
-
-shirtPlugin = CreationPluginHelper('shirt', createShirt)
-pantsPlugin = CreationPluginHelper('pants', createPants)
-underwearPlugin = CreationPluginHelper('underwear', createUnderwear)
=== removed file 'Imaginary/imaginary/plugins/imaginary_basic.py'
--- Imaginary/imaginary/plugins/imaginary_basic.py 2008-04-06 18:53:16 +0000
+++ Imaginary/imaginary/plugins/imaginary_basic.py 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-# -*- test-case-name: imaginary.test.test_create -*-
-
-"""
-Imaginary-supplied plugins for simple built-in functionality.
-"""
-
-from imaginary.creation import CreationPluginHelper, createCreator
-
-thingPlugin = CreationPluginHelper("thing", createCreator())
=== removed file 'Imaginary/imaginary/plugins/lighting.py'
--- Imaginary/imaginary/plugins/lighting.py 2007-08-17 04:46:38 +0000
+++ Imaginary/imaginary/plugins/lighting.py 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-
-from imaginary.objects import LightSource
-from imaginary.creation import CreationPluginHelper, createCreator
-
-theTorchPlugin = CreationPluginHelper(
- u"torch", createCreator((LightSource, {"candelas": 80})))
=== removed file 'Imaginary/imaginary/pyparsing.py'
--- Imaginary/imaginary/pyparsing.py 2007-08-17 04:46:38 +0000
+++ Imaginary/imaginary/pyparsing.py 1970-01-01 00:00:00 +0000
@@ -1,2641 +0,0 @@
-# module pyparsing.py
-#
-# Copyright (c) 2003-2006 Paul T. McGuire
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Todo:
-# - add pprint() - pretty-print output of defined BNF
-#
-#from __future__ import generators
-
-__doc__ = \
-"""
-pyparsing module - Classes and methods to define and execute parsing grammars
-
-The pyparsing module is an alternative approach to creating and executing simple grammars,
-vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you
-don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
-provides a library of classes that you use to construct the grammar directly in Python.
-
-Here is a program to parse "Hello, World!" (or any greeting of the form "<salutation>, <addressee>!")::
-
- from pyparsing import Word, alphas
-
- # define grammar of a greeting
- greet = Word( alphas ) + "," + Word( alphas ) + "!"
-
- hello = "Hello, World!"
- print hello, "->", greet.parseString( hello )
-
-The program outputs the following::
-
- Hello, World! -> ['Hello', ',', 'World', '!']
-
-The Python representation of the grammar is quite readable, owing to the self-explanatory
-class names, and the use of '+', '|' and '^' operators.
-
-The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an
-object with named attributes.
-
-The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
- - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.)
- - quoted strings
- - embedded comments
-"""
-__version__ = "1.4.2"
-__versionTime__ = "31 March 2006 17:53"
-__author__ = "Paul McGuire <ptmcg@xxxxxxxxxxxxxxxxxxxxx>"
-
-import string
-import copy,sys
-import warnings
-import re
-#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
-
-def _ustr(obj):
- """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
- str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
- then < returns the unicode object | encodes it with the default encoding | ... >.
- """
- try:
- # If this works, then _ustr(obj) has the same behaviour as str(obj), so
- # it won't break any existing code.
- return str(obj)
-
- except UnicodeEncodeError, e:
- # The Python docs (http://docs.python.org/ref/customization.html#l2h-182)
- # state that "The return value must be a string object". However, does a
- # unicode object (being a subclass of basestring) count as a "string
- # object"?
- # If so, then return a unicode object:
- return unicode(obj)
- # Else encode it... but how? There are many choices... :)
- # Replace unprintables with escape codes?
- #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors')
- # Replace unprintables with question marks?
- #return unicode(obj).encode(sys.getdefaultencoding(), 'replace')
- # ...
-
-def _str2dict(strg):
- return dict( [(c,0) for c in strg] )
-
-alphas = string.lowercase + string.uppercase
-nums = string.digits
-hexnums = nums + "ABCDEFabcdef"
-alphanums = alphas + nums
-
-class ParseBaseException(Exception):
- """base exception class for all parsing runtime exceptions"""
- __slots__ = ( "loc","msg","pstr","parserElement" )
- # Performance tuning: we construct a *lot* of these, so keep this
- # constructor as small and fast as possible
- def __init__( self, pstr, loc, msg, elem=None ):
- self.loc = loc
- self.msg = msg
- self.pstr = pstr
- self.parserElement = elem
-
- def __getattr__( self, aname ):
- """supported attributes by name are:
- - lineno - returns the line number of the exception text
- - col - returns the column number of the exception text
- - line - returns the line containing the exception text
- """
- if( aname == "lineno" ):
- return lineno( self.loc, self.pstr )
- elif( aname in ("col", "column") ):
- return col( self.loc, self.pstr )
- elif( aname == "line" ):
- return line( self.loc, self.pstr )
- else:
- raise AttributeError, aname
-
- def __str__( self ):
- return "%s (at char %d), (line:%d, col:%d)" % ( self.msg, self.loc, self.lineno, self.column )
- def __repr__( self ):
- return _ustr(self)
- def markInputline( self, markerString = ">!<" ):
- """Extracts the exception line from the input string, and marks
- the location of the exception with a special symbol.
- """
- line_str = self.line
- line_column = self.column - 1
- if markerString:
- line_str = "".join( [line_str[:line_column], markerString, line_str[line_column:]])
- return line_str.strip()
-
-class ParseException(ParseBaseException):
- """exception thrown when parse expressions don't match class"""
- """supported attributes by name are:
- - lineno - returns the line number of the exception text
- - col - returns the column number of the exception text
- - line - returns the line containing the exception text
- """
- pass
-
-class ParseFatalException(ParseBaseException):
- """user-throwable exception thrown when inconsistent parse content
- is found; stops all parsing immediately"""
- pass
-
-class RecursiveGrammarException(Exception):
- """exception thrown by validate() if the grammar could be improperly recursive"""
- def __init__( self, parseElementList ):
- self.parseElementTrace = parseElementList
-
- def __str__( self ):
- return "RecursiveGrammarException: %s" % self.parseElementTrace
-
-class ParseResults(object):
- """Structured parse results, to provide multiple means of access to the parsed data:
- - as a list (len(results))
- - by list index (results[0], results[1], etc.)
- - by attribute (results.<resultsName>)
- """
- __slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__modal" )
- def __new__(cls, toklist, name=None, asList=True, modal=True ):
- if isinstance(toklist, cls):
- return toklist
- retobj = object.__new__(cls)
- retobj.__doinit = True
- return retobj
-
- # Performance tuning: we construct a *lot* of these, so keep this
- # constructor as small and fast as possible
- def __init__( self, toklist, name=None, asList=True, modal=True ):
- if self.__doinit:
- self.__doinit = False
- self.__name = None
- self.__parent = None
- self.__modal = modal
- if isinstance(toklist, list):
- self.__toklist = toklist[:]
- else:
- self.__toklist = [toklist]
- self.__tokdict = dict()
-
- # this line is related to debugging the asXML bug
- #~ asList = False
-
- if name:
- if not self.__name:
- self.__modal = self.__modal and modal
- if isinstance(name,int):
- name = _ustr(name) # will always return a str, but use _ustr for consistency
- self.__name = name
- if not toklist in (None,'',[]):
- if isinstance(toklist,basestring):
- toklist = [ toklist ]
- if asList:
- if isinstance(toklist,ParseResults):
- self[name] = (toklist.copy(),-1)
- else:
- self[name] = (ParseResults(toklist[0]),-1)
- self[name].__name = name
- else:
- try:
- self[name] = toklist[0]
- except TypeError:
- self[name] = toklist
-
- def __getitem__( self, i ):
- if isinstance( i, (int,slice) ):
- return self.__toklist[i]
- else:
- if self.__modal:
- return self.__tokdict[i][-1][0]
- else:
- return ParseResults([ v[0] for v in self.__tokdict[i] ])
-
- def __setitem__( self, k, v ):
- if isinstance(v,tuple):
- self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
- sub = v[0]
- else:
- self.__tokdict[k] = self.__tokdict.get(k,list()) + [(v,0)]
- sub = v
- if isinstance(sub,ParseResults):
- sub.__parent = self
-
- def __delitem__( self, i ):
- del self.__toklist[i]
-
- def __contains__( self, k ):
- return self.__tokdict.has_key(k)
-
- def __len__( self ): return len( self.__toklist )
- def __iter__( self ): return iter( self.__toklist )
- def keys( self ):
- """Returns all named result keys."""
- return self.__tokdict.keys()
-
- def items( self ):
- """Returns all named result keys and values as a list of tuples."""
- return [(k,v[-1][0]) for k,v in self.__tokdict.items()]
-
- def values( self ):
- """Returns all named result values."""
- return [ v[-1][0] for v in self.__tokdict.values() ]
-
- def __getattr__( self, name ):
- if name not in self.__slots__:
- if self.__tokdict.has_key( name ):
- if self.__modal:
- return self.__tokdict[name][-1][0]
- else:
- return ParseResults([ v[0] for v in self.__tokdict[name] ])
- else:
- return ""
- return None
-
- def __iadd__( self, other ):
- if other.__tokdict:
- offset = len(self.__toklist)
- addoffset = ( lambda a: (a<0 and offset) or (a+offset) )
- otherdictitems = [(k,(v[0],addoffset(v[1])) ) for (k,vlist) in other.__tokdict.items() for v in vlist]
- for k,v in otherdictitems:
- self[k] = v
- if isinstance(v[0],ParseResults):
- v[0].__parent = self
- self.__toklist += other.__toklist
- del other
- return self
-
- def __repr__( self ):
- return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
-
- def __str__( self ):
- out = "["
- sep = ""
- for i in self.__toklist:
- if isinstance(i, ParseResults):
- out += sep + _ustr(i)
- else:
- out += sep + repr(i)
- sep = ", "
- out += "]"
- return out
-
- def _asStringList( self, sep='' ):
- out = []
- for item in self.__toklist:
- if out and sep:
- out.append(sep)
- if isinstance( item, ParseResults ):
- out += item._asStringList()
- else:
- out.append( _ustr(item) )
- return out
-
- def asList( self ):
- """Returns the parse results as a nested list of matching tokens, all converted to strings."""
- out = []
- for res in self.__toklist:
- if isinstance(res,ParseResults):
- out.append( res.asList() )
- else:
- out.append( res )
- return out
-
- def asDict( self ):
- """Returns the named parse results as dictionary."""
- return dict( self.items() )
-
- def copy( self ):
- """Returns a new copy of a ParseResults object."""
- ret = ParseResults( self.__toklist )
- ret.__tokdict = self.__tokdict.copy()
- ret.__parent = self.__parent
- ret.__modal = self.__modal
- ret.__name = self.__name
- return ret
-
- def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
- """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names."""
- nl = "\n"
- out = []
- namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() for v in vlist ] )
- nextLevelIndent = indent + " "
-
- # collapse out indents if formatting is not desired
- if not formatted:
- indent = ""
- nextLevelIndent = ""
- nl = ""
-
- selfTag = None
- if doctag is not None:
- selfTag = doctag
- else:
- if self.__name:
- selfTag = self.__name
-
- if not selfTag:
- if namedItemsOnly:
- return ""
- else:
- selfTag = "ITEM"
-
- out += [ nl, indent, "<", selfTag, ">" ]
-
- worklist = self.__toklist
- for i,res in enumerate(worklist):
- if isinstance(res,ParseResults):
- if i in namedItems:
- out += [ res.asXML(namedItems[i], namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
- else:
- out += [ res.asXML(None, namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
- else:
- # individual token, see if there is a name for it
- resTag = None
- if i in namedItems:
- resTag = namedItems[i]
- if not resTag:
- if namedItemsOnly:
- continue
- else:
- resTag = "ITEM"
- out += [ nl, nextLevelIndent, "<", resTag, ">", _ustr(res), "</", resTag, ">" ]
-
- out += [ nl, indent, "</", selfTag, ">" ]
- return "".join(out)
-
- def __lookup(self,sub):
- for k,vlist in self.__tokdict.items():
- for v,loc in vlist:
- if sub is v:
- return k
- return None
-
- def getName(self):
- """Returns the results name for this token expression."""
- if self.__name:
- return self.__name
- elif self.__parent:
- par = self.__parent
- if par:
- return par.__lookup(self)
- else:
- return None
- elif (len(self) == 1 and
- len(self.__tokdict) == 1 and
- self.__tokdict.values()[0][0][1] in (0,-1)):
- return self.__tokdict.keys()[0]
- else:
- return None
-
- def dump(self,indent='',depth=0):
- """Diagnostic method for listing out the contents of a ParseResults.
- Accepts an optional indent argument so that this string can be embedded
- in a nested display of other data."""
- out = []
- keys = self.items()
- keys.sort()
- for k,v in keys:
- if out:
- out.append('\n')
- out.append( "%s%s- %s: " % (indent,(' '*depth), k) )
- if isinstance(v,ParseResults):
- if v.keys():
- out.append('\n')
- out.append( self.dump(v,indent,depth+1) )
- out.append('\n')
- else:
- out.append(str(v))
- else:
- out.append(str(v))
- out.append('\n')
- out.append( indent+str(self.asList()) )
- return "".join(out)
-
-def col (loc,strg):
- """Returns current column within a string, counting newlines as line separators.
- The first column is number 1.
- """
- return loc - strg.rfind("\n", 0, loc)
-
-def lineno(loc,strg):
- """Returns current line number within a string, counting newlines as line separators.
- The first line is number 1.
- """
- return strg.count("\n",0,loc) + 1
-
-def line( loc, strg ):
- """Returns the line of text containing loc within a string, counting newlines as line separators.
- """
- lastCR = strg.rfind("\n", 0, loc)
- nextCR = strg.find("\n", loc)
- if nextCR > 0:
- return strg[lastCR+1:nextCR]
- else:
- return strg[lastCR+1:]
-
-def _defaultStartDebugAction( instring, loc, expr ):
- print "Match",expr,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
-
-def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
- print "Matched",expr,"->",toks.asList()
-
-def _defaultExceptionDebugAction( instring, loc, expr, exc ):
- print "Exception raised:", exc
-
-def nullDebugAction(*args):
- """'Do-nothing' debug action, to suppress debugging output during parsing."""
- pass
-
-class ParserElement(object):
- """Abstract base level parser element class."""
- DEFAULT_WHITE_CHARS = " \n\t\r"
-
- def setDefaultWhitespaceChars( chars ):
- """Overrides the default whitespace chars
- """
- ParserElement.DEFAULT_WHITE_CHARS = chars
- setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars)
-
- def __init__( self, savelist=False ):
- self.parseAction = list()
- #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall
- self.strRepr = None
- self.resultsName = None
- self.saveAsList = savelist
- self.skipWhitespace = True
- self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
- self.mayReturnEmpty = False
- self.keepTabs = False
- self.ignoreExprs = list()
- self.debug = False
- self.streamlined = False
- self.mayIndexError = True
- self.errmsg = ""
- self.modalResults = True
- self.debugActions = ( None, None, None )
- self.re = None
-
- def copy( self ):
- """Make a copy of this ParserElement. Useful for defining different parse actions
- for the same parsing pattern, using copies of the original parse element."""
- cpy = copy.copy( self )
- cpy.parseAction = self.parseAction[:]
- cpy.ignoreExprs = self.ignoreExprs[:]
- cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
- return cpy
-
- def setName( self, name ):
- """Define name for this expression, for use in debugging."""
- self.name = name
- self.errmsg = "Expected " + self.name
- return self
-
- def setResultsName( self, name, listAllMatches=False ):
- """Define name for referencing matching tokens as a nested attribute
- of the returned parse results.
- NOTE: this returns a *copy* of the original ParserElement object;
- this is so that the client can define a basic element, such as an
- integer, and reference it in multiple places with different names.
- """
- newself = self.copy()
- newself.resultsName = name
- newself.modalResults = not listAllMatches
- return newself
-
- def setParseAction( self, *fns ):
- """Define action to perform when successfully matching parse element definition.
- Parse action fn is a callable method with the arguments (s, loc, toks) where:
- - s = the original string being parsed
- - loc = the location of the matching substring
- - toks = a list of the matched tokens, packaged as a ParseResults object
- If the functions in fns modify the tokens, it can return them as the return
- value from fn, and the modified list of tokens will replace the original.
- Otherwise, fn does not need to return any value.
- """
- self.parseAction += fns
- return self
-
- def skipIgnorables( self, instring, loc ):
- exprsFound = True
- while exprsFound:
- exprsFound = False
- for e in self.ignoreExprs:
- try:
- while 1:
- loc,dummy = e._parse( instring, loc )
- exprsFound = True
- except ParseException:
- pass
- return loc
-
- def preParse( self, instring, loc ):
- if self.ignoreExprs:
- loc = self.skipIgnorables( instring, loc )
-
- if self.skipWhitespace:
- wt = self.whiteChars
- instrlen = len(instring)
- while loc < instrlen and instring[loc] in wt:
- loc += 1
-
- return loc
-
- def parseImpl( self, instring, loc, doActions=True ):
- return loc, []
-
- def postParse( self, instring, loc, tokenlist ):
- return tokenlist
-
- #~ @profile
- def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
- debugging = ( self.debug ) #and doActions )
-
- if debugging:
- #~ print "Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
- if (self.debugActions[0] ):
- self.debugActions[0]( instring, loc, self )
- if callPreParse:
- loc = self.preParse( instring, loc )
- tokensStart = loc
- try:
- try:
- loc,tokens = self.parseImpl( instring, loc, doActions )
- except IndexError:
- raise ParseException( instring, len(instring), self.errmsg, self )
- except ParseException, err:
- #~ print "Exception raised:", err
- if (self.debugActions[2] ):
- self.debugActions[2]( instring, tokensStart, self, err )
- raise
- else:
- if callPreParse:
- loc = self.preParse( instring, loc )
- tokensStart = loc
- if self.mayIndexError or loc >= len(instring):
- try:
- loc,tokens = self.parseImpl( instring, loc, doActions )
- except IndexError:
- raise ParseException( instring, len(instring), self.errmsg, self )
- else:
- loc,tokens = self.parseImpl( instring, loc, doActions )
-
- tokens = self.postParse( instring, loc, tokens )
-
- retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
- if self.parseAction and doActions:
- if debugging:
- try:
- for fn in self.parseAction:
- tokens = fn( instring, tokensStart, retTokens )
- if tokens is not None:
- if isinstance(tokens,tuple):
- tokens = tokens[1]
- warnings.warn("Returning loc from parse actions is deprecated, return only modified tokens", DeprecationWarning,stacklevel=2)
- retTokens = ParseResults( tokens,
- self.resultsName,
- asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
- modal=self.modalResults )
- except ParseException, err:
- #~ print "Exception raised in user parse action:", err
- if (self.debugActions[2] ):
- self.debugActions[2]( instring, tokensStart, self, err )
- raise
- else:
- for fn in self.parseAction:
- tokens = fn( instring, tokensStart, retTokens )
- if tokens is not None:
- if isinstance(tokens,tuple):
- tokens = tokens[1]
- warnings.warn("Returning loc from parse actions is deprecated, return only modified tokens", DeprecationWarning,stacklevel=2)
- retTokens = ParseResults( tokens,
- self.resultsName,
- asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
- modal=self.modalResults )
-
- if debugging:
- #~ print "Matched",self,"->",retTokens.asList()
- if (self.debugActions[1] ):
- self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
-
- return loc, retTokens
-
- def tryParse( self, instring, loc ):
- return self._parse( instring, loc, doActions=False )[0]
-
- # this method gets repeatedly called during backtracking with the same arguments -
- # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
- def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
- lookup = (self,instring,loc,callPreParse)
- if lookup in ParserElement._exprArgCache:
- value = ParserElement._exprArgCache[ lookup ]
- if isinstance(value,Exception):
- if isinstance(value,ParseBaseException):
- value.loc = loc
- raise value
- return value
- else:
- try:
- ParserElement._exprArgCache[ lookup ] = \
- value = self._parseNoCache( instring, loc, doActions, callPreParse )
- return value
- except Exception, pe:
- ParserElement._exprArgCache[ lookup ] = pe
- raise
-
- _parse = _parseNoCache
-
- # argument cache for optimizing repeated calls when backtracking through recursive expressions
- _exprArgCache = {}
- def resetCache():
- ParserElement._exprArgCache.clear()
- resetCache = staticmethod(resetCache)
-
- _packratEnabled = False
- def enablePackrat():
- """Enables "packrat" parsing, which adds memoizing to the parsing logic.
- Repeated parse attempts at the same string location (which happens
- often in many complex grammars) can immediately return a cached value,
- instead of re-executing parsing/validating code. Memoizing is done of
- both valid results and parsing exceptions.
-
- This speedup may break existing programs that use parse actions that
- have side-effects. For this reason, packrat parsing is disabled when
- you first import pyparsing. To activate the packrat feature, your
- program must call the class method ParserElement.enablePackrat(). If
- your program uses psyco to "compile as you go", you must call
- enablePackrat before calling psyco.full(). If you do not do this,
- Python will crash. For best results, call enablePackrat() immediately
- after importing pyparsing.
- """
- if not ParserElement._packratEnabled:
- ParserElement._packratEnabled = True
- ParserElement._parse = ParserElement._parseCache
- enablePackrat = staticmethod(enablePackrat)
-
- def parseString( self, instring ):
- """Execute the parse expression with the given string.
- This is the main interface to the client code, once the complete
- expression has been built.
- """
- ParserElement.resetCache()
- if not self.streamlined:
- self.streamline()
- self.saveAsList = True
- for e in self.ignoreExprs:
- e.streamline()
- if self.keepTabs:
- loc, tokens = self._parse( instring, 0 )
- else:
- loc, tokens = self._parse( instring.expandtabs(), 0 )
- return tokens
-
- def scanString( self, instring ):
- """Scan the input string for expression matches. Each match will return the matching tokens, start location, and end location."""
- if not self.streamlined:
- self.streamline()
- for e in self.ignoreExprs:
- e.streamline()
-
- if not self.keepTabs:
- instring = instring.expandtabs()
- instrlen = len(instring)
- loc = 0
- preparseFn = self.preParse
- parseFn = self._parse
- ParserElement.resetCache()
- while loc < instrlen:
- try:
- loc = preparseFn( instring, loc )
- nextLoc,tokens = parseFn( instring, loc, callPreParse=False )
- except ParseException:
- loc += 1
- else:
- yield tokens, loc, nextLoc
- loc = nextLoc
-
- def transformString( self, instring ):
- """Extension to scanString, to modify matching text with modified tokens that may
- be returned from a parse action. To use transformString, define a grammar and
- attach a parse action to it that modifies the returned token list.
- Invoking transformString() on a target string will then scan for matches,
- and replace the matched text patterns according to the logic in the parse
- action. transformString() returns the resulting transformed string."""
- out = []
- lastE = 0
- # force preservation of <TAB>s, to minimize unwanted transformation of string, and to
- # keep string locs straight between transformString and scanString
- self.keepTabs = True
- for t,s,e in self.scanString( instring ):
- out.append( instring[lastE:s] )
- if t:
- if isinstance(t,ParseResults):
- out += t.asList()
- elif isinstance(t,list):
- out += t
- else:
- out.append(t)
- lastE = e
- out.append(instring[lastE:])
- return "".join(out)
-
- def searchString( self, instring ):
- """Another extension to scanString, simplifying the access to the tokens found
- to match the given parse expression.
- """
- return [ t[0] for t,s,e in self.scanString( instring ) ]
-
- def __add__(self, other ):
- """Implementation of + operator - returns And"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return And( [ self, other ] )
-
- def __radd__(self, other ):
- """Implementation of += operator"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return other + self
-
- def __or__(self, other ):
- """Implementation of | operator - returns MatchFirst"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return MatchFirst( [ self, other ] )
-
- def __ror__(self, other ):
- """Implementation of |= operator"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return other | self
-
- def __xor__(self, other ):
- """Implementation of ^ operator - returns Or"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return Or( [ self, other ] )
-
- def __rxor__(self, other ):
- """Implementation of ^= operator"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return other ^ self
-
- def __and__(self, other ):
- """Implementation of & operator - returns Each"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return Each( [ self, other ] )
-
- def __rand__(self, other ):
- """Implementation of right-& operator"""
- if isinstance( other, basestring ):
- other = Literal( other )
- if not isinstance( other, ParserElement ):
- warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
- SyntaxWarning, stacklevel=2)
- return other & self
-
- def __invert__( self ):
- """Implementation of ~ operator - returns NotAny"""
- return NotAny( self )
-
- def suppress( self ):
- """Suppresses the output of this ParserElement; useful to keep punctuation from
- cluttering up returned output.
- """
- return Suppress( self )
-
- def leaveWhitespace( self ):
- """Disables the skipping of whitespace before matching the characters in the
- ParserElement's defined pattern. This is normally only used internally by
- the pyparsing module, but may be needed in some whitespace-sensitive grammars.
- """
- self.skipWhitespace = False
- return self
-
- def setWhitespaceChars( self, chars ):
- """Overrides the default whitespace chars
- """
- self.skipWhitespace = True
- self.whiteChars = chars
-
- def parseWithTabs( self ):
- """Overrides default behavior to expand <TAB>s to spaces before parsing the input string.
- Must be called before parseString when the input grammar contains elements that
- match <TAB> characters."""
- self.keepTabs = True
- return self
-
- def ignore( self, other ):
- """Define expression to be ignored (e.g., comments) while doing pattern
- matching; may be called repeatedly, to define multiple comment or other
- ignorable patterns.
- """
- if isinstance( other, Suppress ):
- if other not in self.ignoreExprs:
- self.ignoreExprs.append( other )
- else:
- self.ignoreExprs.append( Suppress( other ) )
- return self
-
- def setDebugActions( self, startAction, successAction, exceptionAction ):
- """Enable display of debugging messages while doing pattern matching."""
- self.debugActions = (startAction or _defaultStartDebugAction,
- successAction or _defaultSuccessDebugAction,
- exceptionAction or _defaultExceptionDebugAction)
- self.debug = True
- return self
-
- def setDebug( self, flag=True ):
- """Enable display of debugging messages while doing pattern matching."""
- if flag:
- self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
- else:
- self.debug = False
- return self
-
- def __str__( self ):
- return self.name
-
- def __repr__( self ):
- return _ustr(self)
-
- def streamline( self ):
- self.streamlined = True
- self.strRepr = None
- return self
-
- def checkRecursion( self, parseElementList ):
- pass
-
- def validate( self, validateTrace=[] ):
- """Check defined expressions for valid structure, check for infinite recursive definitions."""
- self.checkRecursion( [] )
-
- def parseFile( self, file_or_filename ):
- """Execute the parse expression on the given file or filename.
- If a filename is specified (instead of a file object),
- the entire file is opened, read, and closed before parsing.
- """
- try:
- file_contents = file_or_filename.read()
- except AttributeError:
- f = open(file_or_filename, "rb")
- file_contents = f.read()
- f.close()
- return self.parseString(file_contents)
-
-
-class Token(ParserElement):
- """Abstract ParserElement subclass, for defining atomic matching patterns."""
- def __init__( self ):
- super(Token,self).__init__( savelist=False )
- self.myException = ParseException("",0,"",self)
-
- def setName(self, name):
- s = super(Token,self).setName(name)
- self.errmsg = "Expected " + self.name
- s.myException.msg = self.errmsg
- return s
-
-
-class Empty(Token):
- """An empty token, will always match."""
- def __init__( self ):
- super(Empty,self).__init__()
- self.name = "Empty"
- self.mayReturnEmpty = True
- self.mayIndexError = False
-
-
-class NoMatch(Token):
- """A token that will never match."""
- def __init__( self ):
- super(NoMatch,self).__init__()
- self.name = "NoMatch"
- self.mayReturnEmpty = True
- self.mayIndexError = False
- self.errmsg = "Unmatchable token"
- self.myException.msg = self.errmsg
-
- def parseImpl( self, instring, loc, doActions=True ):
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
-
-class Literal(Token):
- """Token to exactly match a specified string."""
- def __init__( self, matchString ):
- super(Literal,self).__init__()
- self.match = matchString
- self.matchLen = len(matchString)
- try:
- self.firstMatchChar = matchString[0]
- except IndexError:
- warnings.warn("null string passed to Literal; use Empty() instead",
- SyntaxWarning, stacklevel=2)
- self.__class__ = Empty
- self.name = '"%s"' % self.match
- self.errmsg = "Expected " + self.name
- self.mayReturnEmpty = False
- self.myException.msg = self.errmsg
- self.mayIndexError = False
-
- # Performance tuning: this routine gets called a *lot*
- # if this is a single character match string and the first character matches,
- # short-circuit as quickly as possible, and avoid calling startswith
- #~ @profile
- def parseImpl( self, instring, loc, doActions=True ):
- if (instring[loc] == self.firstMatchChar and
- (self.matchLen==1 or instring.startswith(self.match,loc)) ):
- return loc+self.matchLen, self.match
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
-class Keyword(Token):
- """Token to exactly match a specified string as a keyword, that is, it must be
- immediately followed by a non-keyword character. Compare with Literal::
- Literal("if") will match the leading 'if' in 'ifAndOnlyIf'.
- Keyword("if") will not; it will only match the leading 'if in 'if x=1', or 'if(y==2)'
- Accepts two optional constructor arguments in addition to the keyword string:
- identChars is a string of characters that would be valid identifier characters,
- defaulting to all alphanumerics + "_" and "$"; caseless allows case-insensitive
- matching, default is False.
- """
- DEFAULT_KEYWORD_CHARS = alphanums+"_$"
-
- def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ):
- super(Keyword,self).__init__()
- self.match = matchString
- self.matchLen = len(matchString)
- try:
- self.firstMatchChar = matchString[0]
- except IndexError:
- warnings.warn("null string passed to Keyword; use Empty() instead",
- SyntaxWarning, stacklevel=2)
- self.name = '"%s"' % self.match
- self.errmsg = "Expected " + self.name
- self.mayReturnEmpty = False
- self.myException.msg = self.errmsg
- self.mayIndexError = False
- self.caseless = caseless
- if caseless:
- self.caselessmatch = matchString.upper()
- identChars = identChars.upper()
- self.identChars = _str2dict(identChars)
-
- def parseImpl( self, instring, loc, doActions=True ):
- if self.caseless:
- if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
- (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
- (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
- return loc+self.matchLen, self.match
- else:
- if (instring[loc] == self.firstMatchChar and
- (self.matchLen==1 or instring.startswith(self.match,loc)) and
- (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
- (loc == 0 or instring[loc-1] not in self.identChars) ):
- return loc+self.matchLen, self.match
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- def copy(self):
- c = super(Keyword,self).copy()
- c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
- return c
-
- def setDefaultKeywordChars( chars ):
- """Overrides the default Keyword chars
- """
- Keyword.DEFAULT_KEYWORD_CHARS = chars
- setDefaultKeywordChars = staticmethod(setDefaultKeywordChars)
-
-
-class CaselessLiteral(Literal):
- """Token to match a specified string, ignoring case of letters.
- Note: the matched results will always be in the case of the given
- match string, NOT the case of the input text.
- """
- def __init__( self, matchString ):
- super(CaselessLiteral,self).__init__( matchString.upper() )
- # Preserve the defining literal.
- self.returnString = matchString
- self.name = "'%s'" % self.returnString
- self.errmsg = "Expected " + self.name
- self.myException.msg = self.errmsg
-
- def parseImpl( self, instring, loc, doActions=True ):
- if instring[ loc:loc+self.matchLen ].upper() == self.match:
- return loc+self.matchLen, self.returnString
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
-class CaselessKeyword(Keyword):
- def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ):
- super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
-
- def parseImpl( self, instring, loc, doActions=True ):
- if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
- (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
- return loc+self.matchLen, self.match
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
-class Word(Token):
- """Token for matching words composed of allowed character sets.
- Defined with string containing all allowed initial characters,
- an optional string containing allowed body characters (if omitted,
- defaults to the initial character set), and an optional minimum,
- maximum, and/or exact length.
- """
- def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0 ):
- super(Word,self).__init__()
- self.initCharsOrig = initChars
- self.initChars = _str2dict(initChars)
- if bodyChars :
- self.bodyCharsOrig = bodyChars
- self.bodyChars = _str2dict(bodyChars)
- else:
- self.bodyCharsOrig = initChars
- self.bodyChars = _str2dict(initChars)
-
- self.maxSpecified = max > 0
-
- self.minLen = min
-
- if max > 0:
- self.maxLen = max
- else:
- self.maxLen = sys.maxint
-
- if exact > 0:
- self.maxLen = exact
- self.minLen = exact
-
- self.name = _ustr(self)
- self.errmsg = "Expected " + self.name
- self.myException.msg = self.errmsg
- self.mayIndexError = False
-
- if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
- if self.bodyCharsOrig == self.initCharsOrig:
- self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
- elif len(self.bodyCharsOrig) == 1:
- self.reString = "%s[%s]*" % \
- (re.escape(self.initCharsOrig),
- _escapeRegexRangeChars(self.bodyCharsOrig),)
- else:
- self.reString = "[%s][%s]*" % \
- (_escapeRegexRangeChars(self.initCharsOrig),
- _escapeRegexRangeChars(self.bodyCharsOrig),)
- try:
- self.re = re.compile( self.reString )
- except:
- self.re = None
-
- def parseImpl( self, instring, loc, doActions=True ):
- if self.re:
- result = self.re.match(instring,loc)
- if not result:
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- loc = result.end()
- return loc,result.group()
-
- if not(instring[ loc ] in self.initChars):
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- start = loc
- loc += 1
- instrlen = len(instring)
- bodychars = self.bodyChars
- maxloc = start + self.maxLen
- maxloc = min( maxloc, instrlen )
- while loc < maxloc and instring[loc] in bodychars:
- loc += 1
-
- throwException = False
- if loc - start < self.minLen:
- throwException = True
- if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
- throwException = True
-
- if throwException:
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- return loc, instring[start:loc]
-
- def __str__( self ):
- try:
- return super(Word,self).__str__()
- except:
- pass
-
-
- if self.strRepr is None:
-
- def charsAsStr(s):
- if len(s)>4:
- return s[:4]+"..."
- else:
- return s
-
- if ( self.initCharsOrig != self.bodyCharsOrig ):
- self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
- else:
- self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
-
- return self.strRepr
-
-
-class Regex(Token):
- """Token for matching strings that match a given regular expression.
- Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
- """
- def __init__( self, pattern, flags=0):
- """The parameters pattern and flags are passed to the re.compile() function as-is. See the Python re module for an explanation of the acceptable patterns and flags."""
- super(Regex,self).__init__()
-
- if len(pattern) == 0:
- warnings.warn("null string passed to Regex; use Empty() instead",
- SyntaxWarning, stacklevel=2)
-
- self.pattern = pattern
- self.flags = flags
-
- try:
- self.re = re.compile(self.pattern, self.flags)
- self.reString = self.pattern
- except Exception,e:
- warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
- SyntaxWarning, stacklevel=2)
- raise
-
- self.name = _ustr(self)
- self.errmsg = "Expected " + self.name
- self.myException.msg = self.errmsg
- self.mayIndexError = False
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- result = self.re.match(instring,loc)
- if not result:
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- loc = result.end()
- d = result.groupdict()
- ret = ParseResults(result.group())
- if d:
- for k in d.keys():
- ret[k] = d[k]
- return loc,ret
-
- def __str__( self ):
- try:
- return super(Regex,self).__str__()
- except:
- pass
-
- if self.strRepr is None:
- self.strRepr = "Re:(%s)" % repr(self.pattern)
-
- return self.strRepr
-
-
-class QuotedString(Token):
- """Token for matching strings that are delimited by quoting characters.
- """
- def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None):
- """
- Defined with the following parameters:
- - quoteChar - string of one or more characters defining the quote delimiting string
- - escChar - character to escape quotes, typically backslash (default=None)
- - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None)
- - multiline - boolean indicating whether quotes can span multiple lines (default=False)
- - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True)
- - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar)
- """
- super(QuotedString,self).__init__()
-
- # remove white space from quote chars - wont work anyway
- quoteChar = quoteChar.strip()
- if len(quoteChar) == 0:
- warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
- raise SyntaxError()
-
- if endQuoteChar is None:
- endQuoteChar = quoteChar
- else:
- endQuoteChar = endQuoteChar.strip()
- if len(endQuoteChar) == 0:
- warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
- raise SyntaxError()
-
- self.quoteChar = quoteChar
- self.quoteCharLen = len(quoteChar)
- self.firstQuoteChar = quoteChar[0]
- self.endQuoteChar = endQuoteChar
- self.endQuoteCharLen = len(endQuoteChar)
- self.escChar = escChar
- self.escQuote = escQuote
- self.unquoteResults = unquoteResults
-
- if multiline:
- self.flags = re.MULTILINE | re.DOTALL
- self.pattern = r'%s([^%s%s]' % \
- ( re.escape(self.quoteChar),
- _escapeRegexRangeChars(self.endQuoteChar[0]),
- (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
- else:
- self.flags = 0
- self.pattern = r'%s([^%s\n\r%s]' % \
- ( re.escape(self.quoteChar),
- _escapeRegexRangeChars(self.endQuoteChar[0]),
- (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
- if len(self.endQuoteChar) > 1:
- self.pattern += (
- '|(' + ')|('.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
- _escapeRegexRangeChars(self.endQuoteChar[i]))
- for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')'
- )
- if escQuote:
- self.pattern += (r'|(%s)' % re.escape(escQuote))
- if escChar:
- self.pattern += (r'|(%s.)' % re.escape(escChar))
- self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
- self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
-
- try:
- self.re = re.compile(self.pattern, self.flags)
- self.reString = self.pattern
- except Exception,e:
- warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
- SyntaxWarning, stacklevel=2)
- raise
-
- self.name = _ustr(self)
- self.errmsg = "Expected " + self.name
- self.myException.msg = self.errmsg
- self.mayIndexError = False
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
- if not result:
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- loc = result.end()
- ret = result.group()
-
- if self.unquoteResults:
-
- # strip off quotes
- ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
-
- if isinstance(ret,basestring):
- # replace escaped characters
- if self.escChar:
- ret = re.sub(self.escCharReplacePattern,"\g<1>",ret)
-
- # replace escaped quotes
- if self.escQuote:
- ret = ret.replace(self.escQuote, self.endQuoteChar)
-
- return loc, ret
-
- def __str__( self ):
- try:
- return super(QuotedString,self).__str__()
- except:
- pass
-
- if self.strRepr is None:
- self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
-
- return self.strRepr
-
-
-class CharsNotIn(Token):
- """Token for matching words composed of characters *not* in a given set.
- Defined with string containing all disallowed characters, and an optional
- minimum, maximum, and/or exact length.
- """
- def __init__( self, notChars, min=1, max=0, exact=0 ):
- super(CharsNotIn,self).__init__()
- self.skipWhitespace = False
- self.notChars = notChars
-
- self.minLen = min
-
- if max > 0:
- self.maxLen = max
- else:
- self.maxLen = sys.maxint
-
- if exact > 0:
- self.maxLen = exact
- self.minLen = exact
-
- self.name = _ustr(self)
- self.errmsg = "Expected " + self.name
- self.mayReturnEmpty = ( self.minLen == 0 )
- self.myException.msg = self.errmsg
- self.mayIndexError = False
-
- def parseImpl( self, instring, loc, doActions=True ):
- if instring[loc] in self.notChars:
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- start = loc
- loc += 1
- notchars = self.notChars
- maxlen = min( start+self.maxLen, len(instring) )
- while loc < maxlen and \
- (instring[loc] not in notchars):
- loc += 1
-
- if loc - start < self.minLen:
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- return loc, instring[start:loc]
-
- def __str__( self ):
- try:
- return super(CharsNotIn, self).__str__()
- except:
- pass
-
- if self.strRepr is None:
- if len(self.notChars) > 4:
- self.strRepr = "!W:(%s...)" % self.notChars[:4]
- else:
- self.strRepr = "!W:(%s)" % self.notChars
-
- return self.strRepr
-
-class White(Token):
- """Special matching class for matching whitespace. Normally, whitespace is ignored
- by pyparsing grammars. This class is included when some whitespace structures
- are significant. Define with a string containing the whitespace characters to be
- matched; default is " \\t\\n". Also takes optional min, max, and exact arguments,
- as defined for the Word class."""
- whiteStrs = {
- " " : "<SPC>",
- "\t": "<TAB>",
- "\n": "<LF>",
- "\r": "<CR>",
- "\f": "<FF>",
- }
- def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
- super(White,self).__init__()
- self.matchWhite = ws
- self.whiteChars = "".join([c for c in self.whiteChars if c not in self.matchWhite])
- #~ self.leaveWhitespace()
- self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite]))
- self.mayReturnEmpty = True
- self.errmsg = "Expected " + self.name
- self.myException.msg = self.errmsg
-
- self.minLen = min
-
- if max > 0:
- self.maxLen = max
- else:
- self.maxLen = sys.maxint
-
- if exact > 0:
- self.maxLen = exact
- self.minLen = exact
-
- def parseImpl( self, instring, loc, doActions=True ):
- if not(instring[ loc ] in self.matchWhite):
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- start = loc
- loc += 1
- maxloc = start + self.maxLen
- maxloc = min( maxloc, len(instring) )
- while loc < maxloc and instring[loc] in self.matchWhite:
- loc += 1
-
- if loc - start < self.minLen:
- #~ raise ParseException( instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
- return loc, instring[start:loc]
-
-
-class PositionToken(Token):
- def __init__( self ):
- super(PositionToken,self).__init__()
- self.name=self.__class__.__name__
- self.mayReturnEmpty = True
-
-class GoToColumn(PositionToken):
- """Token to advance to a specific column of input text; useful for tabular report scraping."""
- def __init__( self, colno ):
- super(GoToColumn,self).__init__()
- self.col = colno
-
- def preParse( self, instring, loc ):
- if col(loc,instring) != self.col:
- instrlen = len(instring)
- if self.ignoreExprs:
- loc = self.skipIgnorables( instring, loc )
- while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
- loc += 1
- return loc
-
- def parseImpl( self, instring, loc, doActions=True ):
- thiscol = col( loc, instring )
- if thiscol > self.col:
- raise ParseException( instring, loc, "Text not in expected column", self )
- newloc = loc + self.col - thiscol
- ret = instring[ loc: newloc ]
- return newloc, ret
-
-class LineStart(PositionToken):
- """Matches if current position is at the beginning of a line within the parse string"""
- def __init__( self ):
- super(LineStart,self).__init__()
- self.whiteChars = " \t"
- self.errmsg = "Expected start of line"
- self.myException.msg = self.errmsg
-
- def preParse( self, instring, loc ):
- loc = super(LineStart,self).preParse(instring,loc)
- if instring[loc] == "\n":
- loc += 1
- return loc
-
- def parseImpl( self, instring, loc, doActions=True ):
- if not( loc==0 or ( loc<len(instring) and instring[loc-1] == "\n" ) ): #col(loc, instring) != 1:
- #~ raise ParseException( instring, loc, "Expected start of line" )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- return loc, []
-
-class LineEnd(PositionToken):
- """Matches if current position is at the end of a line within the parse string"""
- def __init__( self ):
- super(LineEnd,self).__init__()
- self.whiteChars = " \t"
- self.errmsg = "Expected end of line"
- self.myException.msg = self.errmsg
-
- def parseImpl( self, instring, loc, doActions=True ):
- if loc<len(instring):
- if instring[loc] == "\n":
- return loc+1, "\n"
- else:
- #~ raise ParseException( instring, loc, "Expected end of line" )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- else:
- return loc, []
-
-class StringStart(PositionToken):
- """Matches if current position is at the beginning of the parse string"""
- def __init__( self ):
- super(StringStart,self).__init__()
- self.errmsg = "Expected start of text"
- self.myException.msg = self.errmsg
-
- def parseImpl( self, instring, loc, doActions=True ):
- if loc != 0:
- # see if entire string up to here is just whitespace and ignoreables
- if loc != self.preParse( instring, 0 ):
- #~ raise ParseException( instring, loc, "Expected start of text" )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- return loc, []
-
-class StringEnd(PositionToken):
- """Matches if current position is at the end of the parse string"""
- def __init__( self ):
- super(StringEnd,self).__init__()
- self.errmsg = "Expected end of text"
- self.myException.msg = self.errmsg
-
- def parseImpl( self, instring, loc, doActions=True ):
- if loc < len(instring):
- #~ raise ParseException( instring, loc, "Expected end of text" )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- return loc, []
-
-
-class ParseExpression(ParserElement):
- """Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
- def __init__( self, exprs, savelist = False ):
- super(ParseExpression,self).__init__(savelist)
- if isinstance( exprs, list ):
- self.exprs = exprs
- elif isinstance( exprs, basestring ):
- self.exprs = [ Literal( exprs ) ]
- else:
- self.exprs = [ exprs ]
-
- def __getitem__( self, i ):
- return self.exprs[i]
-
- def append( self, other ):
- self.exprs.append( other )
- self.strRepr = None
- return self
-
- def leaveWhitespace( self ):
- """Extends leaveWhitespace defined in base class, and also invokes leaveWhitespace on
- all contained expressions."""
- self.skipWhitespace = False
- self.exprs = [ copy.copy(e) for e in self.exprs ]
- for e in self.exprs:
- e.leaveWhitespace()
- return self
-
- def ignore( self, other ):
- if isinstance( other, Suppress ):
- if other not in self.ignoreExprs:
- super( ParseExpression, self).ignore( other )
- for e in self.exprs:
- e.ignore( self.ignoreExprs[-1] )
- else:
- super( ParseExpression, self).ignore( other )
- for e in self.exprs:
- e.ignore( self.ignoreExprs[-1] )
- return self
-
- def __str__( self ):
- try:
- return super(ParseExpression,self).__str__()
- except:
- pass
-
- if self.strRepr is None:
- self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) )
- return self.strRepr
-
- def streamline( self ):
- super(ParseExpression,self).streamline()
-
- for e in self.exprs:
- e.streamline()
-
- # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d )
- # but only if there are no parse actions or resultsNames on the nested And's
- # (likewise for Or's and MatchFirst's)
- if ( len(self.exprs) == 2 ):
- other = self.exprs[0]
- if ( isinstance( other, self.__class__ ) and
- not(other.parseAction) and
- other.resultsName is None and
- not other.debug ):
- self.exprs = other.exprs[:] + [ self.exprs[1] ]
- self.strRepr = None
-
- other = self.exprs[-1]
- if ( isinstance( other, self.__class__ ) and
- not(other.parseAction) and
- other.resultsName is None and
- not other.debug ):
- self.exprs = self.exprs[:-1] + other.exprs[:]
- self.strRepr = None
-
- return self
-
- def setResultsName( self, name, listAllMatches=False ):
- ret = super(ParseExpression,self).setResultsName(name,listAllMatches)
- #~ ret.saveAsList = True
- return ret
-
- def validate( self, validateTrace=[] ):
- tmp = validateTrace[:]+[self]
- for e in self.exprs:
- e.validate(tmp)
- self.checkRecursion( [] )
-
- def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
- if self.parseAction and doActions:
- return self._parseNoCache( instring, loc, doActions, callPreParse )
- return super(ParseExpression,self)._parseCache( instring, loc, doActions, callPreParse )
-
-class And(ParseExpression):
- """Requires all given ParseExpressions to be found in the given order.
- Expressions may be separated by whitespace.
- May be constructed using the '+' operator.
- """
- def __init__( self, exprs, savelist = True ):
- super(And,self).__init__(exprs, savelist)
- self.mayReturnEmpty = True
- for e in self.exprs:
- if not e.mayReturnEmpty:
- self.mayReturnEmpty = False
- break
- self.skipWhitespace = exprs[0].skipWhitespace
- self.whiteChars = exprs[0].whiteChars
-
- def parseImpl( self, instring, loc, doActions=True ):
- loc, resultlist = self.exprs[0]._parse( instring, loc, doActions )
- for e in self.exprs[1:]:
- loc, exprtokens = e._parse( instring, loc, doActions )
- if exprtokens or exprtokens.keys():
- resultlist += exprtokens
- return loc, resultlist
-
- def __iadd__(self, other ):
- if isinstance( other, basestring ):
- other = Literal( other )
- return self.append( other ) #And( [ self, other ] )
-
- def checkRecursion( self, parseElementList ):
- subRecCheckList = parseElementList[:] + [ self ]
- for e in self.exprs:
- e.checkRecursion( subRecCheckList )
- if not e.mayReturnEmpty:
- break
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "{" + " ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
-
- return self.strRepr
-
-
-class Or(ParseExpression):
- """Requires that at least one ParseExpression is found.
- If two expressions match, the expression that matches the longest string will be used.
- May be constructed using the '^' operator.
- """
- def __init__( self, exprs, savelist = False ):
- super(Or,self).__init__(exprs, savelist)
- self.mayReturnEmpty = False
- for e in self.exprs:
- if e.mayReturnEmpty:
- self.mayReturnEmpty = True
- break
-
- def parseImpl( self, instring, loc, doActions=True ):
- maxExcLoc = -1
- maxMatchLoc = -1
- for e in self.exprs:
- try:
- loc2 = e.tryParse( instring, loc )
- except ParseException, err:
- if err.loc > maxExcLoc:
- maxException = err
- maxExcLoc = err.loc
- except IndexError, err:
- if len(instring) > maxExcLoc:
- maxException = ParseException(instring,len(instring),e.errmsg,self)
- maxExcLoc = len(instring)
- else:
- if loc2 > maxMatchLoc:
- maxMatchLoc = loc2
- maxMatchExp = e
-
- if maxMatchLoc < 0:
- if self.exprs:
- raise maxException
- else:
- raise ParseException(instring, loc, "no defined alternatives to match", self)
-
- return maxMatchExp._parse( instring, loc, doActions )
-
- def __ixor__(self, other ):
- if isinstance( other, basestring ):
- other = Literal( other )
- return self.append( other ) #Or( [ self, other ] )
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
-
- return self.strRepr
-
- def checkRecursion( self, parseElementList ):
- subRecCheckList = parseElementList[:] + [ self ]
- for e in self.exprs:
- e.checkRecursion( subRecCheckList )
-
-
-class MatchFirst(ParseExpression):
- """Requires that at least one ParseExpression is found.
- If two expressions match, the first one listed is the one that will match.
- May be constructed using the '|' operator.
- """
- def __init__( self, exprs, savelist = False ):
- super(MatchFirst,self).__init__(exprs, savelist)
- if exprs:
- self.mayReturnEmpty = False
- for e in self.exprs:
- if e.mayReturnEmpty:
- self.mayReturnEmpty = True
- break
- else:
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- maxExcLoc = -1
- for e in self.exprs:
- try:
- ret = e._parse( instring, loc, doActions )
- return ret
- except ParseException, err:
- if err.loc > maxExcLoc:
- maxException = err
- maxExcLoc = err.loc
- except IndexError, err:
- if len(instring) > maxExcLoc:
- maxException = ParseException(instring,len(instring),e.errmsg,self)
- maxExcLoc = len(instring)
-
- # only got here if no expression matched, raise exception for match that made it the furthest
- else:
- if self.exprs:
- raise maxException
- else:
- raise ParseException(instring, loc, "no defined alternatives to match", self)
-
- def __ior__(self, other ):
- if isinstance( other, basestring ):
- other = Literal( other )
- return self.append( other ) #MatchFirst( [ self, other ] )
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
-
- return self.strRepr
-
- def checkRecursion( self, parseElementList ):
- subRecCheckList = parseElementList[:] + [ self ]
- for e in self.exprs:
- e.checkRecursion( subRecCheckList )
-
-class Each(ParseExpression):
- """Requires all given ParseExpressions to be found, but in any order.
- Expressions may be separated by whitespace.
- May be constructed using the '&' operator.
- """
- def __init__( self, exprs, savelist = True ):
- super(Each,self).__init__(exprs, savelist)
- self.mayReturnEmpty = True
- for e in self.exprs:
- if not e.mayReturnEmpty:
- self.mayReturnEmpty = False
- break
- self.skipWhitespace = True
- self.optionals = [ e.expr for e in exprs if isinstance(e,Optional) ]
- self.multioptionals = [ e.expr for e in exprs if isinstance(e,ZeroOrMore) ]
- self.multirequired = [ e.expr for e in exprs if isinstance(e,OneOrMore) ]
- self.required = [ e for e in exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
- self.required += self.multirequired
-
- def parseImpl( self, instring, loc, doActions=True ):
- tmpLoc = loc
- tmpReqd = self.required[:]
- tmpOpt = self.optionals[:]
- matchOrder = []
-
- keepMatching = True
- while keepMatching:
- tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
- failed = []
- for e in tmpExprs:
- try:
- tmpLoc = e.tryParse( instring, tmpLoc )
- except ParseException:
- failed.append(e)
- else:
- matchOrder.append(e)
- if e in tmpReqd:
- tmpReqd.remove(e)
- elif e in tmpOpt:
- tmpOpt.remove(e)
- if len(failed) == len(tmpExprs):
- keepMatching = False
-
- if tmpReqd:
- missing = ", ".join( [ str(e) for e in tmpReqd ] )
- raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
-
- resultlist = []
- for e in matchOrder:
- loc,results = e._parse(instring,loc,doActions)
- resultlist.append(results)
-
- finalResults = ParseResults([])
- for r in resultlist:
- dups = {}
- for k in r.keys():
- if k in finalResults.keys():
- tmp = ParseResults(finalResults[k])
- tmp += ParseResults(r[k])
- dups[k] = tmp
- finalResults += ParseResults(r)
- for k,v in dups.items():
- finalResults[k] = v
- return loc, finalResults
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
-
- return self.strRepr
-
- def checkRecursion( self, parseElementList ):
- subRecCheckList = parseElementList[:] + [ self ]
- for e in self.exprs:
- e.checkRecursion( subRecCheckList )
-
-
-class ParseElementEnhance(ParserElement):
- """Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
- def __init__( self, expr, savelist=False ):
- super(ParseElementEnhance,self).__init__(savelist)
- if isinstance( expr, basestring ):
- expr = Literal(expr)
- self.expr = expr
- self.strRepr = None
- if expr is not None:
- self.mayIndexError = expr.mayIndexError
- self.skipWhitespace = expr.skipWhitespace
- self.whiteChars = expr.whiteChars
- self.saveAsList = expr.saveAsList
-
- def parseImpl( self, instring, loc, doActions=True ):
- if self.expr is not None:
- return self.expr._parse( instring, loc, doActions )
- else:
- raise ParseException("",loc,self.errmsg,self)
-
- def leaveWhitespace( self ):
- self.skipWhitespace = False
- self.expr = copy.copy(self.expr)
- if self.expr is not None:
- self.expr.leaveWhitespace()
- return self
-
- def ignore( self, other ):
- if isinstance( other, Suppress ):
- if other not in self.ignoreExprs:
- super( ParseElementEnhance, self).ignore( other )
- if self.expr is not None:
- self.expr.ignore( self.ignoreExprs[-1] )
- else:
- super( ParseElementEnhance, self).ignore( other )
- if self.expr is not None:
- self.expr.ignore( self.ignoreExprs[-1] )
- return self
-
- def streamline( self ):
- super(ParseElementEnhance,self).streamline()
- if self.expr is not None:
- self.expr.streamline()
- return self
-
- def checkRecursion( self, parseElementList ):
- if self in parseElementList:
- raise RecursiveGrammarException( parseElementList+[self] )
- subRecCheckList = parseElementList[:] + [ self ]
- if self.expr is not None:
- self.expr.checkRecursion( subRecCheckList )
-
- def validate( self, validateTrace=[] ):
- tmp = validateTrace[:]+[self]
- if self.expr is not None:
- self.expr.validate(tmp)
- self.checkRecursion( [] )
-
- def __str__( self ):
- try:
- return super(ParseElementEnhance,self).__str__()
- except:
- pass
-
- if self.strRepr is None and self.expr is not None:
- self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
- return self.strRepr
-
-
-class FollowedBy(ParseElementEnhance):
- """Lookahead matching of the given parse expression. FollowedBy
- does *not* advance the parsing position within the input string, it only
- verifies that the specified parse expression matches at the current
- position. FollowedBy always returns a null token list."""
- def __init__( self, expr ):
- super(FollowedBy,self).__init__(expr)
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- self.expr.tryParse( instring, loc )
- return loc, []
-
-
-class NotAny(ParseElementEnhance):
- """Lookahead to disallow matching with the given parse expression. NotAny
- does *not* advance the parsing position within the input string, it only
- verifies that the specified parse expression does *not* match at the current
- position. Also, NotAny does *not* skip over leading whitespace. NotAny
- always returns a null token list. May be constructed using the '~' operator."""
- def __init__( self, expr ):
- super(NotAny,self).__init__(expr)
- #~ self.leaveWhitespace()
- self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
- self.mayReturnEmpty = True
- self.errmsg = "Found unexpected token, "+_ustr(self.expr)
- self.myException = ParseException("",0,self.errmsg,self)
-
- def parseImpl( self, instring, loc, doActions=True ):
- try:
- self.expr.tryParse( instring, loc )
- except (ParseException,IndexError):
- pass
- else:
- #~ raise ParseException(instring, loc, self.errmsg )
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
- return loc, []
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "~{" + _ustr(self.expr) + "}"
-
- return self.strRepr
-
-
-class ZeroOrMore(ParseElementEnhance):
- """Optional repetition of zero or more of the given expression."""
- def __init__( self, expr ):
- super(ZeroOrMore,self).__init__(expr)
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- tokens = []
- try:
- loc, tokens = self.expr._parse( instring, loc, doActions )
- hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
- while 1:
- if hasIgnoreExprs:
- loc = self.skipIgnorables( instring, loc )
- loc, tmptokens = self.expr._parse( instring, loc, doActions )
- if tmptokens or tmptokens.keys():
- tokens += tmptokens
- except (ParseException,IndexError):
- pass
- except Exception,e:
- print "####",e
-
- return loc, tokens
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "[" + _ustr(self.expr) + "]..."
-
- return self.strRepr
-
- def setResultsName( self, name, listAllMatches=False ):
- ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches)
- ret.saveAsList = True
- return ret
-
-
-class OneOrMore(ParseElementEnhance):
- """Repetition of one or more of the given expression."""
- def parseImpl( self, instring, loc, doActions=True ):
- # must be at least one
- loc, tokens = self.expr._parse( instring, loc, doActions )
- try:
- hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
- while 1:
- if hasIgnoreExprs:
- loc = self.skipIgnorables( instring, loc )
- loc, tmptokens = self.expr._parse( instring, loc, doActions )
- if tmptokens or tmptokens.keys():
- tokens += tmptokens
- except (ParseException,IndexError):
- pass
-
- return loc, tokens
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "{" + _ustr(self.expr) + "}..."
-
- return self.strRepr
-
- def setResultsName( self, name, listAllMatches=False ):
- ret = super(OneOrMore,self).setResultsName(name,listAllMatches)
- ret.saveAsList = True
- return ret
-
-class _NullToken(object):
- def __bool__(self):
- return False
- def __str__(self):
- return ""
-
-_optionalNotMatched = _NullToken()
-class Optional(ParseElementEnhance):
- """Optional matching of the given expression.
- A default return string can also be specified, if the optional expression
- is not found.
- """
- def __init__( self, exprs, default=_optionalNotMatched ):
- super(Optional,self).__init__( exprs, savelist=False )
- self.defaultValue = default
- self.mayReturnEmpty = True
-
- def parseImpl( self, instring, loc, doActions=True ):
- try:
- loc, tokens = self.expr._parse( instring, loc, doActions )
- except (ParseException,IndexError):
- if self.defaultValue is not _optionalNotMatched:
- tokens = [ self.defaultValue ]
- else:
- tokens = []
-
- return loc, tokens
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- if self.strRepr is None:
- self.strRepr = "[" + _ustr(self.expr) + "]"
-
- return self.strRepr
-
-
-class SkipTo(ParseElementEnhance):
- """Token for skipping over all undefined text until the matched expression is found.
- If include is set to true, the matched expression is also consumed. The ignore
- argument is used to define grammars (typically quoted strings and comments) that
- might contain false matches.
- """
- def __init__( self, other, include=False, ignore=None ):
- super( SkipTo, self ).__init__( other )
- if ignore is not None:
- self.expr = copy.copy( self.expr )
- self.expr.ignore(ignore)
- self.mayReturnEmpty = True
- self.mayIndexError = False
- self.includeMatch = include
- self.errmsg = "No match found for "+_ustr(self.expr)
- self.myException = ParseException("",0,self.errmsg,self)
-
- def parseImpl( self, instring, loc, doActions=True ):
- startLoc = loc
- instrlen = len(instring)
- expr = self.expr
- while loc < instrlen:
- try:
- loc = expr.skipIgnorables( instring, loc )
- expr._parse( instring, loc, doActions=False, callPreParse=False )
- if self.includeMatch:
- skipText = instring[startLoc:loc]
- loc,mat = expr._parse(instring,loc)
- if mat:
- return loc, [ skipText, mat ]
- else:
- return loc, [ skipText ]
- else:
- return loc, [ instring[startLoc:loc] ]
- except (ParseException,IndexError):
- loc += 1
- exc = self.myException
- exc.loc = loc
- exc.pstr = instring
- raise exc
-
-class Forward(ParseElementEnhance):
- """Forward declaration of an expression to be defined later -
- used for recursive grammars, such as algebraic infix notation.
- When the expression is known, it is assigned to the Forward variable using the '<<' operator.
-
- Note: take care when assigning to Forward to not overlook precedence of operators.
- Specifically, '|' has a lower precedence than '<<', so that::
- fwdExpr << a | b | c
- will actually be evaluated as::
- (fwdExpr << a) | b | c
- thereby leaving b and c out as parseable alternatives. It is recommended that you
- explicitly group the values inserted into the Forward::
- fwdExpr << (a | b | c)
- """
- def __init__( self, other=None ):
- super(Forward,self).__init__( other, savelist=False )
-
- def __lshift__( self, other ):
- self.expr = other
- self.mayReturnEmpty = other.mayReturnEmpty
- self.strRepr = None
- return self
-
- def leaveWhitespace( self ):
- self.skipWhitespace = False
- return self
-
- def streamline( self ):
- if not self.streamlined:
- self.streamlined = True
- if self.expr is not None:
- self.expr.streamline()
- return self
-
- def validate( self, validateTrace=[] ):
- if self not in validateTrace:
- tmp = validateTrace[:]+[self]
- if self.expr is not None:
- self.expr.validate(tmp)
- self.checkRecursion([])
-
- def __str__( self ):
- if hasattr(self,"name"):
- return self.name
-
- self.__class__ = _ForwardNoRecurse
- try:
- if self.expr is not None:
- retString = _ustr(self.expr)
- else:
- retString = "None"
- finally:
- self.__class__ = Forward
- return "Forward: "+retString
-
-class _ForwardNoRecurse(Forward):
- def __str__( self ):
- return "..."
-
-class TokenConverter(ParseElementEnhance):
- """Abstract subclass of ParseExpression, for converting parsed results."""
- def __init__( self, expr, savelist=False ):
- super(TokenConverter,self).__init__( expr )#, savelist )
- self.saveAsList = False
-
-
-class Upcase(TokenConverter):
- """Converter to upper case all matching tokens."""
- def __init__(self, *args):
- super(Upcase,self).__init__(*args)
- warnings.warn("Upcase class is deprecated, use upcaseTokens parse action instead",
- DeprecationWarning,stacklevel=2)
-
- def postParse( self, instring, loc, tokenlist ):
- return map( string.upper, tokenlist )
-
-
-class Combine(TokenConverter):
- """Converter to concatenate all matching tokens to a single string.
- By default, the matching patterns must also be contiguous in the input string;
- this can be disabled by specifying 'adjacent=False' in the constructor.
- """
- def __init__( self, expr, joinString="", adjacent=True ):
- super(Combine,self).__init__( expr )
- # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
- if adjacent:
- self.leaveWhitespace()
- self.adjacent = adjacent
- self.skipWhitespace = True
- self.joinString = joinString
-
- def ignore( self, other ):
- if self.adjacent:
- ParserElement.ignore(self, other)
- else:
- super( Combine, self).ignore( other )
- return self
-
- def postParse( self, instring, loc, tokenlist ):
- retToks = tokenlist.copy()
- del retToks[:]
- retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
-
- if self.resultsName and len(retToks.keys())>0:
- return [ retToks ]
- else:
- return retToks
-
-class Group(TokenConverter):
- """Converter to return the matched tokens as a list - useful for returning tokens of ZeroOrMore and OneOrMore expressions."""
- def __init__( self, expr ):
- super(Group,self).__init__( expr )
- self.saveAsList = True
-
- def postParse( self, instring, loc, tokenlist ):
- return [ tokenlist ]
-
-class Dict(TokenConverter):
- """Converter to return a repetitive expression as a list, but also as a dictionary.
- Each element can also be referenced using the first token in the expression as its key.
- Useful for tabular report scraping when the first column can be used as a item key.
- """
- def __init__( self, exprs ):
- super(Dict,self).__init__( exprs )
- self.saveAsList = True
-
- def postParse( self, instring, loc, tokenlist ):
- for i,tok in enumerate(tokenlist):
- ikey = _ustr(tok[0]).strip()
- if len(tok)==1:
- tokenlist[ikey] = ("",i)
- elif len(tok)==2 and not isinstance(tok[1],ParseResults):
- tokenlist[ikey] = (tok[1],i)
- else:
- dictvalue = tok.copy() #ParseResults(i)
- del dictvalue[0]
- if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()):
- tokenlist[ikey] = (dictvalue,i)
- else:
- tokenlist[ikey] = (dictvalue[0],i)
-
- if self.resultsName:
- return [ tokenlist ]
- else:
- return tokenlist
-
-
-class Suppress(TokenConverter):
- """Converter for ignoring the results of a parsed expression."""
- def postParse( self, instring, loc, tokenlist ):
- return []
-
- def suppress( self ):
- return self
-
-#
-# global helpers
-#
-def delimitedList( expr, delim=",", combine=False ):
- """Helper to define a delimited list of expressions - the delimiter defaults to ','.
- By default, the list elements and delimiters can have intervening whitespace, and
- comments, but this can be overridden by passing 'combine=True' in the constructor.
- If combine is set to True, the matching tokens are returned as a single token
- string, with the delimiters included; otherwise, the matching tokens are returned
- as a list of tokens, with the delimiters suppressed.
- """
- if combine:
- return Combine( expr + ZeroOrMore( delim + expr ) ).setName(_ustr(expr)+_ustr(delim)+"...")
- else:
- return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(_ustr(expr)+_ustr(delim)+"...")
-
-def countedArray( expr ):
- """Helper to define a counted list of expressions.
- This helper defines a pattern of the form::
- integer expr expr expr...
- where the leading integer tells how many expr expressions follow.
- The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
- """
- arrayExpr = Forward()
- def countFieldParseAction(s,l,t):
- n = int(t[0])
- arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
- return []
- return ( Word(nums).setParseAction(countFieldParseAction) + arrayExpr )
-
-def _escapeRegexRangeChars(s):
- #~ escape these chars: ^-]
- for c in r"\^-]":
- s = s.replace(c,"\\"+c)
- s = s.replace("\n",r"\n")
- s = s.replace("\t",r"\t")
- return _ustr(s)
-
-def oneOf( strs, caseless=False, useRegex=True ):
- """Helper to quickly define a set of alternative Literals, and makes sure to do
- longest-first testing when there is a conflict, regardless of the input order,
- but returns a MatchFirst for best performance.
-
- Parameters:
- - strs - a string of space-delimited literals, or a list of string literals
- - caseless - (default=False) - treat all literals as caseless
- - useRegex - (default=True) - as an optimization, will generate a Regex
- object; otherwise, will generate a MatchFirst object (if caseless=True, or
- if creating a Regex raises an exception)
- """
- if caseless:
- isequal = ( lambda a,b: a.upper() == b.upper() )
- masks = ( lambda a,b: b.upper().startswith(a.upper()) )
- parseElementClass = CaselessLiteral
- else:
- isequal = ( lambda a,b: a == b )
- masks = ( lambda a,b: b.startswith(a) )
- parseElementClass = Literal
-
- if isinstance(strs,(list,tuple)):
- symbols = strs[:]
- elif isinstance(strs,basestring):
- symbols = strs.split()
- else:
- warnings.warn("Invalid argument to oneOf, expected string or list",
- SyntaxWarning, stacklevel=2)
-
- i = 0
- while i < len(symbols)-1:
- cur = symbols[i]
- for j,other in enumerate(symbols[i+1:]):
- if ( isequal(other, cur) ):
- del symbols[i+j+1]
- break
- elif ( masks(cur, other) ):
- del symbols[i+j+1]
- symbols.insert(i,other)
- cur = other
- break
- else:
- i += 1
-
- if not caseless and useRegex:
- #~ print strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )
- try:
- if len(symbols)==len("".join(symbols)):
- return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) )
- else:
- return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) )
- except:
- warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
- SyntaxWarning, stacklevel=2)
-
-
- # last resort, just use MatchFirst
- return MatchFirst( [ parseElementClass(sym) for sym in symbols ] )
-
-def dictOf( key, value ):
- """Helper to easily and clearly define a dictionary by specifying the respective patterns
- for the key and value. Takes care of defining the Dict, ZeroOrMore, and Group tokens
- in the proper order. The key pattern can include delimiting markers or punctuation,
- as long as they are suppressed, thereby leaving the significant key text. The value
- pattern can include named results, so that the Dict results can include named token
- fields.
- """
- return Dict( ZeroOrMore( Group ( key + value ) ) )
-
-_bslash = "\\"
-printables = "".join( [ c for c in string.printable if c not in string.whitespace ] )
-
-# convenience constants for positional expressions
-empty = Empty().setName("empty")
-lineStart = LineStart().setName("lineStart")
-lineEnd = LineEnd().setName("lineEnd")
-stringStart = StringStart().setName("stringStart")
-stringEnd = StringEnd().setName("stringEnd")
-
-_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
-_printables_less_backslash = "".join([ c for c in printables if c not in r"\]" ])
-_escapedHexChar = Combine( Suppress(_bslash + "0x") + Word(hexnums) ).setParseAction(lambda s,l,t:unichr(int(t[0],16)))
-_escapedOctChar = Combine( Suppress(_bslash) + Word("0","01234567") ).setParseAction(lambda s,l,t:unichr(int(t[0],8)))
-_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1)
-_charRange = Group(_singleChar + Suppress("-") + _singleChar)
-_reBracketExpr = "[" + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
-
-_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p)
-
-def srange(s):
- r"""Helper to easily define string ranges for use in Word construction. Borrows
- syntax from regexp '[]' string range definitions::
- srange("[0-9]") -> "0123456789"
- srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz"
- srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
- The input string must be enclosed in []'s, and the returned string is the expanded
- character set joined into a single string.
- The values enclosed in the []'s may be::
- a single character
- an escaped character with a leading backslash (such as \- or \])
- an escaped hex character with a leading '\0x' (\0x21, which is a '!' character)
- an escaped octal character with a leading '\0' (\041, which is a '!' character)
- a range of any of the above, separated by a dash ('a-z', etc.)
- any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.)
- """
- try:
- return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body])
- except:
- return ""
-
-def replaceWith(replStr):
- """Helper method for common parse actions that simply return a literal value. Especially
- useful when used with transformString().
- """
- def _replFunc(*args):
- return [replStr]
- return _replFunc
-
-def removeQuotes(s,l,t):
- """Helper parse action for removing quotation marks from parsed quoted strings.
- To use, add this parse action to quoted string using::
- quotedString.setParseAction( removeQuotes )
- """
- return t[0][1:-1]
-
-def upcaseTokens(s,l,t):
- """Helper parse action to convert tokens to upper case."""
- return map( str.upper, t )
-
-def downcaseTokens(s,l,t):
- """Helper parse action to convert tokens to lower case."""
- return map( str.lower, t )
-
-def _makeTags(tagStr, xml):
- """Internal helper to construct opening and closing tag expressions, given a tag name"""
- tagAttrName = Word(alphanums)
- if (xml):
- tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
- openTag = Suppress("<") + Keyword(tagStr) + \
- Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
- Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
- else:
- printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] )
- tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
- openTag = Suppress("<") + Keyword(tagStr,caseless=True) + \
- Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
- Suppress("=") + tagAttrValue ))) + \
- Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
- closeTag = Combine("</" + Keyword(tagStr,caseless=not xml) + ">")
-
- openTag = openTag.setResultsName("start"+"".join(tagStr.replace(":"," ").title().split())).setName("<%s>" % tagStr)
- closeTag = closeTag.setResultsName("end"+"".join(tagStr.replace(":"," ").title().split())).setName("</%s>" % tagStr)
-
- return openTag, closeTag
-
-def makeHTMLTags(tagStr):
- """Helper to construct opening and closing tag expressions for HTML, given a tag name"""
- return _makeTags( tagStr, False )
-
-def makeXMLTags(tagStr):
- """Helper to construct opening and closing tag expressions for XML, given a tag name"""
- return _makeTags( tagStr, True )
-
-alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xfe]")
-
-_escapedChar = Regex(r"\\.")
-dblQuotedString = Regex(r'"([^"\n\r\\]|("")|(\\.))*"').setName("string enclosed in double quotes")
-sglQuotedString = Regex(r"'([^'\n\r\\]|('')|(\\.))*'").setName("string enclosed in single quotes")
-quotedString = Regex(r'''("([^"\n\r\\]|("")|(\\.))*")|('([^'\n\r\\]|('')|(\\.))*')''').setName("quotedString using single or double quotes")
-
-# it's easy to get these comment structures wrong - they're very common, so may as well make them available
-cStyleComment = Regex(r"\/\*[\s\S]*?\*\/").setName("C style comment")
-htmlComment = Regex(r"<!--[\s\S]*?-->")
-restOfLine = Regex(r".*").leaveWhitespace()
-dblSlashComment = Regex(r"\/\/.*").setName("// comment")
-cppStyleComment = Regex(r"(\/\*[\s\S]*?\*\/)|(\/\/.*)").setName("C++ style comment")
-javaStyleComment = cppStyleComment
-pythonStyleComment = Regex(r"#.*").setName("Python style comment")
-_noncomma = "".join( [ c for c in printables if c != "," ] )
-_commasepitem = Combine(OneOrMore(Word(_noncomma) +
- Optional( Word(" \t") +
- ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem")
-commaSeparatedList = delimitedList( Optional( quotedString | _commasepitem, default="") ).setName("commaSeparatedList")
-
-
-if __name__ == "__main__":
-
- def test( teststring ):
- print teststring,"->",
- try:
- tokens = simpleSQL.parseString( teststring )
- tokenlist = tokens.asList()
- print tokenlist
- print "tokens = ", tokens
- print "tokens.columns =", tokens.columns
- print "tokens.tables =", tokens.tables
- print tokens.asXML("SQL",True)
- except ParseException, err:
- print err.line
- print " "*(err.column-1) + "^"
- print err
- print
-
- selectToken = CaselessLiteral( "select" )
- fromToken = CaselessLiteral( "from" )
-
- ident = Word( alphas, alphanums + "_$" )
- columnName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
- columnNameList = Group( delimitedList( columnName ) )#.setName("columns")
- tableName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
- tableNameList = Group( delimitedList( tableName ) )#.setName("tables")
- simpleSQL = ( selectToken + \
- ( '*' | columnNameList ).setResultsName( "columns" ) + \
- fromToken + \
- tableNameList.setResultsName( "tables" ) )
-
- test( "SELECT * from XYZZY, ABC" )
- test( "select * from SYS.XYZZY" )
- test( "Select A from Sys.dual" )
- test( "Select AA,BB,CC from Sys.dual" )
- test( "Select A, B, C from Sys.dual" )
- test( "Select A, B, C from Sys.dual" )
- test( "Xelect A, B, C from Sys.dual" )
- test( "Select A, B, C frox Sys.dual" )
- test( "Select" )
- test( "Select ^^^ frox Sys.dual" )
- test( "Select A, B, C from Sys.dual, Table2 " )
=== removed directory 'Imaginary/imaginary/resources'
=== removed file 'Imaginary/imaginary/resources/__init__.py'
=== removed directory 'Imaginary/imaginary/resources/help'
=== removed file 'Imaginary/imaginary/resources/help/actions'
--- Imaginary/imaginary/resources/help/actions 2013-06-09 16:07:17 +0000
+++ Imaginary/imaginary/resources/help/actions 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-ACTIONS
-
-Usage: actions
-
-List all actions available to you.
=== removed file 'Imaginary/imaginary/resources/help/bury'
--- Imaginary/imaginary/resources/help/bury 2013-09-22 10:10:38 +0000
+++ Imaginary/imaginary/resources/help/bury 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-BURY
-
-Usage: bury <north | south | east | west>
-
-Block off the exit in the indicated direction. Short directions (n, s, e, w)
-may be used in place of the full direction names.
=== removed file 'Imaginary/imaginary/resources/help/close'
--- Imaginary/imaginary/resources/help/close 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/close 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-CLOSE
-
-Usage: close <name>
-
-Attempt to close an open container.
=== removed file 'Imaginary/imaginary/resources/help/commands'
--- Imaginary/imaginary/resources/help/commands 2013-06-09 16:07:17 +0000
+++ Imaginary/imaginary/resources/help/commands 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-COMMANDS
-
-See: help actions
=== removed file 'Imaginary/imaginary/resources/help/create'
--- Imaginary/imaginary/resources/help/create 2008-04-28 01:46:25 +0000
+++ Imaginary/imaginary/resources/help/create 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-CREATE
-
-Usage: create [a | an | the] <type> named <name> [description]
-
-Bring a new object of the specified type into existence, using the given name
-and, if provided, the description. If the "a" or "an" form is used, or if no
-article is supplied, the resulting object's name will be considered a common
-noun; if "the" is used, the name is considered a proper noun. The object will
-be created in your inventory. Creation may fail if you are unable to carry it.
-Anyone able to see you or the created object will witness the creation. The
-list of type available for creation is determined from the available
-IObjectType plugins on the system.
=== removed file 'Imaginary/imaginary/resources/help/describe'
--- Imaginary/imaginary/resources/help/describe 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/describe 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-DESCRIBE
-
-Usage: describe <name> <description>
-
-Change the description of the object with the given name.
=== removed file 'Imaginary/imaginary/resources/help/dig'
--- Imaginary/imaginary/resources/help/dig 2013-09-22 10:10:38 +0000
+++ Imaginary/imaginary/resources/help/dig 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-DIG
-
-Usage: dig <north | south | east | west> <name>
-
-Create a new location with the indicated name and create a two-way
-passage between it and the current location. The exit will be in
-the specified direction from the current location to the new
-location. Short directions (n, s, e, w) may be used in place of the
-full direction names.
=== removed file 'Imaginary/imaginary/resources/help/drop'
--- Imaginary/imaginary/resources/help/drop 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/drop 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-DROP
-
-Usage: drop <name>
-
-Get rid of the object in your inventory with the given name by
-depositing it in your current location.
=== removed file 'Imaginary/imaginary/resources/help/eat'
--- Imaginary/imaginary/resources/help/eat 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/eat 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-EAT
-
-Usage: eat <name>
-
-Consume the object with the given name.
=== removed file 'Imaginary/imaginary/resources/help/emote'
--- Imaginary/imaginary/resources/help/emote 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/emote 1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-EMOTE
-
-Usage: emote <expression>
-
-From WordNet (r) 2.0 [wn]:
-
- emote
- v : give expression or emotion to, in a stage or movie role
-
=== removed file 'Imaginary/imaginary/resources/help/equipment'
--- Imaginary/imaginary/resources/help/equipment 2006-04-19 23:48:41 +0000
+++ Imaginary/imaginary/resources/help/equipment 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-EQUIPMENT
-
-Usage: equipment
-
-Display the garments you are currently wearing.
=== removed file 'Imaginary/imaginary/resources/help/find'
--- Imaginary/imaginary/resources/help/find 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/find 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-FIND (DEPRECATED)
-
-Usage: find <name>
-
-Look around the immediate area for an object with the given name.
=== removed file 'Imaginary/imaginary/resources/help/get'
--- Imaginary/imaginary/resources/help/get 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/get 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-GET
-
-Usage: get <name>
-
-Retrieve the object with the given name from the immediate vicinity
-and stash it in your inventory.
=== removed file 'Imaginary/imaginary/resources/help/go'
--- Imaginary/imaginary/resources/help/go 2013-09-22 10:10:38 +0000
+++ Imaginary/imaginary/resources/help/go 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-GO
-
-Usage: go <north | south | east | west>
-
-Travel in the indicated direction. Short directions (n, s, e, w) may be used
-in place of the full direction names.
=== removed file 'Imaginary/imaginary/resources/help/help'
--- Imaginary/imaginary/resources/help/help 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/help 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-HELP
-
-Usage: help <command>
-
-Provides information on the usage of the indicated command.
=== removed file 'Imaginary/imaginary/resources/help/hit'
--- Imaginary/imaginary/resources/help/hit 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/hit 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-HIT
-
-Usage: hit <name>
-
-Violently attack the animal, mineral, or vegetable with the given name.
=== removed file 'Imaginary/imaginary/resources/help/illuminate'
--- Imaginary/imaginary/resources/help/illuminate 2006-05-14 03:23:29 +0000
+++ Imaginary/imaginary/resources/help/illuminate 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-ILLUMINATE
-
-Usage: illuminate <candelas>
-
-Set the ambient illumination level of your current location. Candelas is a
-non-negative integer. A hand-held torch is approximately 80 candelas.
=== removed file 'Imaginary/imaginary/resources/help/inventory'
--- Imaginary/imaginary/resources/help/inventory 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/inventory 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-INVENTORY
-
-Usage: inventory
-
-Display the objects currently in your possession.
=== removed file 'Imaginary/imaginary/resources/help/list'
--- Imaginary/imaginary/resources/help/list 2008-04-28 01:17:18 +0000
+++ Imaginary/imaginary/resources/help/list 1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-LIST
-
-Usage: list <listable>
-
-<listable> things are thus:
-
- thing types
-
-See "help list <listable>" for more details.
-
=== removed file 'Imaginary/imaginary/resources/help/list thing types'
--- Imaginary/imaginary/resources/help/list thing types 2008-04-28 01:17:18 +0000
+++ Imaginary/imaginary/resources/help/list thing types 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-LIST THING TYPES
-
-Usage: list thing types
-
-Show a list of names of things which can be created with the create command.
=== removed file 'Imaginary/imaginary/resources/help/look'
--- Imaginary/imaginary/resources/help/look 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/look 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
-LOOK
-
-Usage: look [name]
-
-If a name is given, examine something in particular. Otherwise, take
-in your immediate surroundings.
=== removed file 'Imaginary/imaginary/resources/help/name'
--- Imaginary/imaginary/resources/help/name 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/name 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-NAME
-
-Usage: name <old name> <new name>
-
-Change the name of something.
=== removed file 'Imaginary/imaginary/resources/help/open'
--- Imaginary/imaginary/resources/help/open 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/open 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-OPEN
-
-Usage: open <name>
-
-Attempt to open a closed container.
=== removed file 'Imaginary/imaginary/resources/help/put'
--- Imaginary/imaginary/resources/help/put 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/put 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-PUT
-
-Usage: put <item name> in <container name>
-
-Attempt to place an object inside another object.
=== removed file 'Imaginary/imaginary/resources/help/quit'
--- Imaginary/imaginary/resources/help/quit 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/quit 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-QUIT
-
-Usage: quit
-
-Depart the realm.
=== removed file 'Imaginary/imaginary/resources/help/rebuild'
--- Imaginary/imaginary/resources/help/rebuild 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/rebuild 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-REBUILD
-
-Usage: rebuild
-
-Load new source code from disk and attempt to incorporate it into the running world.
=== removed file 'Imaginary/imaginary/resources/help/remove'
--- Imaginary/imaginary/resources/help/remove 2006-04-19 23:48:41 +0000
+++ Imaginary/imaginary/resources/help/remove 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-REMOVE
-
-Usage: remove <name>
-
-Take the piece of clothing named off of your body.
=== removed file 'Imaginary/imaginary/resources/help/restore'
--- Imaginary/imaginary/resources/help/restore 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/restore 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-RESTORE
-
-Usage: restore <name>
-
-Heal, revitalize, and rejuvenate the named animal, mineral, or vegetable.
=== removed file 'Imaginary/imaginary/resources/help/say'
--- Imaginary/imaginary/resources/help/say 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/say 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-SAY
-
-Usage: say <text>
-
-Utter the given words so as to be audible to those in your immediate surroundings.
=== removed file 'Imaginary/imaginary/resources/help/score'
--- Imaginary/imaginary/resources/help/score 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/score 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-SCORE
-
-Usage: score
-
-Reveal the details of your personal progress.
=== removed file 'Imaginary/imaginary/resources/help/scrutinize'
--- Imaginary/imaginary/resources/help/scrutinize 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/scrutinize 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-SCRUTINIZE
-
-Usage: scrutinize <name>
-
-Reveal the innermost structure of the indicated object or actor.
=== removed file 'Imaginary/imaginary/resources/help/search'
--- Imaginary/imaginary/resources/help/search 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/search 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-SEARCH
-
-Usage: search <name>
-
-Look around the immediate area for an object with the given name.
=== removed file 'Imaginary/imaginary/resources/help/set'
--- Imaginary/imaginary/resources/help/set 2008-05-05 00:17:30 +0000
+++ Imaginary/imaginary/resources/help/set 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
-SET
-
-Usage: set <gender | proper> of <target> to <value>
-
-Change the value of a model attribute on a thing to a new value. Acceptable
-values for gender are "male", "female", and "neuter". Acceptable values for
-proper are "true" and "false".
=== removed file 'Imaginary/imaginary/resources/help/take'
--- Imaginary/imaginary/resources/help/take 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/take 1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-TAKE
-
-See GET
=== removed file 'Imaginary/imaginary/resources/help/wear'
--- Imaginary/imaginary/resources/help/wear 2006-04-19 23:48:41 +0000
+++ Imaginary/imaginary/resources/help/wear 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-WEAR
-
-Usage: wear <name>
-
-Put the piece of clothing named onto your body.
=== removed file 'Imaginary/imaginary/resources/help/who'
--- Imaginary/imaginary/resources/help/who 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/resources/help/who 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-WHO
-
-Usage: who
-
-Display a list of currently connected characters.
=== removed file 'Imaginary/imaginary/resources/motd'
--- Imaginary/imaginary/resources/motd 2009-08-29 20:37:07 +0000
+++ Imaginary/imaginary/resources/motd 1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-IMAGINARY %(imaginaryVersion)s
-TWISTED %(twistedVersion)s
-PYTHON %(pythonVersion)s
-
-Created by IMAGINARY TEAM
=== removed directory 'Imaginary/imaginary/test'
=== removed file 'Imaginary/imaginary/test/__init__.py'
--- Imaginary/imaginary/test/__init__.py 2006-04-12 02:41:46 +0000
+++ Imaginary/imaginary/test/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-
=== removed file 'Imaginary/imaginary/test/commandutils.py'
--- Imaginary/imaginary/test/commandutils.py 2013-07-03 22:43:56 +0000
+++ Imaginary/imaginary/test/commandutils.py 1970-01-01 00:00:00 +0000
@@ -1,253 +0,0 @@
-# -*- test-case-name: imaginary.test -*-
-import pprint
-from re import compile, escape as E
-E # export for other modules
-
-from zope.interface import implements
-
-from twisted.trial import unittest
-from twisted.test.proto_helpers import StringTransport
-
-from axiom import store, item, attributes
-
-from imaginary import iimaginary, objects, text, language
-from imaginary.wiring import player
-from imaginary.world import ImaginaryWorld
-
-class PlayerProtocol(object):
- def __init__(self, transport):
- self.transport = transport
-
- def write(self, crap):
- self.transport.write(crap)
-
-
-class CommandTestCaseMixin:
- """
- A mixin for TestCase classes which provides support for testing Imaginary
- environments via command-line transcripts.
-
- @ivar store: the L{store.Store} containing all the relevant game objects.
-
- @ivar location: The location where the test is taking place.
-
- @ivar world: The L{ImaginaryWorld} that created the player.
-
- @ivar player: The L{Thing} representing the main player.
-
- @ivar observer: The L{Thing} representing the observer who sees the main
- player's actions.
- """
- def setUp(self):
- """
- Set up a store with a location, a player and an observer.
- """
- self.store = store.Store()
- locContainer = createLocation(
- self.store, u"Test Location", u"Location for testing.")
- self.location = locContainer.thing
- self.world = ImaginaryWorld(store=self.store, origin=self.location)
- self.player = self.world.create(
- u"Test Player", gender=language.Gender.FEMALE)
- self.playerContainer = iimaginary.IContainer(self.player)
- self.playerWrapper = player.Player(self.player)
-
- self.playerWrapper.useColors = False
- locContainer.add(self.player)
- self.transport = StringTransport()
- self.playerWrapper.setProtocol(PlayerProtocol(self.transport))
-
- self.observer = self.world.create(
- u"Observer Player", gender=language.Gender.FEMALE)
- self.observerWrapper = player.Player(self.observer)
- locContainer.add(self.observer)
- self.otransport = StringTransport()
- self.observerWrapper.setProtocol(PlayerProtocol(self.otransport))
-
- # Clear the transport, since we don't care about the observer
- # arrival event.
- self.transport.clear()
-
-
- def tearDown(self):
- """
- Disconnect the player and observer from their respective transports.
- """
- for p in self.player, self.observer:
- try:
- p.destroy()
- except AttributeError:
- pass
-
-
- def watchCommand(self, command):
- """
- Make C{self.player} run the given command and return the output both
- she and C{self.observer} receive.
-
- @param command: The textual command to run.
- @type command: C{unicode}
- @return: The player's output and the third-party observer's output.
- @rtype: Two-tuple of C{unicode}
- """
- self.playerWrapper.parse(command)
- return (
- self.transport.value().decode('utf-8'),
- self.otransport.value().decode('utf-8'))
-
-
- def assertCommandOutput(self, command, output, observed=()):
- """
- Verify that when C{command} is executed by this
- L{CommandTestCaseMixin.playerWrapper}, C{output} is produced (to the
- actor) and C{observed} is produced (to the observer).
-
- @param command: The string for L{CommandTestCaseMixin.playerWrapper} to
- execute.
- @type command: L{str}
-
- @param output: The expected output of C{command} for
- L{CommandTestCaseMixin.player} to observe.
- @type output: iterable of L{str}
-
- @param observed: The expected output that
- L{CommandTestCaseMixin.observer} will observe.
- @type observed: iterable of L{str}
- """
- if command is not None:
- # Deprecate this or something
- if not isinstance(command, unicode):
- command = unicode(command, 'ascii')
- self.playerWrapper.parse(command)
- output.insert(0, "> " + command)
-
- results = []
- for perspective, xport, oput in ([
- ('actor' ,self.transport, output),
- ('observer', self.otransport, observed)]):
- results.append([])
- gotLines = xport.value().decode('utf-8').splitlines()
- for i, (got, expected) in enumerate(map(None, gotLines, oput)):
- got = got or ''
- expected = expected or '$^'
- m = compile(expected.rstrip() + '$').match(got.rstrip())
- if m is None:
- s1 = pprint.pformat(gotLines)
- s2 = pprint.pformat(oput)
- raise unittest.FailTest(
- "\n%s %s\ndid not match expected\n%s\n(Line %d)" % (
- repr(perspective), s1, s2, i))
- results[-1].append(m)
- xport.clear()
- return results
-
- # Old alias.
- _test = assertCommandOutput
-
-
- def find(self, name):
- return [
- th
- for th in self.player.findProviders(iimaginary.IThing, 1)
- if th.name == name][0]
-
-
-
-def flatten(expr):
- """
- Test utility method to turn a list of strings character attribute
- declarations and similar lists into a single string with all character
- attribute information removed.
- """
- return u''.join(list(text.flatten(expr, currentAttrs=text.AttributeSet())))
-
-
-
-class LanguageMixin(object):
- def flatten(self, expr):
- return flatten(expr)
-
-
-
-class MockIntelligence(item.Item):
- """
- A persistent intelligence which accumulates observed events in a
- list for later retrieval and assertion. This should be
- instantiated and passed to
- L{iimaginary.IActor.setEnduringIntelligence}.
-
- XXX: This should probably be unnecessary at some point. It is used
- with code which assumes a persistent intelligence is involved.
- """
- implements(iimaginary.IEventObserver)
-
- anAttribute = attributes.integer()
- concepts = attributes.inmemory()
-
- def activate(self):
- self.concepts = []
-
-
- def prepare(self, concept):
- return lambda: self.concepts.append(concept)
-
-
-
-class MockEphemeralIntelligence(object):
- """
- Like L{MockIntelligence}, but it should be used with
- L{iimaginary.IActor.setEphemeralIntelligence}.
- """
- implements(iimaginary.IEventObserver)
-
- def __init__(self):
- self.events = []
-
-
- def prepare(self, event):
- return lambda: self.events.append(event)
-
-
-
-def createLocation(store, name, description):
- """
- Create a new L{Thing} and create an L{objects.Container} for it.
-
- @param name: The name given to the created L{Thing}.
- @type name: L{unicode}
-
- @param description: The description given to the created L{Thing}.
- @type description: L{unicode}
-
- @return: The containment enhancement of the created L{Thing}.
- @rtype: L{objects.Container}.
- """
- location = objects.Thing(
- store=store, name=name, description=description, proper=True)
-
- return objects.Container.createFor(
- location, capacity=1000,
- contentsTemplate=u"Here, you see {contents}.")
-
-
-
-def createPlayer(store, name):
- """
- Create a mock player with a mock intelligence with the given
- name. The intelligence is a L{MockIntelligence} which can have its
- concepts introspected.
-
- @type store: L{axiom.store.Store}.
- @type name: C{unicode}.
- @param name: The name of the newly-created player.
- @return: A three-tuple of (playerThing, playerActor, playerIntelligence).
- """
- player = objects.Thing(store=store, name=name)
- objects.Container.createFor(player, capacity=100)
- playerActor = objects.Actor.createFor(player)
- playerIntelligence = MockIntelligence(store=store)
- playerActor.setEnduringIntelligence(playerIntelligence)
- return player, playerActor, playerIntelligence
-
-__all__ = ['E', 'CommandTestCaseMixin', 'createPlayer', 'MockIntelligence',
- 'PlayerProtocol']
=== removed file 'Imaginary/imaginary/test/test_actions.py'
--- Imaginary/imaginary/test/test_actions.py 2013-08-23 20:38:31 +0000
+++ Imaginary/imaginary/test/test_actions.py 1970-01-01 00:00:00 +0000
@@ -1,842 +0,0 @@
-
-"""
-Unit tests for Imaginary actions.
-"""
-
-from twisted.trial import unittest
-from twisted.python import filepath
-
-from imaginary import iimaginary, objects, events
-from imaginary.action import Action, TargetAction, Help
-from imaginary.test import commandutils
-from imaginary.test.commandutils import E
-
-# Regular expression for matching variable parts of the output of certain
-# commands.
-PTR = "[A-F0-9]{1,16}"
-STOREID = "\\d+"
-
-class TransactionalEventBroadcasterTestCase(unittest.TestCase):
- def testAddEvent(self):
- L = []
- teb = events.TransactionalEventBroadcaster()
- teb.addEvent(lambda: L.append('win'))
- teb.addRevertEvent(lambda: L.append('lose'))
- teb.broadcastEvents()
- self.assertEquals(L, ['win'])
-
-
- def testAddRevertEvent(self):
- L = []
- teb = events.TransactionalEventBroadcaster()
- teb.addEvent(lambda: L.append('lose'))
- teb.addRevertEvent(lambda: L.append('win'))
- teb.broadcastRevertEvents()
- self.assertEquals(L, ['win'])
-
-
- def testBadEvents(self):
- teb = events.TransactionalEventBroadcaster()
- self.assertRaises(ValueError, teb.addEvent, None)
- self.assertRaises(ValueError, teb.addRevertEvent, None)
-
-
-
-class TargetActionTests(commandutils.CommandTestCaseMixin, unittest.TestCase):
- """
- Tests for general functionality provided by L{TargetAction} which is not
- specific to any particular action.
- """
- def test_resolveTarget(self):
- """
- L{TargetAction.resolve} finds things by name when passed a C{"target"}
- string.
- """
- self.assertEqual(
- TargetAction().resolve(self.player, "target", u"Observer Player"),
- [self.observer])
-
-
- def test_resolveTargetCaseInsensitively(self):
- """
- L{TargetAction.resolve} considers names case-insensitively when
- searching for things.
- """
- self.assertEqual(
- TargetAction().resolve(self.player, "target", u"observer player"),
- [self.observer])
-
-
-
-class Actions(commandutils.CommandTestCaseMixin, unittest.TestCase):
-
- def testBadCommand(self):
- self._test(
- "jibber jabber",
- ["Bad command or filename"])
-
- def testInventory(self):
- # There ain't no stuff
- self._test(
- "inventory",
- ["Inventory:"])
-
- playerContainer = iimaginary.IContainer(self.player)
-
- # Give 'em something and make sure
- # they show up
- playerContainer.add(objects.Thing(store=self.store, name=u"foobar"))
- self._test(
- "inventory",
- ["Inventory:",
- "foobar"])
-
- # Give 'em a couple more things
- playerContainer.add(objects.Thing(store=self.store, name=u"barbaz"))
- playerContainer.add(objects.Thing(store=self.store, name=u"barbaz"))
- self._test(
- "inventory",
- ["Inventory:",
- "foobar",
- "barbaz",
- "barbaz"])
-
-
- def test_actions(self):
- """
- The I{actions} action lists all of the actions a character can take.
- """
- cmds = dict.fromkeys([
- getattr(cls, 'actionName', cls.__name__.lower())
- for cls
- in Action.actions]).keys()
- cmds.sort()
- self._test(
- "actions",
- [' '.join(cmds)])
-
-
- def test_commands(self):
- """
- The I{commands} action is a stub to help those unfamiliar with
- Imaginary's action system find their way to the I{actions} command
- instead.
- """
- self._test(
- "commands",
- ["Try 'actions' instead."])
-
-
- def testGet(self):
- # Try to get something that does not exist
- self._test(
- "get foobar",
- ["Nothing like that around here."])
-
- # Try to get yourself
- self._test(
- "get self",
- ["You cannot take Test Player."])
- self.assertEquals(self.player.location, self.location)
-
- # Try to get the location
- self._test(
- "get here",
- ["You cannot take Test Location."])
- self.assertEquals(self.location.location, None)
-
- # Make an object and try to get it
- o = objects.Thing(store=self.store, name=u"foo")
- iimaginary.IContainer(self.location).add(o)
- self._test(
- "get foo",
- ["You take a foo."],
- ["Test Player takes a foo."])
- self.assertEquals(o.location, self.player)
-
- # Try to get the observer
- self._test(
- "get 'Observer Player'",
- ["Observer Player is too heavy to pick up."],
- ["Test Player tries to pick you up, but fails."])
- self.assertEquals(self.observer.location, self.location)
-
- # Container stuff
- self._test(
- "get baz from bar",
- ["Nothing like that around here."])
-
- c = objects.Thing(store=self.store, name=u"bar")
- cContainer = objects.Container.createFor(c, capacity=1)
-
- iimaginary.IContainer(self.location).add(c)
- o = objects.Thing(store=self.store, name=u"baz")
- cContainer.add(o)
- self._test(
- "get baz from bar",
- ["You take a baz from the bar."],
- ["Test Player takes a baz from the bar."])
- self.assertEquals(o.location, self.player)
-
- # Can't get things from a closed container
- o.moveTo(c)
- cContainer.closed = True
- self._test(
- "get baz from bar",
- ["Nothing like that around here."],
- [])
- self.assertEquals(o.location, c)
- self.assertEquals(list(cContainer.getContents()), [o])
-
- def testDrop(self):
- self._test(
- "drop foo",
- ["Nothing like that around here."])
-
- o = objects.Thing(store=self.store, name=u"bar")
- iimaginary.IContainer(self.player).add(o)
- self._test(
- "drop bar",
- ["You drop the bar."],
- ["Test Player drops a bar."])
- self.assertEquals(o.location, self.location)
-
-
- def testLook(self):
- self._test(
- "look",
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player."])
-
- self._test(
- "look here",
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player."])
-
- objects.Exit.link(self.location, self.location, u"north")
- self._test(
- "look here",
- [E("[ Test Location ]"),
- E("( north south )"),
- "Location for testing.",
- "Here, you see Observer Player."])
-
- self._test(
- "look me",
- [E("[ Test Player ]"),
- "Test Player is great.",
- "She is naked."])
-
- self._test(
- "look at me",
- [E("[ Test Player ]"),
- "Test Player is great.",
- "She is naked."])
-
- self._test(
- "look at Observer Player",
- [E("[ Observer Player ]"),
- "Observer Player is great.",
- "She is naked."],
- ["Test Player looks at you."])
-
-
- o = objects.Thing(store=self.store, name=u"foo")
- iimaginary.IContainer(self.location).add(o)
- self._test(
- "look at foo",
- [E("[ foo ]")])
-
- self._test(
- "look at bar",
- ["You don't see that."])
-
-
- def testSay(self):
- self._test(
- "say hello",
- ["You say, 'hello'"],
- ["Test Player says, 'hello'"])
-
- self._test(
- "'hello",
- ["You say, 'hello'"],
- ["Test Player says, 'hello'"])
-
- self._test(
- "'hello world! quote -> '",
- ["You say, 'hello world! quote -> ''"],
- ["Test Player says, 'hello world! quote -> ''"])
-
- def testEmote(self):
- self._test(
- "emote jumps up and down",
- ["Test Player jumps up and down"],
- ["Test Player jumps up and down"])
-
- self._test(
- ":jumps up and down",
- ["Test Player jumps up and down"],
- ["Test Player jumps up and down"])
-
- def testSearch(self):
- self._test(
- "search self",
- [E("[ Test Player ]"),
- "Test Player is great.",
- "She is naked.",
- ""])
-
- self._test(
- "search me",
- [E("[ Test Player ]"),
- "Test Player is great.",
- "She is naked.",
- ""])
-
- self._test(
- "search here",
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player.",
- ""])
-
- self._test(
- "search 'Test Player'",
- [E("[ Test Player ]"),
- "Test Player is great.",
- "She is naked.",
- ""])
-
- self._test(
- 'search "Observer Player"',
- [E("[ Observer Player ]"),
- "Observer Player is great.",
- "She is naked.",
- ""])
-
- self._test(
- "search blub",
- [""])
-
- def testDescribe(self):
- self._test(
- "describe me test description",
- ["You change Test Player's description."],
- ["Test Player changes Test Player's description."])
- self.assertEquals(self.player.description,
- "test description")
-
- self._test(
- "describe here description test",
- ["You change Test Location's description."],
- ["Test Player changes Test Location's description."])
- self.assertEquals(self.location.description,
- "description test")
-
-
- def testName(self):
- self._test(
- "name me fooix",
- ["You change Test Player's name."],
- ["Test Player changes Test Player's name to fooix."])
- self.assertEquals(self.player.name,
- "fooix")
-
- self._test(
- "name here CRAP of CRAPness",
- ["You change Test Location's name."],
- ["Fooix changes Test Location's name to CRAP of CRAPness."])
- self.assertEquals(self.location.name,
- "CRAP of CRAPness")
-
-
- def testRestore(self):
- self._test(
- "restore foobar",
- [E("Who's that?")])
-
- self._test(
- "restore here",
- ["Test Location cannot be restored."])
-
- actor = iimaginary.IActor(self.player)
- actor.hitpoints.decrease(25)
- actor.stamina.decrease(25)
- self._test(
- "restore self",
- ["You have fully restored yourself."])
- self.assertEquals(actor.hitpoints.current,
- actor.hitpoints.max)
- self.assertEquals(actor.stamina.current,
- actor.stamina.max)
-
- oactor = iimaginary.IActor(self.observer)
- oactor.hitpoints.decrease(25)
- oactor.stamina.decrease(25)
- self._test(
- "restore Observer Player",
- ["You have restored Observer Player to full health."],
- ["Test Player has restored you to full health."])
- self.assertEquals(oactor.hitpoints.current,
- oactor.hitpoints.max)
- self.assertEquals(oactor.stamina.current,
- oactor.stamina.max)
-
- def testScore(self):
- # XXX This is kind of weak. How can this test be improved?
- x, y = self._test(
- "score",
- [".*",
- ".*Level: +(\\d+) Experience: +(\\d+)",
- ".*Hitpoints: +(\\d+)/(\\d+)",
- ".*Stamina: +(\\d+)/(\\d+)",
- ".*"])
- self.assertEquals(x[0].groups(), ()) # Extra line for the command
- self.assertEquals(x[1].groups(), ())
- self.assertEquals(x[2].groups(), ('0', '0'))
- self.assertEquals(x[3].groups(), ('100', '100'))
- self.assertEquals(x[4].groups(), ('100', '100'))
- self.assertEquals(x[5].groups(), ())
-
- actor = iimaginary.IActor(self.player)
- actor.level = 3
- actor.experience = 63
- actor.hitpoints.current = 32
- actor.hitpoints.max = 74
- actor.stamina.current = 12
- actor.stamina.max = 39
- x, y = self._test(
- "score",
- [".*",
- ".*Level: +(\\d+) Experience: +(\\d+)",
- ".*Hitpoints: +(\\d+)/(\\d+)",
- ".*Stamina: +(\\d+)/(\\d+)",
- ".*"])
- self.assertEquals(x[0].groups(), ())
- self.assertEquals(x[1].groups(), ())
- self.assertEquals(x[2].groups(), ('3', '63'))
- self.assertEquals(x[3].groups(), ('32', '74'))
- self.assertEquals(x[4].groups(), ('12', '39'))
- self.assertEquals(x[5].groups(), ())
-
-
- def test_dig(self):
- """
- The I{dig} action creates a new location connected to the current
- location through an exit in the specified direction.
- """
- self._test(
- "dig west dark tunnel",
- ["You create an exit."],
- ["Test Player created an exit to the west."])
- room = iimaginary.IContainer(self.location).getExitNamed(u'west').toLocation
- self.assertEquals(room.name, u"dark tunnel")
- self.assertEquals(room.description, u'')
- self.assertIdentical(iimaginary.IContainer(room).getExitNamed(u'east').toLocation,
- self.location)
-
- self._test(
- "dig east bright tunnel",
- ["You create an exit."],
- ["Test Player created an exit to the east."])
- room = iimaginary.IContainer(self.location).getExitNamed(u'east').toLocation
- self.assertEquals(room.name, u"bright tunnel")
- self.assertEquals(room.description, u'')
- self.assertIdentical(iimaginary.IContainer(room).getExitNamed(u'west').toLocation, self.location)
-
- self._test(
- "dig west boring tunnel",
- ["There is already an exit in that direction."])
-
-
- def test_digWithDirectionAliases(self):
- """
- The I{dig} action creates a new location connected to the current
- location through an exit in the specified direction even when that
- direction is an alias.
- """
- self._test(
- "dig w dark tunnel",
- ["You create an exit."],
- ["Test Player created an exit to the west."])
- room = iimaginary.IContainer(self.location).getExitNamed(u'west').toLocation
- self.assertEquals(room.name, u"dark tunnel")
- self.assertEquals(room.description, u'')
- self.assertIdentical(iimaginary.IContainer(room).getExitNamed(u'east').toLocation,
- self.location)
-
- self._test(
- "dig e bright tunnel",
- ["You create an exit."],
- ["Test Player created an exit to the east."])
- room = iimaginary.IContainer(self.location).getExitNamed(u'east').toLocation
- self.assertEquals(room.name, u"bright tunnel")
- self.assertEquals(room.description, u'')
- self.assertIdentical(iimaginary.IContainer(room).getExitNamed(u'west').toLocation, self.location)
-
- self._test(
- "dig w boring tunnel",
- ["There is already an exit in that direction."])
-
-
- def test_bury(self):
- """
- The I{bury} action destroys an exit in the specified direction.
- """
- self._test(
- "bury south",
- ["There isn't an exit in that direction."])
- self.assertEquals(list(iimaginary.IContainer(self.location).getExits()), [])
-
- room = objects.Thing(store=self.store, name=u"destination", proper=True)
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(room, self.location, u'north')
-
- self._test(
- "bury south",
- ["It's gone."],
- ["Test Player destroyed the exit to destination."])
-
- self.assertEquals(
- list(iimaginary.IContainer(self.location).getExits()),
- [])
-
- self.assertEquals(
- list(iimaginary.IContainer(room).getExits()),
- [])
-
- objects.Exit.link(self.location, room, u'south')
- self.observer.moveTo(room)
-
- self._test(
- "bury south",
- ["It's gone."],
- ["The exit to Test Location crumbles and disappears."])
- self.assertEquals(
- list(iimaginary.IContainer(self.location).getExits()),
- [])
- self.assertEquals(
- list(iimaginary.IContainer(room).getExits()),
- [])
-
-
- def test_buryWithDirectionAliases(self):
- """
- The I{bury} action destroys an exit in the specified direction even
- when that direction is an alias.
- """
- self._test(
- "bury s",
- ["There isn't an exit in that direction."])
- self.assertEquals(list(iimaginary.IContainer(self.location).getExits()), [])
-
- room = objects.Thing(store=self.store, name=u"destination", proper=True)
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(room, self.location, u'north')
-
- self._test(
- "bury s",
- ["It's gone."],
- ["Test Player destroyed the exit to destination."])
-
- self.assertEquals(
- list(iimaginary.IContainer(self.location).getExits()),
- [])
-
- self.assertEquals(
- list(iimaginary.IContainer(room).getExits()),
- [])
-
- objects.Exit.link(self.location, room, u'south')
- self.observer.moveTo(room)
-
- self._test(
- "bury s",
- ["It's gone."],
- ["The exit to Test Location crumbles and disappears."])
- self.assertEquals(
- list(iimaginary.IContainer(self.location).getExits()),
- [])
- self.assertEquals(
- list(iimaginary.IContainer(room).getExits()),
- [])
-
-
- def test_go(self):
- """
- The I{go} action moves the player through an exit in the specified
- direction.
- """
- self._test(
- "go west",
- ["You can't go that way."])
- self._test(
- "west",
- ["You can't go that way."])
-
- room = objects.Thing(store=self.store, name=u"destination")
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(self.location, room, u"west")
-
- self._test(
- "west",
- [E("[ destination ]"),
- E("( east )"),
- ""],
- ["Test Player leaves west."])
-
- self._test(
- "north",
- ["You can't go that way."])
- self._test(
- "go east",
- [E("[ Test Location ]"),
- E("( west )"),
- "Location for testing.",
- "Here, you see Observer Player."],
- ["Test Player arrives from the west."])
-
-
- def test_goThroughDirectionAliases(self):
- """
- The I{go} action moves the player through an exit in the specified
- direction even when that direction is an alias.
- """
- self._test(
- "go w",
- ["You can't go that way."])
- self._test(
- "w",
- ["You can't go that way."])
-
- room = objects.Thing(store=self.store, name=u"destination")
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(self.location, room, u"west")
-
- self._test(
- "w",
- [E("[ destination ]"),
- E("( east )"),
- ""],
- ["Test Player leaves west."])
-
- self._test(
- "n",
- ["You can't go that way."])
- self._test(
- "go e",
- [E("[ Test Location ]"),
- E("( west )"),
- "Location for testing.",
- "Here, you see Observer Player."],
- ["Test Player arrives from the west."])
-
-
- def test_goThroughOneWayExit(self):
- """
- Going through a one-way exit with a known direction will announce that
- the player arrived from that direction; with an unknown direction it
- will simply announce that they have arrived.
- """
- secretRoom = objects.Thing(store=self.store, name=u'Secret Room!')
- objects.Container.createFor(secretRoom, capacity=1000)
- myExit = objects.Exit(store=self.store, fromLocation=secretRoom,
- toLocation=self.location, name=u'north')
- self.player.moveTo(secretRoom)
- self._test(
- "north",
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player."],
- ["Test Player arrives from the south."])
- self.player.moveTo(secretRoom)
- myExit.name = u'elsewhere'
- self.assertCommandOutput(
- "go elsewhere",
- [E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player."],
- ["Test Player arrives."])
-
-
- def test_goDoesntJumpOverExits(self):
- """
- You can't go through an exit without passing through exits which lead
- to it. Going through an exit named 'east' will only work if it is east
- of your I{present} location, even if it is easily reachable from where
- you stand.
- """
- northRoom = objects.Thing(store=self.store, name=u'Northerly')
- eastRoom = objects.Thing(store=self.store, name=u'Easterly')
- for room in northRoom, eastRoom:
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(self.location, northRoom, u'north', distance=0.1)
- objects.Exit.link(northRoom, eastRoom, u'east', distance=0.1)
- self.assertCommandOutput("go east", [E("You can't go that way.")], [])
-
-
- def test_directionalMovement(self):
- """
- You can move through exits in standard directions by just specifying
- the direction.
- """
- # A couple tweaks to state to make the test simpler
- self.observer.location = None
- self.location.description = None
-
- oldRoom = self.location
- allDirections = ["northwest", "north", "northeast", "east",
- "west", "southwest", "south", "southeast"]
- for d in allDirections[:len(allDirections) / 2]:
- room = objects.Thing(store=self.store, name=u"destination")
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(oldRoom, room, unicode(d, 'ascii'))
- oldRoom = room
-
- for d, rd in zip(allDirections, reversed(allDirections)):
- self._test(
- d,
- [E("[ ") + ".*" + E(" ]"), # Not testing room description
- E("( ") + ".*" + E(" )"), # Just do enough to make sure it was not an error.
- ""])
- shortDirections = ["nw", "n", "ne", "e", "w", "sw", "s", "se"]
- for d, rd in zip(shortDirections, reversed(shortDirections)):
- self._test(
- d,
- [E("[ ") + ".*" + E(" ]"), # Not testing room description
- E("( ") + ".*" + E(" )"), # Just do enough to make sure it was not an error.
- ""])
-
-
- def test_scrutinize(self):
- """
- The scrutinize action takes a thing as a target and displays a lot of
- details about its internal state and construction.
- """
- self._test(
- "scrutinize me",
- [E("('Thing',"),
- E(" {'contents': [],"),
- E(" 'description': u'',"),
- E(" 'gender': 2,"),
- E(" 'location': Thing(description=u'Location for testing.', "
- "gender=3, location=None, name=u'Test Location', portable=True, "
- "proper=True, weight=1, storeID=") + STOREID + E(")@0x") + PTR
- + E(","),
- E(" 'name': u'Test Player',"),
- E(" 'portable': True,"),
- E(" 'proper': True,"),
- E(" 'weight': 100})"),
- ])
-
- self._test(
- "scrutinize here",
- [E("('Thing',"),
- E(" {'contents': [Thing(description=u'', gender=2, location="
- "reference(") +
- STOREID + E("), name=u'Test Player', portable=True, proper="
- "True, weight=100, storeID=") +
- STOREID + E(")@0x") + PTR + E(","),
- E(" Thing(description=u'', gender=2, location="
- "reference(") +
- STOREID + E("), name=u'Observer Player', portable=True, "
- "proper=True, weight=100, storeID=") +
- STOREID + E(")@0x") + PTR + E("],"),
- E(" 'description': u'Location for testing.',"),
- E(" 'gender': 3,"),
- E(" 'location': None,"),
- E(" 'name': u'Test Location',"),
- E(" 'portable': True,"),
- E(" 'proper': True,"),
- E(" 'weight': 1})")])
-
-
- def test_scrutinizeNonContainer(self):
- """
- The scrutinize action produces results for a thing which is not a
- container.
- """
- o = objects.Thing(store=self.store, name=u"foo")
- iimaginary.IContainer(self.location).add(o)
- self._test(
- "scrutinize foo",
- [E(u"('Thing',"),
- E(u" {'description': u'',"),
- E(u" 'gender': 3,"),
- E(u" 'location': Thing(description=u'Location for testing.', "
- "gender=3, location=None, name=u'Test Location', portable="
- "True, proper=True, weight=1, storeID=") +
- STOREID + E(")@0x") + PTR + E(","),
- E(u" 'name': u'foo',"),
- E(u" 'portable': True,"),
- E(u" 'proper': False,"),
- E(u" 'weight': 1})")])
-
-
- def testOpenClose(self):
- container = objects.Thing(store=self.store, name=u"container")
- objects.Container.createFor(container, capacity=1)
- iimaginary.IContainer(self.location).add(container)
- self._test(
- "close container",
- ["You close the container."],
- ["Test Player closes a container."])
- self._test(
- "close container",
- ["The container is already closed."],
- [])
- self._test(
- "open container",
- ["You open the container."],
- ["Test Player opens a container."])
- self._test(
- "open container",
- ["The container is already open."],
- [])
-
-
-
- def test_invalidHelp(self):
- """
- The help action tells the player that there is no help for topics for
- which there is no help.
- """
- self._test(
- # Hope you don't make a command with this name.
- "help abcxyz123",
- ["No help available on abcxyz123."],
- [])
- self._test(
- "help /etc/passwd",
- ["No help available on /etc/passwd."],
- [])
-
-
- def test_help(self):
- """
- The help action displays information from files in the resource
- directory.
- """
- resources = filepath.FilePath(__file__).parent().sibling("resources")
- self._test(
- "help help",
- resources.child("help").child("help").getContent().splitlines(),
- [])
-
-
- def test_helpMultiword(self):
- """
- The help action supports arguments with spaces in them.
- """
- fakeHelp = filepath.FilePath(self.mktemp())
- fakeHelp.makedirs()
- fakeHelp.child("foo bar").setContent("baz")
- original = Help.helpContentPath
- try:
- Help.helpContentPath = fakeHelp
- self._test("help foo bar", ["baz"], [])
- finally:
- Help.helpContentPath = original
=== removed file 'Imaginary/imaginary/test/test_actor.py'
--- Imaginary/imaginary/test/test_actor.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_actor.py 1970-01-01 00:00:00 +0000
@@ -1,37 +0,0 @@
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import iimaginary, objects
-
-from imaginary.test import commandutils
-
-
-class ActorTest(unittest.TestCase, commandutils.LanguageMixin):
- def setUp(self):
- self.store = store.Store()
-
- def testPoweringUp(self):
- o = objects.Thing(store=self.store, name=u"wannabe")
- self.assertEquals(iimaginary.IActor(o, "hah"), "hah")
- a = objects.Actor.createFor(o)
- self.assertEquals(iimaginary.IActor(o, None), a)
-
- def testCondition(self):
- o = objects.Thing(store=self.store, name=u"wannabe")
- actor = objects.Actor.createFor(o)
- self.failUnless("great" in self.flatten(actor.conceptualize().plaintext(o)))
-
- def testHitPoints(self):
- o = objects.Thing(store=self.store, name=u"hitty")
- a = objects.Actor.createFor(o)
- self.assertEquals(a.hitpoints, 100)
-
- def testExperience(self):
- o = objects.Thing(store=self.store, name=u"hitty")
- a = objects.Actor.createFor(o)
- self.assertEquals(a.experience, 0)
- a.gainExperience(1100)
- self.assertEquals(a.experience, 1100)
- self.assertEquals(a.level, 10)
-
=== removed file 'Imaginary/imaginary/test/test_concept.py'
--- Imaginary/imaginary/test/test_concept.py 2007-08-17 04:46:38 +0000
+++ Imaginary/imaginary/test/test_concept.py 1970-01-01 00:00:00 +0000
@@ -1,245 +0,0 @@
-
-"""
-Tests for the conversion between abstract objects representing the world or
-changes in the world into concrete per-user-interface content.
-"""
-
-from twisted.trial import unittest
-
-from epsilon import structlike
-
-from imaginary import language, unc, text as T
-from imaginary.test import commandutils
-
-class FakeThing(object):
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
-
-
-class FakeDescriptionContributor:
- def __init__(self, description):
- self.descr = description
-
-
- def conceptualize(self):
- return language.ExpressString(self.descr)
-
-
-
-class NounTestCase(unittest.TestCase):
- def setUp(self):
-
- self.thing = FakeThing(
- name=u'fake thing',
- description=u"Fake Thing Description",
- gender="!@>",
- proper=False,
- powerupsFor=lambda iface: [],
- )
- self.male = FakeThing(
- name=u"billy",
- gender=language.Gender.MALE,
- )
- self.female = FakeThing(
- name=u"janey",
- gender=language.Gender.FEMALE,
- )
- self.observer = FakeThing()
- self.noun = language.Noun(self.thing)
- self.malenoun = language.Noun(self.male)
- self.femalenoun = language.Noun(self.female)
-
-
-
-class SharedTextyTests(commandutils.LanguageMixin):
- def format(self, concept):
- raise NotImplementedError("Implement me")
-
- def testExpressString(self):
- self.assertEquals(self.format(language.ExpressString(u"foo bar")), u"foo bar")
-
-
- def testExpressList(self):
- self.assertEquals(self.format(language.ExpressList([
- language.ExpressString(u"foo"),
- u" ",
- language.ExpressString(u"bar")])),
- u"foo bar")
-
- def testItemizedList(self):
- self.assertEquals(self.format(language.ItemizedList([])),
- u'') # XXX Does this make sense?
-
- self.assertEquals(self.format(language.ItemizedList([
- u'foo'])),
- u'foo')
- self.assertEquals(self.format(language.ItemizedList([
- u'foo', u'bar'])),
- u'foo and bar')
- self.assertEquals(self.format(language.ItemizedList([
- u'foo', u'bar', u'baz'])),
- u'foo, bar, and baz')
-
-
- def testShortName(self):
- self.assertEquals(self.format(self.noun.shortName()), u"fake thing")
-
-
- def testNounPhrase(self):
- self.assertEquals(self.format(self.noun.nounPhrase()), u"a fake thing")
-
-
- def testProperNounPhrase(self):
- self.thing.proper = True
- self.assertEquals(self.format(self.noun.nounPhrase()), u"fake thing")
-
-
- def testDefiniteNounPhrase(self):
- self.assertEquals(self.format(self.noun.definiteNounPhrase()), u"the fake thing")
-
-
- def testProperDefiniteNounPhrase(self):
- self.thing.proper = True
- self.assertEquals(self.format(self.noun.definiteNounPhrase()), u"fake thing")
-
-
- def testPersonalPronoun(self):
- self.assertEquals(self.format(self.malenoun.heShe()), u"he")
- self.assertEquals(self.format(self.femalenoun.heShe()), u"she")
- self.assertEquals(self.format(self.noun.heShe()), u"it")
-
-
- def testObjectivePronoun(self):
- self.assertEquals(self.format(self.malenoun.himHer()), u'him')
- self.assertEquals(self.format(self.femalenoun.himHer()), u'her')
- self.assertEquals(self.format(self.noun.himHer()), u'it')
-
-
- def testPossessivePronoun(self):
- self.assertEquals(self.format(self.malenoun.hisHer()), u'his')
- self.assertEquals(self.format(self.femalenoun.hisHer()), u'her')
- self.assertEquals(self.format(self.noun.hisHer()), u'its')
-
-
-
- def testCapitalization(self):
- self.assertEquals(
- self.format(language.ExpressString(u"foo").capitalizeConcept()),
- u"Foo")
- self.assertEquals(
- self.format(language.ExpressList([[[[u"hi"]]]]).capitalizeConcept()),
- u"Hi")
- self.assertEquals(
- self.format(language.ItemizedList([u"foo", u"bar", u"baz"]).capitalizeConcept()),
- u"Foo, bar, and baz")
-
-
- def testSentence(self):
- self.assertEquals(
- self.format(language.Sentence([self.noun.nounPhrase(), u" is awesome."])),
- u"A fake thing is awesome.")
-
-
-
-
-class BasicConceptTestCasePlaintext(NounTestCase, SharedTextyTests):
-
- def format(self, concept):
- return self.flatten(concept.plaintext(self.observer))
-
-
- def testMissingDescription(self):
- self.thing.description = None
- self.assertEquals(self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- u'[ fake thing ]\n')
-
-
- def testEmptyDescription(self):
- self.thing.description = u''
- self.assertEquals(self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- u'[ fake thing ]\n')
-
-
- def testDescription(self):
- self.assertEquals(self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- u'[ fake thing ]\n'
- u'Fake Thing Description\n')
-
-
- def testExitsDescription(self):
- exits = [StubExit(name=u"north"), StubExit(name=u"west")]
- self.assertEquals(self.format(language.DescriptionConcept(self.thing.name, self.thing.description, exits)),
- u'[ fake thing ]\n'
- u'( north west )\n'
- u'Fake Thing Description\n')
-
-
- def testDescriptionContributors(self):
- a = FakeDescriptionContributor(u"first part")
- b = FakeDescriptionContributor(u"last part")
- self.assertEquals(self.format(language.DescriptionConcept(self.thing.name, self.thing.description, others=[a, b])),
- u'[ fake thing ]\n'
- u'Fake Thing Description\n' +
- a.descr + u"\n" +
- b.descr)
-
-
-class StubExit(structlike.record("name")):
- pass
-
-class VT102Tests(NounTestCase, SharedTextyTests):
- def format(self, concept):
- return self.flatten(concept.vt102(self.observer))
-
-
- def unparse(self, s):
- print repr(s)
- return list(unc.parser(unc.tokenize(s)))
-
- def _assertECMA48Equality(self, a, b):
- errorLines = ['%-38s|%38s' % ('received', 'expected')]
- for la, lb in map(None,
- unc.prettystring(a).splitlines(),
- unc.prettystring(b).splitlines()):
- errorLines.append('%-38s|%38s' % (la, lb))
-
- self.assertEquals(a, b, '\nERROR!\n' + '\n'.join(errorLines))
-
- def testMissingDescription(self):
- self.thing.description = None
- self._assertECMA48Equality(
- self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- self.flatten([T.bold, T.fg.green, u'[ ', [T.fg.normal, "fake thing"], u' ]\n']))
-
-
- def testEmptyDescription(self):
- self.thing.description = u''
- self._assertECMA48Equality(
- self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- self.flatten([T.bold, T.fg.green, u'[ ', [T.fg.normal, "fake thing"], u' ]\n']))
-
-
- def testDescription(self):
- self._assertECMA48Equality(
- self.format(language.DescriptionConcept(self.thing.name, self.thing.description)),
- self.flatten([[T.bold, T.fg.green, u'[ ', [T.fg.normal, "fake thing"], u' ]\n'],
- T.fg.green, u'Fake Thing Description\n']))
-
-
- def testExitsDescription(self):
- exits = [StubExit(name=u"north"), StubExit(name=u"west")]
- self._assertECMA48Equality(
- self.format(language.DescriptionConcept(self.thing.name, self.thing.description, exits)),
- self.flatten([[T.bold, T.fg.green, u'[ ', [T.fg.normal, "fake thing"], u' ]\n'],
- [T.bold, T.fg.green, u'( ', [T.fg.normal, T.fg.yellow, u'north west'], u' )', u'\n'],
- T.fg.green, u'Fake Thing Description\n']))
-
-
- def testDescriptionContributors(self):
- a = FakeDescriptionContributor(u"first part")
- b = FakeDescriptionContributor(u"last part")
- self._assertECMA48Equality(
- self.format(language.DescriptionConcept(self.thing.name, self.thing.description, others=[a, b])),
- self.flatten([[[T.bold, T.fg.green, u'[ ', [T.fg.normal, "fake thing"], u' ]\n'],
- T.fg.green, u'Fake Thing Description\n'], a.descr + u"\n" + b.descr]))
=== removed file 'Imaginary/imaginary/test/test_container.py'
--- Imaginary/imaginary/test/test_container.py 2013-07-24 22:20:29 +0000
+++ Imaginary/imaginary/test/test_container.py 1970-01-01 00:00:00 +0000
@@ -1,286 +0,0 @@
-# -*- test-case-name: imaginary.test -*-
-
-from zope.interface.verify import verifyObject
-
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import iimaginary, eimaginary, objects
-from imaginary.test.commandutils import (
- CommandTestCaseMixin, E, createLocation, flatten)
-from imaginary.language import ExpressList
-
-class ContainerTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
- self.containmentCore = objects.Thing(store=self.store, name=u"container")
- self.container = objects.Container.createFor(self.containmentCore, capacity=1)
- self.object = objects.Thing(store=self.store, name=u"object")
-
-
- def testAdd(self):
- """
- Test that successfully adding an object to a container properly adjusts
- the world graph - in particular, the contents list of the container and
- the location of the object.
- """
- self.container.add(self.object)
- self.assertEquals(list(self.container.getContents()), [self.object])
- self.assertIdentical(self.object.location, self.containmentCore)
-
-
- def testRemove(self):
- """
- Test that successfully removing an object from a container properly
- adjusts the world graph - in particular, the contents list of the
- container and the location of the object.
- """
- self.testAdd()
- self.container.remove(self.object)
- self.assertEquals(list(self.container.getContents()), [])
- self.assertIdentical(self.object.location, None)
-
-
- def testOverflowing(self):
- """
- Test the capacity feature of the container implementation as it
- interacts with the weight feature of the object implementation.
- """
- self.container.capacity = 1
- self.object.weight = 2
- self.assertRaises(eimaginary.DoesntFit, self.container.add, self.object)
- self.assertEquals(list(self.container.getContents()), [])
- self.assertIdentical(self.object.location, None)
-
-
- def testClosed(self):
- """
- Test the closed feature of the container implementation.
- """
- self.container.closed = True
- self.assertRaises(eimaginary.Closed, self.container.add, self.object)
- self.assertEquals(list(self.container.getContents()), [])
- self.assertIdentical(self.object.location, None)
-
- self.container.closed = False
- self.container.add(self.object)
- self.container.closed = True
-
- self.assertRaises(eimaginary.Closed, self.container.remove, self.object)
- self.assertEquals(list(self.container.getContents()), [self.object])
- self.assertIdentical(self.object.location, self.containmentCore)
-
-
-
-class ExpressContentsTests(unittest.TestCase):
- """
- Tests for L{ExpressContents}.
- """
- def setUp(self):
- self.store = store.Store()
- self.box = objects.Thing(store=self.store, name=u"box")
- self.container = objects.Container.createFor(self.box, capacity=123)
- self.concept = objects.ExpressContents(self.container)
- self.observer = objects.Thing(store=self.store, name=u"observer")
-
-
- def addContents(self, names):
- """
- Add a new L{Thing} to C{self.container} for each element of C{names}.
-
- @param names: An iterable of L{unicode} giving the names of the things
- to create and add.
- """
- things = []
- for name in names:
- thing = objects.Thing(store=self.store, name=name, proper=True)
- thing.moveTo(self.container)
- things.append(thing)
- return things
-
-
- def test_interface(self):
- """
- An instance of L{ExpressContents} provides L{IConcept}.
- """
- self.assertTrue(verifyObject(iimaginary.IConcept, self.concept))
-
-
- def test_contentConceptsEmpty(self):
- """
- L{ExpressContents._contentConcepts} returns an empty L{list} if the
- L{Container} the L{ExpressContents} instance is initialized with has no
- contents.
- """
- contents = self.concept._contentConcepts(self.observer)
- self.assertEqual([], contents)
-
-
- def test_contentConcepts(self):
- """
- L{ExpressContents._contentConcepts} returns a L{list} of L{IConcept}
- providers representing the things contained by the L{Container} the
- L{ExpressContents} instance is initialized with.
- """
- [something] = self.addContents([u"something"])
-
- contents = self.concept._contentConcepts(self.observer)
- self.assertEqual([something], contents)
-
-
- def test_contentConceptsExcludesObserver(self):
- """
- The L{list} returned by L{ExpressContents._contentConcepts} does not
- include the observer, even if the observer is contained by the
- L{Container} the L{ExpressContents} instance is initialized with.
- """
- [something] = self.addContents([u"something"])
- self.observer.moveTo(self.container)
-
- concepts = self.concept._contentConcepts(self.observer)
- self.assertEqual([something], concepts)
-
-
- def test_contentConceptsExcludesUnseen(self):
- """
- If the L{Container} used to initialize L{ExpressContents} cannot be
- seen by the observer passed to L{ExpressContents._contentConcepts}, it
- is not included in the returned L{list}.
- """
- objects.LocationLighting.createFor(self.box, candelas=0)
- [something] = self.addContents([u"something"])
-
- concepts = self.concept._contentConcepts(self.observer)
- self.assertEqual([], concepts)
-
-
- def test_template(self):
- """
- L{ExpressContents.template} evaluates to the value of the
- C{contentsTemplate} attribute of the L{Container} used to initialize
- the L{ExpressContents} instance.
- """
- template = u"{pronoun} is carrying {contents}."
- self.container.contentsTemplate = template
- self.assertEqual(template, self.concept.template)
-
-
- def test_defaultTemplate(self):
- """
- If the wrapped L{Container}'s C{contentsTemplate} is C{None},
- L{ExpressContents.template} evaluates to a string giving a simple,
- generic English-language template.
- """
- self.container.contentsTemplate = None
- self.assertEqual(
- u"{subject:pronoun} contains {contents}.", self.concept.template)
-
-
- def test_expandSubject(self):
- """
- L{ExpressContents.expand} expands a concept template string using
- the wrapped L{Container}'s L{Thing} as I{subject}.
- """
- self.assertEqual(
- [self.box.name],
- list(self.concept.expand(u"{subject:name}", self.observer)))
-
-
- def conceptAsText(self, concept, observer):
- """
- Express C{concept} to C{observer} and flatten the result into a
- L{unicode} string.
-
- @return: The text result expressing the concept.
- """
- return flatten(
- ExpressList(concept.concepts(observer)).plaintext(observer))
-
-
- def test_expandContents(self):
- """
- L{ExpressContents.expand} expands a concept template string using the
- contents of the L{Thing} as I{contents}.
- """
- self.addContents([u"something", u"something else"])
-
- contents = self.concept.expand(u"{contents}", self.observer)
- self.assertEqual(
- u"something and something else",
- self.conceptAsText(ExpressList(contents), self.observer))
-
-
- def test_concepts(self):
- """
- L{ExpressContents.concepts} returns a L{list} expressing the contents
- of the wrapped container to the given observer.
- """
- self.addContents([u"red fish", u"blue fish"])
- self.assertEqual(
- u"it contains red fish and blue fish.",
- self.conceptAsText(self.concept, self.observer))
-
-
- def test_emptyConcepts(self):
- """
- If the wrapped container is empty, L{ExpressContents.concepts} returns
- an empty list.
- """
- self.assertEqual(
- u"", self.conceptAsText(self.concept, self.observer))
-
-
-
-class IngressAndEgressTestCase(CommandTestCaseMixin, unittest.TestCase):
- """
- I should be able to enter and exit containers that are sufficiently big.
- """
-
- def setUp(self):
- """
- Create a container, C{self.box} that is large enough to stand in.
- """
- CommandTestCaseMixin.setUp(self)
- self.container = createLocation(self.store, u"box", None)
- self.box = self.container.thing
- self.box.proper = False
- self.box.moveTo(self.location)
-
-
- def test_enterBox(self):
- """
- I should be able to enter the box.
- """
- self.assertCommandOutput(
- 'enter box',
- [E('[ Test Location ]'),
- 'Location for testing.',
- 'Here, you see Observer Player and a box.'],
- ['Test Player leaves into the box.'])
-
-
- def test_exitBox(self):
- """
- I should be able to exit the box.
- """
- self.player.moveTo(self.container)
- self.assertCommandOutput(
- 'exit out',
- [E('[ Test Location ]'),
- 'Location for testing.',
- 'Here, you see Observer Player and a box.'],
- ['Test Player leaves out of the box.'])
- self.assertEquals(self.player.location,
- self.location)
-
-
- def test_enterWhileHoldingBox(self):
- """
- When I'm holding a container, I shouldn't be able to enter it.
- """
- self.container.thing.moveTo(self.player)
- self.assertCommandOutput('enter box',
- ["The box won't fit inside itself."],
- [])
-
=== removed file 'Imaginary/imaginary/test/test_create.py'
--- Imaginary/imaginary/test/test_create.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_create.py 1970-01-01 00:00:00 +0000
@@ -1,269 +0,0 @@
-
-
-from zope.interface import Interface, implements, directlyProvides
-from zope.interface.verify import verifyObject
-
-from twisted.trial import unittest
-
-from axiom import store, item, attributes
-
-from imaginary import iimaginary, plugins, creation
-from imaginary.creation import createCreator
-from imaginary.plugins import imaginary_basic
-from imaginary.enhancement import Enhancement
-
-from imaginary.test import commandutils
-
-
-
-class ThingPlugin(commandutils.CommandTestCaseMixin, unittest.TestCase):
- """
- Tests for L{imaginary_basic.thingPlugin}, a plugin for creating simple
- things with no special behavior.
- """
- def test_createThing(self):
- """
- L{plugins.thingPlugin} creates a L{Thing} with no additional behavior.
- """
- st = store.Store()
- thing = imaginary_basic.thingPlugin.getType()(store=st, name=u"foo")
- self.assertTrue(verifyObject(iimaginary.IThing, thing))
- self.assertIdentical(thing.store, st)
- self.assertEqual(thing.name, u"foo")
-
-
- def test_createThingCommand(self):
- """
- Things can be created with the I{create} command.
- """
- self._test(
- "create a thing named foo",
- ["You create a foo."],
- ["Test Player creates a foo."])
- [foo] = self.playerContainer.getContents()
- self.assertEqual(foo.name, u"foo")
- self.assertFalse(foo.proper)
-
-
-
-class IFruit(Interface):
- pass
-
-
-
-class Fruit(item.Item, Enhancement):
- implements(IFruit)
- powerupInterfaces = (IFruit,)
-
- fresh = attributes.boolean(default=False)
- thing = attributes.reference(allowNone=False)
-
-
-
-class FruitPlugin(object):
- directlyProvides(iimaginary.IThingType)
-
- type = 'fruit'
-
- def getType(cls):
- return createCreator((Fruit, {'fresh': True}))
- getType = classmethod(getType)
-
-
-
-class CreateTest(commandutils.CommandTestCaseMixin, unittest.TestCase):
- """
- Tests for the I{create} action.
- """
- def _getPlugins(self, iface, package):
- self.assertIdentical(iface, iimaginary.IThingType)
- self.assertIdentical(package, plugins)
- return [FruitPlugin]
-
-
- def setUp(self):
- self.old_getPlugins = creation.getPlugins
- creation.getPlugins = self._getPlugins
- return commandutils.CommandTestCaseMixin.setUp(self)
-
-
- def tearDown(self):
- creation.getPlugins = self.old_getPlugins
- return commandutils.CommandTestCaseMixin.tearDown(self)
-
-
- def test_createAThing(self):
- """
- The I{create a} form of the I{create} action makes a new L{Thing} using
- the plugin which matches the type name specified and marks its name as
- a common noun.
- """
- self._test(
- "create a fruit named apple",
- ["You create an apple."],
- ["Test Player creates an apple."])
- apple = self.find(u"apple")
- self.assertEquals(apple.name, "apple")
- self.assertFalse(apple.proper)
- self.assertEquals(apple.description, "an undescribed object")
- self.assertEquals(apple.location, self.player)
- fruit = IFruit(apple)
- self.assertTrue(isinstance(fruit, Fruit))
- self.assertTrue(fruit.fresh)
-
-
- def test_createAnThing(self):
- """
- The I{create an} form of the I{create} action makes a new L{Thing}
- using the plugin which matches the type name specified and marks its
- name as a common noun.
- """
- self._test(
- "create an fruit named pear",
- ["You create a pear."],
- ["Test Player creates a pear."])
- pear = self.find(u"pear")
- self.assertEquals(pear.name, "pear")
- self.assertFalse(pear.proper)
- self.assertEquals(pear.description, "an undescribed object")
- self.assertEquals(pear.location, self.player)
- fruit = IFruit(pear)
- self.assertTrue(isinstance(fruit, Fruit))
- self.assertTrue(fruit.fresh)
-
-
- def test_createImpliedCommonNounThing(self):
- """
- The I{create} form of the I{create} action implies a common noun name
- and behaves the same way as the I{create a} and I{create an} forms.
- """
- self._test(
- "create fruit named 'bunch of grapes'",
- ["You create a bunch of grapes."],
- ["Test Player creates a bunch of grapes."])
- pear = self.find(u"bunch of grapes")
- self.assertEquals(pear.name, "bunch of grapes")
- self.assertFalse(pear.proper)
- self.assertEquals(pear.description, "an undescribed object")
- self.assertEquals(pear.location, self.player)
- fruit = IFruit(pear)
- self.assertTrue(isinstance(fruit, Fruit))
- self.assertTrue(fruit.fresh)
-
-
- def test_createTheThing(self):
- """
- The I{create the} form of the I{create} action makes a new L{Thing}
- using the plugin which matches the type name specified and marks its
- name as a proper noun.
- """
- self._test(
- "create the fruit named 'The Golden Apple'",
- ["You create The Golden Apple."],
- ["Test Player creates The Golden Apple."])
- apple = self.find(u"The Golden Apple")
- self.assertEqual(apple.name, "The Golden Apple")
- self.assertTrue(apple.proper)
- self.assertEqual(apple.description, "an undescribed object")
- self.assertEqual(apple.location, self.player)
- fruit = IFruit(apple)
- self.assertTrue(isinstance(fruit, Fruit))
- self.assertTrue(fruit.fresh)
-
-
- def test_createMultiwordWithDescription(self):
- """
- The I{create} command creates a thing of the type specified by its
- first argument, with the name specified by its second argument, and
- with a description specified by the remainder of the input line.
- """
- self._test(
- "create a fruit named 'described fruit' This is the fruit's description.",
- ["You create a described fruit."],
- ["Test Player creates a described fruit."])
- [thing] = self.playerContainer.getContents()
- self.assertEquals(thing.name, "described fruit")
- self.assertEquals(thing.description, "This is the fruit's description.")
- self.assertEquals(thing.location, self.player)
-
-
-
-class ListCreatablesTests(commandutils.CommandTestCaseMixin, unittest.TestCase):
- """
- Tests for C{list creatables}.
- """
-
- def _getPlugins(self, interface, package):
- """
- A stub implementation of L{creation.getPlugins} meant to replace it
- temporarily during tests.
-
- @param interface: Must be IThingType.
- @param package: Must be L{imaginary.plugins}.
- @return: A list of two instances of L{FruitPlugin}.
- """
- self.assertIdentical(interface, iimaginary.IThingType)
- self.assertIdentical(package, plugins)
- foo = FruitPlugin()
- bar = FruitPlugin()
- foo.type = "foo"
- # Include some non-ascii to make sure it supports non-ascii.
- bar.type = u"bar\N{HIRAGANA LETTER A}"
- return [foo, bar]
-
-
- def setUp(self):
- """
- Monkeypatch L{creation.getPlugins} with L{_getPlugins}.
- """
- self.oldGetPlugins = creation.getPlugins
- creation.getPlugins = self._getPlugins
- return commandutils.CommandTestCaseMixin.setUp(self)
-
-
- def tearDown(self):
- """
- Unmonkeypatch L{creation.getPlugins}.
- """
- creation.getPlugins = self.oldGetPlugins
- return commandutils.CommandTestCaseMixin.tearDown(self)
-
-
- def test_listThingTypes(self):
- """
- L{listThingTypes} returns a list of strings in alphabetical order
- describing types which can be created.
- """
- self.assertEqual(creation.listThingTypes(),
- [u"bar\N{HIRAGANA LETTER A}", u"foo"])
-
-
- def test_listThingTypesCommand(self):
- """
- I{list thing types} displays the names of all types which can be
- created.
- """
- self._test(
- "list thing types",
- [u"bar\N{HIRAGANA LETTER A}", u"foo"],
- [])
-
-
- def test_helpListThingTypes(self):
- """
- I{help list thing types} gives usage information for the I{list thing
- types} action.
- """
- actorOutput, otherOutput = self.watchCommand("help list thing types")
- self.assertIn("Show a list of names of things which can be created",
- actorOutput)
- self.assertEquals(otherOutput, "")
-
-
- def test_helpList(self):
- """
- The I{list} help text refers to I{list thing types}.
- """
- actorOutput, otherOutput = self.watchCommand("help list")
- self.assertIn("thing types", actorOutput)
- self.assertEqual(otherOutput, u"")
=== removed file 'Imaginary/imaginary/test/test_drop.py'
--- Imaginary/imaginary/test/test_drop.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_drop.py 1970-01-01 00:00:00 +0000
@@ -1,30 +0,0 @@
-
-from twisted.trial.unittest import TestCase
-
-from axiom.store import Store
-
-from imaginary.test.commandutils import createPlayer
-from imaginary.objects import Thing, Container
-from imaginary.action import Drop
-from imaginary.events import ArrivalEvent
-
-
-class DropTestCase(TestCase):
- def test_arrivalEvent(self):
- """
- Test that when a thing is dropped, an ArrivalEvent instance is
- broadcast to the room it is dropped into.
- """
- st = Store()
-
- player, actor, intelligence = createPlayer(st, u"Foo")
- place = Thing(store=st, name=u"soko")
- player.moveTo(Container.createFor(place, capacity=1000))
-
- bauble = Thing(store=st, name=u"bauble")
- bauble.moveTo(player)
-
- Drop().runEventTransaction(player, None, dict(target=bauble.name))
- self.assertEquals(len([concept for concept
- in intelligence.concepts
- if isinstance(concept, ArrivalEvent)]), 1)
=== removed file 'Imaginary/imaginary/test/test_enhancement.py'
--- Imaginary/imaginary/test/test_enhancement.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_enhancement.py 1970-01-01 00:00:00 +0000
@@ -1,194 +0,0 @@
-
-"""
-Tests for L{imaginary.enhancement}.
-"""
-
-from zope.interface import Interface, implements
-
-from twisted.trial.unittest import TestCase
-
-from axiom.store import Store
-from axiom.item import Item
-from axiom.attributes import integer, reference, boolean
-from axiom.dependency import installOn
-
-from imaginary.enhancement import Enhancement
-from imaginary.objects import Thing
-
-class INonPowerupInterface(Interface):
- """
- This is an interface, but not a powerup interface.
- """
-
-
-
-class IStubSimulation(Interface):
- """
- A stub interface for simulations.
- """
-
-
-
-class StubEnhancement(Item, Enhancement):
- """
- An enhancement for testing. This adds functionality to a L{Thing}.
- """
-
- implements(IStubSimulation, INonPowerupInterface)
- powerupInterfaces = [IStubSimulation]
-
- thing = reference()
- stubValue = integer()
-
-
-
-class StrictEnhancement(Item, Enhancement):
- """
- An enhancement for testing with an attribute that has C{allowNone=False}
- and no default.
- """
-
- requiredValue = integer(allowNone=False)
- thing = reference(allowNone=False)
-
-
-
-class CustomizedEnhancement(Item, Enhancement):
- """
- An enhancement which has customized apply / remove behavior.
- """
-
- thing = reference(allowNone=False)
- applied = boolean()
- removed = boolean()
-
- def applyEnhancement(self):
- """
- The enhancement is about to be applied; modify our attributes to
- account for that.
- """
- self.applied = True
- super(CustomizedEnhancement, self).applyEnhancement()
-
-
- def removeEnhancement(self):
- """
- The enhancement is about to be removed; modify our attributes to
- account for that.
- """
- self.removed = True
- super(CustomizedEnhancement, self).removeEnhancement()
-
-
-
-class EnhancementTests(TestCase):
- """
- Tests for L{Enhancement}
- """
-
- def setUp(self):
- """
- Create a store with a thing in it.
- """
- self.store = Store()
- self.thing = Thing(store=self.store, name=u'test object')
-
-
- def test_createForSimple(self):
- """
- L{Enhancement.createFor} will create an enhancement of the appropriate
- type and install it as a powerup on the Thing it is passed.
- """
- stub = StubEnhancement.createFor(self.thing)
- self.assertIdentical(stub.thing, self.thing)
- self.assertIdentical(IStubSimulation(self.thing), stub)
- self.assertIdentical(INonPowerupInterface(self.thing, None), None)
-
-
- def test_createForArguments(self):
- """
- Keyword arguments passed to L{Enhancement.createFor} will be passed on
- to the class.
- """
- stub = StubEnhancement.createFor(self.thing, stubValue=4321)
- self.assertEquals(stub.stubValue, 4321)
-
-
- def test_createForAllowNoneFalse(self):
- """
- If an L{Enhancement} subclass requires a particular attribute,
- L{Enhancement.createFor} will require that argument just as
- L{Item.__init__} would.
- """
- self.assertRaises(
- TypeError, StrictEnhancement.createFor, self.thing)
-
-
- def test_overrideApplyEnhancement(self):
- """
- Subclasses of L{Enhancement} can override applyEnhancement to determine
- what happens when createFor does its powering up.
- """
- custom = CustomizedEnhancement.createFor(self.thing, applied=False)
- self.assertEquals(custom.applied, True)
-
-
- def test_dontRelyOnInstalledHook(self):
- """
- L{Enhancement.installed} raises a L{RuntimeError}, to make sure that
- nothing uses L{installOn} to install enhancements any more.
- """
- se = StubEnhancement(store=self.store, thing=self.thing)
- theError = self.assertRaises(RuntimeError, installOn, se, self.thing)
- self.assertEquals(str(theError),
- "Use Enhancement.createFor, not installOn(), "
- "to apply an Enhancement to a Thing.")
-
-
- def test_destroyFor(self):
- """
- L{Enhancement.destroyFor} powers down the L{Enhancement} from its
- L{Thing}, and removes it from its store.
- """
- StubEnhancement.createFor(self.thing)
- otherThing = Thing(store=self.store, name=u'test other thing')
- stub2 = StubEnhancement.createFor(otherThing)
- StubEnhancement.destroyFor(self.thing)
- self.assertIdentical(IStubSimulation(self.thing, None), None)
- self.assertEquals([stub2], list(self.store.query(StubEnhancement)))
-
-
- def test_removeEnhancement(self):
- """
- L{Enhancement.removeEnhancement} removes the L{Enhancement} from its
- L{Thing}, but leaves it in place.
- """
- stub = StubEnhancement.createFor(self.thing)
- stub.removeEnhancement()
- self.assertIdentical(IStubSimulation(self.thing, None), None)
- self.assertEquals([stub], list(self.store.query(StubEnhancement)))
-
-
- def test_destroyForRemovesEnhancement(self):
- """
- L{Enhancement.destroyFor} will first invoke C{removeEnhancement},
- allowing subclasses to hook it to provide custom cleanup logic.
- """
- custom = CustomizedEnhancement.createFor(
- self.thing, applied=False, removed=False)
- CustomizedEnhancement.destroyFor(self.thing)
- self.assertEquals(custom.removed, True)
-
-
- def test_destroyForNothing(self):
- """
- L{Enhancement.destroyFor} does nothing when invoked on a Thing that
- doesn't have any enhancements of the specified type installed.
- """
- # I have to write code in order to make this happen, rather than an
- # exception getting raised; i.e. a 'default=None'. So it's worth
- # testing. Unfortunately I don't actually have anything to assert
- # about it except "an exception wasn't raised, and all the other stuff
- # in the other tests still work"
- StubEnhancement.destroyFor(self.thing)
-
=== removed file 'Imaginary/imaginary/test/test_garments.py'
--- Imaginary/imaginary/test/test_garments.py 2013-06-30 19:00:05 +0000
+++ Imaginary/imaginary/test/test_garments.py 1970-01-01 00:00:00 +0000
@@ -1,306 +0,0 @@
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import iimaginary, objects, garments, language
-from imaginary.eimaginary import ActionFailure
-from imaginary.test import commandutils
-from imaginary.test.commandutils import E
-from imaginary.world import ImaginaryWorld
-
-class WearIt(unittest.TestCase, commandutils.LanguageMixin):
-
- def setUp(self):
- self.store = store.Store()
-
- self.dummy = objects.Thing(store=self.store, name=u'dummy')
- self.dummyContainer = objects.Container.createFor(self.dummy, capacity=100)
-
- self.shirt = objects.Thing(store=self.store, name=u'shirt')
- self.shirtGarment = garments.Garment.createFor(
- self.shirt,
- garmentDescription=u'a shirt',
- garmentSlots=[garments.GarmentSlot.LEFT_ARM,
- garments.GarmentSlot.RIGHT_ARM,
- garments.GarmentSlot.CHEST,
- garments.GarmentSlot.BACK,
- ])
-
- self.wearer = garments.Wearer.createFor(self.dummy)
-
-
- def testWearing(self):
- self.wearer.putOn(self.shirtGarment)
- self.assertIdentical(self.shirt.location, self.dummy)
-
-
-
-class GarmentPluginTestCase(commandutils.LanguageMixin, unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
- self.world = ImaginaryWorld(store=self.store)
- self.daisy = self.world.create(u"daisy", gender=language.Gender.FEMALE)
- self.observer = self.world.create(u"NONDESCRIPT", gender=language.Gender.MALE)
- self.dukes = garments.createPants(store=self.store,
- name=u'pair of Daisy Dukes')
- self.blouse = garments.createShirt(store=self.store,
- name=u"blue blouse")
- self.undies = garments.createUnderwear(store=self.store,
- name=u"pair of lacy underwear")
-
-
- def _creationTest(self, garment):
- self.failUnless(
- iimaginary.IClothing.providedBy(iimaginary.IClothing(garment)))
-
-
- def testShirtCreation(self):
- self._creationTest(
- garments.createShirt(store=self.store, name=u'red shirt'))
-
-
- def testPantsCreation(self):
- self._creationTest(
- garments.createPants(store=self.store, name=u'blue pants'))
-
-
- def testPersonIsAWearer(self):
- self.failUnless(iimaginary.IClothingWearer.providedBy(
- iimaginary.IClothingWearer(self.daisy)))
-
-
- def testPersonWearsPants(self):
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
-
- description = self.daisy.visualize()
- self.assertEquals(
- self.flatten(description.plaintext(self.observer)),
- u'[ daisy ]\n'
- u'daisy is great.\n'
- u'She is wearing a pair of Daisy Dukes.')
-
-
- def testPersonRemovesPants(self):
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
- iimaginary.IClothingWearer(self.daisy).takeOff(
- iimaginary.IClothing(self.dukes))
- description = self.daisy.visualize()
- self.assertEquals(
- self.flatten(description.plaintext(self.observer)),
- u'[ daisy ]\n'
- u'daisy is great.\n'
- u'She is naked.\n'
- u'She is carrying a pair of Daisy Dukes.'
- )
- self.assertIdentical(self.dukes.location, self.daisy)
-
-
- def testPersonRemovesPantsAndUnderwear(self):
- wearer = iimaginary.IClothingWearer(self.daisy)
- wearer.putOn(iimaginary.IClothing(self.undies))
- wearer.putOn(iimaginary.IClothing(self.dukes))
- wearer.takeOff(iimaginary.IClothing(self.dukes))
- wearer.takeOff(iimaginary.IClothing(self.undies))
- description = self.daisy.visualize()
- self.assertEquals(
- self.flatten(description.plaintext(self.observer)),
- u'[ daisy ]\n'
- u'daisy is great.\n'
- u'She is naked.\n'
- u'She is carrying a pair of Daisy Dukes and a pair of lacy '
- u'underwear.'
- )
- self.assertIdentical(self.dukes.location, self.daisy)
-
-
- def test_cantDropSomethingYouAreWearing(self):
- """
- If you're wearing an article of clothing, you should not be able to
- drop it until you first take it off. After taking it off, however, you
- can move it around just fine.
- """
- wearer = iimaginary.IClothingWearer(self.daisy)
- wearer.putOn(iimaginary.IClothing(self.undies))
- af = self.assertRaises(ActionFailure, self.undies.moveTo,
- self.daisy.location)
- self.assertEquals(
- u''.join(af.event.plaintext(self.daisy)),
- u"You can't move the pair of lacy underwear "
- u"without removing it first.\n")
-
- wearer.takeOff(iimaginary.IClothing(self.undies))
- self.undies.moveTo(self.daisy.location)
- self.assertEquals(self.daisy.location, self.undies.location)
-
-
- def testTakeOffUnderwearBeforePants(self):
- # TODO - underwear removal skill
- wearer = iimaginary.IClothingWearer(self.daisy)
- wearer.putOn(iimaginary.IClothing(self.undies))
- wearer.putOn(iimaginary.IClothing(self.dukes))
-
- self.assertRaises(garments.InaccessibleGarment,
- wearer.takeOff, iimaginary.IClothing(self.undies))
-
-
- def testPersonWearsPantsAndShirt(self):
- description = self.daisy.visualize()
-
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.blouse))
-
- self.assertEquals(
- self.flatten(description.plaintext(self.observer)),
- u"[ daisy ]\n"
- u"daisy is great.\n"
- u"She is wearing a blue blouse and a pair of Daisy Dukes.")
-
-
- def testPersonWearsUnderpantsAndPants(self):
- description = self.daisy.visualize()
-
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.undies))
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
-
- self.assertEquals(
- self.flatten(description.plaintext(self.observer)),
- u"[ daisy ]\n"
- u"daisy is great.\n"
- u"She is wearing a pair of Daisy Dukes.")
-
-
- def testPersonWearsPantsAndFailsAtPuttingOnUnderpants(self):
- description = self.daisy.visualize()
-
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
- self.assertRaises(garments.TooBulky,
- iimaginary.IClothingWearer(self.daisy).putOn,
- iimaginary.IClothing(self.undies))
-
- def testWornClothingIsFindable(self):
- iimaginary.IClothingWearer(self.daisy).putOn(
- iimaginary.IClothing(self.dukes))
- dukes = list(self.daisy.findProviders(
- iimaginary.IClothing, 0))
- self.assertEquals(len(dukes), 1)
- self.assertIdentical(dukes[0].thing, self.dukes)
-
-
-class FunSimulationStuff(commandutils.CommandTestCaseMixin, unittest.TestCase):
-
- def createPants(self):
- """
- Create a pair of Daisy Dukes for the test player to wear.
- """
- self._test("create pants named 'pair of daisy dukes'",
- ["You create a pair of daisy dukes."],
- ["Test Player creates a pair of daisy dukes."])
-
-
-
- def testWearIt(self):
- self.createPants()
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
-
-
- def test_takeItOff(self):
- """
- A garment can be removed with the I{take off} action or the
- I{remove} action.
- """
- self.createPants()
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
- self._test("take off 'pair of daisy dukes'",
- ["You take off the pair of daisy dukes."],
- ["Test Player takes off a pair of daisy dukes."])
-
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
- self._test("remove 'pair of daisy dukes'",
- ["You take off the pair of daisy dukes."],
- ["Test Player takes off a pair of daisy dukes."])
-
-
- def testProperlyDressed(self):
- self.createPants()
- self._test("create underwear named 'pair of lace panties'",
- ["You create a pair of lace panties."],
- ["Test Player creates a pair of lace panties."])
- self._test("wear 'pair of lace panties'",
- ["You put on the pair of lace panties."],
- ["Test Player puts on a pair of lace panties."])
-
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
- self._test("look me",
- [E("[ Test Player ]"),
- E("Test Player is great."),
- E("She is wearing a pair of daisy dukes.")])
-
-
- def testTooBulky(self):
- self.createPants()
- self._test("create pants named 'pair of overalls'",
- ["You create a pair of overalls."],
- ["Test Player creates a pair of overalls."])
- self._test("wear 'pair of overalls'",
- ["You put on the pair of overalls."],
- ["Test Player puts on a pair of overalls."])
- self._test("wear 'pair of daisy dukes'",
- ["The pair of overalls you are already wearing is too bulky for you to do that."],
- ["Test Player wrestles with basic personal problems."])
- self._test("look me",
- [E("[ Test Player ]"),
- E("Test Player is great."),
- E("She is wearing a pair of overalls."),
- E("She is carrying a pair of daisy dukes."),
- ])
-
-
- def testInaccessibleGarment(self):
- self.createPants()
- self._test("create underwear named 'pair of lace panties'",
- ["You create a pair of lace panties."],
- ["Test Player creates a pair of lace panties."])
- self._test("wear 'pair of lace panties'",
- ["You put on the pair of lace panties."],
- ["Test Player puts on a pair of lace panties."])
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
- self._test("remove 'pair of lace panties'",
- [E("You cannot take off the pair of lace panties because you are wearing a pair of daisy dukes.")],
- ["Test Player gets a dumb look on her face."])
-
-
- def testEquipment(self):
- self.createPants()
- self._test("create underwear named 'pair of lace panties'",
- ["You create a pair of lace panties."],
- ["Test Player creates a pair of lace panties."])
- self._test("wear 'pair of lace panties'",
- ["You put on the pair of lace panties."],
- ["Test Player puts on a pair of lace panties."])
- self._test("wear 'pair of daisy dukes'",
- ["You put on the pair of daisy dukes."],
- ["Test Player puts on a pair of daisy dukes."])
- self._test("equipment",
- ["You are wearing a pair of daisy dukes and a pair of lace panties."]),
-
-
- def testNoEquipment(self):
- self._test("equipment",
- ["You aren't wearing any equipment."])
=== removed file 'Imaginary/imaginary/test/test_hit.py'
--- Imaginary/imaginary/test/test_hit.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_hit.py 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
-
-from twisted.trial import unittest
-
-from imaginary.test import commandutils
-from imaginary.test.commandutils import E
-
-from imaginary import objects, iimaginary
-
-class HitTestCase(commandutils.CommandTestCaseMixin, unittest.TestCase):
- def testHit(self):
- self._test(
- "hit self",
- [E("Hit yourself? Stupid.")])
-
- self._test(
- "hit foobar",
- [E("Who's that?")])
-
- actor = iimaginary.IActor(self.player)
- actor.stamina.current = 0
- self._test(
- "hit Observer Player",
- ["You're too tired!"])
-
- actor.stamina.current = actor.stamina.max
-
- x, y = self._test(
- "hit Observer Player",
- ["You hit Observer Player for (\\d+) hitpoints."],
- ["Test Player hits you for (\\d+) hitpoints."])
- self.assertEquals(x[1].groups(), y[0].groups())
-
- actor.stamina.current = actor.stamina.max
-
- x, y = self._test(
- "attack Observer Player",
- ["You hit Observer Player for (\\d+) hitpoints."],
- ["Test Player hits you for (\\d+) hitpoints."])
- self.assertEquals(x[1].groups(), y[0].groups())
-
-
- monster = objects.Thing(store=self.store, name=u"monster")
- objects.Actor.createFor(monster)
- monster.moveTo(self.location)
- x, y = self._test(
- "hit monster",
- ["You hit the monster for (\\d+) hitpoints."],
- ["Test Player hits a monster."])
- monster.destroy()
-
-
- def testInvalidAttacks(self):
- self._test(
- "hit here",
- [E("Who's that?")],
- [])
-
- obj = objects.Thing(store=self.store, name=u"quiche")
- obj.moveTo(self.location)
- self._test(
- "hit quiche",
- [E("Who's that?")],
- [])
=== removed file 'Imaginary/imaginary/test/test_idea.py'
--- Imaginary/imaginary/test/test_idea.py 2010-04-24 21:54:09 +0000
+++ Imaginary/imaginary/test/test_idea.py 1970-01-01 00:00:00 +0000
@@ -1,241 +0,0 @@
-
-"""
-Some basic unit tests for L{imaginary.idea} (but many tests for this code are in
-other modules instead).
-"""
-
-from zope.interface import implements
-
-from twisted.trial.unittest import TestCase
-
-from epsilon.structlike import record
-
-from imaginary.iimaginary import (
- IWhyNot, INameable, ILinkContributor, IObstruction, ILinkAnnotator,
- IElectromagneticMedium)
-from imaginary.language import ExpressString
-from imaginary.idea import (
- Idea, Link, Path, AlsoKnownAs, ProviderOf, Named, DelegatingRetriever,
- Reachable, CanSee)
-
-
-class Reprable(record('repr')):
- def __repr__(self):
- return self.repr
-
-
-class PathTests(TestCase):
- """
- Tests for L{imaginary.idea.Path}.
- """
- def test_repr(self):
- """
- A L{Path} instance can be rendered into a string by C{repr}.
- """
- key = Idea(AlsoKnownAs("key"))
- table = Idea(AlsoKnownAs("table"))
- hall = Idea(AlsoKnownAs("hall"))
- path = Path([Link(hall, table), Link(table, key)])
- self.assertEquals(
- repr(path),
- "Path(\n"
- "\t'hall' => 'table' []\n"
- "\t'table' => 'key' [])")
-
-
- def test_unnamedDelegate(self):
- """
- The I{repr} of a L{Path} containing delegates without names includes the
- I{repr} of the delegates.
- """
- key = Idea(Reprable("key"))
- table = Idea(Reprable("table"))
- hall = Idea(Reprable("hall"))
- path = Path([Link(hall, table), Link(table, key)])
- self.assertEquals(
- repr(path),
- "Path(\n"
- "\thall => table []\n"
- "\ttable => key [])")
-
-
-
-class OneLink(record('link')):
- implements(ILinkContributor)
-
- def links(self):
- return [self.link]
-
-
-class TooHigh(object):
- implements(IWhyNot)
-
- def tellMeWhyNot(self):
- return ExpressString("the table is too high")
-
-
-class ArmsReach(DelegatingRetriever):
- """
- Restrict retrievable to things within arm's reach.
-
- alas for poor Alice! when she got to the door, she found he had
- forgotten the little golden key, and when she went back to the table for
- it, she found she could not possibly reach it:
- """
- def moreObjectionsTo(self, path, result):
- """
- Object to finding the key.
- """
- # This isn't a very good implementation of ArmsReach. It doesn't
- # actually check distances or paths or anything. It just knows the
- # key is on the table, and Alice is too short.
- named = path.targetAs(INameable)
- if named.knownTo(None, "key"):
- return [TooHigh()]
- return []
-
-
-class WonderlandSetupMixin:
- """
- A test case mixin which sets up a graph based on a scene from Alice in
- Wonderland.
- """
- def setUp(self):
- garden = Idea(AlsoKnownAs("garden"))
- door = Idea(AlsoKnownAs("door"))
- hall = Idea(AlsoKnownAs("hall"))
- alice = Idea(AlsoKnownAs("alice"))
- key = Idea(AlsoKnownAs("key"))
- table = Idea(AlsoKnownAs("table"))
-
- alice.linkers.append(OneLink(Link(alice, hall)))
- hall.linkers.append(OneLink(Link(hall, door)))
- hall.linkers.append(OneLink(Link(hall, table)))
- table.linkers.append(OneLink(Link(table, key)))
- door.linkers.append(OneLink(Link(door, garden)))
-
- self.alice = alice
- self.hall = hall
- self.door = door
- self.garden = garden
- self.table = table
- self.key = key
-
-
-
-class IdeaTests(WonderlandSetupMixin, TestCase):
- """
- Tests for L{imaginary.idea.Idea}.
- """
- def test_objections(self):
- """
- The L{IRetriver} passed to L{Idea.obtain} can object to certain results.
- This excludes them from the result returned by L{Idea.obtain}.
- """
- # XXX The last argument is the observer, and is supposed to be an
- # IThing.
- retriever = Named("key", ProviderOf(INameable), self.alice)
-
- # Sanity check. Alice should be able to reach the key if we don't
- # restrict things based on her height.
- self.assertEquals(
- list(self.alice.obtain(retriever)), [self.key.delegate])
-
- # But when we consider how short she is, she should not be able to reach
- # it.
- results = self.alice.obtain(ArmsReach(retriever))
- self.assertEquals(list(results), [])
-
-
-class Closed(object):
- implements(IObstruction)
-
- def whyNot(self):
- return ExpressString("the door is closed")
-
-
-
-class ConstantAnnotation(record('annotation')):
- implements(ILinkAnnotator)
-
- def annotationsFor(self, link, idea):
- return [self.annotation]
-
-
-
-class ReachableTests(WonderlandSetupMixin, TestCase):
- """
- Tests for L{imaginary.idea.Reachable}.
- """
- def setUp(self):
- WonderlandSetupMixin.setUp(self)
- # XXX The last argument is the observer, and is supposed to be an
- # IThing.
- self.retriever = Reachable(
- Named("garden", ProviderOf(INameable), self.alice))
-
-
- def test_anyObstruction(self):
- """
- If there are any obstructions in the path traversed by the retriever
- wrapped by L{Reachable}, L{Reachable} objects to them and they are not
- returned by L{Idea.obtain}.
- """
- # Make the door closed.. Now Alice cannot reach the garden.
- self.door.annotators.append(ConstantAnnotation(Closed()))
- self.assertEquals(list(self.alice.obtain(self.retriever)), [])
-
-
- def test_noObstruction(self):
- """
- If there are no obstructions in the path traversed by the retriever
- wrapped by L{Reachable}, all results are returned by L{Idea.obtain}.
- """
- self.assertEquals(
- list(self.alice.obtain(self.retriever)),
- [self.garden.delegate])
-
-
-class Wood(object):
- implements(IElectromagneticMedium)
-
- def isOpaque(self):
- return True
-
-
-
-class Glass(object):
- implements(IElectromagneticMedium)
-
- def isOpaque(self):
- return False
-
-
-class CanSeeTests(WonderlandSetupMixin, TestCase):
- """
- Tests for L{imaginary.idea.CanSee}.
- """
- def setUp(self):
- WonderlandSetupMixin.setUp(self)
- self.retriever = CanSee(
- Named("garden", ProviderOf(INameable), self.alice))
-
-
- def test_throughTransparent(self):
- """
- L{Idea.obtain} continues past an L{IElectromagneticMedium} which returns
- C{False} from its C{isOpaque} method.
- """
- self.door.annotators.append(ConstantAnnotation(Glass()))
- self.assertEquals(
- list(self.alice.obtain(self.retriever)), [self.garden.delegate])
-
-
- def test_notThroughOpaque(self):
- """
- L{Idea.obtain} does not continue past an L{IElectromagneticMedium} which
- returns C{True} from its C{isOpaque} method.
- """
- # Make the door opaque. Now Alice cannot see the garden.
- self.door.annotators.append(ConstantAnnotation(Wood()))
- self.assertEquals(list(self.alice.obtain(self.retriever)), [])
=== removed file 'Imaginary/imaginary/test/test_illumination.py'
--- Imaginary/imaginary/test/test_illumination.py 2013-06-30 19:00:05 +0000
+++ Imaginary/imaginary/test/test_illumination.py 1970-01-01 00:00:00 +0000
@@ -1,370 +0,0 @@
-
-from zope.interface import implements
-
-from twisted.trial import unittest
-
-from axiom import store, item, attributes
-
-from imaginary.enhancement import Enhancement
-from imaginary import iimaginary, objects, idea
-from imaginary.language import ExpressString
-from imaginary.manipulation import Manipulator
-
-from imaginary.test import commandutils
-
-
-class DarknessTestCase(unittest.TestCase):
-
- def setUp(self):
- self.store = store.Store()
- self.location = objects.Thing(store=self.store, name=u"Dark Room")
- objects.Container.createFor(self.location, capacity=1000)
-
- objects.LocationLighting.createFor(self.location, candelas=0)
-
- self.rock = objects.Thing(store=self.store, name=u"Rock")
-
- self.observer = objects.Thing(store=self.store, name=u"Observer")
-
- self.rock.moveTo(self.location)
- self.observer.moveTo(self.location)
-
-
- def assertDarkRoom(self, visible):
- """
- Assert that the given L{IVisible} provider is a dark room.
- """
- descr = visible.visualize()
- expressed = descr.plaintext(self.observer)
- lines = commandutils.flatten(expressed).splitlines()
-
- self.assertEquals(
- lines,
- [u"[ Blackness ]",
- u"You cannot see anything because it is very dark."])
-
-
- def testDarkenedRoom(self):
- """
- Test that when a 'dark' LocationLighting proxy is on a location,
- only darkness can be seen.
- """
- darkThings = list(self.observer.findProviders(iimaginary.IVisible, 1))
- self.assertDarkRoom(darkThings[0])
- self.assertEquals(len(darkThings), 1)
-
-
- def testLookingOut(self):
- """
- Test that when findProviders is called on an observer in a dark
- location, objects in nearby illuminated rooms are returned.
- """
- nearby = objects.Thing(store=self.store, name=u"other room")
- objects.Container.createFor(nearby, capacity=1000)
- ball = objects.Thing(store=self.store, name=u"ball")
- ball.moveTo(nearby)
-
- objects.Exit.link(self.location, nearby, u"west")
-
- found = list(self.observer.findProviders(iimaginary.IVisible, 3))
- self.assertDarkRoom(found[0])
- self.assertEquals(found[1:], [nearby, ball])
- self.assertEquals(len(found), 3)
-
-
- def test_nonVisibilityAffected(self):
- """
- L{LocationLightning} blocks out non-IVisible stuff from
- L{Thing.findProviders} by default.
- """
- self.assertEquals(
- list(self.observer.findProviders(iimaginary.IThing, 3)),
- [])
- # XXX need another test: not blocked out from ...
-
-
- def test_nonVisibilityUnaffected(self):
- """
- L{LocationLightning} should not block out non-IVisible stuff from a
- plain L{Idea.obtain} query.
- """
- self.assertEquals(
- list(self.observer.idea.obtain(
- idea.Proximity(3, idea.ProviderOf(iimaginary.IThing)))),
- [self.observer, self.location, self.rock]
- )
-
-
- def testLightSourceInLocation(self):
- """
- Test that a light source in a dark room causes things to be visible
- again.
- """
- torch = objects.Thing(store=self.store, name=u"torch")
- objects.LightSource.createFor(torch, candelas=80)
- torch.moveTo(self.location)
-
- self.assertEquals(
- list(self.observer.findProviders(iimaginary.IVisible, 1)),
- [self.observer, self.location, self.rock, torch])
-
-
- def testHeldLightSource(self):
- """
- Test that a torch in an open container lights up a location.
- """
- torch = objects.Thing(store=self.store, name=u"torch")
- objects.LightSource.createFor(torch, candelas=80)
-
- objects.Container.createFor(self.observer, capacity=1000)
-
- torch.moveTo(self.observer)
-
- self.assertEquals(
- list(self.observer.findProviders(iimaginary.IVisible, 1)),
- [self.observer, torch, self.location, self.rock])
-
-
- def testOccultedLightSource(self):
- """
- Test that a light source which is obscured somehow does not actually
- illuminate a location.
- """
- torch = objects.Thing(store=self.store, name=u"torch")
- objects.LightSource.createFor(torch, candelas=80)
-
- c = objects.Container.createFor(self.observer, capacity=1000)
-
- torch.moveTo(self.observer)
- c.closed = True
-
- found = list(self.observer.findProviders(iimaginary.IVisible, 1))
- self.assertDarkRoom(found[0])
- self.assertEquals(len(found), 1)
-
-
-
-class DarknessCommandTestCase(commandutils.CommandTestCaseMixin, unittest.TestCase):
- def testLookingIntoDarkness(self):
- objects.LocationLighting.createFor(self.location, candelas=0)
- self._test(
- "look",
- [commandutils.E("[ Blackness ]"),
- "You cannot see anything because it is very dark."])
-
-
- def testTorch(self):
- objects.LocationLighting.createFor(self.location, candelas=0)
- self._test(
- "create a torch named torch",
- ["You create a torch."],
- ["Test Player creates a torch."])
-
- self._test(
- "look",
- [commandutils.E("[ Test Location ]"),
- "Location for testing.",
- "Here, you see Observer Player."])
-
-
- def test_changeIlluminationLevel(self):
- """
- An administrator can change the illumination level of a room to a fixed
- number by using the "illuminate" command.
- """
- fade_to_black = "Your environs fade to black due to Ineffable Spooky Magic."
- no_change = "You do it. Swell."
- dark_to_light = "Your environs are suddenly alight."
- brighten = "Your environs seem slightly brighter."
- endarken = "Your environs seem slightly dimmer."
- theAdmin = Manipulator(store=self.store, thing=self.playerWrapper.actor)
- self.playerWrapper.actor.powerUp(theAdmin)
-
- self._test(
- "illuminate 0",
- [fade_to_black],
- [fade_to_black])
-
- ll = self.store.findUnique(
- objects.LocationLighting,
- objects.LocationLighting.thing == self.location)
- self.assertEquals(ll.candelas, 0)
-
- self._test(
- "illuminate 0",
- [no_change])
- self.assertEquals(ll.candelas, 0)
-
- self._test(
- "illuminate 100",
- [dark_to_light],
- [dark_to_light])
- self.assertEquals(ll.candelas, 100)
-
- self._test(
- "illuminate 110",
- [brighten],
- [brighten])
- self.assertEquals(ll.candelas, 110)
-
- self._test(
- "illuminate 100",
- [endarken],
- [endarken])
- self.assertEquals(ll.candelas, 100)
-
- self._test(
- "illuminate 0",
- [fade_to_black],
- [fade_to_black])
- self.assertEquals(ll.candelas, 0)
-
-
- def test_regularUserCantIlluminate(self):
- """
- A regular, non-administrative user should not be able to illuminate a
- room with the administrative command.
- """
- objects.LocationLighting(thing=self.location,
- store=self.location.store,
- candelas=100)
- self._test(
- "illuminate 0",
- ["You are insufficiently brilliant to do that directly."])
- self.assertEquals(self.store.findUnique(
- objects.LocationLighting,
- objects.LocationLighting.thing == self.location).candelas, 100)
-
-
-class ActionsInDarkRoomTestCase(commandutils.CommandTestCaseMixin,
- unittest.TestCase):
- """
- Darkness interferes with other commands.
- """
-
- def setUp(self):
- """
- There's a room which is dark, where the player is trying to do things.
- """
- commandutils.CommandTestCaseMixin.setUp(self)
- self.lighting = objects.LocationLighting.createFor(
- self.location, candelas=0)
-
-
- def test_actionWithTargetInDarkRoom(self):
- """
- By default, actions which require objects in a darkened room should
- fail, because it's too dark.
- """
- self.assertCommandOutput(
- "create pants named 'pair of pants'",
- ["You create a pair of pants."],
- ["Test Player creates a pair of pants."])
-
- # The action is going to try to locate its target. During the graph
- # traversal it shouldn't find _any_ pants. Whether or not we find any
- # pants, we want the message to note that it's too dark. The reason is
- # actually a property of a link (or perhaps a set of links: i.e. the
- # me->me link, the me->chair link, the chair->room link) so the
- # retriever is going to need to keep a list of those (Refusals) as it
- # retrieves each one.
- #
- # resolve calls search
- # search calls findProviders
- # findProviders constructs a thingy, calls obtain()
-
- self.test_actionWithNoTargetInDarkRoom()
-
-
- def test_actionWithTargetInAdjacentDarkRoom(self):
- """
- If a player is standing I{next} to a dark room, they should not be able
- to locate targets in the dark room, but the reporting in this case
- should be normal, not the "It's too dark to see" that would result if
- they were in the dark room themselves.
- """
- self.otherRoom = objects.Thing(store=self.store, name=u'Elsewhere')
- objects.Container.createFor(self.otherRoom, capacity=1000)
- objects.Exit.link(self.location, self.otherRoom, u'west')
- self.player.moveTo(self.otherRoom)
- self.observer.moveTo(self.otherRoom)
- self.assertCommandOutput(
- "wear pants",
- [commandutils.E(u"Who's that?")],
- [])
-
-
- def test_actionWithNoTargetInDarkRoom(self):
- """
- By default, actions which require objects in a darkened room should
- fail because it's too dark, even if there is actually no target to be
- picked up.
- """
- self._test(
- "wear pants",
- ["It's too dark to see."], # to dark to see... the pants? any pants?
- [])
-
-
- def test_examiningNonThing(self):
- """
- When examining an L{IVisible} which is not also an L{IThing}, it should
- be dark.
- """
- t = objects.Thing(name=u"magic stone", store=self.store)
- t.powerUp(MagicStone(thing=t, store=self.store))
- t.moveTo(self.location)
-
- self.assertCommandOutput(
- "look at rune",
- ["It's too dark to see."],
- [])
- self.lighting.candelas = 100
- self.assertCommandOutput(
- "look at rune",
- ["A totally mystical rune."],
- [])
-
-
-
-class Rune(object):
- """
- This is an example provider of L{iimaginary.IVisible} which is not an
- L{iimaginary.IThing}.
- """
-
- implements(iimaginary.IVisible, iimaginary.INameable)
-
- def visualize(self):
- """
- Return an L{ExpressString} with a sample string that can be tested
- against.
- """
- return ExpressString("A totally mystical rune.")
-
-
- def knownTo(self, observer, asName):
- """
- Implement L{iimaginary.INameable.knownTo} to respond to the word 'rune'
- and nothing else, so that this object may be found by
- L{imaginary.idea.Idea.obtain}.
- """
- return (asName == "rune")
-
-
-
-class MagicStone(item.Item, Enhancement):
- """
- This is a magic stone that has a rune on it which you can examine.
- """
-
- implements(iimaginary.ILinkContributor)
- powerupInterfaces = [iimaginary.ILinkContributor]
- thing = attributes.reference()
-
- def links(self):
- """
- Implement L{ILinkContributor} to yield a single link to a L{Rune}.
- """
- runeIdea = idea.Idea(Rune())
- yield idea.Link(self.thing.idea, runeIdea)
=== removed file 'Imaginary/imaginary/test/test_language.py'
--- Imaginary/imaginary/test/test_language.py 2013-07-24 22:20:04 +0000
+++ Imaginary/imaginary/test/test_language.py 1970-01-01 00:00:00 +0000
@@ -1,116 +0,0 @@
-
-from twisted.trial.unittest import TestCase
-
-from imaginary.objects import Thing
-from imaginary.language import Gender, ConceptTemplate, ExpressList
-from imaginary.test.commandutils import flatten
-
-class ConceptTemplateTests(TestCase):
- """
- Tests for L{imaginary.language.ConceptTemplate}.
- """
- def setUp(self):
- self.thing = Thing(name=u"alice", gender=Gender.FEMALE)
-
-
- def expandToText(self, template, values):
- """
- Expand the given L{ConceptTemplate} with the given values and flatten
- the result into a L{unicode} string.
- """
- return flatten(ExpressList(template.expand(values)).plaintext(None))
-
-
- def test_unexpandedLiteral(self):
- """
- A template string containing no substitution markers expands to itself.
- """
- self.assertEqual(
- u"hello world",
- self.expandToText(ConceptTemplate(u"hello world"), {}))
-
-
- def test_expandedName(self):
- """
- I{field:name} can be used to substitute the name of the value given by
- C{"field"}.
- """
- template = ConceptTemplate(u"{a:name}")
- self.assertEqual(
- u"alice",
- self.expandToText(template, dict(a=self.thing)))
-
-
- def test_expandedPronoun(self):
- """
- I{field:pronoun} can be used to substitute the personal pronoun of the
- value given by C{"field"}.
- """
- template = ConceptTemplate(u"{b:pronoun}")
- self.assertEqual(
- u"she",
- self.expandToText(template, dict(b=self.thing)))
-
-
- def test_intermixed(self):
- """
- Literals and subsitution markers may be combined in a single template.
- """
- template = ConceptTemplate(u"{c:pronoun} wins.")
- self.assertEqual(
- u"she wins.",
- self.expandToText(template, dict(c=self.thing)))
-
-
- def test_multiples(self):
- """
- Multiple substitution markers may be used in a single template.
- """
- another = Thing(name=u"bob", gender=Gender.FEMALE)
- template = ConceptTemplate(u"{a:name} hits {b:name}.")
- self.assertEqual(
- u"alice hits bob.",
- self.expandToText(template, dict(a=self.thing, b=another)))
-
-
- def test_adjacent(self):
- """
- Adjacent substitution markers are expanded without introducing
- extraneous intervening characters.
- """
- another = Thing(name=u"bob", gender=Gender.FEMALE)
- template = ConceptTemplate(u"{a:name}{b:name}")
- self.assertEqual(
- u"alicebob",
- self.expandToText(template, dict(a=self.thing, b=another)))
-
-
- def test_missingTarget(self):
- """
- A missing target is expanded to a warning about a bad template.
- """
- template = ConceptTemplate(u"{c} wins.")
- self.assertEqual(
- u"<missing target 'c' for expansion> wins.",
- self.expandToText(template, dict()))
-
-
- def test_missingTargetWithSpecifier(self):
- """
- A missing target is expanded to a warning about a bad template.
- """
- template = ConceptTemplate(u"{c:pronoun} wins.")
- self.assertEqual(
- u"<missing target 'c' for 'pronoun' expansion> wins.",
- self.expandToText(template, dict()))
-
-
- def test_unsupportedSpecifier(self):
- """
- A specifier not supported on the identified target is expanded to a
- warning about a bad template.
- """
- template = ConceptTemplate(u"{c:glorbex} wins.")
- self.assertEqual(
- u"<'glorbex' unsupported by target 'c'> wins.",
- self.expandToText(template, dict(c=self.thing)))
=== removed file 'Imaginary/imaginary/test/test_look.py'
--- Imaginary/imaginary/test/test_look.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_look.py 1970-01-01 00:00:00 +0000
@@ -1,65 +0,0 @@
-
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import iimaginary, objects, language, action, events
-from imaginary.world import ImaginaryWorld
-from imaginary.test import commandutils
-
-
-class TestIntelligence(object):
- def __init__(self):
- self.observedConcepts = []
-
-
- def prepare(self, concept):
- return lambda: self.observedConcepts.append(concept)
-
-
-
-class LookTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
- self.location = objects.Thing(
- store=self.store,
- name=u"Test Location",
- description=u"Location for testing.",
- proper=True)
-
- locContainer = objects.Container.createFor(
- self.location, capacity=1000)
-
- self.world = ImaginaryWorld(store=self.store)
- self.player = self.world.create(u"Test Player", gender=language.Gender.FEMALE)
- locContainer.add(self.player)
- self.actor = iimaginary.IActor(self.player)
- self.actor.setEphemeralIntelligence(TestIntelligence())
-
-
- def testLookAroundEventBroadcasting(self):
- action.LookAround().runEventTransaction(
- self.player, u"look", {})
- evts = self.actor.getIntelligence().observedConcepts
- self.assertEquals(len(evts), 1)
- self.failUnless(isinstance(evts[0], events.Success))
-
-
- def testLookAtExitNameEventBroadcasting(self):
- target = objects.Thing(
- store=self.store,
- name=u"Visible Location",
- description=u"Description of visible location.",
- proper=True)
- objects.Container.createFor(target, capacity=1000)
- objects.Exit.link(self.location, target, u"south")
-
- action.LookAt().runEventTransaction(
- self.player, u"look", {"target": u"south"})
- evts = self.actor.getIntelligence().observedConcepts
- self.assertEquals(len(evts), 1)
- self.failUnless(isinstance(evts[0], events.Success))
- self.assertEquals(
- commandutils.flatten(evts[0].actorMessage.plaintext(self.actor)),
- u"[ Visible Location ]\n( north )\nDescription of visible location.\n")
=== removed file 'Imaginary/imaginary/test/test_objects.py'
--- Imaginary/imaginary/test/test_objects.py 2009-08-17 02:40:03 +0000
+++ Imaginary/imaginary/test/test_objects.py 1970-01-01 00:00:00 +0000
@@ -1,439 +0,0 @@
-
-from zope.interface import Interface
-
-from twisted.trial import unittest
-from twisted.python import components
-
-from axiom import store
-
-from imaginary import iimaginary, eimaginary, objects, events
-from imaginary.test import commandutils
-
-
-
-class PointsTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
- def testInitialiation(self):
- p = objects.Points(store=self.store, max=100)
- self.assertEquals(p.current, p.max)
- self.assertEquals(p.max, 100)
-
-
- def testMutation(self):
- p = objects.Points(store=self.store, max=100)
- p.increase(10)
- self.assertEquals(p.current, 100)
-
- p.decrease(10)
- self.assertEquals(p.current, 90)
-
- p.increase(20)
- self.assertEquals(p.current, 100)
-
- p.decrease(110)
- self.assertEquals(p.current, 0)
-
- p.decrease(10)
- self.assertEquals(p.current, 0)
-
- p.modify(10)
- self.assertEquals(p.current, 10)
-
- p.modify(-10)
- self.assertEquals(p.current, 0)
-
-
- def testRepresentation(self):
- p = objects.Points(store=self.store, max=100)
- self.assertEquals(str(p), '100/100')
- self.assertEquals(repr(p), 'imaginary.objects.Points(100, 100)')
-
- p.decrease(10)
- self.assertEquals(str(p), '90/100')
- self.assertEquals(repr(p), 'imaginary.objects.Points(100, 90)')
-
- p.decrease(90)
- self.assertEquals(str(p), '0/100')
- self.assertEquals(repr(p), 'imaginary.objects.Points(100, 0)')
-
-
-
-
-class ObjectTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
-
- def testCreation(self):
- obj = objects.Thing(store=self.store, name=u"test object", description=u"lame description")
- self.assertEquals(obj.name, u"test object")
- self.assertEquals(obj.description, u"lame description")
-
-
- def testDestroy(self):
- obj = objects.Thing(store=self.store, name=u"x")
- obj.destroy()
-
- room = objects.Thing(store=self.store, name=u"test location")
- locContainer = objects.Container.createFor(room, capacity=1000)
- obj = objects.Thing(store=self.store, name=u"y")
- obj.moveTo(room)
-
- obj.destroy()
- self.assertIdentical(obj.location, None)
- self.assertEquals(list(locContainer.getContents()), [])
-
-
- def testMoving(self):
- obj = objects.Thing(store=self.store, name=u"DOG")
- room = objects.Thing(store=self.store, name=u"HOUSE")
- objects.Container.createFor(room, capacity=1000)
- obj.moveTo(room)
- self.assertIdentical(obj.location, room)
- obj.moveTo(room)
- self.assertIdentical(obj.location, room)
-
-
- def testNonPortable(self):
- """
- Test that the C{portable} flag is respected and prevents movement
- between locations.
- """
- obj = objects.Thing(store=self.store, name=u"mountain")
- obj.portable = False
- room = objects.Thing(store=self.store, name=u"place")
- objects.Container.createFor(room, capacity=1000)
- obj.moveTo(room)
- elsewhere = objects.Thing(store=self.store, name=u"different place")
- container = objects.Container.createFor(elsewhere, capacity=1000)
- self.assertRaises(eimaginary.CannotMove, obj.moveTo, elsewhere)
- self.assertIdentical(obj.location, room)
- self.assertEquals(list(iimaginary.IContainer(room).getContents()), [obj])
- self.assertEquals(list(container.getContents()), [])
-
-
-
-class MovementTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
- obj = objects.Thing(store=self.store, name=u"DOG")
- room = objects.Thing(store=self.store, name=u"HOUSE")
- objects.Container.createFor(room, capacity=1000)
- obj.moveTo(room)
-
- observer = objects.Thing(store=self.store, name=u"OBSERVER")
- actor = objects.Actor.createFor(observer)
- intelligence = commandutils.MockEphemeralIntelligence()
- actor.setEphemeralIntelligence(intelligence)
-
- self.obj = obj
- self.room = room
- self.observer = observer
- self.intelligence = intelligence
- self.actor = actor
-
-
- def testMovementDepartureEvent(self):
- """
- Test that when a Thing is moved out of a location, a departure event is
- broadcast to that location.
- """
- self.observer.moveTo(self.room)
- self.intelligence.events[:] = []
-
- self.obj.moveTo(None)
-
- evts = self.intelligence.events
- self.assertEquals(len(evts), 1)
- self.failUnless(
- isinstance(evts[0], events.DepartureEvent))
- self.assertIdentical(evts[0].location, self.room)
- self.assertIdentical(evts[0].actor, self.obj)
-
-
- def testMovementArrivalEvent(self):
- """
- Test that when a Thing is moved to a location, an arrival event is
- broadcast to that location.
- """
- destination = objects.Thing(store=self.store, name=u'ELSEWHERE')
- objects.Container.createFor(destination, capacity=1000)
-
- self.observer.moveTo(destination,
- arrivalEventFactory=events.MovementArrivalEvent)
-
- evts = self.intelligence.events
- self.assertEquals(len(evts), 1)
- self.failUnless(isinstance(evts[0], events.MovementArrivalEvent))
- self.assertIdentical(evts[0].thing, self.observer)
- self.assertIdentical(evts[0].location, destination)
- evts[:] = []
-
- self.obj.moveTo(destination, arrivalEventFactory=events.MovementArrivalEvent)
-
- evts = self.intelligence.events
- self.assertEquals(len(evts), 1)
- self.failUnless(
- isinstance(evts[0], events.ArrivalEvent))
- self.assertIdentical(evts[0].location, destination)
- self.assertIdentical(evts[0].thing, self.obj)
-
- # TODO - Test that a guy moving around sees first his own departure event
- # and then his arrival event.
-
- def test_parameterizedArrivalEvent(self):
- """
- moveTo should take a parameter which allows customization of
- the arrival event that it emits.
- """
- destination = objects.Thing(store=self.store, name=u'ELSEWHERE')
- objects.Container.createFor(destination, capacity=1000)
-
- class DroppedEvent(events.MovementArrivalEvent):
- def conceptFor(self, observer):
- return "you rock."
- self.observer.moveTo(destination, arrivalEventFactory=DroppedEvent)
-
- evts = self.intelligence.events
- self.assertEquals(len(evts), 1)
- self.failUnless(isinstance(evts[0], DroppedEvent))
- self.assertIdentical(evts[0].thing, self.observer)
- self.assertIdentical(evts[0].location, destination)
-
- def test_parameterizedArrivalAsNone(self):
- """
- If the parameter for customizing the arrival event is None, no
- arrival event should be broadcast.
- """
- destination = objects.Thing(store=self.store, name=u'ELSEWHERE')
- objects.Container.createFor(destination, capacity=1000)
-
- self.observer.moveTo(destination, arrivalEventFactory=None)
- self.assertEquals(self.intelligence.events, [])
-
-
- def test_parameterizedArrivalDefaultsNone(self):
- """
- The default should be for moveTo not to broadcast an event.
- """
- destination = objects.Thing(store=self.store, name=u'ELSEWHERE')
- objects.Container.createFor(destination, capacity=1000)
-
- self.observer.moveTo(destination)
- self.assertEquals(self.intelligence.events, [])
-
-
-
-unexpected = object()
-class IFoo(Interface):
- """
- Stupid thing to help tests out.
- """
-
-components.registerAdapter(lambda o: (unexpected, o), objects.Thing, IFoo)
-
-
-
-class FindProvidersTestCase(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
- self.retained = []
- obj = objects.Thing(store=self.store, name=u"generic object")
- room = objects.Thing(store=self.store, name=u"room")
- objects.Container.createFor(room, capacity=1000)
- obj.moveTo(room)
- self.obj = obj
- self.room = room
-
-
- def tearDown(self):
- """
- Allow the items retained with L{FindProvidersTestCase.retain} to be
- garbage collected.
- """
- del self.retained
-
-
- def retain(self, o):
- """
- Keep the given object in memory until the end of the test, so that its
- 'inmemory' attributes won't be garbage collected.
- """
- self.retained.append(o)
-
-
- def testFindObjects(self):
- """
- Assert that searching for the most basic object interface, L{IObject},
- returns the only two objects available in our test object graph: both
- the location upon which the search was issued and the object which it
- contains.
- """
- self.assertEquals(
- list(self.room.findProviders(iimaginary.IThing, 1)),
- [self.room, self.obj])
-
-
- def testFindContainers(self):
- """
- Very much like testFindObjects, but searching for L{IContainer}, which
- only the location provides, and so only the location should be
- returned.
- """
- self.assertEquals(
- list(self.room.findProviders(iimaginary.IContainer, 1)),
- [iimaginary.IContainer(self.room)])
-
-
- def testFindNothing(self):
- """
- Again, similar to testFindObjects, but search for an interface that
- nothing provides, and assert that nothing is found.
- """
- class IUnprovidable(Interface):
- """
- Test-only interface that nothing provides.
- """
-
- self.assertEquals(
- list(self.room.findProviders(IUnprovidable, 1)),
- [])
-
-
- def testFindOutward(self):
- """
- Conduct a search for all objects on our test graph, but start the
- search on the contained object rather than the container and assert
- that the same results come back, though in a different order: the
- searched upon Thing always comes first.
- """
- self.assertEquals(
- list(self.obj.findProviders(iimaginary.IThing, 1)),
- [self.obj, self.room])
-
-
- def testFindContainersOutward(self):
- """
- Combination of testFindOutward and testFindContainers.
- """
- self.assertEquals(
- list(self.obj.findProviders(iimaginary.IContainer, 1)),
- [iimaginary.IContainer(self.room)])
-
-
-
- def testFindingArbitraryInterface(self):
- """
- Demonstration of the Thing -> IFoo adapter registered earlier in this
- module. If this test fails then some other tests are probably buggy
- too, even if they pass.
-
- Thing must be adaptable to IFoo or the tests which assert that certain
- Things are B{not} present in result sets may incorrectly pass.
- """
- self.assertEquals(
- list(self.obj.findProviders(IFoo, 1)),
- [(unexpected, self.obj), (unexpected, self.room)])
-
-
- def test_exactlyKnownAs(self):
- """
- L{Thing.knownTo} returns C{True} when called with exactly the things
- own name.
- """
- self.assertTrue(self.obj.knownTo(self.obj, self.obj.name))
-
-
- def test_caseInsensitivelyKnownAs(self):
- """
- L{Thing.knownTo} returns C{True} when called with a string which
- differs from its name only in case.
- """
- self.assertTrue(self.obj.knownTo(self.obj, self.obj.name.upper()))
- self.assertTrue(self.obj.knownTo(self.obj, self.obj.name.title()))
-
-
- def test_wholeWordSubstringKnownAs(self):
- """
- L{Thing.knownTo} returns C{True} when called with a string which
- appears in the thing's name delimited by spaces.
- """
- self.obj.name = u"one two three"
- self.assertTrue(self.obj.knownTo(self.obj, u"one"))
- self.assertTrue(self.obj.knownTo(self.obj, u"two"))
- self.assertTrue(self.obj.knownTo(self.obj, u"three"))
-
-
- def test_notKnownAs(self):
- """
- L{Thing.knownTo} returns C{False} when called with a string which
- doesn't satisfy one of the above positive cases.
- """
- self.assertFalse(self.obj.knownTo(self.obj, u"gunk" + self.obj.name))
- self.obj.name = u"one two three"
- self.assertFalse(self.obj.knownTo(self.obj, u"ne tw"))
-
-
- def test_searchForThings(self):
- """
- L{Thing.search} includes L{Thing} instances which are I{nearby} and
- which have matching names.
- """
- name = u"box"
- firstBox = objects.Thing(store=self.store, name=name)
- firstBox.moveTo(self.room)
- secondBox = objects.Thing(store=self.store, name=name)
- secondBox.moveTo(self.room)
-
- boxes = list(self.obj.search(1, iimaginary.IThing, name))
- boxes.sort()
- expected = [firstBox, secondBox]
- expected.sort()
-
- self.assertEqual(boxes, expected)
-
-
- def testSearchFindsExits(self):
- """
- Test that search can find an exit.
- """
- room = objects.Thing(store=self.store, name=u"Northerly Room")
- objects.Container.createFor(room, capacity=1000)
- objects.Exit.link(self.room, room, u"north")
-
- self.assertEquals(
- list(self.obj.search(1, iimaginary.IThing, u"north")),
- [room])
-
-
- def test_searchFindsRelativeExit(self):
- """
- L{Thing.search} should only find the exit known relative to the player
- who is asking. In other words, the room where the player is standing
- may be north from I{somewhere}, but it should not be known as 'north'
- to the player.
- """
- def mkroom(n):
- room = objects.Thing(store=self.store, name=n)
- room.powerUp(objects.Container(store=self.store, capacity=1000,
- thing=room))
- return room
- north = mkroom(u"Northerly")
- middle = self.room
- south = mkroom(u"Southerly")
- objects.Exit.link(south, middle, u"north")
- objects.Exit.link(middle, north, u"north")
-
- self.assertEquals(
- list(self.obj.search(100, iimaginary.IThing, u"north")),
- [north])
- self.assertEquals(
- list(self.obj.search(100, iimaginary.IThing, u"south")),
- [south])
-
-
- # XXX Test: me
- # XXX Test: here
- # XXX Test: self
=== removed file 'Imaginary/imaginary/test/test_player.py'
--- Imaginary/imaginary/test/test_player.py 2009-08-17 02:40:03 +0000
+++ Imaginary/imaginary/test/test_player.py 1970-01-01 00:00:00 +0000
@@ -1,69 +0,0 @@
-
-"""
-Tests for L{imaginary.wiring.player}.
-"""
-
-from twisted.trial import unittest
-
-from axiom import store
-
-from imaginary import objects
-from imaginary.objects import Container
-from imaginary.wiring import player
-
-
-
-class PlayerTest(unittest.TestCase):
- def setUp(self):
- self.store = store.Store()
-
- self.bob = objects.Thing(store=self.store, name=u"bob")
- self.room = objects.Thing(store=self.store, name=u"a place")
- roomContainer = Container.createFor(self.room, capacity=1000)
- self.bob.moveTo(roomContainer)
-
- self.actor = objects.Actor.createFor(self.bob)
-
- self.player = player.Player(self.bob)
- self.player.useColors = False
-
- from twisted.test.proto_helpers import StringTransport
- self.transport = StringTransport()
- class Protocol:
- write = self.transport.write
- self.player.setProtocol(Protocol())
-
-
- def testSend(self):
- self.player.send("Hi\n")
- self.assertEquals(self.transport.value(), "Hi\n")
- self.player.send(("Hi", "\n"))
- self.assertEquals(self.transport.value(), "Hi\nHi\n")
- self.player.send(["Hi", "\n"])
- self.assertEquals(self.transport.value(), "Hi\nHi\nHi\n")
- self.player.send(i for i in ("Hi", "\n"))
- self.assertEquals(self.transport.value(), "Hi\nHi\nHi\nHi\n")
-
-
- def testDisconnect(self):
- self.player.proto.terminal = None
- self.player.disconnect()
- self.assertIdentical(self.actor.getIntelligence(), None)
-
-
- def test_ambiguity(self):
- """
- When the player refers to something ambiguously, the error message
- should enumerate the objects in question.
- """
- for color in [u'red', u'green', u'blue']:
- it = objects.Thing(store=self.store, name=u'%s thing' % (color,))
- it.moveTo(self.room)
-
- self.player.parse("take thing")
-
- self.assertEquals(self.transport.value(),
- "> take thing\n"
- "Could you be more specific? When you said 'thing', "
- "did you mean: a red thing, a green thing, "
- "or a blue thing?\r\n")
=== removed file 'Imaginary/imaginary/test/test_put.py'
--- Imaginary/imaginary/test/test_put.py 2009-06-29 04:03:17 +0000
+++ Imaginary/imaginary/test/test_put.py 1970-01-01 00:00:00 +0000
@@ -1,114 +0,0 @@
-
-from twisted.trial import unittest
-
-from imaginary.test import commandutils
-from imaginary import objects
-
-class PutTestCase(commandutils.CommandTestCaseMixin, unittest.TestCase):
- def setUp(self):
- r = commandutils.CommandTestCaseMixin.setUp(self)
- self.object = objects.Thing(store=self.store, name=u"foo")
- self.object.moveTo(self.player)
- self.container = objects.Thing(store=self.store, name=u"bar")
- self.containerContainer = objects.Container.createFor(self.container, capacity=1)
- self.container.moveTo(self.location)
- return r
-
-
- def test_put(self):
- """
- The I{put} action changes the location of a thing from the actor's
- inventory to the specified container.
- """
- self._test(
- "put foo in bar",
- ["You put the foo in the bar."],
- ["Test Player puts a foo in a bar."])
- self.assertIdentical(self.player.location, self.location)
- self.assertIdentical(self.object.location, self.container)
- self.assertIdentical(self.container.location, self.location)
- self.assertEquals(list(self.containerContainer.getContents()), [self.object])
-
-
- def testPutHere(self):
- self._test(
- "put here in bar",
- ["A thing cannot contain itself in euclidean space."],
- [])
- self.assertIdentical(self.location.location, None)
- self.assertNotIn(self.location, self.containerContainer.getContents())
-
-
- def testPutNonContainer(self):
- self._test(
- "put bar in foo",
- ["That doesn't work."],
- [])
- self.assertIdentical(self.container.location, self.location)
-
-
- def testPutRecursive(self):
- self._test(
- "put bar in bar",
- ["A thing cannot contain itself in euclidean space."],
- [])
- self.assertEquals(list(self.containerContainer.getContents()), [])
- self.assertEquals(self.container.location, self.location)
-
-
- def testNestedContainment(self):
- another = objects.Thing(store=self.store, name=u"another")
- objects.Container.createFor(another, capacity=1)
- self.containerContainer.add(another)
-
- self._test(
- "put bar in another",
- ["A thing cannot contain itself in euclidean space."],
- [])
- self.assertIdentical(another.location, self.container)
- self.assertEquals(list(self.containerContainer.getContents()), [another])
-
-
- def testIndirectNestedContainment(self):
- innermost = objects.Thing(store=self.store, name=u"innermost")
- innermostContainer = objects.Container.createFor(innermost, capacity=1)
- middle = objects.Thing(store=self.store, name=u"middle")
- middleContainer = objects.Container.createFor(middle, capacity=1)
- middleContainer.add(innermost)
- self.containerContainer.add(middle)
-
- self._test(
- "put bar in innermost",
- ["A thing cannot contain itself in euclidean space."],
- [])
- self.assertIdentical(self.container.location, self.location)
- self.assertEquals(list(self.containerContainer.getContents()), [middle])
- self.assertIdentical(middle.location, self.container)
- self.assertEquals(list(middleContainer.getContents()), [innermost])
- self.assertIdentical(innermost.location, middle)
- self.assertEquals(list(innermostContainer.getContents()), [])
-
-
- def test_putClosedFails(self):
- """
- The I{put} action fails if the specified container is closed.
- """
- self.containerContainer.closed = True
- self._test(
- "put foo in bar",
- ["The bar is closed."])
- self.assertEquals(list(self.cont
Follow ups