This file is indexed.

/usr/share/pyshared/lazr/restful/interfaces/_rest.py is in python-lazr.restful 0.9.29-0ubuntu2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
# Copyright 2008-2009 Canonical Ltd.  All rights reserved.
#
# This file is part of lazr.restful
#
# lazr.restful is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# lazr.restful is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with lazr.restful.  If not, see <http://www.gnu.org/licenses/>.
"""Interfaces for different kinds of HTTP resources."""

# Pylint doesn't grok zope interfaces.
# pylint: disable-msg=E0211,E0213

__metaclass__ = type
__all__ = [
    'IByteStorage',
    'IByteStorageResource',
    'ICollection',
    'ICollectionResource',
    'IEntry',
    'IEntryField',
    'IEntryFieldResource',
    'IEntryResource',
    'IFieldHTMLRenderer',
    'IFieldMarshaller',
    'IFileLibrarian',
    'IHTTPResource',
    'IJSONPublishable',
    'IJSONRequestCache',
    'IRepresentationCache',
    'IResourceOperation',
    'IResourceGETOperation',
    'IResourceDELETEOperation',
    'IResourcePOSTOperation',
    'IScopedCollection',
    'IServiceRootResource',
    'ITopLevelEntryLink',
    'ITraverseWithGet',
    'IUnmarshallingDoesntNeedValue',
    'IWebServiceConfiguration',
    'IWebBrowserInitiatedRequest',
    'LAZR_WEBSERVICE_NAME',
    'LAZR_WEBSERVICE_NS',
    'IWebServiceClientRequest',
    'IWebServiceLayer',
    'IWebServiceVersion',
    ]

from zope.schema import Bool, Dict, Int, List, Text, TextLine
from zope.interface import Attribute, Interface
# These two should really be imported from zope.interface, but
# the import fascist complains because they are not in __all__ there.
from zope.interface.interface import invariant
from zope.interface.exceptions import Invalid
from zope.publisher.interfaces import IPublishTraverse
from zope.publisher.interfaces.browser import (
    IBrowserRequest, IDefaultBrowserLayer)
from lazr.batchnavigator.interfaces import InvalidBatchSizeError

# Constants for periods of time
HOUR = 3600 # seconds

# The namespace prefix for LAZR web service-related tags.
LAZR_WEBSERVICE_NS = 'lazr.restful'

# The namespace for LAZR web service tags having to do with the names
# of things.
LAZR_WEBSERVICE_NAME = '%s.name' % LAZR_WEBSERVICE_NS


class IHTTPResource(Interface):
    """An object published through HTTP."""

    def __call__():
        """Publish the object."""

    def getETag(media_type):
        "An ETag for this resource's current state."


class IJSONPublishable(Interface):
    """An object that can be published as a JSON data structure."""

    def toDataForJSON():
        """Return a representation that can be turned into JSON.

        The representation must consist entirely of simple data
        structures and IJSONPublishable objects.
        """

class IServiceRootResource(IHTTPResource):
    """A service root object that also acts as a resource."""

    def getTopLevelPublications(request):
        """Return a mapping of top-level link names to published objects."""


class IEntryResource(IHTTPResource):
    """A resource that represents an individual object."""

    def do_GET():
        """Retrieve this entry.

        :return: A string representation.
        """

    def do_PATCH(representation):
        """Update this entry.

        Try to update the entry to the field and values sent by the client.

        :param representation: A JSON representation of the field and values
            that should be modified.
        :return: None or an error message describing validation errors. The
            HTTP status code should be set appropriately.
        """

    def getContext():
        """Return the underlying entry for this resource."""


class IEntryFieldResource(IHTTPResource):
    """A resource that represents one of an entry's fields."""

    def do_GET():
        """Retrieve the value of the field.

        :return: A string representation.
        """


class ICollectionResource(IHTTPResource):
    """A resource that represents a collection of entry resources."""

    def do_GET():
        """Retrieve this collection.

        :return: A string representation.
        """


class IResourceOperation(Interface):
    """A one-off operation invokable on a resource."""

    def __call__():
        """Invoke the operation and create the HTTP response.

        :returns: If the result is a string, it's assumed that the
        Content-Type was set appropriately, and the result is returned
        as is. Otherwise, the result is serialized to JSON and served
        as application/json.
        """

    send_modification_event = Attribute(
        "Whether or not to send out an event when this operation completes.")


class IResourceGETOperation(IResourceOperation):
    """A one-off operation invoked through GET.

    This might be a search or lookup operation.
    """
    return_type = Attribute(
        "The type of the resource returned by this operation, if any.")


