1# -*- test-case-name: nevow -*- 2# Copyright (c) 2004-2009 Divmod. 3# See LICENSE for details. 4 5""" 6Nevow interface definitions. 7""" 8 9from zope.interface import Interface, Attribute 10 11class IQ(Interface): 12 """Interface for querying. Adapters implement this for objects which may 13 appear in the stan DOM to allow introspecting the DOM and finding nodes 14 with certain qualities. 15 """ 16 def patternGenerator(pattern, default=None): 17 """Returns a pseudo-Tag which will generate clones of matching 18 pattern tags forever, looping around to the beginning when running 19 out of unique matches. 20 21 If no matches are found, and default is None, raise an exception, 22 otherwise, generate clones of default forever. 23 24 You can use the normal stan syntax on the return value. 25 26 Useful to find repeating pattern elements. Example rendering 27 function: 28 29 >>> def simpleSequence(context, data): 30 ... pattern = IQ(context).patternGenerator('item') 31 ... return [pattern(data=element) for element in data] 32 """ 33 34 def allPatterns(pattern): 35 """Return a list of all matching pattern tags, cloned. 36 37 Useful if you just want to insert them in the output in one 38 place. 39 40 E.g. the sequence renderer's header and footer are found with this. 41 """ 42 43 def onePattern(pattern): 44 """Return a single matching pattern, cloned. 45 If there is more than one matching pattern or no matching patterns, 46 raise an exception. 47 48 Useful in the case where you want to locate one and only one 49 sub-tag and do something with it. 50 """ 51 52 def keyed(key): 53 """Locate the node with the key 'key', clone it, call fillSlots(key, clone) 54 and return the clone. 55 56 This method lets you effectively locate and mutate a node in the DOM. 57 It is useful for setting the data special on a specific node, and also for 58 calling fillSlots on a specific node, as well as other node-mutation operations 59 such as setting a handler or assigning a class or id to a node. 60 """ 61 62 63class IResource(Interface): 64 def locateChild(ctx, segments): 65 """ 66 Locate another object which can be adapted to IResource. 67 68 @param ctx: The context object for the request being responded to. 69 @param segments: A tuple of strings giving the remaining query segments 70 to resolve into an IResource. 71 72 @return: A two-tuple of an L{IResource} provider and a tuple giving the 73 query segments which remain to be processed. A L{Deferred} which 74 is called back with such a two-tuple may also be returned. 75 """ 76 77 def renderHTTP(ctx): 78 """Render a request 79 """ 80 81 82class IRenderer(Interface): 83 """Things implementing this interface are serialized by calling their 84 'rend' method. 85 """ 86 def rend(ctx, data): 87 """Turn this instance into stan suitable for displaying it in a web page. 88 """ 89 90 91class IRenderable(Interface): 92 def renderer(name): 93 """ 94 Return the render function associated with the given name. 95 96 @type name: C{str} 97 @param name: The value of a render directive encountered in the 98 document returned by a call to L{IRenderable.render}. 99 100 @return: A two-argument callable which will be invoked with the request 101 being responded to and the tag object on which the render directive 102 was encountered. 103 """ 104 105 106 def render(request): 107 """ 108 Get the document for this L{IRenderable}. 109 110 @type request: L{IRequest} provider or L{NoneType} 111 @param request: The request in response to which this method is being 112 invoked. 113 114 @return: An object which can be flattened. 115 """ 116 117 118 119class IRendererFactory(Interface): 120 """A renderer factory is capable of taking a renderer directive (a string) 121 and returning a callable which when called, will render a portion of DOM. 122 """ 123 def renderer(context, name): 124 """Given a context object and a name, return a callable which responds 125 to the signature (context, data) or (data) and returns an object which 126 is flattenable. 127 """ 128 129 130class IMacroFactory(Interface): 131 """A macro factory is capable of taking a macro directive (a string) 132 and returning a callable which when called, will replace the portion 133 of the DOM upon which the macro was placed with some different 134 DOM. 135 """ 136 def macro(context, name): 137 """Given a context object and a name, return a callable which responds 138 to the signature (context, *parameters) and returns an object which 139 is flattenable. 140 """ 141 142 143class IData(Interface): 144 """Any python object to be used as model data to be passed 145 to view functions. Used for marking the context stack only. 146 147 ANY python object is said to implement IData. 148 """ 149 150 151class IGettable(Interface): 152 def get(context): 153 """Return the data 154 155 Return any object 156 """ 157 158 159class ISettable(Interface): 160 def set(context, data): 161 """Set the data 162 163 This might be removed. 164 """ 165 166 167class IContainer(Interface): 168 def child(context, name): 169 """Return a conceptual child; an attribute, or a key, 170 or the result of a function call. 171 172 Returns any object; the result may be adapted to IGettable 173 if possible. 174 175 Return None if the adaptee does not have a child with the 176 given name. 177 178 TODO: Maybe returning None is bad, and .child should just 179 raise whatever exception is natural 180 """ 181 182class IComponentized(Interface): 183 """I am a mixin to allow you to be adapted in various ways persistently. 184 185 I define a list of persistent adapters. This is to allow adapter classes 186 to store system-specific state, and initialized on demand. The 187 getComponent method implements this. You must also register adapters for 188 this class for the interfaces that you wish to pass to getComponent. 189 190 Many other classes and utilities listed here are present in Zope3; this one 191 is specific to Twisted. 192 """ 193 194 def setComponent(interfaceClass, component): 195 """ 196 Add a component to me for the indicated interface. 197 """ 198 199 def addComponent(component, ignoreClass=0, registry=None): 200 """ 201 Add a component to me, for all appropriate interfaces. 202 203 In order to determine which interfaces are appropriate, the component's 204 provided interfaces will be scanned. 205 206 If the argument 'ignoreClass' is True, then all interfaces are 207 considered appropriate. 208 209 Otherwise, an 'appropriate' interface is one for which its class has 210 been registered as an adapter for my class according to the rules of 211 getComponent. 212 213 @return: the list of appropriate interfaces 214 """ 215 216 def getComponent(interface, registry=None, default=None): 217 """Create or retrieve an adapter for the given interface. 218 219 If such an adapter has already been created, retrieve it from the cache 220 that this instance keeps of all its adapters. Adapters created through 221 this mechanism may safely store system-specific state. 222 223 If you want to register an adapter that will be created through 224 getComponent, but you don't require (or don't want) your adapter to be 225 cached and kept alive for the lifetime of this Componentized object, 226 set the attribute 'temporaryAdapter' to True on your adapter class. 227 228 If you want to automatically register an adapter for all appropriate 229 interfaces (with addComponent), set the attribute 'multiComponent' to 230 True on your adapter class. 231 """ 232 233 def unsetComponent(interfaceClass): 234 """Remove my component specified by the given interface class.""" 235 236 def removeComponent(component): 237 """ 238 Remove the given component from me entirely, for all interfaces for which 239 it has been registered. 240 241 @return: a list of the interfaces that were removed. 242 """ 243 244 245 246class ISession(IComponentized): 247 """ 248 A web session 249 250 You can locate a Session object to represent a unique web session using 251 ISession(ctx). This default session implementation uses cookies to 252 store a session identifier in the user's browser. 253 254 TODO: Need better docs; what's a session and why and how do you use it 255 """ 256 257 uid = Attribute("The unique identifier for this session.") 258 259 def setLifetime(lifetime): 260 """ 261 Set the approximate lifetime of this session, in seconds. 262 263 This is highly imprecise, but it allows you to set some general 264 parameters about when this session will expire. A callback will be 265 scheduled each 'lifetime' seconds, and if I have not been 'touch()'ed 266 in half a lifetime, I will be immediately expired. 267 268 If you need to change the lifetime of all the sessions change sessionsLifeTime 269 attribute in class guard.SessionWrapper 270 """ 271 272 273 def notifyOnExpire(callback): 274 """ 275 Call this callback when the session expires or logs out. 276 """ 277 278 279 def expire(): 280 """ 281 Expire/logout of the session. 282 """ 283 284 285 def touch(): 286 """ 287 Refresh the session 288 """ 289 290 291 292class IGuardSession(ISession): 293 """ A web session base interface 294 Needed for guard to do its dirty job 295 296 guard: SessionWrapper object 297 """ 298 def portalLogout(port): 299 """Logout from portal port 300 """ 301 302class IRequest(IComponentized): 303 """A HTTP request. 304 305 Subclasses should override the process() method to determine how 306 the request will be processed. 307 308 @ivar method: The HTTP method that was used. 309 @ivar uri: The full URI that was requested (includes arguments). 310 @ivar path: The path only (arguments not included). 311 @ivar args: All of the arguments, including URL and POST arguments. 312 @type args: A mapping of strings (the argument names) to lists of values. 313 i.e., ?foo=bar&foo=baz&quux=spam results in 314 {'foo': ['bar', 'baz'], 'quux': ['spam']}. 315 @ivar requestHeaders: Header fields received in the request. 316 @ivar received_headers: DEPRECATED: All received headers. 317 """ 318 method = Attribute("The HTTP method that was used.") 319 uri = Attribute("The full URI that was requested (includes arguments).") 320 path = Attribute("The path only (arguments not included).") 321 prepath = Attribute("Path segments that have already been handled.") 322 postpath = Attribute("Path segments still to be handled.") 323 args = Attribute("All of the arguments, including URL and POST arguments.") 324 requestHeaders = Attribute( 325 "A L{http_headers.Headers} instance giving all received HTTP request " 326 "header fields.") 327 deferred = Attribute("Fired once request processing is finished.") 328 client = Attribute("The client that sent this request.") 329 content = Attribute("File-like object containing the request body.") 330 331 # DEPRECATED: 332 received_headers = Attribute("DEPRECATED: All received headers.") 333 334 # Methods for received request 335 def getHeader(key): 336 """Get a header that was sent from the network. 337 338 Return C{None} if the header is not present. 339 """ 340 341 342 def getCookie(key): 343 """Get a cookie that was sent from the network. 344 """ 345 346 347 def getAllHeaders(): 348 """Return dictionary of all headers the request received.""" 349 350 def getRequestHostname(): 351 """Get the hostname that the user passed in to the request. 352 353 This will either use the Host: header (if it is available) or the 354 host we are listening on if the header is unavailable. 355 """ 356 357 def getHost(): 358 """Get my originally requesting transport's host. 359 360 Don't rely on the 'transport' attribute, since Request objects may be 361 copied remotely. For information on this method's return value, see 362 twisted.internet.tcp.Port. 363 """ 364 365 def getClientIP(): 366 pass 367 368 def getClient(): 369 pass 370 371 def getUser(): 372 pass 373 374 def getPassword(): 375 pass 376 377 def isSecure(): 378 pass 379 380 def getSession(sessionInterface = None): 381 pass 382 383 def URLPath(): 384 pass 385 386 def prePathURL(): 387 pass 388 389 def rememberRootURL(): 390 """ 391 Remember the currently-processed part of the URL for later 392 recalling. 393 """ 394 395 def getRootURL(): 396 """ 397 Get a previously-remembered URL. 398 """ 399 400 # Methods for outgoing request 401 def finish(): 402 """We are finished writing data.""" 403 404 def write(data): 405 """ 406 Write some data as a result of an HTTP request. The first 407 time this is called, it writes out response data. 408 """ 409 410 def addCookie(k, v, expires=None, domain=None, path=None, max_age=None, comment=None, secure=None): 411 """Set an outgoing HTTP cookie. 412 413 In general, you should consider using sessions instead of cookies, see 414 twisted.web.server.Request.getSession and the 415 twisted.web.server.Session class for details. 416 """ 417 418 def setResponseCode(code, message=None): 419 """Set the HTTP response code. 420 """ 421 422 def setHeader(k, v): 423 """Set an outgoing HTTP header. 424 """ 425 426 def redirect(url): 427 """Utility function that does a redirect. 428 429 The request should have finish() called after this. 430 """ 431 432 def setLastModified(when): 433 """Set the X{Last-Modified} time for the response to this request. 434 435 If I am called more than once, I ignore attempts to set 436 Last-Modified earlier, only replacing the Last-Modified time 437 if it is to a later value. 438 439 If I am a conditional request, I may modify my response code 440 to L{NOT_MODIFIED} if appropriate for the time given. 441 442 @param when: The last time the resource being returned was 443 modified, in seconds since the epoch. 444 @type when: number 445 @return: If I am a X{If-Modified-Since} conditional request and 446 the time given is not newer than the condition, I return 447 L{http.CACHED<CACHED>} to indicate that you should write no 448 body. Otherwise, I return a false value. 449 """ 450 451 def setETag(etag): 452 """Set an X{entity tag} for the outgoing response. 453 454 That's \"entity tag\" as in the HTTP/1.1 X{ETag} header, \"used 455 for comparing two or more entities from the same requested 456 resource.\" 457 458 If I am a conditional request, I may modify my response code 459 to L{NOT_MODIFIED<twisted.protocols.http.NOT_MODIFIED>} or 460 L{PRECONDITION_FAILED<twisted.protocols.http.PRECONDITION_FAILED>}, 461 if appropriate for the tag given. 462 463 @param etag: The entity tag for the resource being returned. 464 @type etag: string 465 @return: If I am a X{If-None-Match} conditional request and 466 the tag matches one in the request, I return 467 L{CACHED<twisted.protocols.http.CACHED>} to indicate that 468 you should write no body. Otherwise, I return a false 469 value. 470 """ 471 472 def setHost(host, port, ssl=0): 473 """Change the host and port the request thinks it's using. 474 475 This method is useful for working with reverse HTTP proxies (e.g. 476 both Squid and Apache's mod_proxy can do this), when the address 477 the HTTP client is using is different than the one we're listening on. 478 479 For example, Apache may be listening on https://www.example.com, and then 480 forwarding requests to http://localhost:8080, but we don't want HTML produced 481 by Twisted to say 'http://localhost:8080', they should say 'https://www.example.com', 482 so we do: 483 484 >>> request.setHost('www.example.com', 443, ssl=1) 485 486 This method is experimental. 487 """ 488 489 490 def notifyFinish(success): 491 """ 492 Return a deferred that fires when the request is finished. 493 494 The deferred will fire with C{None} if the request finished 495 successfully, or with the error that caused it to be unsuccessful. 496 """ 497 498 499 500class ISerializable(Interface): 501 """DEPRECATED. Use nevow.flat.registerFlattener instead of registering 502 an ISerializable adapter. 503 """ 504 def serialize(context): 505 """Serialize the adaptee, with the given context 506 stack if necessary. 507 """ 508 509class IStatusMessage(Interface): 510 """A marker interface, which should be set on the user's web session 511 to an object which can be cast to a string, which will be shown to the 512 user to indicate the status of the most recent operation. 513 """ 514 515 516class IHand(Interface): 517 """A marker interface which indicates what object the user is currently 518 holding in their hand. This is conceptually the "result" of the last operation; 519 this interface can be used to mark a status string which indicates whether 520 the most recent operation completed successfully, or can be used to hold 521 an object which resulted from the most recent operation. 522 """ 523 524 525class ICanHandleException(Interface): 526 def renderHTTP_exception(context, failure): 527 """Render an exception to the given request object. 528 """ 529 530 def renderInlineException(context, reason): 531 """Return stan representing the exception, to be printed in the page, 532 not replacing the page.""" 533 534 535class ICanHandleNotFound(Interface): 536 def renderHTTP_notFound(context): 537 """Render a not found message to the given request. 538 """ 539 540 541class IEventMaster(Interface): 542 pass 543 544 545class IDocFactory(Interface): 546 """Interface for objects that load and parse templates for Nevow's 547 renderers. 548 549 The load method's context arg is optional. Loaders should be written to cope 550 with no context arg and either create a new context (if necessary) or raise 551 a ValueError if the context of the caller is important. 552 553 If a context is passed to load() it should *not* be passed on to the 554 flattener/precompiler; a new context should be created if necessary. This 555 measure is to ensure that nothing remembered in the caller's context, i.e. 556 personal information in the session, leaks into the template until it is 557 actually rendered. 558 """ 559 560 def load(ctx=None, preprocessors=(), precompile=None): 561 """ 562 Load a template and return a stan document tree. 563 564 @param preprocessors: An iterable of one-argument callables which will 565 be given the stan document tree to transform before it is compiled. 566 """ 567 568 569class IRemainingSegments(Interface): 570 """During the URL traversal process, requesting this from the context 571 will result in a tuple of the segments remaining to be processed. 572 573 Equivalent to request.postpath in twisted.web 574 """ 575 576 577class ICurrentSegments(Interface): 578 """Requesting this from the context will result in a tuple of path segments 579 which have been consumed to reach the current Page instance during 580 the URL traversal process. 581 582 Equivalent to request.prepath in twisted.web 583 """ 584 585 586class IViewParameters(Interface): 587 """An interface used by url.viewhere. When this interface is remembered 588 above a url.viewhere embedded in a page, and the url to the current page 589 is rendered, this object will be consulted for additional manipulations 590 to perform on the url object before returning it. 591 """ 592 def __iter__(): 593 """Return an iterator which yields a series of (command, args, kw) triples, 594 where 'command' is a string, indicating which url method to call, 'args' is a 595 list indicating the arguments to be passed to this method, and 'kw' is a dict 596 of keyword arguments to pass to this method. 597 """ 598 599class II18NConfig(Interface): 600 """ 601 Interface for I18N configuration. 602 603 @ivar domain: the gettext domain 604 605 @type domain: str 606 607 @ivar localeDir: path to the messages files or None to use the 608 system default 609 610 @type localeDir: str or None 611 """ 612 domain = Attribute("The gettext domain") 613 localeDir = Attribute("Path to the messages files or None to use the system default") 614 615 616class ILanguages(Interface): 617 """ 618 Marker interface for the sequence of strings that defines the 619 languages requested by the user. 620 """ 621 622 623class ILogger(Interface): 624 """ 625 An access.log writing interface. 626 627 Remember this interface in the context stack to use alternative 628 logging for the resources below that point in the tree. 629 """ 630 def log(ctx): 631 """Write a log entry for this request.""" 632 633 634 635class IFilesystemPackage(Interface): 636 """ 637 Represents information about the filesystem layout of a set of modules. 638 """ 639 mapping = Attribute(""" 640 A C{dict} mapping C{unicode} to C{str}. The keys in this dictionary are 641 CSS or Javascript module names which can be imported by 642 L{nevow.athena.LivePage}. The values give locations in the filesystem 643 where the implementation of each module can be found. 644 """) 645 646 647 648class IJavascriptPackage(IFilesystemPackage): 649 """ 650 Represents information about the filesystem layout of a set of JavaScript 651 modules. 652 """ 653 654 655 656class ICSSPackage(IFilesystemPackage): 657 """ 658 Represents information about the filesystem layout of a set of CSS 659 modules. 660 """ 661 662 663 664class IAthenaTransportable(Interface): 665 """ 666 An object which can be sent by Athena from the Python server to the 667 JavaScript client. 668 """ 669 jsClass = Attribute( 670 """ 671 A C{unicode} string giving the fully-qualified name of a JavaScript 672 function which will be invoked to unserialize the serialized form of 673 this object. 674 675 The current serialization implementation is limited to supporting 676 values for this attribute which refer to JavaScript functions which 677 are defined in modules which have already been imported by the 678 client receiving the serialized data. An attempt to lift this 679 limitation will likely be made at some future point. 680 """) 681 682 683 def getInitialArguments(): 684 """ 685 Define the arguments which will be passed to L{jsClass}. 686 687 @rtype: L{tuple} 688 @return: A tuple of simple types which will be passed as positional 689 arguments to L{jsClass}. 690 """ 691