Skip to main content
This is a detailed list of all changes. For a higher level view, see the Release notes. Atoti Python SDK implements Atoti version policy in a specific manner to follow Semantic Versioning.

0.9.18

Released on September 30, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.25.

Fixed

  • Joining a distributed cluster rebuilt the cube, re-feeding all aggregated data and re-issuing every aggregation query against the database, which could be very expensive in a DirectQuery setup 6.
  • A role restricted on a slicing hierarchy holding a single level saw an empty cube instead of the restricted members 4. This applies to both atoti.Cube.restrictions and atoti.tables.Tables.restrictions.
  • Generating a token on the MCP credentials page failed 5. The page was also only reachable at /mcp-credentials/index.html, not at /mcp-credentials.
  • A data cube could be missing from the cluster it had joined, leaving the query cube without any of its measures 7. A query cube under load could drop its answer to a join request instead of sending it, and nothing sent that answer again. After ten unanswered attempts the data cube gave up and formed a cluster of its own, while the query cube had already counted it in as a member. Several cubes joining at once, typically when the cluster restarts, made it more likely.
  • atoti.Table.load() raised a NullPointerException instead of a descriptive error when its transaction failed at commit time 9.
  • atoti.agg.sum_product() rejected array columns of type float[], long[], and int[] with TypeError: Only array columns of type double[] are supported 11.
  • atoti.Session.logs_path named a file that was never written when the observability plugin was installed 13. The session logged to the standard output only, whether the file’s location came from atoti.LoggingConfig.destination or from the default one under $ATOTI_HOME.
  • atoti.Table.load() hung forever when a data model change, such as assigning a measure with atoti.Cube.measures from another thread, was requested while a load was running 12. The data model change waited for the load to end while the load waited for the change to open, and every later load or request reading the data model then hung too, until the session was restarted.
  • Changing several things at once, such as updating the role_mapping of oidc with more than one entry, no longer raises TypeError: Invalid AST Node when graphql-core 3.3 is installed 8. The Atoti Python SDK combines these changes into a single request, and graphql-core 3.3 no longer accepted the way that request was built.

Security

Internal issue tracker references

0.9.17

Released on August 13, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.24.
  • atoti.Session.start() raises a RuntimeError when atoti.SessionConfig.ai is passed but the started server exposes no AI service 14. This is most often a license missing the ai-essentials component, which the error message calls out. Such a session previously started successfully with atoti.Session.chat and atoti.Cube.auto_explain silently set to None. To start a session without AI, do not pass ai:
    Sessions that do not pass ai are unaffected, including those where the ai plugin is installed.
  • 0.9.x versions are no longer published on PyPI 17. Only the latest version line of the Atoti Python SDK is published there, and that line is now 6.2.x. 0.9.x versions are only available from ActiveViam’s repository.

Security

Internal issue tracker references

0.9.16.1

Released on July 31, 2026.
This version is not published on PyPI, it is only available on ActiveViam’s repository.

Fixed

  • Improved query interruption checks, boosting performance for large cross-joins and the descendants MDX function, including cases where the JVM heap was not freed after a query timeout or cancellation.
  • Fixed an issue with query plan validation affecting specific edge cases.

0.9.16

Released on July 10, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.23.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.25.
  • The Atoti UI app is served in development mode if __debug__ is True. See deployment setup.
  • When atoti.SessionConfig.ai is not None, the session’s MCP server exposes an OAuth 2.1 flow, so MCP clients such as Claude Desktop or Claude Code can authenticate without a manually provisioned Bearer token. If the session delegates authentication to an OIDC provider (OidcConfig), the MCP server reuses it (external mode: clients authenticate against that provider, which already guards the MCP endpoint). Otherwise the MCP server acts as its own OAuth 2.1 authorization server (self-issued mode: a browser login and consent against the session’s own authentication). HTTP Basic authentication on the MCP endpoint keeps working, so programmatic and headless clients are unaffected. Override with the atoti.server.endpoint.mcp.oauth2.* server properties 27.
  • Changing atoti.Hierarchy.virtual to True does not restart the cube 28.
  • atoti.AiConfig has moved to atoti_ai.AiConfig 22. The ChatConfig and ConnectionConfig base classes have moved from atoti.config.ai to atoti_ai as well.

Deprecated

Fixed

  • create_parameter_hierarchy_from_column() supports using the target field of a join 21.
  • query() and query() raising an error when a LocalDate column member is outside the pandas datetime range 23.
  • LoggingCsvHealthEventHandler no longer logs spurious errors when non-CSV health events are dispatched to it 24.
  • JdbcPingDiscoveryProtocol backed by an embedded H2 file database intermittently failing to form the cluster, because the query and data nodes, which run in separate JVMs, could not open the discovery database concurrently. AUTO_SERVER=TRUE is enabled automatically for embedded H2 databases so that the query and data nodes can access the discovery table concurrently 26.

