0.9.0a0 (Aug 01, 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#

Session start and configuration#

  • atoti.Session.__init__() has been replaced with atoti.Session.start() and the top-level config parameters have been grouped into SessionConfig:

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

      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#

  • 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.

User interface#

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:

    - from atoti_query import QuerySession
    + import atoti as tt
    - existing_session = QuerySession(url)
    + existing_session = tt.Session.connect(url)
      existing_session.query_mdx(...)
    

    Projects exclusively using Atoti as a Python client to connect() to existing sessions (i.e. projects that never start() new sessions) can depend on atoti-client instead of atoti to significantly reduce the size of installed dependencies:

    - pip install atoti-query
    + pip install atoti-client
    
  • 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#