Hacker News new | ask | show | jobs
by pbreit 5440 days ago
This seems interesting but I'm not sure why. What are some use cases?
2 comments

Building web apps! Basically, it's meant to be a replacement for WSGI. In my view, the problems with WSGI are that it has an unpythonic API (see: start_response and environ), and that it doesn't come with standard middleware that all frameworks use, so they all end up reinventing the wheel. Pump does a better job of abstracting out the details of HTTP, and also comes with a lot of useful middleware. This makes it really simple to write a web framework: just implement the routing and glue together a bunch of middlewares. For an example, see Picasso (https://github.com/adeel/picasso), a simple but functional framework I built on top of Pump.
> In my view, the problems with WSGI are that it has an unpythonic API (see: start_response and environ),

Why do you find `start_response` unpythonic?

The problems with start_response have been discussed at length in Web-SIG. As far as I know, they're planning to remove it from the spec in WSGI 2.0 (whenever that's published).
I see http://wsgi.org/wsgi/WSGI_2.0 mentions:

> We could remove start_response and the writer that it implies.

I searched for `wsgi start_response issues` and didn't get anything useful. Care to point out what's the fuss with start_response and why it's unpythonic?

I think this was the original wart that started the whole WSGI 2.0 process. As I recall, it was PJE himself who recommended dropping start_response and replacing it with a return tuple of (status, headers, iterable). PJE comments in one thread that this isn't a reduction in features, but an improvement in usability:

"Note that in the WSGI 2 calling protocol, you would simply modify your return values, rather than needing to create a function and pass it down the call chain."

http://mail.python.org/pipermail/web-sig/2009-November/00424...

Here is an example of a thread where it's discussed: http://mail.python.org/pipermail/web-sig/2009-November/threa...
I believe the intent is to be Rack[1] for Python. The beauty of Rack is that I can build a new web framework, web server, or web app plugin and have it "just work" with the rest of the ecosystem. And because the Rack API is so simple, building to spec is easy.

In the Ruby world if I want to use the awesome library Sass all I have to do is:

    gem install sass
Because it functions as a Rack plugin it automatically works with any Ruby web framework & Ruby web server combo I choose. No special setup required.

-----

[1] http://rack.rubyforge.org/

    # WSGI
    def app(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/plain')])
        yield 'Hello World\n'

    # Rack
    app = proc do |env|
    [ 200, {'Content-Type' => 'text/plain'}, "a" ]
    end
WSGI is the Rack for Python. In fact, WSGI predates Rack, and Rack is WSGI inspired.
Rack was based on WSGI, however the point is valid since Pump is using an API closer to Rack than WSGI. Indeed, the Pump website states: "No fancy start_response or environ here."

    # Pump
    def app(request):
        return {
          "status": 200,
          "headers": {"content_type": "text/plain"},
          "body": "Hello World"}
You sure have put effort and the project looks good, but I am missing the purpose. If the problem it tries to solve is parsing environ to form response objects, or providing vanilla middlewares, that problem is very well solved by a wsgi library. Have you looked at werkzeug?
Pump aims to replace WSGI entirely. That is, I believe it does a better job of what WSGI was intended to do.

I understand your point that web developers don't necessarily work with WSGI on a day-to-day basis. But if you look at the Ruby web community, Rack middlewares are much more prevalent than WSGI middlewares. Application developers (as opposed to framework developers) often add functionality as a Rack middleware, so that it can be reused in different applications, even using different frameworks. Why isn't that happening with Python as much? In the Python world, instead of writing even simple middlewares to for basic functionality like https://github.com/adeel/pump/blob/master/pump/middleware/pa... or https://github.com/adeel/pump/blob/master/pump/middleware/co..., every framework ends up reimplementing it. I believe this is because the WSGI API is ugly and not as easy to understand as it could be (just look at the average WSGI middleware).

It seems that what you ended up doing is, in fact, reimplementing things that were implemented zillions of times before. Am I wrong or the Pump middleware doesn't work for any WSGI app? If it had followed the WSGI middleware basic concept, you'd be closer to achieve the goal of reusable components across frameworks.

"Pump aims to replace WSGI entirely." <- this is very ambitious. :)

They are both predated by:

    public class App extends HttpServlet {
      public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain");
        response.getWriter().println("Hello world");
      }
    }
And that is predated by

    # hello.cgi
    print "Hello World\n";
I wasn't trying to claim WSGI is the first web server to application server interface. I was just showing Rack and WSGI are similar, and Rack was WSGI inspired.
Yes, but IMHO servlets got it all wrong, and WSGI took very little from servlets (though for instance Webware, a pre-WSGI framework did use the servlet model). But it owes much to the superior CGI model; replace processes with function calls and structure the response lightly and you have WSGI.
Ianb, may I inquire as to what is the difference you mean between servlets and cgi. A cgi written in perl for example, was essentially a perl servlet, I think. How is the CGI model fundamentally different from a servlet model, where your application code is given a request as a parameter to a function, and must return a response?
> How is the CGI model fundamentally different from a servlet model,

Since both are web server to application server interfaces, they aren't fundamentally different - the difference is cgi was language independent and hence defined for the common minimum. cgi couldn't have been defined in request and response objects - it would have caused trouble for languages which doesn't have objects.

> where your application code is given a request as a parameter to a function, and must return a response?

cgi is not given a request parameter - the request parameters are passed in the environment. And cgi doesn't return a response object - whatever it writes to stdout constitutes the response. cgi had to cater to all sorts of implementation - assuming request/response objects wasn't a possibility.

Servlets and cgi aren't fundamentally different, but I guess we can agree they are sufficiently different.

Yes, Pump was heavily inspired by Rack and especially Clojure's Ring (https://github.com/mmcgrana/ring).
I don't get the purpose. WSGI was meant to low level to cover the common minimum. If you want request, response semantics, use a higher level library - I use werkzeug which wraps wsgi, or flask which is small web framework built on werkzeug.

I don't think anyone other than wsgi library implementors code to WSGI. WSGI would be a problem if that's how python web programming was to be done - but that's not the case.

I like how the circle if inspiration loops back to Python: Python WSGI inspired Ruby Rack. Ruby Rack inspired Clojure Ring. Clojure Ring inspired Python Pump.