Security

Internal issue tracker references

0.9.15

Released on May 29, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.20.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.24.
  • The Atoti UI app is served using its development build when __debug__ is True. It is strongly recommended to use Python’s optimized mode in production to avoid this development build’s overhead.
  • Accept using the JDK that the JAVA_HOME environment variable points to even if its version is greater than 21.

Fixed

Internal issue tracker references

0.9.14

Released on April 17, 2026.

Added

  • OpenTelemetry spans around the main functions and methods of the library. See atoti_observability for example traces.

Changed

  • Upgraded Atoti Server to 6.1.19.

Deprecated

Fixed

Internal issue tracker references

0.9.13

Released on March 10, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.18.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.20.
  • Renamed cloud storage packages:
    • atoti-client-aws → atoti-client-storage-aws
    • atoti-server-aws → atoti-server-storage-aws
    • atoti-client-azure → atoti-client-storage-azure
    • atoti-server-azure → atoti-server-storage-azure
    • atoti-client-gcp → atoti-client-storage-gcp
    • atoti-server-gcp → atoti-server-storage-gcp
    The module names have also changed:

Deprecated

  • atoti-client-aws, atoti-server-aws, and the atoti_aws module. Use atoti-client-storage-aws, atoti-server-storage-aws, and atoti_storage_aws instead.
  • atoti-client-azure, atoti-server-azure, and the atoti_azure module. Use atoti-client-storage-azure, atoti-server-storage-azure, and atoti_storage_azure instead.
  • atoti-client-gcp, atoti-server-gcp, and the atoti_gcp module. Use atoti-client-storage-gcp, atoti-server-storage-gcp, and atoti_storage_gcp instead.

Fixed

Internal issue tracker references

0.9.12

Released on January 23, 2026.

Added

Changed

  • Upgraded Atoti Server to 6.1.16.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.18.
  • Loading Apache Parquet files requires the new atoti-client-parquet and atoti-server-parquet packages 40. Installing the atoti package also installs these packages but the next breaking release will make them opt-in.
    If you do no use Parquet files and wish to reduce the size of your dependencies, you can skip the installation of the atoti package and manually install the atoti-client and atoti-server packages instead:
    Or, if you use some extras:

Deprecated

  • atoti.ParquetLoad 40. Use atoti_parquet.ParquetLoad instead:
  • read_parquet() since support for Apache Parquet will become opt-in 40. Use infer_data_types(), create_table(), and load() instead:
  • atoti.Session.query_mdx() and atoti.Cube.query()’s timeout parameter 41. The default value has also been changed from datetime.timedelta(seconds=30) to None to automatically use shared_context’s queriesTimeLimit . Use the context parameter to specify a custom timeout:

Fixed

  • Atoti Admin UI connecting to wrong server due to wrong order of WebJars in the server’s classpath 43.
  • Hierarchies disappearing from the Data model tree when editing the data model of a secured session 42.

Internal issue tracker references

0.9.11

Released on December 16, 2025.

Added

Changed

  • Upgraded Atoti Server to 6.1.15.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.17.
  • atoti.Measure.description returns "" instead of None 47.
  • Everything related to Security is kept in memory instead of being persisted in the user_content_storage 44. This makes the API more consistent since all the other methods on atoti.Session and its related classes never persisted their changes either. This improves performance, both when configuring these properties but also when executing queries.
    Basic authentication credentials are unaffected since, for security reasons, they were already only kept in memory.

Deprecated

  • atoti.Measure.description’s deleter 47. Set the description to a blank string instead:

Fixed

Internal issue tracker references

0.9.10

Released on October 31, 2025.

Added

Changed

  • Upgraded Atoti Server to 6.1.13.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.15.
  • Installation instructions with Conda to recommend Miniforge over Anaconda’s installer to not be tied to Anaconda’s license requirements 53.
  • Configuring branding does not remove the By ActiveViam signature at the bottom right corner of the app anymore. It is still possible to remove this signature through a custom app extension 51.

Internal issue tracker references

0.9.9.2

Released on October 20, 2025.
This version is not published on PyPI, it is only available on ActiveViam’s repository.

Added

Changed

  • Improved planning of MDX queries requesting many specific cells of the cube 54.
  • Reduce number of requests made when representing (or evaluating in a Jupyter notebook cell) cubes, levels, measures, etc of a connected session 56.

Fixed

Internal issue tracker references

0.9.9.1

Released on September 30, 2025.
This version is not published on PyPI, it is only available on ActiveViam’s repository.

Changed

  • Improved planning of MDX queries requesting many specific cells of the cube 58.

