Gramex 1.69 release notes

Gramex 1.69 makes it easier to auto-render template files, generate Donut charts, and offline access to Google Data.

Auto-render template files

Let’s say you have a folder of HTML files. But only 1 file, say report.html, uses FileHandler templates.

Earlier, you would have had to create a separate FileHandler for this with template: true.

Now, just rename it to report.tmpl.html or report.template.html, and it will be rendered as a template.

You can choose any file pattern to render as HTML. For example, this renders report*.html and template*.html as templates, but other files are rendered as-is.

url:
  template:
    pattern: ...
    handler: FileHandler
    kwargs:
      path: ...
      template: ["report*.html", "template*.html"]

Donut Charts in PPTXHandler

You can update the data for a Donut Chart in PPTXHandler, like any chart.

Donut chart

Offline access to Google data

You can set up GoogleAuth to have offline access

To perform offline actions on behalf of the user (e.g. send email, poll Google Drive, etc), you need to request offline access by adding access_type: offline under extra_params.

url:
  login/google:
    pattern: /$YAMLURL/google # Map this URL
    handler: GoogleAuth # to the GoogleAuth handler
    kwargs:
      key: YOURKEY # Set your app key
      secret: YOURSECRET # Set your app secret
      # Scope list: https://developers.google.com/identity/protocols/googlescopes
      scope:
        - https://www.googleapis.com/auth/contacts.readonly
        - https://www.googleapis.com/auth/gmail.readonly
      extra_params:
        access_type: offline

When the user logs in for the first time, Google sends a refresh token that you can access via handler.current_user.refresh_token.

If the access_token has expired, you will get a HTTP 401 Unauthorized error, with a JSON response like this:

{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials...",
    "status": "UNAUTHENTICATED"
  }
}

In this case, you can get a new access token using GoogleAuth.exchange_refresh_token():

@tornado.gen.coroutine
def get_contacts(handler):
    # Make an authenticated request
    url = 'https://www.google.com/m8/feeds/contacts/default/full'
    headers = {'Authorization': 'Bearer ' + handler.current_user.get('access_token', '')}
    r = requests.get(url, headers=headers)
    # If the access token has expired
    if r.status_code == 401:
        # Exchange refresh token
        yield gramex.service.url['login/google'].handler_class.exchange_refresh_token(
            handler.current_user)
        # Make the request again
        headers = {'Authorization': 'Bearer ' + handler.current_user.get('access_token', '')}
        r = requests.get(url, headers=headers)
    return r.text

Other improvements

Bug fixes

What next

Gramex 1.70 will be released on 1 Mar 2021 and will feature an improved Log Viewer and Admin Panel. The Log Viewer was promised in 1.69, but is delayed.

Statistics

The Gramex code base has:

How to install

See the Gramex installation and upgrade instructions (which are much better now 😃)

Note: Gramex 1.69 does not work with Python 3.8. We recommend Python 3.7.