Metadata-Version: 2.4
Name: pysisense
Version: 2.0.0
Summary: A Python SDK for interacting with Sisense API
Author: Sisense Ltd.
Maintainer-email: Himanshu Negi <himanshu.negi@sisense.com>, Jeremy Friedel <jeremy.friedel@sisense.com>
License: PYSISENSE SDK
        END USER LICENSE AGREEMENT
        
        This End User License Agreement (“EULA”) forms a binding agreement between you individually or the entity on whose behalf you are accepting this agreement (“You”) and describes the terms and conditions governing the use of any application programming interface, software development kit, code snippet, sample code, user interface component, visualization, CLI tools, or sample data, and the corresponding documentation for each, any updates and upgrades thereto, and any modifications, enhancements, or improvements, of any of the foregoing (each, a “Tool” and collectively, the “Tools”), made available by Sisense Ltd. or its affiliates (“Sisense”).
        
        1. ACCEPTANCE
        By downloading, importing, installing and/or using any Tool (or any portion thereof), You represent and warrant that: (a) You have read, understand and accept all of the provisions of this EULA; and (b) if You are accepting on behalf of an entity, You are an employee, contractor or agent of such entity and have the authority and all legal power to accept on behalf of such entity.
        
        2. LICENSE SCOPE
        Subject to the terms and conditions of this EULA, Sisense hereby grants You a royalty-free, non-exclusive, non-transferable, limited license to access, download and use the Tools (in the manner described in the documentation for such Tool) solely for utilization with Your use of the applicable Sisense subscription product (the “Product”), to which You must have purchased the necessary license and use rights pursuant to a separate written agreement with Sisense (the “Master Subscription Agreement”).
        
        3. RESTRICTIONS
        You agree that You will not (and have no license to) and will not permit any third party to: (i) use the Tools except as permitted under this EULA; (ii) sell, resell, license, sublicense, rent, lease, encumber, lend, distribute, transfer, or provide a third party with access to the Tools; (iii) modify or create derivative works of the Tools; (iv) circumvent or remove by any means any copy protection used by Sisense in connection with the Tools; (v) use the Tools to develop a competitive product offering; (vi) use the Tools to access Sisense products in a manner not authorized by the Master Subscription Agreement or this EULA; or (vii) use the Tools in any manner that violates the Master Subscription Agreement or any applicable laws or regulations.
        
        4. SISENSE OWNERSHIP
        Except for those portions licensed to Sisense by third parties, Sisense retains all right, title and interest in and to the Tools, including without limitation all copyrights and other intellectual property or other proprietary rights worldwide therein (including but not limited to all patent, trademark, service mark, copyright, trade secret, know-how, moral right, and any other intellectual and intangible property rights, including all continuations, continuations in part, applications, renewals, and extensions of any of the foregoing, whether registered or unregistered). All rights not expressly granted herein are reserved. You may not remove, delete or modify any of the Sisense copyright statements in the Tools.
        
        5. OPEN SOURCE COMPONENTS
        To the extent any open source software components are provided with or used by the Tools, such components are licensed to You under the terms of the applicable license agreements included with such open source software components.
        
        6. THIRD-PARTY COMPONENTS
        To the extent that any Tool includes one or more components licensed by a third party (a “Component”), and such third party’s license requirements apply to such Component in a Tool, such additional license terms will be provided in the open source disclosure file provided with or within a Tool download. Third-party license terms shall take precedence over this EULA to the extent that they impose additional restrictions or limitations on You than the license provided herein for download and use of a Component. You agree that: (a) to the extent that the terms between You and the third party for use of a third-party technology accessed by the Component are more restrictive, such terms shall apply to Your use of the Component; (b) Sisense, and not the third party, is responsible for the Component including, without limitation, for any warranties, maintenance, and support thereof, and the third party does not warrant the Component’s accuracy, reliability, completeness, usefulness, non-infringement, or quality of the Component, and will not be liable for any losses or damages of any kind, including lost profits or other indirect or consequential damages, relating to use of or reliance on the Component; and (c) the third party owns all right, title, and interest in and to the Component, including all intellectual property rights therein.
        
        7. TERM, TERMINATION, AND CHANGES
        This EULA shall continue as long as You are in compliance with the terms specified herein or until otherwise terminated. This EULA shall automatically terminate upon the expiration or termination of the Master Subscription Agreement. You agree, upon termination, to destroy all copies of the Tools within Your possession or control. The Disclaimer of Warranties, Limitation of Liability and Indemnification sections set out in this EULA shall survive any termination or expiration of this EULA. Sisense may, in its sole discretion, update this EULA from time to time.
        
        8. NO DUTY TO SUPPORT
        You expressly acknowledge that Sisense has no duty or obligation to support the Tools, or to provide updates or bug fixes to the Tools.
        
        9. DISCLAIMER OF WARRANTIES
        THE TOOLS ARE PROVIDED “AS IS” WITHOUT ANY WARRANTIES OF ANY KIND. TO THE MAXIMUM EXTENT PERMITTED BY LAW, SISENSE DISCLAIMS RESPONSIBILITY FOR ANY HARM RESULTING FROM YOUR USE OF ANY TOOL. SISENSE DISCLAIMS TO THE FULLEST EXTENT PERMITTED, ALL GUARANTEES AND EXPRESS, IMPLIED AND STATUTORY WARRANTIES, INCLUDING WITHOUT LIMITATION THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT OF PROPRIETARY RIGHTS, AND ANY WARRANTIES REGARDING THE AVAILABILITY, SECURITY, RELIABILITY, TIMELINESS AND PERFORMANCE OF ANY TOOL. YOU ACKNOWLEDGE THAT YOU DOWNLOAD AND USE THE TOOLS AT YOUR OWN DISCRETION AND RISK, AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGES TO HARDWARE DEVICES OR LOSS OF DATA THAT RESULT FROM THE DOWNLOAD OR USE OF ANY TOOL.
        
        10. LIMITATION OF LIABILITY
        TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL SISENSE BE LIABLE FOR ANY LOST PROFITS OR BUSINESS OPPORTUNITIES, LOSS OF USE, BUSINESS INTERRUPTION, LOSS OF DATA, OR ANY OTHER INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR FROM YOUR USE OF THE TOOLS, UNDER ANY THEORY OF LIABILITY, WHETHER BASED IN CONTRACT, TORT, NEGLIGENCE, PRODUCT LIABILITY, OR OTHERWISE. TO THE EXTENT THE PRECEDING LIMITATION DOES NOT APPLY UNDER APPLICABLE LAW, SISENSE’S LIABILITY ARISING OUT OF THE TOOLS PROVIDED HEREUNDER SHALL NOT, IN ANY EVENT, EXCEED USD $100.00. THE FOREGOING LIMITATIONS SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, REGARDLESS OF WHETHER A PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND REGARDLESS OF WHETHER ANY REMEDY FAILS OF ITS ESSENTIAL PURPOSE.
        
        11. INDEMNIFICATION
        You agree to defend, indemnify and hold harmless Sisense, and any of its directors, officers, employees, affiliates, subsidiaries or agents, from and against any and all claims, losses, damages, liabilities and other expenses (including reasonable attorneys' fees), arising from or related to: (i) Your use of the Tools; (ii) any derivative works You create using the Tools; and (iii) Your breach of this EULA.
        
        12. EXPORT CONTROL
        The Tools are provided subject to the U.S. Export Administration Regulations and the regulations of other jurisdictions (e.g., the European Union). Diversion contrary to applicable law is prohibited. Without limiting the foregoing, You agree that (i) You are not acting on behalf of any person who is a citizen, national, or resident of, or who is controlled by the government of any country to which the United States or other applicable government body has prohibited export transactions; (ii) You are not acting on behalf of, any person or entity listed on a relevant list of persons to whom export is prohibited (e.g., the U.S. Treasury Department list of Specially Designated Nationals and Blocked Persons, the U.S. Commerce Department Denied Persons List or Entity List, etc.); and (iii) You will not use the Tools for any purpose prohibited by applicable law.
        
        13. GOVERNMENT USE
        If a Tool provided under the Master Subscription Agreement is software, then it is commercial computer software developed exclusively at private expense. Unless otherwise set forth in the Master Subscription Agreement, use, duplication, and disclosure by civilian agencies of the U.S. Government will not exceed those minimum rights set forth in FAR 52.227-19(c) or successor regulations. Use, duplication, and disclosure by U.S. Department of Defense agencies is subject solely to the license terms contained in this EULA, as stated in DFARS 227.7202 or successor regulations. U.S. Government rights will apply only to the specific agency and program for which the Product is obtained.
        
        14. GOVERNING LAW; ENTIRE AGREEMENT
        This EULA shall be governed by the laws of the State of New York and the United States of America without regard to conflict of laws principles. You may not assign any part of this EULA without the prior written consent of Sisense. Any attempted assignment without consent shall be void. This EULA represents the entire agreement between You and Sisense with respect to the Tools and supersedes all prior written or oral communications, understandings and agreements containing the subject matter contained herein. Any waiver of these terms must be in writing to be effective. If any provision of these terms is found to be invalid or unenforceable, the remaining terms will continue to be valid and enforceable to the fullest extent permitted by law. In the event of a conflict between this EULA and the Master Subscription Agreement, the terms of this EULA will prevail to the extent applicable to the license and use of the Tools.
        
Project-URL: Homepage, https://github.com/sisense/pysisense
Project-URL: Documentation, https://github.com/sisense/pysisense/tree/main/docs
Project-URL: Issues, https://github.com/sisense/pysisense/issues
Project-URL: Source, https://github.com/sisense/pysisense
Keywords: Sisense,API,SDK,analytics,BI
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.32.3
Requires-Dist: PyYAML>=6.0.2
Requires-Dist: pandas>=2.2.3
Requires-Dist: jsbeautifier>=1.15.4
Requires-Dist: pydantic>=2.13.4
Requires-Dist: typing-extensions>=4.9
Provides-Extra: dev
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: pytest>=8.4.2; extra == "dev"
Requires-Dist: python-semantic-release>=10.5.3; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Dynamic: license-file

# 📊 Sisense SDK (`pysisense`)

**pysisense** is a Python SDK designed for seamless and structured interaction with the **Sisense API**.  
It simplifies complex API operations and allows you to automate and manage **users**, **groups**, **dashboards**, **data models**, and more.

> ✅ Built for automation, debugging, and extensibility.

---

## ⚠️ Disclaimer — Community / Field Engineering Project

**`pysisense` is *not* an official Sisense product or SDK.** It is a community project built and maintained by members of the Sisense Field Engineering team on a **best-effort basis**.

Please note:

- **No SLA or official support** — this project is not covered by any Sisense Service Level Agreement or support contract. Do not open Sisense Support tickets for issues with this SDK; use the GitHub issue tracker instead.
- **Not part of Sisense's product processes** — the SDK does not go through Sisense's official product QA, security review, or release lifecycle.
- **No compatibility guarantees** — the REST APIs wrapped here may change between Sisense versions without notice, and SDK methods may break as a result.
- **Use at your own risk** — always validate behavior in a non-production environment before running anything against production, especially write operations (migrations, ownership changes, deletions).
- **Best-effort maintenance** — issues and pull requests are welcome and reviewed as time permits, with no guaranteed response times.

---

## 📦 Installation

You can install `pysisense` from [PyPI](https://pypi.org/project/pysisense/):

```bash
pip install pysisense
```

For local development, install in editable mode:

```bash
pip install -e .
```

### ⬆️ Upgrading from 1.x to 2.0

**2.0 contains breaking changes.** `pysisense` follows semantic versioning, so pinning
`pysisense>=1,<2` keeps you on 1.x until you choose to move.

📖 **[Full upgrade guide](./docs/upgrading.md)** — every change mapped old-to-new, with
a symptom → cause → fix table. Complete detail in the [changelog](./CHANGELOG.md).

The user row is **additive** — `ROLE_NAME` and `GROUPS` keep their 1.x names and meanings,
so role comparisons and group reads keep working. New fields (`ROLE_DISPLAY_NAME`,
`ROLE_RAW_NAME`, `GROUP_IDS`) sit alongside them. What needs action:

1. **`GROUPS` now includes `Everyone`**, which `get_users_all()` used to strip out. The key
   and its meaning are unchanged; only this value was added.
2. **Detect failures with `result.get("ok") is False`** — every failure dict now carries that
   marker, and methods that used to fail with `[]`, `None` or an `"Error: ..."` string now
   return the standard error dict. An empty list always means a genuinely empty result.
3. **`get_unused_columns_bulk` returns a dict**, not a list — read `result["results"]`.
4. **`get_connections` was removed** — use `get_connections_all`.

Check what you are running with `python -c "import pysisense; print(pysisense.__version__)"`.

### Alternative Package Names

If you search for `pysisense` and find a different package, or if you mistyped the package name, PyPI has redirect stub packages registered:

- **`sisense-py`** — redirects to `pysisense`
- **`pysisense-sdk`** — redirects to `pysisense`
- **`sisense-sdk`** — redirects to `pysisense`

These packages raise an error with a clear message if you try to import them, pointing you to the correct `pysisense` package. The canonical package name is always **`pysisense`**.

---

## 🚀 Quick Start

### 1️⃣ Create your YAML config files

Create one or more YAML files (use the templates in `examples/` as reference only):

- `config.yaml` – for single-environment operations
- `source.yaml` and `target.yaml` – for migration scenarios

Each file should follow this structure:

```yaml
domain: "your-domain.com"
is_ssl: true
token: "<your_api_token>"
```

For **non-SSL** connections (`is_ssl: false`), HTTP requests use port **30845** by default. You can override it with an optional `port` field (ignored when `is_ssl` is `true`):

```yaml
domain: "192.168.1.100"
is_ssl: false
port: 30845   # optional, omit to use the default 30845
token: "<your_api_token>"
```

See [`config.yaml.example`](./examples/config.yaml) for the template.

⚠️ **Do not commit your tokens. The provided YAMLs contain placeholder structure only.**

⚠️ **TLS certificate verification is enabled by default.** Only disable it (`verify_ssl: false`) for trusted internal networks with self-signed certificates; doing so exposes your API token to on-path interception.

If your Sisense server uses a self-signed or internal-CA certificate and you still want verification enabled, point `ssl_path` at the CA bundle file (or directory) instead of disabling verification:

```yaml
domain: "your-domain.com"
is_ssl: true
token: "<your_api_token>"
ssl_path: "/path/to/ca-bundle.pem"
```

`ssl_path` takes precedence over `verify_ssl` when both are set, unless `verify_ssl` is explicitly `false`, in that case verification stays fully disabled and `ssl_path` is ignored.

### 🔑 Tokens and Permissions

The SDK works with **any Sisense user's API token** — admin access is not a general requirement. Permissions are enforced by Sisense itself: every API call runs with the role and access rights of the user whose token you configure, so each method can only see and do what that user could see and do in the Sisense UI.

This means the same method can return different results depending on the token. For example, fetching dashboards with an admin token may return every dashboard on the instance, while the same call with a viewer's token returns only the dashboards shared with that user.

Some operations, however, are inherently administrative and will fail or behave inconsistently without full admin privileges — for these, use a dedicated Sisense admin user's token in your `config.yaml`:

- Folder and dashboard ownership changes
- Granting or modifying permissions across environments
- System-wide migrations (users, groups, data models, dashboards)
- Instance-wide listings and admin exports (e.g., methods using `adminAccess=true`)

---

### 2. Explore Example Guides

The [`examples/`](./examples) folder contains Markdown guides. Each guide explains common workflows and includes copy-pasteable code snippets you can adapt in your own project:

- [`access_management_example.md`](./examples/access_management_example.md)  
  Identity & Governance — manage users, groups, folder access, and governance tasks (e.g., unused assets).

- [`datamodel_example.md`](./examples/datamodel_example.md)  
  Data Modeling — work with datasets, tables, columns, and schema within Sisense data models.

- [`dashboard_example.md`](./examples/dashboard_example.md)  
  Dashboard Lifecycle — retrieve, update, reassign ownership, and manage shares of dashboards.

- [`folder_example.md`](./examples/folder_example.md)  
  Folder Management — create, list, update, and delete Sisense dashboard folders.

- [`migration_example.md`](./examples/migration_example.md)  
  Environment Migration — migrate users, dashboards, and data models across environments (e.g., dev → prod).

- [`wellcheck_example.md`](./examples/wellcheck_example.md)  
  Data Health & Complexity — run structural checks on dashboards and data models (widget counts, pivot fields, island tables, RLS datatypes, import queries, many-to-many relationships, and unused columns).

Note: These guides are not meant to be executed end-to-end. Copy the relevant snippets into your own Python files or notebooks, update configuration (YAML paths, IDs, etc.), and run them in your environment.

---

### 3️⃣ Logs

All logs are saved automatically to a local folder:

```
logs/pysisense.log
```

You don’t need to create this folder manually — it will be created at runtime in the **same directory where you run your scripts**.

Logs rotate automatically at midnight and keep **7 days of history**. The active file is always named `pysisense.log`; each day's log is renamed to `pysisense.log.YYYY-MM-DD` at rotation time, and once more than 7 dated backups exist, the oldest one is deleted. The active log file's name never changes and it is never overwritten mid-rotation — only rotated out at day's end.

---

## ✅ Features

- 👥 **User & Group Management** – Create, update, delete, and fetch users or groups
- 📊 **Dashboard Management** – Export, share, and migrate dashboards
- 📦 **Data Models** – Explore, describe, and update schemas and security
- 🔐 **Permissions** – Resolve and apply share rules (users & groups)
- 🔄 **Cross-Environment Migrations** – Move dashboards, models, and users
- ✅ **WellCheck** – Analyze dashboard and data model health (structure complexity, widget density, pivot fields, island tables, RLS datatypes, import queries, many-to-many relationships, and unused columns)
- 🧠 **Smart Logging & Data Helpers** – Auto log capture, CSV export, and DataFrame conversion
- ➕ **And many more** – Refer to the documentation for full details

---

## 🔧 Design Philosophy

- Pythonic SDK with class-based structure (`Dashboard`, `DataModel`, `AccessManagement`, `Migration`)
- Additional analysis module: `WellCheck` – Run dashboard and data model health checks (structure, complexity, and best-practice validations)
- Modular YAML-based authentication
- Built-in logging and exception handling
- Designed for end-to-end automation and real-world use

---

## 🤖 Stable Contracts for Programmatic Consumers

Tools that generate schemas by introspecting this package (agents, MCP servers, code generators) can rely on the following as **stable public API**:

### Facade registry

`pysisense.FACADES` is an explicit tuple of the tool-bearing facade classes (`AccessManagement`, `DataModel`, `Dashboard`, …). Iterate it to discover the SDK's operational surface — do **not** iterate `__all__`, which also contains TypedDict payload types and utility functions. `SisenseClient` is intentionally excluded (it is the shared HTTP/auth client, not an operation facade).

### Error-dict shape

Failure returns follow one shape across the SDK:

```python
{"ok": False, "error": "<human-readable message>", "status_code": <int>}   # status_code present only when an HTTP status exists
```

Detect failure by the explicit **`"ok": False` marker** (`payload.get("ok") is False`) — the forward-compatible check — or by the presence of the `"error"` key. Never match an exact key set. The failure dict may gain **additive** keys in minor releases (`status_code` arrived in 1.1.0; some methods add context keys), so a consumer checking `keys() == {"error"}` will silently misclassify failures as successes. Renaming or removing `"error"`/`"status_code"` is treated as a breaking change; adding keys is not.

Since 2.0, `"error"` is always a **clean sentence**: either the recognised Sisense reason (from the body's `detail`/`message`/`title`/`error` key) or an honest label like `"unrecognized error body"`. When the body could not be recognized, the redacted, 300-char-truncated dump travels separately in an additive **`"raw_body"`** key, so consumers with different trust boundaries can relay or drop it independently of the sentence.

Two adjacent guarantees:

- **Redaction is part of the contract, not a courtesy:** credential-shaped values are stripped by `redact_secrets()` *before* the message is built, so the `"error"` string is safe to relay verbatim across trust boundaries (e.g. privacy modes where the failure reason is the only data that reaches a model).
- **Resolver envelopes are their own stable shape:** `resolve_dashboard_reference` and `resolve_datamodel_reference` return `{"success", "status_code", "<entity>_id", "<entity>_title", "error"}` on both success and failure. Detect their outcome via `success`, not via error-key matching — they carry payload keys alongside `"error"`, and they will **not** be folded into the generic error dict.

Connection-level failures carry `"error"` without `"status_code"` (no HTTP status exists; the absence is itself signal).

**All live methods follow the contract.** The pre-2.0 failure-shape exceptions (`[]`, `"Error: ..."` strings, `None`, list-wrapped error dicts) were converged onto the error dict in 2.0 — an empty list from a read method now always means a genuinely empty result, never a swallowed failure. Two footnotes:

- **Deprecated aliases are fossils:** methods carrying `__deprecated__` (e.g. `get_user_with_role_and_group_names`, `users_per_group_all`, `get_unused_columns`) keep their old, frozen shapes — including old failure shapes — until removal. Skip them via the `__deprecated__` marker.
- **Write methods return dicts on success too:** `add_dashboard_script` / `add_widget_script` return `{"success": True, "message": ...}`; `add_dashboard_shares` returns `{"success": True, "message": ..., "new_shares": n, "updated_shares": n}`; `get_unused_columns_bulk` always returns `{"results": [...], "errors": [{"ref", "error"}]}` (with `"ok": False` + top-level `"error"` added when nothing could be processed).

### Payload contracts

Dict parameters are typed with TypedDicts from `pysisense/payloads.py` (also exported at package root). Required vs. optional fields introspect via `__required_keys__` / `__optional_keys__`; annotations resolve at runtime (`inspect.signature(..., eval_str=True)`). Deprecated method aliases are decorated with `@typing_extensions.deprecated(...)` (PEP 702), so `__deprecated__` is introspectable. Enum-valued string parameters use `typing.Literal`.

---

📚 Documentation

Comprehensive module-level documentation is available in the `docs/` folder:

-   [Index](docs/index.md) – Overview of the SDK structure and modules
-   [Sisense Client](docs/sisenseclient.md) – Base API wrapper for all HTTP operations
-   [Access Management](docs/access_management.md) – Manage users, groups, roles, and permissions
-   [Data Model](docs/datamodel.md) – Handle datasets, tables, schemas, security, and deployment
-   [Dashboard](docs/dashboard.md) – Retrieve, modify, and share Sisense dashboards
-   [Migration](docs/migration.md) – Migrate users, dashboards, and models between environments
-   [Utils](docs/utils.md) – Helper functions for export, formatting, and data operations
-   [WellCheck](docs/wellcheck.md) – Run health checks on dashboards and data models (structure, complexity, and best-practice validations)

You can also explore:

-   Inline method docstrings using `help()` in Python or directly within your IDE.

---

## 📄 License

This project is licensed under the Sisense End User License Agreement (EULA).
See the [LICENSE](./LICENSE) file for the full text.

© 2026 Sisense Ltd. “Sisense” and related marks are trademarks of Sisense Ltd.
