diff --git a/README.md b/README.md index 2192ecd..5928a1c 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,27 @@ # PyTabular [![PyPI version](https://badge.fury.io/py/python-tabular.svg)](https://badge.fury.io/py/python-tabular) +[![Downloads](https://pepy.tech/badge/python-tabular)](https://pepy.tech/project/python-tabular) [![readthedocs](https://github.com/Curts0/PyTabular/actions/workflows/readthedocs.yml/badge.svg)](https://github.com/Curts0/PyTabular/actions/workflows/readthedocs.yml) [![pages-build-deployment](https://github.com/Curts0/PyTabular/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/Curts0/PyTabular/actions/workflows/pages/pages-build-deployment) ### 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 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. +PyTabular (python-tabular in [pypi](https://pypi.org/project/python-tabular/)) 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. Please send bugs my way! Preferably in the issues section in Github. I want to harden this project so many can use it easily. I currently have local pytest for python 3.6 to 3.11 and run those tests through a local AAS and Gen2 model. ### Getting Started - +See the [Pypi project](https://pypi.org/project/python-tabular/) for available version. ```powershell -python3 -m pip install python_tabular +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) ``` -Query Model - +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')" @@ -37,8 +36,7 @@ Query Model model.Query(SINGLE_VALUE_QUERY_EX) #returns 1 ``` -See [Refresh Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh). - +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') @@ -73,7 +71,7 @@ Built In Dax Query Helpers. In-case you want to run some quick queries similar t model.Query_Every_Table() #Will return pd.DataFrame() ''' - NOTE, notice the default values for the query_function argument. + 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. @@ -81,14 +79,14 @@ Built In Dax Query Helpers. In-case you want to run some quick queries similar t ''' ``` -Backup & Revert a Table in Memory. USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. +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. ```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. Roadmap to make this more robust, and allow you to run all the command line interfaces that TE2 has to offer. +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. ```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/dist/python_tabular-0.1.0-py3-none-any.whl b/dist/python_tabular-0.1.0-py3-none-any.whl new file mode 100644 index 0000000..5eeff65 Binary files /dev/null and b/dist/python_tabular-0.1.0-py3-none-any.whl differ diff --git a/dist/python_tabular-0.1.0.tar.gz b/dist/python_tabular-0.1.0.tar.gz new file mode 100644 index 0000000..0fbfc04 Binary files /dev/null and b/dist/python_tabular-0.1.0.tar.gz differ diff --git a/docs/Tabular.md b/docs/Tabular.md index b051f9a..5fb0673 100644 --- a/docs/Tabular.md +++ b/docs/Tabular.md @@ -11,7 +11,7 @@ Tabular( --- -Tabular Class to perform operations: [Microsoft.AnalysisServices.Tabular](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular?view=analysisservices-dotnet) +Tabular Class to perform operations: [Microsoft.AnalysisServices.Tabular](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular?view=analysisservices-dotnet). You can use this class as your main way to interact with your model. **Args** @@ -19,12 +19,24 @@ Tabular Class to perform operations: [Microsoft.AnalysisServices.Tabular](https: * **CONNECTION_STR** (str) : Valid [Connection String](https://docs.microsoft.com/en-us/analysis-services/instances/connection-string-properties-analysis-services?view=asallproducts-allversions) for connecting to a Tabular Model. +**Attributes** + +* **Server** (Server) : See [Server MS Docs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.server?view=analysisservices-dotnet). +* **Catalog** (str) : Name of Database. See [Catalog MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.connectioninfo.catalog?view=analysisservices-dotnet#microsoft-analysisservices-connectioninfo-catalog). +* **Model** (Model) : See [Model MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.model?view=analysisservices-dotnet). +* **AdomdConnection** (AdomdConnection) : For querying. See [AdomdConnection MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.adomdclient.adomdconnection?view=analysisservices-dotnet). Connection made from parts of the originally provided connection string. +* **Tables** (List[Table]) : Easy access list of tables from model. See [Table MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.table?view=analysisservices-dotnet). +* **Columns** (List[Column]) : Easy access list of columns from model. See [Column MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.column?view=analysisservices-dotnet). +* **Partitions** (List[Partition]) : Easy access list of partitions from model. See [Partition MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.partition?view=analysisservices-dotnet). +* **Measures** (List[Measure]) : Easy access list of measures from model. See [Measure MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.table.measures?view=analysisservices-dotnet#microsoft-analysisservices-tabular-table-measures). + + **Methods:** ### .Reload_Model_Info -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L58) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L69) ```python .Reload_Model_Info() ``` @@ -39,7 +51,7 @@ Runs on __init__ iterates through details, can be called after any model changes ### .Disconnect -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L70) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L81) ```python .Disconnect() ``` @@ -54,7 +66,7 @@ Disconnects from Model ### .Refresh -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L78) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L89) ```python .Refresh( Object: Union[str, Table, Partition, Dict[str, Any]], @@ -89,7 +101,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\#L171) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L182) ```python .Update( UpdateOptions: UpdateOptions = UpdateOptions.ExpandFull @@ -111,14 +123,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\#L182) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L193) ```python .SaveChanges() ``` ### .Backup_Table -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L204) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L215) ```python .Backup_Table( table_str: str @@ -142,7 +154,7 @@ Refresh is performed from source during backup. ### .Revert_Table -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L271) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L282) ```python .Revert_Table( table_str: str @@ -170,7 +182,7 @@ Example scenario -> ### .Query -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L336) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L347) ```python .Query( Query_Str: str @@ -194,7 +206,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\#L377) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L388) ```python .Query_Every_Column( query_function: str = 'COUNTROWS(VALUES(_))' @@ -217,7 +229,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\#L399) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L410) ```python .Query_Every_Table( query_function: str = 'COUNTROWS(_)' @@ -240,7 +252,7 @@ It will replace the _ with the table to run. ### .Analyze_BPA -[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L419) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L430) ```python .Analyze_BPA( Tabular_Editor_Exe: str, Best_Practice_Analyzer: str @@ -265,7 +277,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\#L443) +[source](https://github.com/Curts0/PyTabular\blob\master\pytabular/pytabular.py\#L454) ```python .Create_Table( df: pd.DataFrame, table_name: str diff --git a/docs/index.md b/docs/index.md index fa477f2..5928a1c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,28 +1,27 @@ # PyTabular [![PyPI version](https://badge.fury.io/py/python-tabular.svg)](https://badge.fury.io/py/python-tabular) +[![Downloads](https://pepy.tech/badge/python-tabular)](https://pepy.tech/project/python-tabular) [![readthedocs](https://github.com/Curts0/PyTabular/actions/workflows/readthedocs.yml/badge.svg)](https://github.com/Curts0/PyTabular/actions/workflows/readthedocs.yml) [![pages-build-deployment](https://github.com/Curts0/PyTabular/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/Curts0/PyTabular/actions/workflows/pages/pages-build-deployment) ### 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 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. +PyTabular (python-tabular in [pypi](https://pypi.org/project/python-tabular/)) 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. Please send bugs my way! Preferably in the issues section in Github. I want to harden this project so many can use it easily. I currently have local pytest for python 3.6 to 3.11 and run those tests through a local AAS and Gen2 model. ### Getting Started - +See the [Pypi project](https://pypi.org/project/python-tabular/) for available version. ```powershell -python3 -m pip install python_tabular +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) ``` -Query Model - +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')" @@ -37,8 +36,7 @@ Query Model model.Query(SINGLE_VALUE_QUERY_EX) #returns 1 ``` -See [Refresh Tables and Partitions](https://curts0.github.io/PyTabular/Tabular/#refresh). - +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') @@ -73,7 +71,7 @@ Built In Dax Query Helpers. In-case you want to run some quick queries similar t model.Query_Every_Table() #Will return pd.DataFrame() ''' - NOTE, notice the default values for the query_function argument. + 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. @@ -81,16 +79,16 @@ Built In Dax Query Helpers. In-case you want to run some quick queries similar t ''' ``` -Backup & Revert a Table in Memory. USE WITH CAUTION, obviously not in PROD. I have been experimenting with this concept. +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. ```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. Roadmap to make this more robust, and allow you to run all the command line interfaces that TE2 has to offer. +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. ```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_Path,BPA.Location) #This will output a list of BPA violations... + model.Analyze_BPA(TE2.EXE,BPA.Location) #This will output a list of BPA violations... ``` \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index f084d43..12800d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "python_tabular" -version = "0.0.90" +version = "0.1.0" authors = [ { name="Curtis Stallings", email="curtisrstallings@gmail.com" }, ] @@ -20,6 +20,8 @@ readme = "README.md" requires-python = ">=3.6" classifiers = [ "Programming Language :: Python :: 3.10", + "Development Status :: 3 - Alpha", + "Operating System :: Microsoft", "License :: OSI Approved :: MIT License" ] diff --git a/pytabular/pytabular.py b/pytabular/pytabular.py index 62b603b..ee94072 100644 --- a/pytabular/pytabular.py +++ b/pytabular/pytabular.py @@ -24,14 +24,23 @@ class Tabular: - '''Tabular Class to perform operations: [Microsoft.AnalysisServices.Tabular](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular?view=analysisservices-dotnet) + '''Tabular Class to perform operations: [Microsoft.AnalysisServices.Tabular](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular?view=analysisservices-dotnet). You can use this class as your main way to interact with your model. Args: CONNECTION_STR (str): Valid [Connection String](https://docs.microsoft.com/en-us/analysis-services/instances/connection-string-properties-analysis-services?view=asallproducts-allversions) for connecting to a Tabular Model. + Attributes: + Server (Server): See [Server MS Docs](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.server?view=analysisservices-dotnet). + Catalog (str): Name of Database. See [Catalog MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.connectioninfo.catalog?view=analysisservices-dotnet#microsoft-analysisservices-connectioninfo-catalog). + Model (Model): See [Model MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.model?view=analysisservices-dotnet). + AdomdConnection (AdomdConnection): For querying. See [AdomdConnection MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.adomdclient.adomdconnection?view=analysisservices-dotnet). Connection made from parts of the originally provided connection string. + Tables (List[Table]): Easy access list of tables from model. See [Table MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.table?view=analysisservices-dotnet). + Columns (List[Column]): Easy access list of columns from model. See [Column MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.column?view=analysisservices-dotnet). + Partitions (List[Partition]): Easy access list of partitions from model. See [Partition MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.partition?view=analysisservices-dotnet). + Measures (List[Measure]): Easy access list of measures from model. See [Measure MS Docs](https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.tabular.table.measures?view=analysisservices-dotnet#microsoft-analysisservices-tabular-table-measures). ''' def __init__(self,CONNECTION_STR:str): logger.debug(f'Initializing Tabular Class') - self.Server = Server() #[Server](https://docs.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.server?view=analysisservices-dotnet) + self.Server = Server() self.Server.Connect(CONNECTION_STR) logger.info(f'Connected to Server - {self.Server.Name}') self.Catalog = self.Server.ConnectionInfo.Catalog @@ -39,14 +48,16 @@ def __init__(self,CONNECTION_STR:str): try: self.Database = [database for database in self.Server.Databases.GetEnumerator() if database.Name == self.Catalog][0] except: - logger.error(f'Unable to find Database... {self.Catalog}') + err_msg = f'Unable to find Database... {self.Catalog}' + logger.error(err_msg) + raise Exception(err_msg) logger.info(f'Connected to Database - {self.Database.Name}') self.CompatibilityLevel: int = self.Database.CompatibilityLevel self.CompatibilityMode: int = self.Database.CompatibilityMode.value__ self.Model = self.Database.Model logger.info(f'Connected to Model - {self.Model.Name}') - self.DaxConnection = AdomdConnection() - self.DaxConnection.ConnectionString = f"{self.Server.ConnectionString}Password='{self.Server.ConnectionInfo.Password}'" + self.AdomdConnection = AdomdConnection() + self.AdomdConnection.ConnectionString = f"{self.Server.ConnectionString}Password='{self.Server.ConnectionInfo.Password}'" self.Reload_Model_Info() logger.debug(f'Class Initialization Completed') logger.debug(f'Registering Disconnect on Termination...') @@ -353,13 +364,13 @@ def Query(self,Query_Str:str) -> Union[pd.DataFrame,str,int]: try: logger.debug(f'Attempting to Open Adomd Connection...') - self.DaxConnection.Open() + self.AdomdConnection.Open() logger.debug(f'Connected!') except: logger.debug(f'Connection skipped already connected...') pass logger.info(f'Querying Model...') - Query = AdomdCommand(Query_Str, self.DaxConnection).ExecuteReader() + Query = AdomdCommand(Query_Str, self.AdomdConnection).ExecuteReader() logger.debug(f'Determining Field Count...') Column_Headers = [(index,Query.GetName(index)) for index in range(0,Query.FieldCount)] Results = list() @@ -428,10 +439,10 @@ def Analyze_BPA(self,Tabular_Editor_Exe:str,Best_Practice_Analyzer:str) -> List[ Returns: List[str]: Assuming no failure, will return list of BPA violations. Else will return error from command line. ''' - #Working TE2 Script in Python os.system(f"start /wait {te2.EXE_Path} \"Provider=MSOLAP;{model.DaxConnection.ConnectionString}\" FINANCE -B \"{os.getcwd()}\\Model.bim\" -A {l.BPA_LOCAL_FILE_PATH} -V/?") + #Working TE2 Script in Python os.system(f"start /wait {te2.EXE_Path} \"Provider=MSOLAP;{model.AdomdConnection.ConnectionString}\" FINANCE -B \"{os.getcwd()}\\Model.bim\" -A {l.BPA_LOCAL_FILE_PATH} -V/?") #start /wait logger.debug(f'Beginning request to talk with TE2 & Find BPA...') - cmd = f"{Tabular_Editor_Exe} \"Provider=MSOLAP;{self.DaxConnection.ConnectionString}\" {self.Database.Name} -B \"{os.getcwd()}\\Model.bim\" -A {Best_Practice_Analyzer} -V/?" + cmd = f"{Tabular_Editor_Exe} \"Provider=MSOLAP;{self.AdomdConnection.ConnectionString}\" {self.Database.Name} -B \"{os.getcwd()}\\Model.bim\" -A {Best_Practice_Analyzer} -V/?" logger.debug(f'Command Generated') logger.debug(f'Submitting Command...') sp = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,universal_newlines=True) @@ -477,4 +488,4 @@ def Create_Table(self,df:pd.DataFrame, table_name:str) -> bool: self.Model.Tables.Add(new_table) self.Refresh([new_table]) self.SaveChanges() - return True + return True \ No newline at end of file