Introduction
The conventions shared by every function of the CAT Python module (package justcatit). Read this page once; the function pages assume it.
The CAT Python module — package justcatit on PyPI, module justcatit.cat — drives CAT from Python: it opens a project file (.cat.yaml), runs its tests, hands the results back as objects, and manages the installation. It works with the same project file and runs tests with the same engine as CAT Studio, CAT CLI and the PowerShell module — which tool you use is a matter of environment and taste, not of capability. Under the hood it loads CAT’s .NET engine into the Python process through pythonnet, which is why the objects it returns are .NET objects (see below) and why an installed .NET runtime is a prerequisite. For a hands-on first contact, follow the Get started with the Python module tutorial; this section is the reference.
Install and import
pip install justcatit
plus an installed .NET runtime, version 8 or later — see Installation. Then:
from justcatit import cat
Importing loads nothing of .NET yet; the engine is loaded by the first function you call. Every public function has a docstring (help(cat.invoke_project)).
Functions
By task:
| Task | Functions |
|---|---|
| Run tests in one go | invoke_project |
| Open a project and work with it | open_project · invoke_tests · close_project |
| Inspect the open project | get_data_sources · get_data_source_lists · get_tests · get_test_lists |
| Read the results of the last run | get_test_results_summary · get_test_results |
| Query a data source directly | invoke_command |
| Create a project | new_project · get_project_templates |
| The installation | get_instance · set_instance |
Plus the cat.LoggingLevel enum (below) and the exception classes (below). Everything else in the module is private.
The session model
The module keeps one session and at most one open project per Python process.
- The first function you call loads the .NET engine, creates the session, and — for every function except
get_instanceandset_instance— signs in and checks the plan. This happens once per process; later calls reuse the session. open_project(andinvoke_project, which opens internally) makes a project the open project. Functions that work with “the project” —get_tests,get_data_sources,invoke_tests,invoke_command, … — use it and fail when there is none. Opening another project replaces the first.invoke_projectis the one-liner: open, run, return the summary. After it, the project stays open andget_test_results_summary()/get_test_results()still read its results.close_project()forgets the open project; the session and the last results stay. It is never required.
Paths
project_file_path (open_project, invoke_project) is a path to a .cat.yaml file or to a directory that contains exactly one *.cat.yaml file — none or more than one is an error naming the files found. The argument is required; there is no “current directory” default in Python. A relative path is resolved against the process’s current working directory. Relative paths inside the project file (test lists, outputs, CSV files, …) are resolved against the project file’s folder.
Logging
cat.LoggingLevel has the members NOTHING, FATAL, ERROR, WARNING, INFORMATION, DEBUG. Pass one as loggingLevel / logging_level to the function that makes the first call of the process — the level is fixed when the engine is loaded, and the parameter is ignored on every later call. NOTHING and None both mean the engine’s default, which is INFORMATION; logging cannot be switched off from Python in the current version.
Log lines go to standard output ([HH:mm:ss INF] …) and to the log file Documents\CAT\Logs\cat-log<yyyyMMddHH>.log on Windows (./CAT/Logs/ under the current directory on Linux). INFORMATION shows what CAT does step by step — which project it opened, how many data sources and tests it loaded from where, each test as it finishes.
.NET objects in Python
Except invoke_command (a dict) and the functions that return nothing, every function returns the engine’s own .NET object. Three things to know:
- Properties are PascalCase and read like attributes:
summary.FailedCount,test.TestFullName,instance.LicenseKey. The function pages list them. - Collections iterate and support
len():for t in cat.get_tests(): …. They are not Python lists; wrap them (list(cat.get_tests())) if you need list methods. - Numbers and dates are .NET types. Counts are plain
int. Rates (PassRate,FailedRate, …) areSystem.Decimal:str()and f-strings print them,float(x)raisesTypeError— usefloat(str(x)). Dates and durations (StartedOn,Duration) print fine; call.ToString()for formatting. Test IDs areSystem.Guidobjects (hand them back as they are; strings are not accepted).
Exceptions
Refusals from the sign-in and plan check raise typed exceptions from justcatit.exceptions (the base class and the first six are also importable from justcatit directly); args[0] carries the message:
| Exception | Meaning |
|---|---|
TokenMissingError |
CAT_PORTAL_TOKEN is not set. |
TokenInvalidError |
The token was rejected by the portal. |
PlanNotAllowedError |
The plan does not include the Python module (Starter, Professional). |
OfflineExpiredError |
The portal is unreachable and no cached authorisation can be used. |
VersionExpiredError |
The plan or version has expired. |
InteractiveUsageError |
Interactive-only plan (Team) started by a CI/CD platform or a scheduler. |
PlanLimitExceededError |
The project exceeds a per-project limit of the plan (open_project). |
CatPortalError |
Base class of all of the above. |
set_instance raises ValueError when it refuses a key. Everything else that goes wrong inside the engine — a project file that does not parse, an unknown data source name, a data source that cannot be reached while loading — surfaces as the .NET exception pythonnet wraps (System.Exception, JC.Cat.Core.Exceptions.CatException, …); e.Message is the message, str(e) adds the .NET stack trace. In the current version, calling a project function with no open project raises a bare TypeError: exceptions must derive from BaseException rather than a readable error — open a project first.
Failed tests are not exceptions. invoke_project and invoke_tests return normally whatever the results; a script that must fail on failed tests reads the summary:
summary = cat.invoke_project("D:/Testing/DwhTests.cat.yaml")
if summary.FailedCount > 0 or summary.ErrorCount > 0:
raise SystemExit(1)
Sign-in, plans and the license key
The command-line tools are available in the Team and Enterprise plans; Starter and Professional cover CAT Studio only — the module refuses to work under them (PlanNotAllowedError). See Compare plans.
Team signs in to CAT Portal with a personal access token: create one under Developer → Personal access tokens and put it into the CAT_PORTAL_TOKEN environment variable before the process starts (or os.environ["CAT_PORTAL_TOKEN"] = "…" before the first call). The Team plan is for interactive use only: when CAT detects that it was started by a CI/CD platform (GitHub Actions, GitLab CI, Azure Pipelines, Jenkins, TeamCity and others, through their environment variables) or by a scheduler (Windows Task Scheduler, SQL Server Agent, cron — through the parent process; on Linux also a container runtime), it refuses with InteractiveUsageError. Nothing detected means allowed.
Once signed in, CAT caches the authorisation and keeps working without the portal for a limited time; during that time the first call emits a UserWarning Working offline; authorised until <date>. Reconnect before then. (silence it with the warnings module). When the portal is unreachable and no usable cache exists, it refuses with OfflineExpiredError.
Enterprise needs no sign-in and no network at all: set the license key once with set_instance and every function is unlocked, also behind a firewall; with a valid key in place CAT_PORTAL_TOKEN is not read. The key is shared with the other CAT tools on the machine. See Get CAT license and Apply a license key.
The check runs before any work, so a refused call does nothing — no project is opened, no test runs, no output is written. After a refusal the process is not poisoned: set the variable or the key and call again. get_instance and set_instance skip the check.
Environment variables
| Variable | Purpose |
|---|---|
CAT_PORTAL_TOKEN |
Personal access token used to sign in (Team plan). Not read when a valid Enterprise key is set. |
DOTNET_ROOT |
Read by pythonnet to find the .NET runtime when it is not on PATH. |
Project files can reference environment variables of their own (connection strings, paths, passwords) — see Environment variables and Use environment variables.
Files the module touches
| Windows | Linux | Content |
|---|---|---|
%APPDATA%\CAT\.catconfig |
~/.config/CAT/.catconfig |
Instance identity and the license key (get_instance / set_instance). |
%APPDATA%\CAT\Templates\Projects\ |
~/.config/CAT/Templates/Projects/ |
Project templates, including those downloaded with online=True. |
Documents\CAT\Logs\ |
./CAT/Logs/ |
Log files. |
| Next to the project file | Whatever the project’s Output settings say (see Outputs); skip_outputs=True skips them. |
Platforms
The package is built and tested on Windows x64; it needs a 64-bit Python and an installed .NET runtime (8 or later). On Linux the engine loads and runs with an installed .NET runtime, but with limits: the providers built on Windows components (Dax@1, Dax@2, PowerBI@1, PowerBI@2, CsvOleDB@1, ExcelOleDB@1) are unavailable, the DuckDB-based Csv@2 / Excel@2 providers lack their Linux native library in the package, and the xlsx output fails after the tests ran (use json, yaml, junit or a database output, or skip_outputs=True). The PowerShell module is the supported way to run CAT on Linux. Running CAT inside Databricks or Microsoft Fabric notebooks is discussed in the how-to guides CAT in Databricks notebooks and CAT and Microsoft Fabric.
Related
- Installation — pip, the .NET runtime, Python versions, upgrade, uninstall.
- Get started with the Python module — the tutorial.
- Run your tests — the same task across all tools.
- Project file — what the functions operate on.