class IResourceDELETEOperation(IResourceOperation):
    """A destructor operation invoked through DELETE.

    This should be an operation that deletes an entry.
    """


class IResourcePOSTOperation(IResourceOperation):
    """A one-off operation invoked through POST.

    This should be an operation that modifies the data set.
    """


class IEntry(Interface):
    """An entry, exposed as a resource by an IEntryResource."""

    schema = Attribute(
        'The schema describing the data fields on this entry.')

    @invariant
    def schemaIsProvided(value):
        """Make sure that the entry also provides its schema."""
        if not value.schema.providedBy(value):
            raise Invalid(
                "%s doesn't provide its %s schema." % (
                    type(value).__name__, value.schema.__name__))


class ICollection(Interface):
    """A collection, driven by an ICollectionResource."""

    entry_schema = Attribute("The schema for this collection's entries.")

    def find():
        """Retrieve all entries in the collection under the given scope.

        :return: A list of IEntry objects.
        """


class IScopedCollection(ICollection):

    relationship = Attribute("The relationship between an entry and a "
                             "collection.")
    collection = Attribute("The collection scoped to an entry.")


class IFieldHTMLRenderer(Interface):
    """An interface that renders generic strings as HTML representations.

    This can be a callable class, or a function that returns another
    function.
    """

    def __call__(value):
        """Render the given string as HTML."""


class IEntryField(Interface):
    """An individual field of an entry."""

    entry = Attribute("The entry whose field this is.")

    field = Attribute("The field, bound to the entry.")


class ITopLevelEntryLink(Interface):
    """A link to a special entry.

    For instance, an alias for the currently logged-in user.

    The link will be present in the representation of the service root
    resource.
    """

    link_name = Attribute("The name of the link to this entry in the "
                          "representation of the service root resource. "
                          "'_link' will be automatically appended.")

    entry_type = Attribute("The interface defined by the entry on the "
                           "other end of the link.")


class IWebServiceClientRequest(IBrowserRequest):
    """Interface for requests to the web service."""
    version = Attribute("The version of the web service that the client "
                        "requested.")


class IWebServiceLayer(IWebServiceClientRequest, IDefaultBrowserLayer):
    """Marker interface for registering views on the web service."""


class IWebServiceVersion(Interface):
    """Used to register IWebServiceClientRequest subclasses as utilities.

    Every version of a web service must register a subclass of
    IWebServiceClientRequest as an IWebServiceVersion utility, with a
    name that's the web service version name. For instance:

    registerUtility(IWebServiceClientRequestBeta,
                    IWebServiceVersion, name="beta")
    """
    pass

class IJSONRequestCache(Interface):
    """A cache of objects exposed as URLs or JSON representations."""

    links = Attribute("Objects whose links need to be exposed.")
    objects = Attribute("Objects whose JSON representations need "
                        "to be exposed.")


class IByteStorage(Interface):
    """A sequence of bytes stored on the server.

    The bytestream is expected to have a URL other than the one used
    by the web service.
    """

    alias_url = Attribute("The external URL to the byte stream.")
    filename = Attribute("Filename for the byte stream.")
    is_stored = Attribute("Whether or not there's a previously created "
                          "external byte stream here.")

    def createStored(mediaType, representation, filename=None):
        """Create a new stored bytestream.

        :param filename: The name of the file being stored. If None,
        the name of the storage field is used instead.
        """

    def deleteStored():
        """Delete an existing stored bytestream."""


class IByteStorageResource(IHTTPResource):
    """A resource that represents an external binary file."""

    def do_GET():
        """Redirect the client to the externally hosted file."""

    def do_PUT(media_type, representation):
        """Update the stored bytestream.

        :param media_type: The media type of the proposed new bytesteram.
        :param representation: The proposed new bytesteram.
        :return: None or an error message describing validation errors. The
            HTTP status code should be set appropriately.
        """

    def do_DELETE():
        """Delete the stored bytestream."""


class IFileLibrarian(Interface):
    """A class for managing uploaded files."""

    def get(key):
        """Retrieve a file by key."""

    def put(representation, filename):
        """Store a file in the librarian."""

    def delete(key):
        """Delete a file from the librarian."""


