pymsasdax


Namepymsasdax JSON
Version 2023.1020 PyPI version JSON
download
home_page
SummaryRun DAX queries against Analysis Services and get Pandas Dataframes
upload_time2023-06-19 16:26:00
maintainer
docs_urlNone
author
requires_python>=3.9
licenseMIT License Copyright (c) 2023 grenzi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords dax msas analysis services ssas powerbi power bi xmla
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # About

I wanted to consume some info from Azure Analysis Services from python and didn't see a convenient way to to do, so I wrote this. It should also work just fine with XMLA endpoints on Power BI Premium. 

pymsasdax is a small Python Module for running DAX queries against Microsoft Analysis Services, using COM Interop. It does some basic typesniffing and returns a best guess Pandas Dataframe. 

This does assume that the MSOLAP client is installed - you can get it from [here](https://learn.microsoft.com/en-us/analysis-services/client-libraries?view=asallproducts-allversions)

I've done very little testing, so consider this alpha code. If you run into timeouts, make sure you're setting the timeout to an appropriate duration when creating the Connection. 

tidy_column_names will remove brackets and replace spaces with underscores in the returned dataframe's columns. Set it to False in the Connection init if you don't want this behavior.

Also, this is my first module up on pypi and I'm not exactly an expert on python, so feel free to submit an issue or a pull request. If I ended up reinventing the wheel here (ha!) and there was an easier way to do this, also please let me know.

I hope you find this useful!

## Python before 3.9

This should actually work fine with for python 3 under 3.9. I've used this code for a couple of years now without incident -- I was just lazy when building this package. I **think** you'd need backports to support [dateparser](https://pypi.org/project/dateparser/). Feel free to path and submit a PR if you like. 

# Usage examples

## Have an interactive prompt for Login to the resource

```python
from pymsasdax import dax

with dax.Connection(
        data_source='asazure://<region name>.asazure.windows.net/<instance here>,
        initial_catalog='<my tabular database>'
    ) as conn:
    df = conn.query('EVALUATE ROW("a", 1)')
    print(df)
```

## Query a Power BI Premium Workspace XMLA endpoint

You can also find the endpoint in your workspace settings, as shown below. You'll use the dataset name as the initial_catalog.

<img src="./doc/images/xmla_endpoint.jpg" alt="Screen capture of powerbi workspace settings" style="width:70%;">


```python
from pymsasdax import dax

with dax.Connection(
        data_source='powerbi://api.powerbi.com/v1.0/myorg/<workspace name, spaces are fine>',
        initial_catalog='<dataset name - spaces are fine>'
    ) as conn:
    df = conn.query('EVALUATE ROW("a", 1)')
    print(df)
```

## Use an app id

```python
from pymsasdax import dax

with dax.Connection(
        data_source='asazure://<region name>.asazure.windows.net/<instance here>',
        initial_catalog='<my tabular database>'
        uid='app:<client id>@<tenant id>',
        password='<client secret>'
    ) as conn:
    df = conn.query('EVALUATE ROW("a", 1)')
    df.to_csv("raw_data.csv", index=False)        
```

## Rename columns your way
```python
from pymsasdax import dax

def my_column_renamer(colname):
    return colname.lower()

with dax.Connection(
        data_source='asazure://<region name>.asazure.windows.net/<instance here>',
        initial_catalog='<my tabular database>',
        tidy_map_function = my_column_renamer
    ) as conn:
    df = conn.query('EVALUATE SUMMARIZECOLUMNS (etc....etc...etc...)')
    print(df)
```

# Dev Notes

## Version History

* 2023.1020
  * fix timeout not being honored as CommandTimeout
* 2023.1018
  * fix bug using effective_user_name or kwargs
* ~~2023.1017~~
  * ~~fix bug using effective_user_name~~
* 2023.1016
  * Add at least some docstrings
  * Add Premium XMLA endpoint example
  * Add effective_user_name parameter to connection
  * Pass **kwargs as additional connection string key value pairs
* 2023.1013
  * Fix issue with column names populating from when i made initial package version
  * Allow specificiation of column name cleanup function
* 2023.1001 - Initial

## Tests

Yes. There aren't any. Feel free to submit a PR. 

## Building

This might not be right but if you ever go to update pypi - 
```
bumpver update --dry --set-version="2023.1020"
pip-compile pyproject.toml
python -m pip install -e . 
#test
python -m build
twine check dist/*
twine upload dist/*
```


            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "pymsasdax",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "",
    "keywords": "dax,MSAS,Analysis Services,SSAS,PowerBI,Power BI,XMLA",
    "author": "",
    "author_email": "Gage Renzi <gagerenzi+pypy@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/03/9f/c1cd5bacec0cb7bfcc7543344006a068aa944233d71546988a40d535c829/pymsasdax-2023.1020.tar.gz",
    "platform": null,
    "description": "# About\r\n\r\nI wanted to consume some info from Azure Analysis Services from python and didn't see a convenient way to to do, so I wrote this. It should also work just fine with XMLA endpoints on Power BI Premium. \r\n\r\npymsasdax is a small Python Module for running DAX queries against Microsoft Analysis Services, using COM Interop. It does some basic typesniffing and returns a best guess Pandas Dataframe. \r\n\r\nThis does assume that the MSOLAP client is installed - you can get it from [here](https://learn.microsoft.com/en-us/analysis-services/client-libraries?view=asallproducts-allversions)\r\n\r\nI've done very little testing, so consider this alpha code. If you run into timeouts, make sure you're setting the timeout to an appropriate duration when creating the Connection. \r\n\r\ntidy_column_names will remove brackets and replace spaces with underscores in the returned dataframe's columns. Set it to False in the Connection init if you don't want this behavior.\r\n\r\nAlso, this is my first module up on pypi and I'm not exactly an expert on python, so feel free to submit an issue or a pull request. If I ended up reinventing the wheel here (ha!) and there was an easier way to do this, also please let me know.\r\n\r\nI hope you find this useful!\r\n\r\n## Python before 3.9\r\n\r\nThis should actually work fine with for python 3 under 3.9. I've used this code for a couple of years now without incident -- I was just lazy when building this package. I **think** you'd need backports to support [dateparser](https://pypi.org/project/dateparser/). Feel free to path and submit a PR if you like. \r\n\r\n# Usage examples\r\n\r\n## Have an interactive prompt for Login to the resource\r\n\r\n```python\r\nfrom pymsasdax import dax\r\n\r\nwith dax.Connection(\r\n        data_source='asazure://<region name>.asazure.windows.net/<instance here>,\r\n        initial_catalog='<my tabular database>'\r\n    ) as conn:\r\n    df = conn.query('EVALUATE ROW(\"a\", 1)')\r\n    print(df)\r\n```\r\n\r\n## Query a Power BI Premium Workspace XMLA endpoint\r\n\r\nYou can also find the endpoint in your workspace settings, as shown below. You'll use the dataset name as the initial_catalog.\r\n\r\n<img src=\"./doc/images/xmla_endpoint.jpg\" alt=\"Screen capture of powerbi workspace settings\" style=\"width:70%;\">\r\n\r\n\r\n```python\r\nfrom pymsasdax import dax\r\n\r\nwith dax.Connection(\r\n        data_source='powerbi://api.powerbi.com/v1.0/myorg/<workspace name, spaces are fine>',\r\n        initial_catalog='<dataset name - spaces are fine>'\r\n    ) as conn:\r\n    df = conn.query('EVALUATE ROW(\"a\", 1)')\r\n    print(df)\r\n```\r\n\r\n## Use an app id\r\n\r\n```python\r\nfrom pymsasdax import dax\r\n\r\nwith dax.Connection(\r\n        data_source='asazure://<region name>.asazure.windows.net/<instance here>',\r\n        initial_catalog='<my tabular database>'\r\n        uid='app:<client id>@<tenant id>',\r\n        password='<client secret>'\r\n    ) as conn:\r\n    df = conn.query('EVALUATE ROW(\"a\", 1)')\r\n    df.to_csv(\"raw_data.csv\", index=False)        \r\n```\r\n\r\n## Rename columns your way\r\n```python\r\nfrom pymsasdax import dax\r\n\r\ndef my_column_renamer(colname):\r\n    return colname.lower()\r\n\r\nwith dax.Connection(\r\n        data_source='asazure://<region name>.asazure.windows.net/<instance here>',\r\n        initial_catalog='<my tabular database>',\r\n        tidy_map_function = my_column_renamer\r\n    ) as conn:\r\n    df = conn.query('EVALUATE SUMMARIZECOLUMNS (etc....etc...etc...)')\r\n    print(df)\r\n```\r\n\r\n# Dev Notes\r\n\r\n## Version History\r\n\r\n* 2023.1020\r\n  * fix timeout not being honored as CommandTimeout\r\n* 2023.1018\r\n  * fix bug using effective_user_name or kwargs\r\n* ~~2023.1017~~\r\n  * ~~fix bug using effective_user_name~~\r\n* 2023.1016\r\n  * Add at least some docstrings\r\n  * Add Premium XMLA endpoint example\r\n  * Add effective_user_name parameter to connection\r\n  * Pass **kwargs as additional connection string key value pairs\r\n* 2023.1013\r\n  * Fix issue with column names populating from when i made initial package version\r\n  * Allow specificiation of column name cleanup function\r\n* 2023.1001 - Initial\r\n\r\n## Tests\r\n\r\nYes. There aren't any. Feel free to submit a PR. \r\n\r\n## Building\r\n\r\nThis might not be right but if you ever go to update pypi - \r\n```\r\nbumpver update --dry --set-version=\"2023.1020\"\r\npip-compile pyproject.toml\r\npython -m pip install -e . \r\n#test\r\npython -m build\r\ntwine check dist/*\r\ntwine upload dist/*\r\n```\r\n\r\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2023 grenzi  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
    "summary": "Run DAX queries against Analysis Services and get Pandas Dataframes",
    "version": "2023.1020",
    "project_urls": {
        "Homepage": "https://github.com/grenzi/pymsasdax"
    },
    "split_keywords": [
        "dax",
        "msas",
        "analysis services",
        "ssas",
        "powerbi",
        "power bi",
        "xmla"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0870085afe6702a8f0820cd7e74d7effd37d93a18839e6e9f107b24bbeea0a2b",
                "md5": "a82c6979f4f1bb5d60d77a01de8ffc68",
                "sha256": "f87229642392c0d0de015bf2c340f3c71ed783f8bb705d2588b5494fcca12b97"
            },
            "downloads": -1,
            "filename": "pymsasdax-2023.1020-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a82c6979f4f1bb5d60d77a01de8ffc68",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 7185,
            "upload_time": "2023-06-19T16:25:58",
            "upload_time_iso_8601": "2023-06-19T16:25:58.497073Z",
            "url": "https://files.pythonhosted.org/packages/08/70/085afe6702a8f0820cd7e74d7effd37d93a18839e6e9f107b24bbeea0a2b/pymsasdax-2023.1020-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "039fc1cd5bacec0cb7bfcc7543344006a068aa944233d71546988a40d535c829",
                "md5": "779b303451ff90570b8e1cd9dd866694",
                "sha256": "7adafd5935e1b8c3e7cc836ccc2f43991c1050b888cdae98dfd39762b8bcbc7e"
            },
            "downloads": -1,
            "filename": "pymsasdax-2023.1020.tar.gz",
            "has_sig": false,
            "md5_digest": "779b303451ff90570b8e1cd9dd866694",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 7325,
            "upload_time": "2023-06-19T16:26:00",
            "upload_time_iso_8601": "2023-06-19T16:26:00.238729Z",
            "url": "https://files.pythonhosted.org/packages/03/9f/c1cd5bacec0cb7bfcc7543344006a068aa944233d71546988a40d535c829/pymsasdax-2023.1020.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-19 16:26:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "grenzi",
    "github_project": "pymsasdax",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "pymsasdax"
}
        
Elapsed time: 0.07730s