atoti.experimental.distributed package

Submodules

atoti.experimental.distributed.cube module

class atoti.experimental.distributed.cube.DistributedCube(java_api, name, session)

Bases: atoti._local_cube.ALocalCube

Cube of a distributed session.

property aggregates_cache

Aggregates cache of the cube.

Return type

AggregatesCache

explain_query(*measures, levels=None, condition=None, scenario='Base', timeout=30)

Run the query but return an explanation of the query instead of the result.

The explanation contains a summary, global timings and the query plan with all the retrievals.

Parameters
  • measures (~_Measure) – The measures to query. If None, all the measures are queried.

  • levels (Union[~_Level, Sequence[~_Level], None]) – The levels to split on. If None, the value of the measures at the top of the cube is returned.

  • condition (Union[LevelCondition, MultiCondition, LevelIsInCondition, HierarchyIsInCondition, None]) –

    The filtering condition. Only conditions on level equality with a string are supported. For instance:

    • lvl["Country"] == "France"

    • (lvl["Country"] == "USA") & (lvl["Currency"] == "USD")

  • scenario (str) – The scenario to query.

  • timeout (int) – The query timeout in seconds.

Return type

QueryAnalysis

Returns

The query explanation.

property hierarchies

Hierarchies of the cube.

Return type

~_Hierarchies

property levels

Levels of the cube.

Return type

~_Levels

property measures

Measures of the cube.

Return type

~_Measures

property name

Name of the cube.

Return type

str

query(*measures, levels=None, condition=None, scenario='Base', timeout=30)

Query the cube to get the value of some measures.

The value of the measures is given on all the members of the given levels.

Parameters
  • measures (~_Measure) – The measures to query. If None, all the measures are queried.

  • levels (Union[~_Level, Sequence[~_Level], None]) – The levels to split on. If None, the value of the measures at the top of the cube is returned.

  • condition (Union[LevelCondition, MultiCondition, LevelIsInCondition, HierarchyIsInCondition, None]) –

    The filtering condition. Only conditions on level equality with a string are supported. For instance:

    • lvl["Country"] == "France"

    • (lvl["Country"] == "USA") & (lvl["Currency"] == "USD")

  • scenario (str) – The scenario to query.

  • timeout (int) – The query timeout in seconds.

Return type

QueryResult

Returns

The resulting DataFrame.

atoti.experimental.distributed.cubes module

class atoti.experimental.distributed.cubes.DistributedCubes(_java_api, _cubes=<factory>)

Bases: MutableMapping[str, atoti.experimental.distributed.cube.DistributedCube]

Manage the distributed cubes.

clear() → None. Remove all items from D.
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D’s items
keys() → a set-like object providing a view on D’s keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() → an object providing a view on D’s values

atoti.experimental.distributed.hierarchies module

class atoti.experimental.distributed.hierarchies.DistributedHierarchies(_java_api, _cube)

Bases: atoti._mappings.DelegateMutableMapping[Tuple[str, str], atoti.query.hierarchy.QueryHierarchy]

Manage the hierarchies.

clear() → None. Remove all items from D.
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items()

Return a set-like object providing a view on the items.

Return type

AbstractSet[Tuple[~_Key, ~_Value]]

keys()

Return a set-like object providing a view on the keys.

Return type

AbstractSet[~_Key]

pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values()

Return an object providing a view on the values.

Return type

ValuesView[~_Value]

atoti.experimental.distributed.hierarchies.to_query_levels(levels)

Convert a dict of cube levels into a dict of query levels.

Return type

ImmutableMapping[str, QueryLevel]

atoti.experimental.distributed.levels module

class atoti.experimental.distributed.levels.DistributedLevels(_hierarchies)

Bases: atoti._base_levels.BaseLevels[atoti.query.level.QueryLevel, atoti.experimental.distributed.hierarchies.DistributedHierarchies]

Flat representation of all the levels in the cube.

get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D’s items
keys() → a set-like object providing a view on D’s keys
values() → an object providing a view on D’s values

atoti.experimental.distributed.measures module

class atoti.experimental.distributed.measures.DistributedMeasures(_java_api, _cube)

Bases: atoti._mappings.DelegateMutableMapping[str, atoti.query.measure.QueryMeasure]

Manage the measures.

clear() → None. Remove all items from D.
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items()

Return a set-like object providing a view on the items.

Return type

AbstractSet[Tuple[~_Key, ~_Value]]

keys()

Return a set-like object providing a view on the keys.

Return type

AbstractSet[~_Key]

pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values()

Return an object providing a view on the values.

Return type

ValuesView[~_Value]

atoti.experimental.distributed.session module

class atoti.experimental.distributed.session.DistributedSession(name, *, config, **kwargs)

Bases: atoti._local_session.ALocalSession

Holds a connection to the Java gateway.

close()

Close this session and free all the associated resources.

Return type

None

property closed

Return whether the session is closed or not.

Return type

bool

create_cube(name)

Create a distributed cube.

Parameters

name (str) – The name of the created cube.

Return type

DistributedCube

property cubes

Cubes of the session.

Return type

DistributedCubes

endpoint(route, *, method='GET')

Create a custom endpoint at f"{session.url}/atoti/pyapi/{route}".

The decorated function must take three arguments with types User, HttpRequest and Session and return a response body as a Python data structure that can be converted to JSON. DELETE, POST, and PUT requests can have a body but it must be JSON.

Path parameters can be configured by wrapping their name in curly braces in the route.