Fixed

  • ArrayIndexOutOfBoundsException when running some MDX queries 59.
  • AssertionError: Output has already been set when deleting a cube 61.
  • GraphQLClientGraphQLMultiError: Structural transaction must be committed by the thread starting it when setting atoti.Measure.visible inside a data_model_transaction() 60.

Internal issue tracker references

0.9.9

Released on September 22, 2025.

Added

Changed

Fixed

Internal issue tracker references

0.9.8

Released on August 12, 2025.

Added

Changed

  • Upgraded Atoti Server to 6.1.11.
  • When atoti.JwtConfig.key_pair is None, the automatically generated key pair will use 3072 bits instead of the old 2048 bits.

Deprecated

  • Requests to endpoints created with atoti.Session.endpoint should now use /proxy instead of /atoti/pyapi. /atoti/pyapi remains available but logs a warning when used 70.
  • The atoti.pyapi module is deprecated, import its classes directly from atoti.User or atoti.endpoint.Request instead 70.

Fixed

Internal issue tracker references

0.9.7

Released on July 01, 2025.

Added

Changed

Deprecated

Fixed

  • where() rejecting condition if it contained a ~hierarchy.isin(...) or ~level.isin(...) leaf 76.
  • atoti.finance.irr() returning nan when the actual rate was too large 78.

Internal issue tracker references

0.9.6

Released on May 17, 2025.

Added

Changed

  • Upgraded Atoti UI and Atoti Admin UI to 5.2.8.
  • Upgraded Atoti Server to 6.1.8.
  • The functions that were in the atoti.experimental subpackage have been moved outside of it and require passing their feature key to experimental():

Deprecated

  • Deleting a level through atoti.Cube.levels. Redefine its hierarchy instead:
  • atoti.date_shift()’s method parameter 85. The new parameter name is fallback:

Fixed

Internal issue tracker references

0.9.5

Released on April 4, 2025.

Security

SSO

The atoti.KerberosConfig.username_case_conversion and atoti.LdapConfig.username_case_conversion attributes have been added to coerce the name of users logging in to the expected case 86. Not picking a case conversion is a source of confusion or bugs so leaving these attributes unset will raise a deprecation warning.

Database access

atoti.tables.Tables.owners and atoti.tables.Tables.readers have been added 87. Their impact is not limited to the Python API. For instance, atoti.tables.Tables.readers will also control whether end users are able to see tables in Atoti Admin UI Database tab.

Dependencies

  • Upgraded Atoti UI and Atoti Admin UI to 5.2.7.
  • Upgraded Atoti Server to 6.1.6.

Fixed

Data loading

Cloud storage
On Windows, passing a URL to atoti.CsvLoad.path or atoti_parquet.ParquetLoad.path raised an InvalidPathException 91.

Data modeling

Conditions
Creating logical conditions (i.e. boolean combinations of leaf conditions such as (level["Product"] == "Phone") | (level["Country"] == "Portugal")) with more than 508 leaves raised a ValidationError because it reached the maximum nesting depth supported by the runtime type checker 92. This was fixed by allowing the internal representation of a logical condition to group more than 2 operands. For example, (a & b) | c | d | f | g (with a maximum depth of 2) replaces the old internal representation (((a & b) | c) | (d | f)) | g (with a maximum depth of 4).

Table columns

Columns are strictly typed: a column with a "LocalDate" data_type can only store dates (or None if its default_value is None); it cannot store a "String" such as "NaN". Since Java has no equivalent of pandas.NaT, the only available values to represent a special null-restricted:
  • "LocalDate" are LocalDate.MIN and LocalDate.MAX,
  • "LocalDateTime" are LocalDateTime.MIN and LocalDateTime.MAX.
However, accessing default_value when it was set to one of these values raised a ValidationError 88. This is fixed.

Measures

  • The type annotation of filter()’s filter parameter never allowed inverted atoti.Level.isin() conditions (e.g. ~level.isin("foo", "bar")) but, by chance, these conditions actually behaved as expected at runtime. However, 0.9.4 introduced runtime validation of condition types which lead to the rejection of these conditions. This regression is fixed: the type annotation of filter accepts these conditions and they are supported at runtime 89.
  • Passing isnull conditions to atoti.where() raised an UnknownUnderlyingMeasureRuntimeException 90.

Internal issue tracker references

0.9.4

Released on February 28, 2025.

Distribution

The name QuerySession, unused since 0.9.0, makes a come back in this release but, this time, with a different meaning. QuerySession becomes the entry point to create clusters of Atoti applications 98. atoti.Cube.restrictions has been introduced to secure query sessions. For the sake of symmetry, atoti.Session.security.restrictions has moved to atoti.tables.Tables.restrictions (the old location remains available but is deprecated). See Scaling with distribution.