class IFieldMarshaller(Interface):
    """A mapper between schema fields and their representation on the wire."""

    representation_name = Attribute(
        'The name to use for this field within the representation.')

    def marshall_from_json_data(value):
        """Transform the given data value into an object.

        This is used in PATCH/PUT requests when modifying the field, to get
        the actual value to use from the data submitted via JSON.

        :param value: A value obtained by deserializing a string into
            a JSON data structure.

        :return: The value that should be used to update the field.

        """

    def marshall_from_request(value):
        """Return the value to use based on the request submitted value.

        This is used by operation where the data comes from either the
        query string or the form-encoded POST data.

        :param value: The value submitted as part of the request.

        :return: The value that should be used to update the field.
        """

    def unmarshall(entry, value):
        """Transform an object value into a value suitable for JSON.

        :param entry: The entry whose field this is.
        :value: The object value of the field.

        :return: A value that can be serialized as part of a JSON hash.
        """

    def unmarshall_to_closeup(entry, value):
        """Transform an object value into a detailed JSON-ready value.

        :param entry: The entry whose field this is.
        :value: The object value of the field.

        :return: A value that can be serialized as the representation of
            a field resource.
        :rtype: Any object that can be serialized to JSON. Usually a
            string.
        """


class IWebServiceConfiguration(Interface):
    """A group of configuration settings for a web service.

    These are miscellaneous strings that may differ in different web
    services.
    """
    caching_policy = List(
        value_type=Int(),
        default = [7 * 24 * HOUR, 1 * HOUR],
        title=u"The web service caching policy.",
        description = u"""A list of two numbers, each to be used in the
        'max-age' field of the Cache-Control header. The first number is
        used when serving the service root for any web service version
        except the latest one. The second number is used when serving the
        service root for the latest version (which probably changes more
        often).""")

    enable_server_side_representation_cache = Bool(
        title=u"Enable the server-side representation cache.",
        default=True,
        description=u"""If this is false, the server-side representation
        cache will not be used, even if one is registered."""
        )

    service_description = TextLine(
        title=u"Service description",
        description=u"""A human-readable description of the web service.

        The description may contain HTML, but if it does, it must be a
        valid XHTML fragment.
        """,
        default=u"",
        )

    view_permission = TextLine(
        title=u"View permission", default=u"zope.View",
        description=u"The permission to use when checking object visibility.")

    path_override = TextLine(
        title=u"Web service path override", default=u"api",
        description=u"The path component for Ajax clients to use when making "
        "HTTP requests to the web service from their current virtual host. "
        "The use of this path component (/api/foo instead of /foo) will "
        "ensure that the request is processed as a web service request "
        "instead of a website request.")

    use_https = Bool(
        title=u"Web service is secured",
        default=True,
        description=u"Whether or not requests to the web service are secured "
        "through SSL.")

    hostname = TextLine(
        title=u"The hostname to be used in generated URLs.",
        description=u"You only need to specify this if you're using the "
        "RootResourceAbsoluteURL class from lazr.restful.simple. This is "
        "the hostname of the lazr.restful application.")

    port = Int(
        title=u"The TCP port on which the web service is running.",
        description=u"Used in generated URLs.",
        default=0)

    service_root_uri_prefix = TextLine(
        title=u"Any URL prefix necessary for the service root.",
        default=u"",
        description=u"If your web service is not located at the root of "
        "its domain (for instance, it's rooted at "
        "http://foo.com/web-service/ instead of http://api.foo/com/, "
        "put the URL prefix here. (In the example case, the URL prefix "
        "is 'web-service/').")

    active_versions = List(
        value_type=TextLine(),
        default = [],
        title=u"The active versions of the web service.",
        description = u"""A list of names of active versions of this
        web service. They might be version numbers, names such as
        "beta", or the date a particular version was finalized.

        Newer versions should show up later in the list than earlier
        versions. It's recommended that the last version, located at
        the end of the list, be a floating development version called
        something like 'trunk' or 'devel': effectively an alias for
        "the most up-to-date code".

        This list must contain at least one version name.""")

    version_descriptions = Dict(
        key_type = TextLine(),
        value_type = Text(),
        title = u"Human-readable descriptions of the web service versions.",
        description = u"""A dictionary mapping version names to
        human-readable descriptions. The descriptions should describe
        what distinguishes this version from other versions, and
        mention if/when the version will be removed.

        The descriptions may contain HTML, but if they do, they must be
        valid XHTML fragments.
        """,
        default = {}
        )

    last_version_with_mutator_named_operations = TextLine(
        default=None,
        description=u"""In earlier versions of lazr.restful, mutator methods
        were also published as named operations. This redundant
        behavior is no longer enabled by default, but this setting
        allows for backwards compatibility.

        Mutator methods will also be published as named operations in
        the version you specify here, and in any previous versions. In
        all subsequent versions, they will not be published as named
        operations.""")

    code_revision = TextLine(
        default=u"",
        description=u"""A string designating the current revision
        number of the code running the webservice. This may be a
        revision number from version control, or a hand-chosen version
        number.""")

    show_tracebacks = Bool(
        title=u"Show tracebacks to end-users",
        default=True,
        description=u"Whether or not to show tracebacks in an HTTP response "
        "for a request that raised an exception.")

    default_batch_size = Int(
        title=u"The default batch size to use when serving a collection",
        default=50,
        description=u"When the client requests a collection and doesn't "
        "specify how many entries they want, this many entries will be "
        "served them in the first page.")

    max_batch_size = Int(
        title=u"The maximum batch size",
        default=300,
        description=u"When the client requests a batch of entries from "
        "a collection, they will not be allowed to request more entries "
        "in the batch than this.")

    compensate_for_mod_compress_etag_modification = Bool(
        title=u"Accept incoming ETags that appear to have been modified "
               "in transit by Apache's mod_compress.",
        default=False,

        description=u"""When mod_compress compresses an outgoing
        representation, it (correctly) modifies the ETag. But when
        that ETag comes back in on a conditional GET or PUT request,
        mod_compress does _not_ transparently remove the modification,
        because it can't be sure which HTTP intermediary was
        responsible for modifying the ETag on the way out.

        Setting this value to True will tell lazr.restful that
        mod_compress is in use. lazr.restful knows what mod_compress
        does to outgoing ETags, and if this value is set, it will
        strip the modification from incoming ETags that appear to have
        been modified by mod_compress.

        Specifically: if lazr.restful generates an etag '"foo"',
        mod_compress will change it to '"foo"-gzip' or '"foo-gzip"',
        depending on the version. If this value is set to False,
        lazr.restful will not recognize '"foo"-gzip' or '"foo-gzip"'
        as being equivalent to '"foo"'. If this value is set to True,
        lazr.restful will treat all three strings the same way.

        This is a hacky solution, but until Apache issue 39727 is
        resolved, it's the best way to get the performance
        improvements of content-encoding in a real setup with multiple
        layers of HTTP intermediary. (An earlier attempt to use
        transfer-encoding instead of content-encoding failed because
        HTTP intermediaries strip the TE header.)
        """)

    def createRequest(body_instream, environ):
        """A factory method that creates a request for the web service.

        It should have the correct publication set for the application.

        :param body_instream: A file-like object containing the request
            input stream.
        :param environ: A dict containing the request environment.
        """

    def get_request_user():
        """The user who made the current web service request.

        'User' here has whatever meaning it has in your application. This
        value will be fed back into your code.
        """


