8000 Release 0.6 by graysonarts · Pull Request #126 · tableau/document-api-python · GitHub
[go: up one dir, main page]

Skip to content

Release 0.6 #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,11 @@ target/
.DS_Store
.idea

#Editor things
*.sublime-project
*.sublime-workspace
settings.json
tasks.json

#Jekyll
docs/_site
7 changes: 4 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ python:
- "3.3"
- "3.4"
- "3.5"
- "3.6"
- "pypy"
# command to install dependencies
install:
- "pip install -e ."
- "pip install pep8"
- "pip install pycodestyle"
# command to run tests
script:
# Tests
- python setup.py test
# pep8
- pep8 .
# pycodestyle
- pycodestyle tableaudocumentapi test samples
# Examples
- (cd "samples/replicate-workbook" && python replicate_workbook.py)
- (cd "samples/list-tds-info" && python list_tds_info.py)
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 06 (11 January 2017)

* Initial SQL and query banding support (#123)
* Fixed bug in xfiles to allow opening workbooks with external file caches (#117, #118)
* Code Cleanup (#120, #121)
* Added Py36 support (#124)
* Switched to pycodestyle from pip8 on travis runs (#124)

## 05 (01 November 2016)

* Added ability to set the port for connections (#97)
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The following people have contributed to this project to make it possible, and w

* [Charley Peng](https://github.com/chid)
* [Miguel Sánchez](https://github.com/MiguelSR)
* [Ryan Richmond](https://github.com/r-richmond)

## Core Team

Expand Down
24 changes: 24 additions & 0 deletions docs/docs/api-ref.md
8000
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,30 @@ class Datasource(dsxml, filename=None)
class Connection(connxml)
```

The Connection class represents a tableau data connection. It can be from any type of connection found in `dbclass.py` via `is_valid_dbclass`

**Params:**

**Raises:**

**Methods:**

**Properities:**

`self.server:` Returns a string containing the server.

`self.dbname:` Returns a string containing the database name.

`self.username:` Returns a string containing the username.

`self.dbclass:` Returns a string containing the database class.

`self.port:` Returns a string containing the port.

`self.query_band:` Returns a string containing the query band.

`self.initial_sql:` Returns a string containing the initial sql.

## Fields
```python
class Workbook(column_xml=None, metadata_xml=None)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name='tableaudocumentapi',
version='0.5',
version='0.6',
author='Tableau',
author_email='github@tableau.com',
url='https://github.com/tableau/document-api-python',
Expand Down
124 changes: 88 additions & 36 deletions tableaudocumentapi/connection.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
###############################################################################
#
# Connection - A class for writing connections to Tableau files
#
###############################################################################
import xml.etree.ElementTree as ET
from tableaudocumentapi.dbclass import is_valid_dbclass


class Connection(object):
"""
A class for writing connections to Tableau files.

"""

###########################################################################
#
# Public API.
#
###########################################################################
"""A class representing connections inside Data Sources."""

def __init__(self, connxml):
"""
Constructor.
"""Connection is usually instantiated by passing in connection elements
in a Data Source. If creating a connection from scratch you can call
`from_attributes` passing in the connection attributes.

"""
self._connectionXML = connxml
Expand All @@ -31,27 +18,33 @@ def __init__(self, connxml):
self._authentication = connxml.get('authentication')
self._class = connxml.get('class')
self._port = connxml.get('port', None)
self._query_band = connxml.get('query-band-spec', None)
self._initial_sql = connxml.get('one-time-sql', None)

def __repr__(self):
return "'<Connection server='{}' dbname='{}' @ {}>'".format(self._server, self._dbname, hex(id(self)))

@classmethod
def from_attributes(cls, server, dbname, username, dbclass, port=None, authentication=''):
def from_attributes(cls, server, dbname, username, dbclass, port=None, query_band=None,
initial_sql=None, authentication=''):
"""Creates a new connection that can be added into a Data Source.
defaults to `''` which will be treated as 'prompt' by Tableau."""

root = ET.Element('connection', authentication=authentication)
xml = cls(root)
xml.server = server
xml.dbname = dbname
xml.username = username
xml.dbclass = dbclass
xml.port = port
xml.query_band = query_band
xml.initial_sql = initial_sql

return xml

###########
# dbname
###########
@property
def dbname(self):
"""Database name for the connection. Not the table name."""
return self._dbname

@dbname.setter
Expand All @@ -69,11 +62,9 @@ def dbname(self, value):
self._dbname = value
self._connectionXML.set('dbname', value)

###########
# server
###########
@property
def server(self):
"""Hostname or IP address of the database server. May also be a URL in some connection types."""
return self._server

@server.setter
Expand All @@ -91,11 +82,9 @@ def server(self, value):
self._server = value
self._connectionXML.set('server', value)

###########
# username
###########
@property
def username(self):
"""Username used to authenticate to the database."""
return self._username

@username.setter
Expand All @@ -113,38 +102,49 @@ def username(self, value):
self._username = value
self._connectionXML.set('username', value)

###########
# authentication
###########
@property
def authentication(self):
return self._authentication

###########
# dbclass
###########
@property
def dbclass(self):
"""The type of connection (e.g. 'MySQL', 'Postgresql'). A complete list
can be found in dbclass.py"""
return self._class

@dbclass.setter
def dbclass(self, value):
"""Set the connection's dbclass property.

Args:
value: New dbclass value. String.

Returns:
Nothing.
"""

if not is_valid_dbclass(value):
raise AttributeError("'{}' is not a valid database type".format(value))

self._class = value
self._connectionXML.set('class', value)

###########
# port
###########
@property
def port(self):
"""Port used to connect to the database."""
return self._port

@port.setter
def port(self, value):
"""Set the connection's port property.

Args:
value: New port value. String.

Returns:
Nothing.
"""

self._port = value
# If port is None we remove the element and don't write it to XML
if value is None:
Expand All @@ -154,3 +154,55 @@ def port(self, value):
pass
else:
self._connectionXML.set('port', value)

@property
def query_band(self):
"""Query band passed on connection to database."""
return self._query_band

@query_band.setter
def query_band(self, value):
"""Set the connection's query_band property.

Args:
value: New query_band value. String.

Returns:
Nothing.
"""

self._query_band = value
# If query band is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['query-band-spec']
except KeyError:
pass
else:
self._connectionXML.set('query-band-spec', value)

@property
def initial_sql(self):
"""Initial SQL to be run."""
return self._initial_sql

@initial_sql.setter
def initial_sql(self, value):
"""Set the connection's initial_sql property.

Args:
value: New initial_sql value. String.

Returns:
Nothing.
"""

self._initial_sql = value
# If initial_sql is None we remove the element and don't write it to XML
if value is None:
try:
del self._connectionXML.attrib['one-time-sql']
except KeyError:
pass
else:
self._connectionXML.set('one-time-sql', value)
Loading
0