Performance

Client/server communication

Most components of Session are exposed through mappings such as Cubes or Tables. As a project grows, a lot of mapping lookups will be made to iteratively define the data model or to pass arguments to methods such as atoti.Cube.query(). For instance, the following code will make 3 lookups:
Each lookup makes a request to the server to check that the key exists. This is pretty quick but, when thousands of lookups are made, this client/server communication can add up. mapping_lookup() allows skipping these server requests.

Cube queries

The aggregate cache of a cube can be restricted to a subset of measures 95. This improvement comes with a new atoti.Cube.aggregate_cache API deprecating the previous atoti.Cube.aggregates_cache (with an “s”) one:

Hierarchy creation

Creating hierarchies from columns of a table fully joined (i.e. all their keys are mapped) to the cube’s fact table do not require “rebuilding” the cube anymore 96. This means that no time will be lost reindexing hierarchies or performing other expensive computations.

Data modeling

Measures

atoti.where() was not respecting the order of condition_to_value when the same value was assigned to multiple conditions 94. For example, in:
Test was equal to -1 because the first and last conditions, being both assigned to the same value, were merged together and that merged condition became the first one evaluating to True. This incorrect merging of conditions has been removed: m["8"] >= 5 is correctly detected as the first condition evaluating to True and so Test is equal to 1.

Table columns

Columns with an arrray data type can be made non-nullable. atoti.Column.default_value’s documentation has been updated accordingly.

Data loading

Transactions

data_transaction()’s tables parameter allows some data transactions to execute concurrently 93.

CSV

The atoti.CsvLoad.true_values and atoti.CsvLoad.false_values attributes can be configured to parse more values than "True", "true", "False", and "false" as "boolean" 97.

Dependencies

  • Atoti Server has been upgraded to 6.1.4.
  • Atoti UI and Atoti Admin UI have been upgraded to 5.2.6.

Internal issue tracker references

0.9.3

Released on January 13, 2025.

Added

Changed

  • Upgraded Atoti Server to 6.1.3.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.4.
  • SessionConfig and its inner classes validate that passed Path attributes exist. It prevents situations such as passing a path containing a typo to extra_jars and being confused that the JAR’s classes still cannot be loaded.

Fixed

  • read_parquet() and ParquetLoad not being able to load Parquet files with extension other than .parquet.
  • NullPointerException returned by the server when executing some MDX queries.

0.9.2

Released on December 05, 2024.

Added

Documentation

Changed

  • Upgraded Atoti Server to 6.1.2.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.3.
  • To support remote clusters, atoti.Session.read_spark() and atoti.Table.load_spark() convert the passed Spark DataFrame to an in-memory Pandas DataFrame instead of exporting it to a Parquet file.

Deprecated

  • atoti.Table.append():
  • atoti.Table.load_arrow():
  • atoti.Table.load_csv():
  • atoti.Table.load_kafka():
  • atoti.Table.load_numpy():
  • atoti.Table.load_pandas():
  • atoti.Table.load_parquet():
  • atoti.Table.load_spark()
  • atoti.Table.load_sql():
  • atoti.Session.read_numpy():
  • atoti.Session.read_spark():
  • atoti.Session.read_sql():
  • create_table(), read_arrow(), read_csv(), read_pandas(), read_parquet()’s types parameter. Use the data_types parameter instead.
  • Inference of read_csv() and read_parquet()’s table_name parameter. Pass a table_name argument instead.

Fixed

0.9.1

Released on October 18, 2024.

Added

Changed

  • Upgraded Atoti Server to 6.1.1.
  • Upgraded Atoti UI and Atoti Admin UI to 5.2.1.

Fixed

0.9.0

Released on 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:
    Data model transactions also replace the private API relying on atoti.MeasureMetadata:
  • 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):
    The top-level config parameters have been grouped into a SessionConfig dataclass providing better error reporting and allowing code reuse:
  • atoti.Session.__init__()’s authentication parameter has been replaced with atoti.SessionConfig.security:
  • atoti.UserContentStorageConfig has been moved to atoti_jdbc.UserContentStorageConfig:
    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.
  • The cache attribute controlling whether DirectQuery connections should use caching has been moved from the connection instance to the connection config:
  • 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():
  • 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:
  • atoti.Session.start_transaction(). Use atoti.tables.Tables.data_transaction() instead:
  • atoti.Session.security.basic. Use basic_authentication:
  • 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:
  • atoti.Hierarchy.levels. Iterate on the Hierarchy instead:

Removed

  • Support for Java 17, 18, 19, and 20.
  • The atoti-query package and its QuerySession class. Use atoti.Session.connect() instead:
  • 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:

Previously deprecated