Example:

@session.endpoint("simple_get")
def callback(request: HttpRequest, user: User, session: Session):
    return "something that will be in response.data"


@session.endpoint(f"simple_post/{store_name}", method="POST")
def callback(request: HttpRequest, user: User, session: Session):
    return request.path_parameters.store_name
Parameters
  • route (str) – The path suffix after /atoti/pyapi/. For instance, if custom/search is passed, a request to /atoti/pyapi/custom/search?query=test#results will match. The route should not contain the query (?) or fragment (#).

  • method (Literal[‘POST’, ‘GET’, ‘PUT’, ‘DELETE’]) – The HTTP method the request must be using to trigger this endpoint.

Return type

Any

property excel_url

URL of the Excel endpoint.

To connect to the session in Excel, create a new connection to an Analysis Services. Use this URL for the server field and choose to connect with “User Name and Password”:

  • Without authentication, leave these fields blank.

  • With Basic authentication, fill them with your username and password.

  • Other authentication types (such as Auth0) are not supported by Excel.

Return type

str

explain_mdx_query(mdx, *, timeout=30)

Explain an MDX query.

Parameters
  • mdx (str) – The MDX SELECT query to execute.

  • timeout (int) – The query timeout in seconds.

Return type

QueryAnalysis

export_translations_template(path)

Export a template containing all translatable values in the session’s cubes.

Parameters

path (Union[str, Path]) – The path at which to write the template.

property logs_path

Path to the session logs file.

Return type

Path

logs_tail(n=20)

Return the n last lines of the logs or all the lines if n <= 0.

Return type

Logs

property name

Name of the session.

Return type

str

property port

Port on which the session is exposed.

Can be set in SessionConfiguration.

Return type

int

query_mdx(mdx, *, timeout=30)

Execute an MDX query and return its result as a pandas DataFrame.

Resulting cells representing totals are ignored, they will not be part of the returned DataFrame. Members for which all the measures are None are ignored too.

Example

An MDX query that would be displayed as this pivot table:

Country

Total Price.SUM

2018-01-01

2019-01-01

2019-01-02

2019-01-05

Price.SUM

Price.SUM

Price.SUM

Price.SUM

Total Country

2,280.00

840.00

1,860.00

810.00

770.00

China

760.00

410.00

350.00

France

1,800.00

480.00

500.00

400.00

420.00

India

760.00

360.00

400.00

UK

960.00

960.00

will return this DataFrame:

Date

Country

Price.SUM

2019-01-02

China

410.0

2019-01-05

China

350.0

2018-01-01

France

480.0

2019-01-01

France

500.0

2019-01-02

France

400.0

2019-01-05

France

420.0

2018-01-01

India

360.0

2019-01-01

India

400.0

2019-01-01

UK

960.0

Parameters
  • mdx (str) – The MDX SELECT query to execute.

  • timeout (int) – The query timeout in seconds.

Return type

QueryResult

property url

Public URL of the session.

Can be set in SessionConfiguration.

Return type

str

visualize(name=None)

Display an atoti widget to explore the session interactively.

Note

This method requires the atoti-jupyterlab plugin.

The widget state will be stored in the cell metadata. This state should not have to be edited but, if desired, it can be found in JupyterLab by opening the “Notebook tools” sidebar and expanding the the “Advanced Tools” section.

Parameters

name (Optional[str]) – The name to give to the widget.

wait()

Wait for the underlying server subprocess to terminate.

This will prevent the Python process to exit.

Return type

None

Module contents

Warning

Experimental features are subject to breaking changes (even removals) in minor and/or patch releases.

atoti supports distributed clusters with several data cubes and one query cube.

This is not the same as a query session: in a query session, the query cube connects to a remote data cube and query its content, while in a distributed setup, multiple data cubes can join a distributed cluster where a distributed cube can be queried to retrieve the union of their data.

Distributed cubes can be used like this:

import atoti as tt

distributed_session = tt.experimental.create_distributed_session("dist-test")

# The distributed cube's structure is the same as that of the data cubes that joined its cluster.
# As a result:
#   - the distributed cube's measures, hierarchies, and levels cannot be modified by the user
#   - all the data cubes in the cluster must have the same measures, hierarchies, and levels
distributed_cube = distributed_session.create_cube("DistributedCube")
m = distributed_cube.measures
lvl = distributed_cube.levels

# Create the local cube and join the distributed cluster
session = tt.create_session()

sales_store = session.read_csv("data/sales.csv", keys=["Sale ID"])
cube = session.create_cube(sales_store, "sales1")

tt.experimental.join_distributed_cluster(cube, distributed_session.url, "DistributedCube")

# The distributed cube can be queried as usual, with `distributed_session.visualize()`, or `distributed_cube.query()` returning a pandas DataFrame.

# Wait for the distributed cube to register the arrival of the data cube
import time

while "Amount.SUM" not in m:
    time.sleep(1)

distributed_cube.query(m["Amount.SUM"], m["Quantity.SUM"], levels=[lvl["Product"]])
atoti.experimental.distributed.create_distributed_session(name='Unnamed', *, config=None, **kwargs)

Create a distributed session.

Parameters
  • name (str) – The name of the session.

  • config (Union[SessionConfiguration, Path, str, None]) – The configuration of the session or the path to a configuration file.

atoti.experimental.distributed.join_distributed_cluster(cube, distributed_session_url, distributed_cube_name)

Join the distributed cluster at the given address for the given distributed cube.