diff --git a/README.md b/README.md
index 5928a1c..8e8b4ea 100644
--- a/README.md
+++ b/README.md
@@ -17,78 +17,104 @@ python3 -m pip install python-tabular
In your python environment, import pytabular and call the main Tabular Class. Only parameter needed is a solid connection string.
```python
- import pytabular
- model = pytabular.Tabular(CONNECTION_STR)
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
```
You can query your models with the Query method from your tabular class. For Dax Queries, it will need the full Dax syntax. See [EVALUATE example](https://dax.guide/st/evaluate/). This will return a [Pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html). If you are looking to return a single value, see below. Simply wrap your query in the the curly brackets. The method will take that single cell table and just return the individual value. You can also query your DMV. See below for example. See [PyTabular Docs for Query](https://curts0.github.io/PyTabular/Tabular/#query).
```python
- #Run basic queries
- DAX_QUERY = "EVALUATE TOPN(100, 'Table1')"
- model.Query(DAX_QUERY) #returns pd.DataFrame()
+#Run basic queries
+DAX_QUERY = "EVALUATE TOPN(100, 'Table1')"
+model.Query(DAX_QUERY) #returns pd.DataFrame()
- #or...
- DMV_QUERY = "select * from $SYSTEM.DISCOVER_TRACE_EVENT_CATEGORIES"
- model.Query(DMV_QUERY) #returns pd.DataFrame()
+#or...
+DMV_QUERY = "select * from $SYSTEM.DISCOVER_TRACE_EVENT_CATEGORIES"
+model.Query(DMV_QUERY) #returns pd.DataFrame()
- #or...
- SINGLE_VALUE_QUERY_EX = "EVALUATE {1}"
- model.Query(SINGLE_VALUE_QUERY_EX) #returns 1
+#or...
+SINGLE_VALUE_QUERY_EX = "EVALUATE {1}"
+model.Query(SINGLE_VALUE_QUERY_EX) #returns 1
```
Refresh method to handle refreshes on your model. This is synchronous. Should be flexible enough to handle a variety of inputs. See [PyTabular Docs for Refreshing Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh). Most basic way to refresh is input the table name string. The method will search for table and output exeption if unable to find it. For partitions you will need a key, value combination. Example, {'Table1':'Partition1'}. You can also take the key value pair and iterate through a group of partitions. Example, {'Table1':['Partition1','Partition2']}. Rather than providing a string, you can also input the actual class. See below for those examples, and you can acess them from the built in attributes self.Tables, self.Partitions or explore through the .Net classes yourself in self.Model.Tables.
```python
- #You have a few options when refreshing.
- model.Refresh('Table Name')
+#You have a few options when refreshing.
+model.Refresh('Table Name')
- #or...
- model.Refresh(['Table1','Table2','Table3'])
+#or...
+model.Refresh(['Table1','Table2','Table3'])
- #or...
- model.Refresh(
)
+#or...
+model.Refresh()
- #or...
- model.Refresh()
+#or...
+model.Refresh()
- #or...
- model.Refresh({'Table Name':'Partition Name'})
+#or...
+model.Refresh({'Table Name':'Partition Name'})
- #or any kind of weird combination like
- model.Refresh([{:,'Table Name':['Partition1','Partition2']},'Table Name','Table Name2'])
+#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)
+#Add Tracing=True for simple Traces tracking the refresh.
+model.Refresh(['Table1','Table2'], Tracing=True)
+```
+
+### Use Cases
+##### If blank table, then refresh table.
+This will use the function [Return_Zero_Row_Tables](https://curts0.github.io/PyTabular/Examples/#return_zero_row_tables) and the method [Refresh](https://curts0.github.io/PyTabular/Tabular/#refresh) from the Tabular class.
+```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+tables = pytabular.Return_Zero_Row_Tables()
+if len(tables) > 0:
+ model.Refresh(tables, Tracing = True) #Add a trace in there for some fun.
```
-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.
+##### Sneak in a refresh.
+This will use the method [Is_Process](https://curts0.github.io/PyTabular/Tabular/#is_process) and the method [Refresh](https://curts0.github.io/PyTabular/Tabular/#refresh) from the Tabular class. It will check the DMV to see if any jobs are currently running classified as processing.
```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+if model.Is_Process():
+ #do what you want if there is a refresh happening
+else:
+ model.Refresh(TABLES_OR_PARTITIONS_TO_REFRESH)
+```
- #Query Every Column
- model.Query_Every_Column() #Will return pd.DataFrame()
-
- #Query Every Table
- model.Query_Every_Table() #Will return pd.DataFrame()
-
- '''
- NOTE the default values for the query_function argument.
- Query_Every_Column will get COUNTROWS(VALUES(_))
- and Query_Every_Table() will get COUNTROWS(_)
- with '_' being replaced with the dax identifier to the table or column in question.
- You can replace this str with anything you want. For example output the MIN(_) or MAX(_) of each column rather than the default queries.
- '''
+##### Show refresh times in model.
+This will use the function [Table_Last_Refresh_Times](https://curts0.github.io/PyTabular/Examples/#table_last_refresh_times) and the method [Create_Table](https://curts0.github.io/PyTabular/Tabular/#create_table) from the Tabular class. It will search through the model for all tables and partitions and pull the 'RefreshedTime' property from it. It will return results into a pandas dataframe, which will then be converted into an M expression used for a new table.
+```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+df = pytabular.Table_Last_Refresh_Times(model, group_partition = False)
+model.Create_Table(df, 'Refresh Times')
```
-Backup & Revert a Table in Memory. USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. Made for selfish reason. Will probably get removed and I'll keep in my own local version.
+
+##### If BPA Violation, then revert deployment.
+Uses a few things. First the [BPA Class](https://curts0.github.io/PyTabular/Best%20Practice%20Analyzer/#bpa), then the [TE2 Class](https://curts0.github.io/PyTabular/Tabular%20Editor%202/), and will finish with the [Analyze_BPA](https://curts0.github.io/PyTabular/Tabular/#analyze_bpa) method. Did not want to re-invent the wheel with the amazing work done with Tabular Editor and it's BPA capabilities.
```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
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+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
+results = model.Analyze_BPA(TE2.EXE,BPA.Location)
+
+if len(results) > 0:
+ #Revert deployment here!
```
-Run BPA from TE2. Did not want to re-invent the wheel with the amazing work done with Tabular Editor and it's BPA capabilities. Two classes exist in the model in very basic form write now. But you can call pytabular.TE2() to download or specify and existing TE2 exe. The same goes for pytabular.BPA(). Input your own location for a BPA json file or will download one. Roadmap to make this more flexible.
+##### Backup & Revert a Table.
+USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. Made for selfish reasons. Will probably get removed and I'll keep in my own local version. But fun to work with. Uses two methods. [Backup_Table](https://curts0.github.io/PyTabular/Tabular/#backup_table) and [Revert_Table](https://curts0.github.io/PyTabular/Tabular/#revert_table)
+
```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
- model.Analyze_BPA(TE2.EXE,BPA.Location) #This will output a list of BPA violations...
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+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
```
\ No newline at end of file
diff --git a/dist/python_tabular-0.1.1-py3-none-any.whl b/dist/python_tabular-0.1.1-py3-none-any.whl
new file mode 100644
index 0000000..05352fe
Binary files /dev/null and b/dist/python_tabular-0.1.1-py3-none-any.whl differ
diff --git a/dist/python_tabular-0.1.1.tar.gz b/dist/python_tabular-0.1.1.tar.gz
new file mode 100644
index 0000000..b451513
Binary files /dev/null and b/dist/python_tabular-0.1.1.tar.gz differ
diff --git a/docs/Tabular.md b/docs/Tabular.md
index 5fb0673..4ad0b93 100644
--- a/docs/Tabular.md
+++ b/docs/Tabular.md
@@ -50,9 +50,24 @@ Runs on __init__ iterates through details, can be called after any model changes
* **bool** : True if successful
-### .Disconnect
+### .Is_Process
[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L81)
```python
+.Is_Process()
+```
+
+---
+Run method to check if Processing is occurring. Will query DMV $SYSTEM.DISCOVER_JOBS to see if any processing is happening.
+
+
+**Returns**
+
+* **bool** : True if DMV shows Process, False if not.
+
+
+### .Disconnect
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L89)
+```python
.Disconnect()
```
@@ -66,7 +81,7 @@ Disconnects from Model
### .Refresh
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L89)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L97)
```python
.Refresh(
Object: Union[str, Table, Partition, Dict[str, Any]],
@@ -101,7 +116,7 @@ Dict[str, Any] == A way to specify a partition of group of partitions. For ex. {
### .Update
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L182)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L191)
```python
.Update(
UpdateOptions: UpdateOptions = UpdateOptions.ExpandFull
@@ -123,14 +138,14 @@ Dict[str, Any] == A way to specify a partition of group of partitions. For ex. {
### .SaveChanges
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L193)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L202)
```python
.SaveChanges()
```
### .Backup_Table
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L215)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L224)
```python
.Backup_Table(
table_str: str
@@ -154,7 +169,7 @@ Refresh is performed from source during backup.
### .Revert_Table
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L282)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L291)
```python
.Revert_Table(
table_str: str
@@ -182,7 +197,7 @@ Example scenario ->
### .Query
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L347)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L356)
```python
.Query(
Query_Str: str
@@ -206,7 +221,7 @@ It is also possible to query DMV. For example. Query("select * from $SYSTEM.DISC
### .Query_Every_Column
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L388)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L397)
```python
.Query_Every_Column(
query_function: str = 'COUNTROWS(VALUES(_))'
@@ -229,7 +244,7 @@ This will dynamically create a query to pull all columns from the model and run
### .Query_Every_Table
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L410)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L419)
```python
.Query_Every_Table(
query_function: str = 'COUNTROWS(_)'
@@ -252,7 +267,7 @@ It will replace the _ with the table to run.
### .Analyze_BPA
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L430)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L439)
```python
.Analyze_BPA(
Tabular_Editor_Exe: str, Best_Practice_Analyzer: str
@@ -277,7 +292,7 @@ Takes your Tabular Model and performs TE2s BPA. Runs through Command line.
### .Create_Table
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L454)
+[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L463)
```python
.Create_Table(
df: pd.DataFrame, table_name: str
diff --git a/docs/Traces.md b/docs/Traces.md
index 7458084..3f2dc81 100644
--- a/docs/Traces.md
+++ b/docs/Traces.md
@@ -128,21 +128,6 @@ Call when you want to drop the Trace
* **None** : Returns None. Unless unsuccessful then it will return the error from Server.
-### .Query_DMV_For_Event_Categories
-[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/tabular_tracing.py\#L111)
-```python
-.Query_DMV_For_Event_Categories()
-```
-
----
-Internal use. Called during the building process to locate allowed columns for event categories. This is done by executing a Tabular().Query() on the DISCOVER_EVENT_CATEGORIES table in the DMV. Then the function will parse the results, as it is xml inside of rows.
-
-
-**Returns**
-
-* **_type_** : _description_
-
-
----
diff --git a/docs/index.md b/docs/index.md
index 5928a1c..8e8b4ea 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -17,78 +17,104 @@ python3 -m pip install python-tabular
In your python environment, import pytabular and call the main Tabular Class. Only parameter needed is a solid connection string.
```python
- import pytabular
- model = pytabular.Tabular(CONNECTION_STR)
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
```
You can query your models with the Query method from your tabular class. For Dax Queries, it will need the full Dax syntax. See [EVALUATE example](https://dax.guide/st/evaluate/). This will return a [Pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html). If you are looking to return a single value, see below. Simply wrap your query in the the curly brackets. The method will take that single cell table and just return the individual value. You can also query your DMV. See below for example. See [PyTabular Docs for Query](https://curts0.github.io/PyTabular/Tabular/#query).
```python
- #Run basic queries
- DAX_QUERY = "EVALUATE TOPN(100, 'Table1')"
- model.Query(DAX_QUERY) #returns pd.DataFrame()
+#Run basic queries
+DAX_QUERY = "EVALUATE TOPN(100, 'Table1')"
+model.Query(DAX_QUERY) #returns pd.DataFrame()
- #or...
- DMV_QUERY = "select * from $SYSTEM.DISCOVER_TRACE_EVENT_CATEGORIES"
- model.Query(DMV_QUERY) #returns pd.DataFrame()
+#or...
+DMV_QUERY = "select * from $SYSTEM.DISCOVER_TRACE_EVENT_CATEGORIES"
+model.Query(DMV_QUERY) #returns pd.DataFrame()
- #or...
- SINGLE_VALUE_QUERY_EX = "EVALUATE {1}"
- model.Query(SINGLE_VALUE_QUERY_EX) #returns 1
+#or...
+SINGLE_VALUE_QUERY_EX = "EVALUATE {1}"
+model.Query(SINGLE_VALUE_QUERY_EX) #returns 1
```
Refresh method to handle refreshes on your model. This is synchronous. Should be flexible enough to handle a variety of inputs. See [PyTabular Docs for Refreshing Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh). Most basic way to refresh is input the table name string. The method will search for table and output exeption if unable to find it. For partitions you will need a key, value combination. Example, {'Table1':'Partition1'}. You can also take the key value pair and iterate through a group of partitions. Example, {'Table1':['Partition1','Partition2']}. Rather than providing a string, you can also input the actual class. See below for those examples, and you can acess them from the built in attributes self.Tables, self.Partitions or explore through the .Net classes yourself in self.Model.Tables.
```python
- #You have a few options when refreshing.
- model.Refresh('Table Name')
+#You have a few options when refreshing.
+model.Refresh('Table Name')
- #or...
- model.Refresh(['Table1','Table2','Table3'])
+#or...
+model.Refresh(['Table1','Table2','Table3'])
- #or...
- model.Refresh()
+#or...
+model.Refresh()
- #or...
- model.Refresh()
+#or...
+model.Refresh()
- #or...
- model.Refresh({'Table Name':'Partition Name'})
+#or...
+model.Refresh({'Table Name':'Partition Name'})
- #or any kind of weird combination like
- model.Refresh([{:,'Table Name':['Partition1','Partition2']},'Table Name','Table Name2'])
+#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)
+#Add Tracing=True for simple Traces tracking the refresh.
+model.Refresh(['Table1','Table2'], Tracing=True)
+```
+
+### Use Cases
+##### If blank table, then refresh table.
+This will use the function [Return_Zero_Row_Tables](https://curts0.github.io/PyTabular/Examples/#return_zero_row_tables) and the method [Refresh](https://curts0.github.io/PyTabular/Tabular/#refresh) from the Tabular class.
+```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+tables = pytabular.Return_Zero_Row_Tables()
+if len(tables) > 0:
+ model.Refresh(tables, Tracing = True) #Add a trace in there for some fun.
```
-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.
+##### Sneak in a refresh.
+This will use the method [Is_Process](https://curts0.github.io/PyTabular/Tabular/#is_process) and the method [Refresh](https://curts0.github.io/PyTabular/Tabular/#refresh) from the Tabular class. It will check the DMV to see if any jobs are currently running classified as processing.
```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+if model.Is_Process():
+ #do what you want if there is a refresh happening
+else:
+ model.Refresh(TABLES_OR_PARTITIONS_TO_REFRESH)
+```
- #Query Every Column
- model.Query_Every_Column() #Will return pd.DataFrame()
-
- #Query Every Table
- model.Query_Every_Table() #Will return pd.DataFrame()
-
- '''
- NOTE the default values for the query_function argument.
- Query_Every_Column will get COUNTROWS(VALUES(_))
- and Query_Every_Table() will get COUNTROWS(_)
- with '_' being replaced with the dax identifier to the table or column in question.
- You can replace this str with anything you want. For example output the MIN(_) or MAX(_) of each column rather than the default queries.
- '''
+##### Show refresh times in model.
+This will use the function [Table_Last_Refresh_Times](https://curts0.github.io/PyTabular/Examples/#table_last_refresh_times) and the method [Create_Table](https://curts0.github.io/PyTabular/Tabular/#create_table) from the Tabular class. It will search through the model for all tables and partitions and pull the 'RefreshedTime' property from it. It will return results into a pandas dataframe, which will then be converted into an M expression used for a new table.
+```python
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+df = pytabular.Table_Last_Refresh_Times(model, group_partition = False)
+model.Create_Table(df, 'Refresh Times')
```
-Backup & Revert a Table in Memory. USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. Made for selfish reason. Will probably get removed and I'll keep in my own local version.
+
+##### If BPA Violation, then revert deployment.
+Uses a few things. First the [BPA Class](https://curts0.github.io/PyTabular/Best%20Practice%20Analyzer/#bpa), then the [TE2 Class](https://curts0.github.io/PyTabular/Tabular%20Editor%202/), and will finish with the [Analyze_BPA](https://curts0.github.io/PyTabular/Tabular/#analyze_bpa) method. Did not want to re-invent the wheel with the amazing work done with Tabular Editor and it's BPA capabilities.
```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
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+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
+results = model.Analyze_BPA(TE2.EXE,BPA.Location)
+
+if len(results) > 0:
+ #Revert deployment here!
```
-Run BPA from TE2. Did not want to re-invent the wheel with the amazing work done with Tabular Editor and it's BPA capabilities. Two classes exist in the model in very basic form write now. But you can call pytabular.TE2() to download or specify and existing TE2 exe. The same goes for pytabular.BPA(). Input your own location for a BPA json file or will download one. Roadmap to make this more flexible.
+##### Backup & Revert a Table.
+USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. Made for selfish reasons. Will probably get removed and I'll keep in my own local version. But fun to work with. Uses two methods. [Backup_Table](https://curts0.github.io/PyTabular/Tabular/#backup_table) and [Revert_Table](https://curts0.github.io/PyTabular/Tabular/#revert_table)
+
```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
- model.Analyze_BPA(TE2.EXE,BPA.Location) #This will output a list of BPA violations...
+import pytabular
+model = pytabular.Tabular(CONNECTION_STR)
+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
```
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 12800d7..3e9b4e3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "python_tabular"
-version = "0.1.0"
+version = "0.1.1"
authors = [
{ name="Curtis Stallings", email="curtisrstallings@gmail.com" },
]
diff --git a/pytabular/pytabular.py b/pytabular/pytabular.py
index ee94072..a3bc971 100644
--- a/pytabular/pytabular.py
+++ b/pytabular/pytabular.py
@@ -78,6 +78,14 @@ def Reload_Model_Info(self) -> bool:
self.Measures = [measure for table in self.Tables for measure in table.Measures.GetEnumerator()]
self.Database.Refresh()
return True
+ def Is_Process(self) -> bool:
+ '''Run method to check if Processing is occurring. Will query DMV $SYSTEM.DISCOVER_JOBS to see if any processing is happening.
+
+ Returns:
+ bool: True if DMV shows Process, False if not.
+ '''
+ _jobs_df = self.Query("select * from $SYSTEM.DISCOVER_JOBS")
+ return True if len(_jobs_df[_jobs_df['JOB_DESCRIPTION']=='Process']) > 0 else False
def Disconnect(self) -> bool:
'''Disconnects from Model
@@ -112,12 +120,15 @@ def Refresh(self,
'''
logger.debug(f'Beginning RequestRefresh cadence...')
- def Refresh_Report(Property_Changes):
+ def _Refresh_Report(Property_Changes) -> pd.DataFrame:
logger.debug(f'Running Refresh Report...')
+ refresh_data = []
for property_change in Property_Changes:
if isinstance(property_change.Object,Partition) and property_change.Property_Name == 'RefreshedTime':
- logger.info(f'{property_change.Object.Table.Name} - {property_change.Object.Name} Refreshed! - {ticks_to_datetime(property_change.New_Value.Ticks).strftime("%m/%d/%Y, %H:%M:%S")}')
- return True
+ table, partition, refreshed_time = property_change.Object.Table.Name, property_change.Object.Name, ticks_to_datetime(property_change.New_Value.Ticks)
+ logger.info(f'{table} - {partition} Refreshed! - {refreshed_time.strftime("%m/%d/%Y, %H:%M:%S")}')
+ refresh_data += [[table, partition, refreshed_time]]
+ return pd.DataFrame(refresh_data, columns=['Table','Partition','Refreshed Time'])
def refresh_table(table:Table) -> None:
logging.info(f'Requesting refresh for {table.Name}')
@@ -176,9 +187,7 @@ def refresh(Object):
rt.Stop()
rt.Drop()
- Refresh_Report(m.Property_Changes)
-
- return m
+ return _Refresh_Report(m.Property_Changes)
def Update(self, UpdateOptions:UpdateOptions = UpdateOptions.ExpandFull) -> None:
'''[Update Model](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.majorobject.update?view=analysisservices-dotnet#microsoft-analysisservices-majorobject-update(microsoft-analysisservices-updateoptions))
diff --git a/pytabular/tabular_tracing.py b/pytabular/tabular_tracing.py
index e85493c..5a3e6ce 100644
--- a/pytabular/tabular_tracing.py
+++ b/pytabular/tabular_tracing.py
@@ -25,7 +25,7 @@ def __init__(self, Tabular_Class, Trace_Events:List[TraceEvent], Trace_Event_Col
self.Trace = Trace(self.Name, self.ID)
logger.debug(f'Trace {self.Trace.Name} created...')
self.Tabular_Class = Tabular_Class
- self.Event_Categories = self.Query_DMV_For_Event_Categories()
+ self.Event_Categories = self._Query_DMV_For_Event_Categories()
self.Trace_Events = Trace_Events
self.Trace_Event_Columns = Trace_Event_Columns
@@ -108,7 +108,7 @@ def Drop(self) -> None:
logger.info(f'Dropping {self.Name} in {self.Tabular_Class.Server.Name}')
return self.Trace.Drop()
- def Query_DMV_For_Event_Categories(self):
+ def _Query_DMV_For_Event_Categories(self):
'''Internal use. Called during the building process to locate allowed columns for event categories. This is done by executing a Tabular().Query() on the DISCOVER_EVENT_CATEGORIES table in the DMV. Then the function will parse the results, as it is xml inside of rows.
Returns: