powerbi-ontology-extractor 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cli/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """CLI module for PowerBI Ontology Extractor."""
@@ -0,0 +1,286 @@
1
+ """
2
+ PowerBI Ontology CLI
3
+
4
+ Command-line interface for PowerBI Ontology Extractor.
5
+ """
6
+
7
+ import json
8
+ import logging
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ try:
13
+ import click
14
+ from rich.console import Console
15
+ from rich.progress import Progress, SpinnerColumn, TextColumn
16
+ from rich.table import Table
17
+ from rich import print as rprint
18
+ except ImportError:
19
+ print("Error: Required packages not installed. Run: pip install click rich")
20
+ sys.exit(1)
21
+
22
+ from powerbi_ontology import PowerBIExtractor, OntologyGenerator, SemanticAnalyzer
23
+ from powerbi_ontology.export import FabricIQExporter, OntoGuardExporter, JSONSchemaExporter, OWLExporter
24
+ from powerbi_ontology import SchemaMapper
25
+ from powerbi_ontology.utils.visualizer import OntologyVisualizer
26
+
27
+ # Setup logging
28
+ logging.basicConfig(
29
+ level=logging.INFO,
30
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
31
+ )
32
+
33
+ console = Console()
34
+
35
+
36
+ @click.group()
37
+ @click.option('--verbose', '-v', is_flag=True, help='Enable verbose logging')
38
+ def cli(verbose):
39
+ """PowerBI Ontology Extractor - Extract semantic intelligence from Power BI dashboards."""
40
+ if verbose:
41
+ logging.getLogger().setLevel(logging.DEBUG)
42
+
43
+
44
+ @cli.command()
45
+ @click.argument('pbix_file', type=click.Path(exists=True))
46
+ @click.option('--output', '-o', type=click.Path(), help='Output file path')
47
+ @click.option('--format', '-f', type=click.Choice(['json', 'fabric-iq', 'ontoguard']), default='json', help='Output format')
48
+ def extract(pbix_file, output, format):
49
+ """Extract ontology from Power BI .pbix file."""
50
+ console.print(f"[bold green]Extracting ontology from[/bold green] {pbix_file}")
51
+
52
+ with Progress(
53
+ SpinnerColumn(),
54
+ TextColumn("[progress.description]{task.description}"),
55
+ console=console
56
+ ) as progress:
57
+ task = progress.add_task("Extracting...", total=None)
58
+
59
+ try:
60
+ extractor = PowerBIExtractor(pbix_file)
61
+ semantic_model = extractor.extract()
62
+
63
+ progress.update(task, description="Generating ontology...")
64
+ generator = OntologyGenerator(semantic_model)
65
+ ontology = generator.generate()
66
+
67
+ # Determine output file
68
+ if not output:
69
+ output = Path(pbix_file).stem + "_ontology.json"
70
+
71
+ # Export based on format
72
+ if format == 'json':
73
+ ontology_dict = {
74
+ "name": ontology.name,
75
+ "version": ontology.version,
76
+ "source": ontology.source,
77
+ "entities": [
78
+ {
79
+ "name": e.name,
80
+ "description": e.description,
81
+ "properties": [
82
+ {
83
+ "name": p.name,
84
+ "type": p.data_type,
85
+ "required": p.required
86
+ }
87
+ for p in e.properties
88
+ ]
89
+ }
90
+ for e in ontology.entities
91
+ ],
92
+ "relationships": [
93
+ {
94
+ "from": r.from_entity,
95
+ "to": r.to_entity,
96
+ "type": r.relationship_type,
97
+ "cardinality": r.cardinality
98
+ }
99
+ for r in ontology.relationships
100
+ ],
101
+ "businessRules": [
102
+ {
103
+ "name": r.name,
104
+ "entity": r.entity,
105
+ "condition": r.condition,
106
+ "action": r.action
107
+ }
108
+ for r in ontology.business_rules
109
+ ]
110
+ }
111
+ with open(output, 'w') as f:
112
+ json.dump(ontology_dict, f, indent=2)
113
+ elif format == 'fabric-iq':
114
+ exporter = FabricIQExporter(ontology)
115
+ fabric_json = exporter.export()
116
+ with open(output, 'w') as f:
117
+ json.dump(fabric_json, f, indent=2)
118
+ elif format == 'ontoguard':
119
+ exporter = OntoGuardExporter(ontology)
120
+ ontoguard_json = exporter.export()
121
+ with open(output, 'w') as f:
122
+ json.dump(ontoguard_json, f, indent=2)
123
+
124
+ progress.update(task, completed=True)
125
+ console.print(f"[bold green]✓[/bold green] Ontology extracted to {output}")
126
+ console.print(f" Entities: {len(ontology.entities)}")
127
+ console.print(f" Relationships: {len(ontology.relationships)}")
128
+ console.print(f" Business Rules: {len(ontology.business_rules)}")
129
+
130
+ except Exception as e:
131
+ console.print(f"[bold red]Error:[/bold red] {e}")
132
+ logging.exception("Extraction failed")
133
+ sys.exit(1)
134
+
135
+
136
+ @cli.command()
137
+ @click.argument('pbix_files', nargs=-1, type=click.Path(exists=True))
138
+ @click.option('--report', '-r', type=click.Path(), help='Output report file (HTML)')
139
+ @click.option('--output-dir', '-d', type=click.Path(), help='Output directory for individual ontologies')
140
+ def analyze(pbix_files, report, output_dir):
141
+ """Analyze multiple Power BI files for conflicts and semantic debt."""
142
+ if not pbix_files:
143
+ console.print("[bold red]Error:[/bold red] No .pbix files provided")
144
+ sys.exit(1)
145
+
146
+ console.print(f"[bold green]Analyzing[/bold green] {len(pbix_files)} Power BI files...")
147
+
148
+ semantic_models = []
149
+
150
+ with Progress(console=console) as progress:
151
+ task = progress.add_task("Loading files...", total=len(pbix_files))
152
+
153
+ for pbix_file in pbix_files:
154
+ try:
155
+ extractor = PowerBIExtractor(pbix_file)
156
+ model = extractor.extract()
157
+ semantic_models.append(model)
158
+ progress.advance(task)
159
+ except Exception as e:
160
+ console.print(f"[bold yellow]Warning:[/bold yellow] Failed to extract {pbix_file}: {e}")
161
+
162
+ if not semantic_models:
163
+ console.print("[bold red]Error:[/bold red] No valid semantic models extracted")
164
+ sys.exit(1)
165
+
166
+ # Analyze
167
+ analyzer = SemanticAnalyzer(semantic_models)
168
+
169
+ console.print("\n[bold]Analysis Results:[/bold]")
170
+
171
+ # Conflicts
172
+ conflicts = analyzer.detect_conflicts()
173
+ console.print(f"\n[bold yellow]Conflicts:[/bold yellow] {len(conflicts)}")
174
+ for conflict in conflicts[:5]: # Show first 5
175
+ console.print(f" • {conflict.concept}: {conflict.dashboard1} vs {conflict.dashboard2}")
176
+ if len(conflicts) > 5:
177
+ console.print(f" ... and {len(conflicts) - 5} more")
178
+
179
+ # Semantic debt
180
+ debt_report = analyzer.calculate_semantic_debt()
181
+ console.print(f"\n[bold red]Semantic Debt:[/bold red] ${debt_report.total_cost:,.0f}")
182
+ console.print(f" {debt_report.message}")
183
+
184
+ # Generate report
185
+ if report:
186
+ analyzer.generate_consolidation_report(report)
187
+ console.print(f"\n[bold green]✓[/bold green] Report saved to {report}")
188
+
189
+
190
+ @cli.command()
191
+ @click.argument('ontology_file', type=click.Path(exists=True))
192
+ @click.option('--format', '-f', type=click.Choice(['fabric-iq', 'ontoguard', 'json-schema', 'owl']), required=True, help='Export format')
193
+ @click.option('--output', '-o', type=click.Path(), help='Output file path')
194
+ def export(ontology_file, format, output):
195
+ """Export ontology to different formats."""
196
+ console.print(f"[bold green]Exporting[/bold green] {ontology_file} to {format} format...")
197
+
198
+ # Load ontology (simplified - would need proper loading)
199
+ console.print("[bold yellow]Note:[/bold yellow] Full export requires loading ontology from file")
200
+ console.print("This is a simplified version. Use 'extract' command with --format option instead.")
201
+
202
+
203
+ @cli.command()
204
+ @click.argument('ontology_file', type=click.Path(exists=True))
205
+ @click.option('--schema', '-s', type=click.Path(), help='Current database schema JSON')
206
+ def validate(ontology_file, schema):
207
+ """Validate schema bindings and detect drift."""
208
+ console.print(f"[bold green]Validating[/bold green] {ontology_file}...")
209
+
210
+ if schema:
211
+ console.print(f" Comparing against schema: {schema}")
212
+ # Load and compare schemas
213
+ console.print("[bold yellow]Note:[/bold yellow] Full validation requires schema mapping setup")
214
+ else:
215
+ console.print("[bold yellow]Warning:[/bold yellow] No schema provided. Cannot detect drift.")
216
+
217
+
218
+ @cli.command()
219
+ @click.argument('ontology_file', type=click.Path(exists=True))
220
+ @click.option('--output', '-o', type=click.Path(), help='Output image file')
221
+ @click.option('--interactive', '-i', is_flag=True, help='Generate interactive HTML')
222
+ @click.option('--format', '-f', type=click.Choice(['png', 'svg', 'pdf']), default='png', help='Image format')
223
+ def visualize(ontology_file, output, interactive, format):
224
+ """Visualize ontology as entity-relationship diagram."""
225
+ console.print(f"[bold green]Visualizing[/bold green] {ontology_file}...")
226
+
227
+ console.print("[bold yellow]Note:[/bold yellow] Full visualization requires loading ontology from file")
228
+ console.print("This is a simplified version. Use 'extract' command first.")
229
+
230
+
231
+ @cli.command()
232
+ @click.option('--input-dir', '-i', type=click.Path(exists=True), required=True, help='Input directory with .pbix files')
233
+ @click.option('--output-dir', '-o', type=click.Path(), required=True, help='Output directory for ontologies')
234
+ def batch(input_dir, output_dir):
235
+ """Process multiple .pbix files in batch."""
236
+ input_path = Path(input_dir)
237
+ output_path = Path(output_dir)
238
+ output_path.mkdir(parents=True, exist_ok=True)
239
+
240
+ pbix_files = list(input_path.glob("*.pbix"))
241
+
242
+ if not pbix_files:
243
+ console.print(f"[bold red]Error:[/bold red] No .pbix files found in {input_dir}")
244
+ sys.exit(1)
245
+
246
+ console.print(f"[bold green]Processing[/bold green] {len(pbix_files)} files...")
247
+
248
+ with Progress(console=console) as progress:
249
+ task = progress.add_task("Processing...", total=len(pbix_files))
250
+
251
+ for pbix_file in pbix_files:
252
+ try:
253
+ extractor = PowerBIExtractor(str(pbix_file))
254
+ semantic_model = extractor.extract()
255
+
256
+ generator = OntologyGenerator(semantic_model)
257
+ ontology = generator.generate()
258
+
259
+ output_file = output_path / f"{pbix_file.stem}_ontology.json"
260
+ ontology_dict = {
261
+ "name": ontology.name,
262
+ "version": ontology.version,
263
+ "source": ontology.source,
264
+ "entities": len(ontology.entities),
265
+ "relationships": len(ontology.relationships),
266
+ "businessRules": len(ontology.business_rules)
267
+ }
268
+
269
+ with open(output_file, 'w') as f:
270
+ json.dump(ontology_dict, f, indent=2)
271
+
272
+ progress.advance(task)
273
+ except Exception as e:
274
+ console.print(f"[bold yellow]Warning:[/bold yellow] Failed to process {pbix_file}: {e}")
275
+ progress.advance(task)
276
+
277
+ console.print(f"[bold green]✓[/bold green] Batch processing complete. Output: {output_dir}")
278
+
279
+
280
+ def main():
281
+ """Main entry point."""
282
+ cli()
283
+
284
+
285
+ if __name__ == '__main__':
286
+ main()
@@ -0,0 +1,38 @@
1
+ """
2
+ PowerBI Ontology Extractor
3
+
4
+ Extract semantic intelligence from Power BI .pbix files and convert to formal ontologies.
5
+ """
6
+
7
+ __version__ = "0.1.0"
8
+ __author__ = "PowerBI Ontology Extractor Contributors"
9
+
10
+ from powerbi_ontology.extractor import PowerBIExtractor, SemanticModel
11
+ from powerbi_ontology.ontology_generator import OntologyGenerator, Ontology
12
+ from powerbi_ontology.analyzer import SemanticAnalyzer
13
+ from powerbi_ontology.contract_builder import ContractBuilder
14
+ from powerbi_ontology.schema_mapper import SchemaMapper
15
+ from powerbi_ontology.semantic_debt import SemanticDebtAnalyzer, SemanticDebtReport, analyze_ontologies
16
+ from powerbi_ontology.ontology_diff import OntologyDiff, DiffReport, diff_ontologies, merge_ontologies
17
+ from powerbi_ontology.review import OntologyReview, ReviewWorkflow, ReviewStatus, create_review
18
+
19
+ __all__ = [
20
+ "PowerBIExtractor",
21
+ "SemanticModel",
22
+ "OntologyGenerator",
23
+ "Ontology",
24
+ "SemanticAnalyzer",
25
+ "ContractBuilder",
26
+ "SchemaMapper",
27
+ "SemanticDebtAnalyzer",
28
+ "SemanticDebtReport",
29
+ "analyze_ontologies",
30
+ "OntologyDiff",
31
+ "DiffReport",
32
+ "diff_ontologies",
33
+ "merge_ontologies",
34
+ "OntologyReview",
35
+ "ReviewWorkflow",
36
+ "ReviewStatus",
37
+ "create_review",
38
+ ]