diff --git a/README.md b/README.md
index 99ae859..3fab71d 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
### What is it?
-PyTabular is a python package that allows for programmatic execution on your tabular models! This is possible thanks to [Pythonnet](https://pythonnet.github.io/) and Microsoft's [.Net APIs on Azure Analysis Services](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices?view=analysisservices-dotnet). The package should have the dll files included when you import it. See [Documentation Here](https://curts0.github.io/PyTabular/)
+PyTabular is a python package that allows for programmatic execution on your tabular models! This is possible thanks to [Pythonnet](https://pythonnet.github.io/) and Microsoft's [.Net APIs on Azure Analysis Services](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices?view=analysisservices-dotnet). The package should have the dll files included when you import it. See [Documentation Here](https://curts0.github.io/PyTabular/). PyTabular is still considered alpha while I'm working on building out the proper tests and testing environments, so I can ensure some kind of stability in features.
### Getting Started
@@ -25,21 +25,41 @@ DAX Query
```python
model.Query(DAX_QUERY)
+
+ #Example Dax Query
+ #EVALUATE
+ #TOPN(100,'Table1')
+
# Returns a Pandas DataFrame
```
-[Refresh Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh)
+See [Refresh Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh).
```python
- #Can be str(table name only), Table object, Partition object, or an iterable combination of the three.
+ #You have a few options when refreshing.
model.Refresh('Table Name')
- tables_to_refresh = ['Table Name 1', 'Table Name 2',
, ]
- #Queue up the tables and partitions that you want to refresh.
- model.Refresh(tables_to_refresh)
- #NOTE if you monitor the logs you will notice a Trace is executed on the refreshes.
+
+ #or...
+ model.Refresh(['Table1','Table2','Table3'])
+
+ #or...
+ model.Refresh()
+
+ #or...
+ model.Refresh()
+
+ #or...
+ model.Refresh({'Table Name':'Partition Name'})
+
+ #or any kind of weird combination like
+ model.Refresh([{:,'Table Name':['Partition1','Partition2']},'Table Name','Table Name2'])
+
+ #Add Tracing=True for simple Traces tracking the refresh.
+ model.Refresh(['Table1','Table2'], Tracing=True)
+
```
-Built In Dax Query Helpers
+Built In Dax Query Helpers. In-case you want to run some quick queries similar to what vertipaq analyzer will do when getting row counts.
```python
#Query Every Column
@@ -57,14 +77,14 @@ Built In Dax Query Helpers
'''
```
-Backup & Revert a Table in Memory
+Backup & Revert a Table in Memory. USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept.
```python
model.Backup_Table('TableName') #This will backup the table with surround items (columns,measures,relationships,roles,hierarchies,etc.) and will add a suffix of '_backup'
#Make any changes to your original table and then revert or delete backup as necessary
model.Revert_Table('TableName') #This will essentially replace your original with _backup
```
-Run BPA from TE2
+Run BPA from TE2. Roadmap to make this more robust, and allow you to run all the command line interfaces that TE2 has to offer.
```python
TE2 = pytabular.TE2() #Feel free to input your TE2 File path or this will download for you.
BPA = pytabular.BPA() #Fee free to input your own BPA file or this will download for you from: https://raw.githubusercontent.com/microsoft/Analysis-Services/master/BestPracticeRules/BPARules.json
diff --git a/pytabular/__init__.py b/pytabular/__init__.py
index a3a1f63..fc696ad 100644
--- a/pytabular/__init__.py
+++ b/pytabular/__init__.py
@@ -30,4 +30,5 @@
from . logic_utils import pd_dataframe_to_m_expression, pandas_datatype_to_tabular_datatype
from . tabular_tracing import Base_Trace, Refresh_Trace
from . tabular_editor import Tabular_Editor
-from . best_practice_analyzer import BPA
\ No newline at end of file
+from . best_practice_analyzer import BPA
+logging.debug(f'Import successful...')
\ No newline at end of file
diff --git a/pytabular/pytabular.py b/pytabular/pytabular.py
index e38def9..b2796e9 100644
--- a/pytabular/pytabular.py
+++ b/pytabular/pytabular.py
@@ -2,19 +2,17 @@
logger = logging.getLogger('PyTabular')
logger.debug(f'Importing Microsoft.AnalysisServices.Tabular')
-from Microsoft.AnalysisServices.Tabular import Server, Database, RefreshType, DataType, ConnectionDetails, ColumnType, MetadataPermission, Table, DataColumn, Partition, MPartitionSource, PartitionSourceType, Trace, TraceEvent, TraceEventHandler
+from Microsoft.AnalysisServices.Tabular import Server, RefreshType, ColumnType, Table, DataColumn, Partition, MPartitionSource
logger.debug(f'Importing Microsoft.AnalysisServices.AdomdClient')
from Microsoft.AnalysisServices.AdomdClient import (AdomdCommand, AdomdConnection)
logger.debug(f'Importing Microsoft.AnalysisServices')
-from Microsoft.AnalysisServices import UpdateOptions, TraceEventClass, TraceEventSubclass, TraceEventCollection, TraceColumn
+from Microsoft.AnalysisServices import UpdateOptions
logger.debug('Importing Other Packages...')
-from typing import Any, Dict, List, Optional, Union, Callable
+from typing import Any, Dict, List, Union
from collections.abc import Iterable
from collections import namedtuple
-import requests as r
import pandas as pd
-import json
import os
import subprocess
import atexit
@@ -89,7 +87,7 @@ def Refresh(self,
str == 'Table_Name'
Table == Table Object
Partition == Partition Object
- Dict[str, Any] == A way to specify a partition of group of partitions. For ex: {'Table_Name':'Partition1'} or {'Table_Name':['Partition1','Partition2']}. NOTE you can also change out the strings for partition or tables objects.
+ Dict[str, Any] == A way to specify a partition of group of partitions. For ex. {'Table_Name':'Partition1'} or {'Table_Name':['Partition1','Partition2']}. NOTE you can also change out the strings for partition or tables objects.
RefreshType (RefreshType, optional): See [RefreshType](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.refreshtype?view=analysisservices-dotnet). Defaults to RefreshType.Full.
Tracing (bool, optional): Currently just some basic tracing to track refreshes. Defaults to False.
@@ -197,10 +195,11 @@ def property_changes(Property_Changes):
Added_Subtree_Roots = Model_Save_Results.Impact.AddedSubtreeRoots
Removed_Objects = Model_Save_Results.Impact.RemovedObjects
Removed_Subtree_Roots = Model_Save_Results.Impact.RemovedSubtreeRoots
- Changes = namedtuple("Changes","Property_Changes Added_Objects Added_Subtree_Roots Removed_Objects Removed_Subtree_Roots")
- [property_changes(Property_Changes), Added_Objects, Added_Subtree_Roots, Removed_Objects, Removed_Subtree_Roots]
+ Xmla_Results = Model_Save_Results.XmlaResults
+ Changes = namedtuple("Changes","Property_Changes Added_Objects Added_Subtree_Roots Removed_Objects Removed_Subtree_Roots Xmla_Results")
+ [property_changes(Property_Changes), Added_Objects, Added_Subtree_Roots, Removed_Objects, Removed_Subtree_Roots, Xmla_Results]
self.Reload_Model_Info()
- return Changes(property_changes(Property_Changes), Added_Objects, Added_Subtree_Roots, Removed_Objects, Removed_Subtree_Roots)
+ return Changes(property_changes(Property_Changes), Added_Objects, Added_Subtree_Roots, Removed_Objects, Removed_Subtree_Roots, Xmla_Results)
def Backup_Table(self,table_str:str) -> bool:
'''USE WITH CAUTION, EXPERIMENTAL. Backs up table in memory, brings with it measures, columns, hierarchies, relationships, roles, etc.
It will add suffix '_backup' to all objects.
@@ -358,7 +357,7 @@ def Query(self,Query_Str:str) -> pd.DataFrame:
logger.debug(f'Converting Results into List...')
while Query.Read():
Results.append([Query.GetValue(index) for index in range(0,len(Column_Headers))])
- logger.info(f'Data retrieved and closing query...')
+ logger.debug(f'Data retrieved and closing query...')
Query.Close()
logger.debug(f'Converting to Pandas DataFrame...')
df = pd.DataFrame(Results,columns=[value for _,value in Column_Headers])