dxp-analyzer-doc
Analyze TIBCO Spotfire .dxp dashboards and assess their migration to
Power BI (with Databricks as the data back-end).
A .dxp file is a ZIP archive of XML documents. dxp-analyzer-doc walks that
structure and produces:
- a structured inventory (pages, visuals, IronPython/JavaScript scripts,
data functions, document properties, calculated columns, custom queries,
source tables, connections) exported as
.xlsx(or.csv); - a migration assessment: every Spotfire capability mapped to its Power BI / Databricks equivalent and classified as native, workaround or not native;
- a normalized complexity index (0–100) and a migration effort estimate (person-days, min / likely / max);
- a migration document in Markdown with a pros/cons synthesis per dashboard.
Output language is selectable: English (default) or Italian (--lang it).
Italiano: libreria per analizzare dashboard Spotfire
.dxpe valutarne la migrazione a Power BI. Output in inglese (default) o italiano (--lang it).
Install
pip install -e . # no dependencies; tables are written as .csv
The migration document is always Markdown (.md). Tables default to .csv
(;-separated, UTF-8-BOM so Excel opens them directly). If you prefer .xlsx
output instead, add the optional extra:
pip install -e ".[xlsx]" # pulls in openpyxl for .xlsx tables
Command line
# Inventory tables + extracted code files
dxp-analyzer-doc analyze dashboard.dxp -o out --lang en
# Migration document (Markdown) for one or many dashboards
dxp-analyzer-doc document a.dxp b.dxp -o migration.md --lang it
# Both, for every .dxp in a folder
dxp-analyzer-doc all ./dashboards -o out
files accepts .dxp files, glob patterns, or directories (all *.dxp inside).
Add --extract-archive to also unpack the raw .dxp contents.
Output location. By default the output is written next to the input
.dxp files, not in the current working directory: analyze/all create
<input folder>/dxp-output/, and document writes
<input folder>/migration_documentation.md. A relative -o also resolves under
the input folder; pass an absolute -o to write anywhere.
Python API
from dxp_analyzer_doc import analyze, assess, build_report
# 1. Structured inventory
result = analyze("dashboard.dxp")
print(len(result.pages), result.total_visuals, len(result.scripts))
# 2. Migration assessment (complexity + effort + capability mapping)
a = assess("dashboard.dxp")
print(a.score.index, a.score.level) # e.g. 42.5 "medium"
print(a.effort.min_days, a.effort.likely_days, a.effort.max_days)
# 3. Markdown migration document (one or many assessments)
md = build_report([a], lang="it")
Export helpers:
from dxp_analyzer_doc.export import export_result, write_summary
export_result(result, "out/dashboard", lang="en")
write_summary([result], "out", lang="en")
The complexity & effort model
The complexity index does not sum raw counts. It groups the incidence variables
into five normalized dimensions, each mapped to 0..1 with a saturating
function so no single factor can dominate, then combines them with configurable
weights into a 0–100 index:
| Dimension | What it captures | Weight |
|---|---|---|
| Breadth / size | pages, total visuals, text areas | 0.15 |
| Data model | source tables, custom queries, calculated columns, data functions | 0.20 |
| Custom code | IronPython/JavaScript scripts and their lines | 0.25 |
| Interactivity | text-area controls, user properties, workaround visuals | 0.15 |
| Migration gap | non-native features/visuals, workarounds, reworked columns | 0.25 |
Levels: Low ≤ 25, Medium ≤ 50, High ≤ 75, Very high > 75.
Effort estimate (two interchangeable models)
The effort is returned in person-days with a min/likely/max band. Two models are
available, selectable via effort_model (or the CLI --effort-model):
-
itemized(default) — bottom-up sum of per-feature costs; produces a full breakdown table. Configured byEffortConfig. -
parametric— top-down formula with diminishing returns, configured byParametricEffortConfig:effort = base + score_coeff · index + Σ coeff_i · ln(1 + n_i)where
n_iare drivers such as scripts, queries, data functions and non-native features.ln(natural log) means the 10th script costs less than the 1st. Defaults:base=0.5,score_coeff=0.05, and coefficientsscripts=0.5, queries=0.7, data_functions=0.9, non_native_features=1.2.
Every coefficient (both models) is overridable:
from dxp_analyzer_doc import ComplexityModel, ParametricEffortConfig, EffortConfig, assess
# tune the itemized model
model = ComplexityModel(effort=EffortConfig(per_data_function=5.0))
# or switch to the parametric formula
model = ComplexityModel(
effort_model="parametric",
parametric_effort=ParametricEffortConfig(score_coeff=0.06, log_coeffs={"scripts": 0.5, "queries": 0.7, "data_functions": 1.0}),
)
a = assess("dashboard.dxp", model=model)
From the CLI, compare the two on real dashboards:
dxp-analyzer-doc document ./dashboards --effort-model parametric
Migration rules
The Spotfire→Power BI mapping lives in dxp_analyzer_doc/migration/rules.py
(bilingual). Each rule is a regex over scripts/expressions/properties plus its
Power BI and Databricks guidance. Add or tune rules there.
Project layout
src/dxp_analyzer_doc/
analyzer.py # DxpAnalyzer: the .dxp parsing engine
model.py # AnalysisResult and its dataclasses
export.py # xlsx/csv tables + extracted files
i18n.py # en/it string catalog
migration/
rules.py # bilingual Spotfire -> Power BI rules
complexity.py # normalized index + effort model
assessment.py # DashboardAssessment
report.py # Markdown migration document
cli.py # dxp-analyzer-doc command
legacy/ # original standalone scripts (reference only)
tests/ # pytest suite + synthetic .dxp
Development
pip install -e ".[dev]"
pytest -q
The test suite builds a synthetic .dxp (see tests/_sample.py) and exercises
the full pipeline in both languages.
License
MIT — see LICENSE.
Metadata
Release files for dxp-analyzer-doc 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dxp_analyzer_doc-0.1.0.tar.gz | 52.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dxp_analyzer_doc-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.9 kB
Release files / dxp_analyzer_doc-0.1.0.tar.gz
| Download URL | dxp_analyzer_doc-0.1.0.tar.gz |
|---|---|
| Size | 52.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f0ee8d137d5e3eafa1c72cbf81307aa80d8e1ad65a3af8aaa37fc219c5e9d49
|
|
BLAKE2b-256 checksum How to use checksums |
cf11c311b5973ec7f5aceb3944856ea51341a4d0077c984747928d354751aa62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / dxp_analyzer_doc-0.1.0-py3-none-any.whl
| Download URL | dxp_analyzer_doc-0.1.0-py3-none-any.whl |
|---|---|
| Size | 51.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ab1169c0d16b4ada7454956c5ea5428430822664ad2936c8e03daafdab48cd17
|
|
BLAKE2b-256 checksum How to use checksums |
90b77812bce2faf05a904d9c2c0b76cc4d5bb4c398fee2c38b809b21649b7233
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Security for dxp-analyzer-doc 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.