Giter VIP home page Giter VIP logo

txyoga's Introduction

txyoga

txyoga is a REST toolkit for Twisted.

You define a collection and some elements for that collection. txyoga gives you a resource, which Twisted then lets you serve to clients.

Where did the name from?

The tx is a common prefix for Twisted community code. It's called yoga because it's Twisted REST. Get it? Yes, I'm terrible.

txyoga's People

Contributors

ltvolks avatar lvh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

txyoga's Issues

TestCases shouldn't be this stateful

When you call _makeRequest (which you pretty much invariably do, indirectly, when you call getElement/getElements/...), it sets a bunch of state on the TestCase. This is really annoying and not pretty.

For example, it forces the following code to be ugly and sequential:

class PartialExposureTest(collections.PartialExposureMixin, TestCase):

...

    def _verifyExposedAttributes(self):
        # Yes, this has to be synchronous (one by one), because
        # getElement tacks a lot of ugly state on to the test case. It
        # really should return a nice (deferred) response object...

        def verifyElementExposure(_)
            for attribute in self.elementClass.exposedAttributes:
                self.assertIn(attribute, self.responseContent)

        d = defer.Deferred()

        for name in names:
            d.addCallback(lambda _: self.getElement(name))
            d.addCallback(verifyElementExposure)

        d.callback(None)
        return d

Query API

Right now, you need to know the name of an element to access it directly. Alternatively, you'd have to walk through all elements in the collection and query them manually. This, obviously, sucks.

This depends on #18.

Dynamic child lookups for `ElementResource`

Right now ElementResource.__init__ puts the Element's children. This is great for almost all use cases of element children, but it means that element children can basically never change.

This could be fixed by looking them up dynamically in ElementResource.getChild.

Element children functionality is untested

There is a glaring eyesore in the coverage. It must be fixed.

Name                            Stmts   Miss  Cover   Missing
-------------------------------------------------------------
txyoga/__init__                     7      0   100%   
txyoga/base                        58      0   100%   
txyoga/interface                   13      0   100%   
txyoga/resource                   196      2    99%   310-311
txyoga/serializers                  1      0   100%   
txyoga/test/__init__                0      0   100%   
txyoga/test/collections            41      0   100%   
txyoga/test/test_acceptheader      29      0   100%   
txyoga/test/test_badrequest        49      0   100%   
txyoga/test/test_collection        51      0   100%   
txyoga/test/test_deletion          28      0   100%   
txyoga/test/test_pagination        43      0   100%   
txyoga/test/test_serialize         40      0   100%   
txyoga/test/test_updating          45      0   100%   
txyoga/test/util                   69      0   100%   
-------------------------------------------------------------
TOTAL                             670      2    99%   

Here's the offending code, in ElementResource.__init__:

    for collectionName in element.children:
        collection = getattr(element, collectionName)
        self.putChild(collectionName, IResource(collection))

Basically, we just need a test that adds some children to an element. Preferably both another collection and another element. Although judging by the code, anything adaptable to an IResource ought to work. That includes a Resource, but that would make txYoga a leaky abstraction, so let's not do that in the test suite.

Add encoding hints and copyright notices

Each module should have an encoding hint specified at the top of the file. Something like:

# -*- coding: utf-8 -*-

Each module should have a copyright notice. Look at Twisted for an idea on how to do that.

Test suite cleanup

The test suite is currently a bit of a mess. Since txYoga was just a component of a previous thing, all of the tests got kind of confuddled in one massive test module, which is now way too long. Additionally, the name test_rest doesn't make any sense anymore, since txYoga is all about REST.

  1. The test modules should be split up in much smaller blocks.
  2. The test_rest module should be renamed to something less stupid.
  3. A bunch of the superclasses and mixins have dumb names.
  4. Generic utility stuff for setting up tests should be moved into a separate module.

Since this is @lvh's mess, @lvh gets to clean it up.

Tutorial

txYoga has no documentation. Not having documentation is pretty bad.

One particularly interesting kind of documentation would be a series of tutorials. The tutorial consists of a few progressively more complex examples of txYoga functionality. Each example consists of two parts:

  1. Examine the source code for the example.
  2. Try it out with some actual HTTP requests and examine the results.

We should definitely have some Sphinx documentation, so maybe this is a good time to introduce that.

There's an interesting tool called Pycco which produces a side by side view of comments and code. That sounds pretty great for the first point, especially if we can link to it from the Sphinx documentation.

Support update PUT with complete state

txYoga Elements have updateableAttributes which will 408 if you supply attributes which cannot be updated, which I think is great... almost. To my knowledge there are two opinions about how state should be represented in a PUT for updating an element:

  1. The state should contain the same attributes as returned in a GET (complete state PUT)
  2. The state may contain a subset of the attributes returned in a GET (partial state PUT)

I don't have a strong opinion in the partial versus complete debate, although I do know there are some AJAX clients (backbone.js for example) which by default assume complete state PUTs. txYoga does not support the complete state PUT but could without sacrificing the requirement to make certain attributes immutable after creation. Implementation could include filtering before doing the update or more thoroughly asserting that keys contained in the PUT body and also in updateableAttribures do not map to values different from those in the extant Element.

