Repository: gratipay/gratipay.com

Issue:
/about/stats.json is broken
[stats.json](https://www.gittip.com/about/stats.json) is broken, I guess because of commit https://github.com/gittip/www.gittip.com/commit/892b1c28d127a18858032c88bd3d065cae973c34 by @clone1018.



Discussion:
@whit537 or @pjz mind jumping in on this one? According to the docs on [negotiated simplates](http://aspen.io/simplates/negotiated/), this should work:

``` python
import foo, json

[---]
data = foo.bar(request)

[---] #!pystache text/plain
{{ data }}

[---] application/json
{{ json.dumps(data) }}
```

And yet when I try that in the `stats.spt` file,

``` python
# ...
[----------------------------------------------------------] application/json
{{ json.dumps({name: globals()[name] for name in names}) }}
[----------------------------------------------------------] text/html
# ...
```

I get a 404

```
Traceback (most recent call last):
  File "www.gittip.com/env/lib/python2.7/site-packages/algorithm.py", line 288, in run
    new_state = function(**deps.as_kwargs)
  File "www.gittip.com/env/lib/python2.7/site-packages/aspen/algorithms/website.py", line 116, in delegate_error_to_simplate
    response = resource.respond(request, response)
  File "www.gittip.com/env/lib/python2.7/site-packages/aspen/resources/dynamic_resource.py", line 68, in respond
    response = self.get_response(context)
  File "www.gittip.com/env/lib/python2.7/site-packages/aspen/resources/negotiated_resource.py", line 93, in get_response
    raise failure
Response: 404 Not Found
```

And when trying the standard way, the plain (and invalid) `{ json }` is returned.

``` python
json = json.dumps({name: globals()[name] for name in names})
[----------------------------------------------------------] application/json
{{ json }}
[----------------------------------------------------------] text/html
```

I think there are several problems. The first one is in aspen documentation because judging from [the code](https://github.com/gittip/aspen-python/blob/94cbba8b700789bd284fc80e4ae2f61e1eca1c79/aspen/resources/negotiated_resource.py#L113) the correct way to specify renderers is to say "application/json via renderer". I have tried it with `stdlib_percent` and it does work.

The other problem is what happens when no renderer is specified. This seems to differ based on mime because html gets jinja2 and json just echos (or I was not able to recognize the renderer - it is certainly not jinja2). According to [the code](https://github.com/gittip/aspen-python/blob/b613678a6c19393cb78e01b61cd66bcf5a6de0c9/aspen/configuration/__init__.py#L55) the default renderer should be stdlib_percent, but it is not. Hmm, gittip resets that to stdlib_format, which works if you use `{json}` but does not work when you use `{ json }` etc.

:wink: While trying to create PR fixing the aspen docs I get

```
ERROR: Permission to gittip/aspen-python.git denied to zwn.
```

Do you mean for push access? You can always create a PR based on your own fork of the repo.

For what it's worth I encountered this problem on development, fixed it with the above commit and then once Jinja2 was pushed to production I tested it again and it was fine.

I also just requested this api endpoint a couple of days ago while working on a JS api for Gittip Everywhere and it was fine.

Wait, 892b1c28d127a18858032c88bd3d065cae973c34 was intentional? `%json` is a valid syntax?

Yes, that was the fix, % is print basically, https://github.com/gittip/www.gittip.com/blob/master/configure-aspen.py#L29

Ah, okay. My brain is being a bit slow today :sweat_smile: 

> Yes, that was the fix, % is print basically, https://github.com/gittip/www.gittip.com/blob/master/configure-aspen.py#L29

How was it supposed to work?

``` python
>>> '%json'.format(json='hi')
'%json'
>>> '{json}'.format(json='hi')
'hi'
>>> '%(json)s' % dict(json='hi')
'hi'
```

`json = json.dumps({name: globals()[name] for name in names})`

@clone1018 was seeing some jinja2 & json related bug which I am not able to reproduce. [IRC](https://botbot.me/freenode/gittip/msg/10440918/)

I can render the json with any one of `stdlib_format` (`{json}`), `stdlib_percent` (`%(json)s`) or `jinja2` (`{{json}}`) renderers.


Resolving patch:
diff --git a/configure-aspen.py b/configure-aspen.py
--- a/configure-aspen.py
+++ b/configure-aspen.py
@@ -26,7 +26,6 @@
 
 
 website.renderer_default = "jinja2"
-website.default_renderers_by_media_type['application/json'] = 'stdlib_format'
 
 website.renderer_factories['jinja2'].Renderer.global_context = {
     'range': range,


Test patch:
diff --git a/tests/test_stats.py b/tests/test_stats.py
--- a/tests/test_stats.py
+++ b/tests/test_stats.py
@@ -2,6 +2,7 @@
 
 import datetime
 from decimal import Decimal
+import json
 
 from mock import patch
 
@@ -74,6 +75,13 @@ def test_get_tip_distribution_ignores_missing_cc(self):
         actual = Participant.from_username('bob').get_tip_distribution()
         assert actual == expected
 
+class TestJson(Harness):
+
+    def test_200(self):
+        response = self.client.GET('/about/stats.json')
+        assert response.code == 200
+        body = json.loads(response.body)
+        assert len(body) > 0
 
 class TestRenderingStatsPage(Harness):
     def get_stats_page(self):