Skip to content

Commit 65fbc80

Browse files
author
Russell Hay
authored
Release 0.6 (#126)
* Fix #117 by only attempting files with the right extension inside the archive (#118) * Commenting and Docstring cleanup. A few very small code cleanups (#120) Add docstrings and remove clutter. I also made some very tiny tweaks to some code for clarity. * Small cleanups for various editors. Play nice with built in test-runners (#121) * Add Py36, update travis to use pycodestyle (#124) * Add `initial sql` and `query band` support (#123) Addresses #109 and #110 * Prep for release of 0.6 (#125) * Prep for release of 0.6 * wordsmithing the changelog
1 parent 8029b4f commit 65fbc80

15 files changed

+204
-109
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,11 @@ target/
6565
.DS_Store
6666
.idea
6767

68+
#Editor things
69+
*.sublime-project
70+
*.sublime-workspace
71+
settings.json
72+
tasks.json
73+
6874
#Jekyll
6975
docs/_site

.travis.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ python:
66
- "3.3"
77
- "3.4"
88
- "3.5"
9+
- "3.6"
910
- "pypy"
1011
# command to install dependencies
1112
install:
1213
- "pip install -e ."
13-
- "pip install pep8"
14+
- "pip install pycodestyle"
1415
# command to run tests
1516
script:
1617
# Tests
1718
- python setup.py test
18-
# pep8
19-
- pep8 .
19+
# pycodestyle
20+
- pycodestyle tableaudocumentapi test samples
2021
# Examples
2122
- (cd "samples/replicate-workbook" && python replicate_workbook.py)
2223
- (cd "samples/list-tds-info" && python list_tds_info.py)

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 06 (11 January 2017)
2+
3+
* Initial SQL and query banding support (#123)
4+
* Fixed bug in xfiles to allow opening workbooks with external file caches (#117, #118)
5+
* Code Cleanup (#120, #121)
6+
* Added Py36 support (#124)
7+
* Switched to pycodestyle from pip8 on travis runs (#124)
8+
19
## 05 (01 November 2016)
210

311
* Added ability to set the port for connections (#97)

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The following people have contributed to this project to make it possible, and w
66

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

1011
## Core Team
1112

docs/docs/api-ref.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ class Datasource(dsxml, filename=None)
4848
class Connection(connxml)
4949
```
5050

51+
The Connection class represents a tableau data connection. It can be from any type of connection found in `dbclass.py` via `is_valid_dbclass`
52+
53+
**Params:**
54+
55+
**Raises:**
56+
57+
**Methods:**
58+
59+
**Properities:**
60+
61+
`self.server:` Returns a string containing the server.
62+
63+
`self.dbname:` Returns a string containing the database name.
64+
65+
`self.username:` Returns a string containing the username.
66+
67+
`self.dbclass:` Returns a string containing the database class.
68+
69+
`self.port:` Returns a string containing the port.
70+
71+
`self.query_band:` Returns a string containing the query band.
72+
73+
`self.initial_sql:` Returns a string containing the initial sql.
74+
5175
## Fields
5276
```python
5377
class Workbook(column_xml=None, metadata_xml=None)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name='tableaudocumentapi',
8-
version='0.5',
8+
version='0.6',
99
author='Tableau',
1010
author_email='github@tableau.com',
1111
url='https://github.com/tableau/document-api-python',

tableaudocumentapi/connection.py

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,14 @@
1-
###############################################################################
2-
#
3-
# Connection - A class for writing connections to Tableau files
4-
#
5-
###############################################################################
61
import xml.etree.ElementTree as ET
72
from tableaudocumentapi.dbclass import is_valid_dbclass
83

94

105
class Connection(object):
11-
"""
12-
A class for writing connections to Tableau files.
13-
14-
"""
15-
16-
###########################################################################
17-
#
18-
# Public API.
19-
#
20-
###########################################################################
6+
"""A class representing connections inside Data Sources."""
217

228
def __init__(self, connxml):
23-
"""
24-
Constructor.
9+
"""Connection is usually instantiated by passing in connection elements
10+
in a Data Source. If creating a connection from scratch you can call
11+
`from_attributes` passing in the connection attributes.
2512
2613
"""
2714
self._connectionXML = connxml
@@ -31,27 +18,33 @@ def __init__(self, connxml):
3118
self._authentication = connxml.get('authentication')
3219
self._class = connxml.get('class')
3320
self._port = connxml.get('port', None)
21+
self._query_band = connxml.get('query-band-spec', None)
22+
self._initial_sql = connxml.get('one-time-sql', None)
3423

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

3827
@classmethod
39-
def from_attributes(cls, server, dbname, username, dbclass, port=None, authentication=''):
28+
def from_attributes(cls, server, dbname, username, dbclass, port=None, query_band=None,
29+
initial_sql=None, authentication=''):
30+
"""Creates a new connection that can be added into a Data Source.
31+
defaults to `''` which will be treated as 'prompt' by Tableau."""
32+
4033
root = ET.Element('connection', authentication=authentication)
4134
xml = cls(root)
4235
xml.server = server
4336
xml.dbname = dbname
4437
xml.username = username
4538
xml.dbclass = dbclass
4639
xml.port = port
40+
xml.query_band = query_band
41+
xml.initial_sql = initial_sql
4742

4843
return xml
4944

50-
###########
51-
# dbname
52-
###########
5345
@property
5446
def dbname(self):
47+
"""Database name for the connection. Not the table name."""
5548
return self._dbname
5649

5750
@dbname.setter
@@ -69,11 +62,9 @@ def dbname(self, value):
6962
self._dbname = value
7063
self._connectionXML.set('dbname', value)
7164

72-
###########
73-
# server
74-
###########
7565
@property
7666
def server(self):
67+
"""Hostname or IP address of the database server. May also be a URL in some connection types."""
7768
return self._server
7869

7970
@server.setter
@@ -91,11 +82,9 @@ def server(self, value):
9182
self._server = value
9283
self._connectionXML.set('server', value)
9384

94-
###########
95-
# username
96-
###########
9785
@property
9886
def username(self):
87+
"""Username used to authenticate to the database."""
9988
return self._username
10089

10190
@username.setter
@@ -113,38 +102,49 @@ def username(self, value):
113102
self._username = value
114103
self._connectionXML.set('username', value)
115104

116-
###########
117-
# authentication
118-
###########
119105
@property
120106
def authentication(self):
121107
return self._authentication
122108

123-
###########
124-
# dbclass
125-
###########
126109
@property
127110
def dbclass(self):
111+
"""The type of connection (e.g. 'MySQL', 'Postgresql'). A complete list
112+
can be found in dbclass.py"""
128113
return self._class
129114

130115
@dbclass.setter
131116
def dbclass(self, value):
117+
"""Set the connection's dbclass property.
118+
119+
Args:
120+
value: New dbclass value. String.
121+
122+
Returns:
123+
Nothing.
124+
"""
132125

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

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

139-
###########
140-
# port
141-
###########
142132
@property
143133
def port(self):
134+
"""Port used to connect to the database."""
144135
return self._port
145136

146137
@port.setter
147138
def port(self, value):
139+
"""Set the connection's port property.
140+
141+
Args:
142+
value: New port value. String.
143+
144+
Returns:
145+
Nothing.
146+
"""
147+
148148
self._port = value
149149
# If port is None we remove the element and don't write it to XML
150150
if value is None:
@@ -154,3 +154,55 @@ def port(self, value):
154154
pass
155155
else:
156156
self._connectionXML.set('port', value)
157+
158+
@property
159+
def query_band(self):
160+
"""Query band passed on connection to database."""
161+
return self._query_band
162+
163+
@query_band.setter
164+
def query_band(self, value):
165+
"""Set the connection's query_band property.
166+
167+
Args:
168+
value: New query_band value. String.
169+
170+
Returns:
171+
Nothing.
172+
"""
173+
174+
self._query_band = value
175+
# If query band is None we remove the element and don't write it to XML
176+
if value is None:
177+
try:
178+
del self._connectionXML.attrib['query-band-spec']
179+
except KeyError:
180+
pass
181+
else:
182+
self._connectionXML.set('query-band-spec', value)
183+
184+
@property
185+
def initial_sql(self):
186+
"""Initial SQL to be run."""
187+
return self._initial_sql
188+
189+
@initial_sql.setter
190+
def initial_sql(self, value):
191+
"""Set the connection's initial_sql property.
192+
193+
Args:
194+
value: New initial_sql value. String.
195+
196+
Returns:
197+
Nothing.
198+
"""
199+
200+
self._initial_sql = value
201+
# If initial_sql is None we remove the element and don't write it to XML
202+
if value is None:
203+
try:
204+
del self._connectionXML.attrib['one-time-sql']
205+
except KeyError:
206+
pass
207+
else:
208+
self._connectionXML.set('one-time-sql', value)

0 commit comments

Comments
 (0)