TL;DR: Python has come to Cube; and this is huge. However, please bear with us for a complete story.

We’re building Cube as a feature-rich, universal semantic layer that works great for many use cases. Consequently, Cube needs and provides a great deal of flexibility in configuration. On the technical side, that includes plenty of environment variables—quite unsurprising for a modern cloud-native application. However, some of the most powerful configuration options, usually related to multitenancy and access control, are provided programmatically in a configuration file.

Usually, real-world Cube deployment will employ both environment variables and a configuration file with dozens, if not hundreds, lines of code. Cube would use programmatic configuration to fine-tune multitenancy, inspect and transform queries on-the-fly, or implement custom authentication to the rich set of APIs that Cube provides; this list can go on and on.

This is very much in sync with the code-first principle that we embrace here at Cube. We firmly believe that application of software engineering best practices—like the use of version control systems, code reviews, and sound code organization—to the data engineering field moves it further in the right direction and helps create high-quality data products. Programmatic configuration is crucial to this approach.

The Good, the Bad, and the Ugly

From its early days, Cube has supported the JavaScript programming language in the cube.js file for defining configuration options. It was handy, since embedded analytics were the very first use case that Cube mastered. Often, it was implemented by software engineers who were quite familiar with JavaScript.

Since then, Cube has grown its audience to an exciting blend of software developers and data engineers, marked by more than 16,000 stars on GitHub. Cube has also expanded supported use cases with connected BI and, of course, AI. With all that, we felt the urge to take Cube further to better serve its expansive, diverse, and opinionated audience.

Introducing Python

Today, we’re happy to announce that now Cube supports Python programming language in the cube.py file to define configuration options!

Look how beautiful it is:

from cube import config, file_repository
config.base_path = '/my-api'
config.scheduled_refresh_time_zones = [
'America/New_York',
'America/Los_Angeles'
]
@config('context_to_app_id')
def context_to_app_id(ctx: dict) -> str:
tenant_id = ctx['securityContext'].setdefault('tenant_id', 0)
return f"CUBE_APP_{tenant_id}"
@config('repository_factory')
def repository_factory(ctx: dict) -> list[dict]:
tenant_id = ctx['securityContext'].setdefault('tenant_id', 0)
return file_repository(f"model/{tenant_id}")
@config('check_auth')
def check_auth(ctx: dict, token: str) -> None:
if token != 'my_precious_secret':
raise Exception('Access denied, try again later')
@config('query_rewrite')
def query_rewrite(query: dict, ctx: dict) -> dict:
context = ctx['securityContext']
if 'user_id' in context:
query['filters'].append({
'member': 'users.id',
'operator': 'equals',
'values': [context['user_id']]
})
return query

We are committed to supporting both Python and JavaScript going forward. Please consider using Python for new Cube projects to benefit from its concise syntax, better readability, and great ecosystem.

We’ve updated the configuration options reference with Python code examples and explained how the cube.py file works. Please feel free to try it out yourself!

Support for Python comes with Cube Core v0.34 release. You can get started today in Cube Cloud; please make sure to switch to the latest version channel. You can also get started with Cube Core; however, please note that macOS on M1/M2 as well as Windows are not supported yet; we’re actively working on introducing the support for these platforms in the nearest future.

Please give Python a try out and join our Slack community to share your thoughts feedback. Also, stay tuned for further updates—we have so much more to share!