Thoughts?

Support for Cross-Origin Resource Sharing (CORS)

APIs are accessed from different domains all the time. However, the default behavior for browsers when doing cross-domain requests is to disallow it due to the Same Origin Policy.

There is an emerging standard for explicitly whitelisting cross-domain requests called CORS. It is a W3C recommendation.

The CORS specification is quite hefty, but here's the gist of it that applies to txyoga. Before starting to make cross-domain requests, the browser will create a pre-flighted request using the OPTIONS method.

CORS won't work on all browsers currently in use.

Surprisingly, Opera is the worst offender here. Support is not available in current-day browsers (11.x), but will probably be available in 12.x.

Less surprisingly, Microsoft's implementation came late and is fairly different from what the other browsers do. They have a separate object (XDomainRequest instead of XMLHTTPRequest) that behaves the same. jQuery currently does not gloss over this difference; but may do so in the future, and currently can using a plugin (upstream ticket).

For backwards compatibility, it may be a good idea to use this information to also (perhaps optionally) generate a crossdomain.xml file for Flash-based cross-domain access. Flash can be used as a fallback for browsers that don't support CORS using flxhr.

Alternatively, browser implementations can use tricks such as nesting iframes that communicate with each other by changing the fragment. This also requires cooperation with the cross-domain site.

Both of these, if implemented, should be on a separate ticket.

_checkBadRequest should not check response status code

Every response should have its status code checked. The fact that _checkBadRequest conflates this with checking the response status code makes refactoring the check for the expected status code look weird/impossible/duplicated. This happens in test_creation.ElementCreationTest._test_createElement and in test_updating.ElementUpdatingTest._test_updateElement, but obviously ever call to _checkBadRequest should be investigated.

Performance benchmarks

There really ought to be a benchmark suite so that performance-oriented changes can be made with some confidence.

Better serialization support

The serializers module currently just exposes the JSON stdlib module or the simplejson module as JSON. It should be fleshed out to have all serialization-specific stuff in there.

Tutorial doctests failing

Looks like [44cf30f] introduced some changes that aren't reflected in the tutorial doctests, so there are now 8 failures

Accessing collections and elements

  • Serializers must be explicit in what content-type they'll accept, so clients must declare a matching Accept header?
  • Twisted.web is returning a transfer-encoding header instead of content-length, so the test fails. Don't know if this is due to my version of twisted (12.0.0) or some other change.

CRUD

  • Updating an elements fails... looks like something has changed in the handling of PUT to an existing element. It appears to be attempting to create a new element instead of updating it.

405 Method Not Allowed uses Twisted's error reporting, not txyoga's

Twisted does this already, bypassing txyoga's error reporting mechanism.

This happens in twisted.web.server.Request.render, where resource.render is called. If that method raises an UnsupportedMethod exception, it gets caught, and the error message gets put out.

So, maybe txyoga's Resources should have smarter render methods. Specifically, it should call Resource.render and catch the UnsupportedMethod exception early.

Note that txyoga should still support HEAD requests (because the RFC says so), and this method is also responsible for handling HEAD. It does this by sending a GET request and discarding the body. While satisfactory, it probably wouldn't hurt to be more explicit about HEAD requests and have tests + an actual render_HEAD method.

Unfortunately because that t.w.s.Request.render method is so large, it's impossible to reuse some of its behavior.

Key function for addressing children/elements

URLs encode bytes. Usually, children of elements and elements of collections have Unicode identifiers, though. Currently this is "fixed" by Python's implicit decoding, which is pretty bad.

Since URLs are an implementation detail of being accessed over HTTP, this belongs in {Collection,Element}Resource.

There should be a test that tries a non-ASCII name first, and verifies that it works when you use lambda s: s.decode("utf-8") as a key function.

Whether the default should be lambda s: s.decode("utf-8") or lambda s: s (or perhaps a special-cased None) is an open question. UTF-8 is probably the only sane default encoding. The API should provide a keyfunc and not an encoding, because using int as a key function for example might make perfect sense.

"MIME type", "content type" and "media type" used interchangably

All of these terms are used to mean the same thing and it's a bit of a mess. Admittedly, it's a bit of a mess because the specification is a bit of a mess, too.

It would be great if one name was chosen and stuck to, unless an important specification like HTTP disagrees strongly.

Asynchronous store interface

This used to be "deferred creation support" because that's where this problem originally showed up. In reality, it's a deeper problem: we don't have an abstracted store interface.

Right now, it is assumed that creation can be done synchronously: it happens right now, or it doesn't happen at all. In the first case, it returns 201 Created. It's possible that resource creation actually takes a while (ie returns a Deferred from the API ;-)), in which case it should say 202 Accepted.

The asynchronous store interface really just becomes most of the methods currently on ICollection.

Serializable error interface

txyoga.resource.SerializableError is pretty much implementation defined at the moment.

In the interest of producing a better serialization mechanism later, it should probably explicitly document its interface.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.