The
gramexsnippets
Visual Studio Code extension lets you build
Gramex applications much faster. Just start typing grx- in any gramex.yaml
file to see the handler configurations.

You can now create URLs like
/dashboard/page instead of /dashboard/page.htmldashboard/chart/bar instead of dashboard/chart.html?type=barFileHandler supports mapping URLs to pages flexibly. This makes links simple for humans and friendly for search engines.
Here’s an example:
url:
dashboards:
pattern: /dashboard/(.*) # Anything under /dashboard/ is mapped
handler: FileHandler
path:
page: dashboard/page.html # /dashboard/page maps to page.html
chart/(.*): dashboard/chart.html # /dashboard/chart/... maps to chart.html
auth: true # All of these pages have auth
Smart alerts sent attachments capturing dashboards as seen by any single logged-in user. But now, the same alert can send dashboards as viewed by different users.
This lets you send each user an attachment with their personalized dashboard.
alert:
send-dashboard:
# ... alert configuration goes here...
attachments:
- http://server/capturehandler/?url=http://server/dashboard&ext=pdf
user:
id: '{{ row['email'] }} # Attach file as view by user in the "email" column

If we use JavaScript to dynamically load data and create a page, the contents may not be available when the page is loaded.
Rather than wait for a fixed number of seconds, the
pytest Gramex plugin plugin supports a
wait: {selector: <selector>} that waits until <selector> has been created.
uitest:
- fetch: "http://example.org/javascript-page"
- wait:
selector: ".chart" # Wait until chart is created
timeout: 20 # ... but not for longer than 20 seconds
You can also wait for any JavaScript expression. For example:
uitest:
- fetch: "http://example.org/javascript-page"
- wait:
script: "window.renderComplete === true" # Wait for this JS expression
It also now supports:
hover: to simulate hovering on any elementclear: to clear the value in any inputGramex session cookies can be specified for wildcard domains:
app:
session:
domain: .acme.com # Note the "." in front of the domain
… then you can run Gramex on multiple servers within the same domain and share
cookies. For example, a user who is logged in on app1.acme.com is also logged
in as the same user in app2.acme.com.
If you refresh page.html which has a template
include {% include template.html %}, then the output is refreshed if
template.html is modified.
(Earlier, there was a bug. The output refreshed if page.html is modified, but
not if template.html is modified.)
Schedulers and alerts support a utc: true.
This interprets the schedule in
UTC time zone
instead of the local time.
schedule:
hours: 6 # Run daily at 6am
utc: true # GMT (or UTC). Set false for local server time
This helps when you have servers on multiple domains. For example, if developers
are in Israel and the server is in Japan, using utc: true runs the alerts
at the same time in both servers. utc: false runs them at 6 am local time.
FormHandler lets you browse files. The result now has 2 new columns:
dir: relative path of the file or directory from the rootlevel: number of folder levels from root to the file
FormHandler functions accept
handler as a variable. This lets you transform the data using URL query
parameters.
For example, if the URL has ?group=city, you can add
function: data.groupby(handler.args.group).sum() to group
(or run any calculation) based on a user-provided input.
FormHandler also reports errors in a more friendly way. Instead of this:

… we now see:

FormHandler tables now allow sorting by multiple columns.
Gramex bundles d3 v5 under ui/d3v5/. This features new charts such as contours and equalEarth projections

The Gramex code base has:
To upgrade Gramex, run:
pip install --upgrade gramex
pip install --upgrade gramexenterprise # If you use DBAuth, LDAPAuth, etc.
gramex setup --all