0.9.0 (September 13, 2024)#

Added#

  • atoti-directquery-jdbc to connect to an external database through JDBC.

  • data_model_transaction(). Batching measure creation with a data model transaction has the same performance as using Measures.update() without being limited to independent measures:

    - m.update({"foo": 13, "bar": 42})
    - m.update({"foo + 1": m["foo"] + 1, "bar + 1": m["bar"] + 1})
    + with session.data_model_transaction():
    +    m["foo"] = 13
    +    m["foo + 1"] = m["foo"] + 1
    +    m["bar"] = 42
    +    m["bar + 1"] = m["bar"] + 1
    

    Data model transactions also replace the private API relying on atoti.MeasureMetadata:

    - m["foo"] = (13, tt.MeasureMetadata(visible=True))
    - m["bar"] = (42, tt.MeasureMetadata(description="The answer"))
    + with session.data_model_transaction():
    +    m["foo"] = 13
    +    m["foo"].visible = True
    +    m["bar"] = 42
    +    m["bar"].description = "The answer"
    
  • atoti_directquery_redshift.ConnectionConfig.connection_pool_size.

User interface#

  • Filters tool in the sidebar of the JupyterLab extension to see default filters.

Changed#

Packaging#

  • The atoti package and most of its plugins (e.g. atoti-aws, atoti-directquery-directquery, atoti-kafka etc.) have been split into atoti-client-* and atoti-server-* packages. The atoti-client-* packages contain the Python code composing the API while the atoti-server-* packages mostly contain the JARs implementing the corresponding features. The advanced installation section explains the goal of this split.

    The atoti package still exists but has become empty, it is only there to provide a convenient way to install both client and server packages. For instance:

    • pip install atoti will install both atoti-client and atoti-server . It will actually also install jdk4py.

      Note: jdk4py is not a dependency of atoti-server so that projects willing to use another JDK can avoid installing jdk4py by dependending on atoti-client and atoti-server directly.

    • pip install "atoti[aws]" will install atoti-client, atoti-aws-client, atoti-aws-server, and atoti-server.

    • pip install "atoti[jupyterlab]" will install atoti-client, atoti-server, and atoti-jupyterlab (no client/server split for this package because it only contains frontend assets).

    Because Conda does not support “extras”, the installation of Atoti plugins with this package manager is more complex. For instance, the command to install atoti and its AWS plugin is: conda install atoti atoti-client-aws atoti-server-aws.

Session start and configuration#

  • atoti.Session.__init__() has been replaced with atoti.Session.start() for symmetry with atoti.Session.connect() (the removed section gives more details about that latter method):

    - session = tt.Session()
    + session = tt.Session.start()
    

    The top-level config parameters have been grouped into a SessionConfig dataclass providing better error reporting and allowing code reuse:

    - session = tt.Session(port=1337)
    + session = tt.Session.start(tt.SessionConfig(port=1337))
    
  • atoti.Session.__init__()’s authentication parameter has been replaced with atoti.SessionConfig.security:

      config = tt.OidcConfig(...)
    - tt.Session(authentication=config)
    + tt.Session.start(tt.SessionConfig(security=tt.SecurityConfig(sso=config)))
    
  • atoti.UserContentStorageConfig has been moved to atoti_jdbc.UserContentStorageConfig:

    - config = tt.UserContentStorageConfig(url=url)
    - tt.Session(user_content_storage=config)
    + from atoti_jdbc import UserContentStorageConfig
    + config = UserContentStorageConfig(url)
    + tt.Session.start(tt.SessionConfig(user_content_storage=config))
    

    It makes it obvious that storing user content in an external database requires atoti-jdbc to be installed.

DirectQuery#

  • DirectQuery *ConnectionInfo and *TableOptions classes have been renamed ConnectionConfig and TableConfig.

    - from atoti_directquery_clickhouse import ClickhouseConnectionInfo
    + from atoti_directquery_clickhouse import ConnectionConfig
    
    - from atoti_directquery_clickhouse import ClickhouseTableOptions
    + from atoti_directquery_clickhouse import TableConfig
    
  • The cache attribute controlling whether DirectQuery connections should use caching has been moved from the connection instance to the connection config:

    - from atoti_directquery_snowflake import SnowflakeConnectionInfo
    + from atoti_directquery_snowflake import ConnectionConfig
    - connection_config = SnowflakeConnectionInfo(url=...)
    + connection_config = ConnectionConfig(url=..., cache=True)
      external_database = session.connect_to_external_database(connection_config)
    - external_database.cache = True
    
  • The DatabricksConnectionInfo.heavy_load_url attribute has been renamed feeding_url.

Other#

  • Upgraded jdk4py dependency to 21.0.4 which adds support for Linux Arm64.

  • atoti_aws.AwsKeyPair, atoti_aws.AwsKmsConfig, and atoti_azure.AzureKeyPair have been renamed KeyPair, KmsConfig, and KeyPair.

  • The atoti-sql package has been renamed atoti-jdbc.

  • atoti.Session.explain_mdx_query() and atoti.Cube.explain_query() have been replaced with an explain parameter to atoti.Session.query_mdx() and atoti.Cube.query():

    - session.explain_mdx_query(mdx)
    + session.query_mdx(mdx, explain=True)
    
  • atoti.Table.keys returns a tuple instead of a list. It communicates that keys cannot be changed once the table exists.

  • create_cube()’s base_table parameter has been renamed fact_table.

User interface#

  • Upgraded Atoti UI and Admin UI to 5.2.0.

Deprecated#

  • atoti.Session.port. Use atoti.Session.url instead:

    - url = f"http://localhost:{session.port}"
    + url = session.url
    
    - port = session.port
    + from urllib.parse import urlparse
    + port = urlparse(session.url).port
    
  • atoti.Session.start_transaction(). Use atoti.tables.Tables.data_transaction() instead:

    - with session.start_transaction(): ...
    + with session.tables.data_model_transaction(): ...
    
  • atoti.Session.security.basic. Use basic_authentication:

    - session.security.basic.credentials
    + session.security.basic_authentication.credentials
    
  • atoti.Table.columns and atoti.ExternalTable.columns. Use list(table) to list column names and for column_name in table: ... to iterate on column names:

    - column_names = table.columns
    + column_names = list(table)
    
  • atoti.Hierarchy.levels. Iterate on the Hierarchy instead:

    - level_names = list(h["Geography"].levels)
    + level_names = list(h["Geography"])
    
    - h["Date parts"] = {**h["Date parts"].levels, "Date": table["Date"]}
    + h["Date parts"] = {**h["Date parts"], "Date": table["Date"]}
    

Removed#

  • Support for Java 17, 18, 19, and 20.

  • The atoti-query package and its QuerySession class. Use atoti.Session.connect() instead:

    - pip install atoti-query
    + pip install atoti-client
    
    - from atoti_query import QuerySession
    + from atoti as tt
    - existing_session = QuerySession(url)
    + existing_session = tt.Session.connect(url)
      existing_session.query_mdx(...)
    
  • atoti.Table.__len__(). It was ambiguous because it could be interpreted as counting either rows or columns. Instead, use atoti.Table.row_count to count rows and len(list(table)) to count columns:

    - row_count = len(table)
    + row_count = table.row_count
    

Previously deprecated#