class IUnmarshallingDoesntNeedValue(Interface):
    """A marker interface for unmarshallers that work without values.

    Most marshallers transform the value they're given, but some work
    entirely on the field name. If they use this marker interface
    we'll save time because we won't have to calculate the value.
    """


class IWebBrowserInitiatedRequest(Interface):
    """A marker interface for requests initiated by a web browser.

    Web browsers are broken in subtle ways that interact in complex
    ways with the parts of HTTP used in web services. It's useful to
    know when a request was initiated by a web browser so that
    responses can be tweaked for their benefit.
    """


class ITraverseWithGet(IPublishTraverse):
    """A marker interface for a class that uses get() for traversal.

    This is a simple way to handle traversal.
    """

    def get(request, name):
        """Traverse to a sub-object."""


class IRepresentationCache(Interface):
    """A cache for resource representations.

    Register an object as the utility for this interface and
    lazr.restful will use that object to cache resource
    representations. If no object is registered as the utility,
    representations will not be cached.

    This is designed to be used with memcached, but you can plug in
    other key-value stores. Note that this cache is intended to store
    string representations, not deserialized JSON objects or anything
    else.
    """

    def get(object, media_Type, version, default=None):
        """Retrieve a representation from the cache.

        :param object: An IEntry--the object whose representation you want.
        :param media_type: The media type of the representation to get.
        :param version: The version of the web service for which to
            fetch a representation.
        :param default: The object to return if no representation is
            cached for this object.

        :return: A string representation, or `default`.
        """
        pass

    def set(object, media_type, version, representation):
        """Add a representation to the cache.

        :param object: An IEntry--the object whose representation this is.
        :param media_type: The media type of the representation.
        :param version: The version of the web service in which this
            representation should be stored.
        :param representation: The string representation to store.
        """
        pass

    def delete(object):
        """Remove *all* of an object's representations from the cache.

        This means representations for every (supported) media type
        and every version of the web service. Currently the only
        supported media type is 'application/json'.

        :param object: An IEntry--the object being represented.
        """
        pass


InvalidBatchSizeError.__lazr_webservice_error__ = 400