8000 Commenting and Docstring cleanup. A few very small code cleanups (#120) · tableau/document-api-python@fe16c0c · GitHub
[go: up one dir, main page]

Skip to content

Commit fe16c0c

Browse files
authored
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.
1 parent fb36a3a commit fe16c0c

File tree

4 files changed

+61
-97
lines changed

4 files changed

+61
-97
lines changed

tableaudocumentapi/connection.py

Lines changed: 30 additions & 35 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 8000 -
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
@@ -37,6 +24,9 @@ def __repr__(self):
3724

3825
@classmethod
3926
def from_attributes(cls, server, dbname, username, dbclass, port=None, authentication=''):
27+
"""Creates a new connection that can be added into a Data Source.
28+
defaults to `''` which will be treated as 'prompt' by Tableau."""
29+
4030
root = ET.Element('connection', authentication=authentication)
4131
xml = cls(root)
4232
xml.server = server
@@ -47,11 +37,9 @@ def from_attributes(cls, server, dbname, username, dbclass, port=None, authentic
4737

4838
return xml
4939

50-
###########
51-
# dbname
52-
###########
5340
@property
5441
def dbname(self):
42+
"""Database name for the connection. Not the table name."""
5543
return self._dbname
5644

5745
@dbname.setter
@@ -69,11 +57,9 @@ def dbname(self, value):
6957
self._dbname = value
7058
self._connectionXML.set('dbname', value)
7159

72-
###########
73-
# server
74-
###########
7560
@property
7661
def server(self):
62+
"""Hostname or IP address of the database server. May also be a URL in some connection types."""
7763
return self._server
7864

7965
@server.setter
@@ -91,11 +77,9 @@ def server(self, value):
9177
self._server = value
9278
self._connectionXML.set('server', value)
9379

94-
###########
95-
# username
96-
###########
9780
@property
9881
def username(self):
82+
"""Username used to authenticate to the database."""
9983
return self._username
10084

10185
@username.setter
@@ -113,38 +97,49 @@ def username(self, value):
11397
self._username = value
11498
self._connectionXML.set('username', value)
11599

116-
###########
117-
# authentication
118-
###########
119100
@property
120101
def authentication(self):
121102
return self._authentication
122103

123-
###########
124-
# dbclass
125-
###########
126104
@property
127105
def dbclass(self):
106+
"""The type of connection (e.g. 'MySQL', 'Postgresql'). A complete list
107+
can be found in dbclass.py"""
128108
return self._class
129109

130110
@dbclass.setter
131111
def dbclass(self, value):
112+
"""Set the connection's dbclass property.
113+
114+
Args:
115+
value: New dbclass value. String.
116+
117+
Returns:
118+
Nothing.
119+
"""
132120

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

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

139-
###########
140-
# port
141-
###########
142127
@property
143128
def port(self):
129+
"""Port used to connect to the database."""
144130
return self._port
145131

146132
@port.setter
147133
def port(self, value):
134+
"""Set the connection's port property.
135+
136+
Args:
137+
value: New port value. String.
138+
139+
Returns:
140+
Nothing.
141+
"""
142+
148143
self._port = value
149144
# If port is None we remove the element and don't write it to XML
150145
if value is None:

tableaudocumentapi/datasource.py

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
###############################################################################
2-
#
3-
# Datasource - A class for writing datasources to Tableau files
4-
#
5-
###############################################################################
61
import collections
72
import itertools
83
import xml.etree.ElementTree as ET
@@ -16,7 +11,7 @@
1611

1712
########
1813
# This is needed in order to determine if something is a string or not. It is necessary because
19-
# of differences between python2 (basestring) and python3 (str). If python2 support is every
14+
# of differences between python2 (basestring) and python3 (str). If python2 support is ever
2015
# dropped, remove this and change the basestring references below to str
2116
try:
2217
basestring
@@ -35,7 +30,7 @@ def _get_metadata_xml_for_field(root_xml, field_name):
3530

3631

3732
def _is_used_by_worksheet(names, field):
38-
return any((y for y in names if y in field.worksheets))
33+
return any(y for y in names if y in field.worksheets)
3934

4035

4136
class FieldDictionary(MultiLookupDict):
@@ -87,27 +82,32 @@ def base36encode(number):
8782
return sign + base36
8883

8984

90-
def make_unique_name(dbclass):
85+
def _make_unique_name(dbclass):
9186
rand_part = base36encode(uuid4().int)
9287
name = dbclass + '.' + rand_part
9388
return name
9489

9590

9691
class ConnectionParser(object):
92+
"""Parser for detecting and extracting connections from differing Tableau file formats."""
9793

9894
def __init__(self, datasource_xml, version):
9995
self._dsxml = datasource_xml
10096
self._dsversion = version
10197

10298
def _extract_federated_connections(self):
10399
connections = list(map(Connection, self._dsxml.findall('.//named-connections/named-connection/*')))
100+
# 'sqlproxy' connections (Tableau Server Connections) are not embedded into named-connection elements
101+
# extract them manually for now
104102
connections.extend(map(Connection, self._dsxml.findall("./connection[@class='sqlproxy']")))
105103
return connections
106104

107105
def _extract_legacy_connection(self):
108106
return list(map(Connection, self._dsxml.findall('connection')))
109107

110108
def get_connections(self):
109+
"""Find and return all connections based on file format version."""
110+
111111
if float(self._dsversion) < 10:
112112
connections = self._extract_legacy_connection()
113113
else:
@@ -116,16 +116,11 @@ def get_connections(self):
116116

117117

118118
class Datasource(object):
119-
"""
120-
A class for writing datasources to Tableau files.
119+
"""A class representing Tableau Data Sources, embedded in workbook files or
120+
in TDS files.
121121
122122
"""
123123

124-
###########################################################################
125-
#
126-
# Public API.
127-
#
128-
###########################################################################
129124
def __init__(self, dsxml, filename=None):
130125
"""
131126
Constructor. Default is to create datasource from xml.
@@ -145,21 +140,23 @@ def __init__(self, dsxml, filename=None):
145140

146141
@classmethod
147142
def from_file(cls, filename):
148-
"""Initialize datasource from file (.tds)"""
143+
"""Initialize datasource from file (.tds ot .tdsx)"""
149144

150-
dsxml = xml_open(filename, cls.__name__.lower()).getroot()
145+
dsxml = xml_open(filename, 'datasource').getroot()
151146
return cls(dsxml, filename)
152147

153148
@classmethod
154149
def from_connections(cls, caption, connections):
150+
"""Create a new Data Source give a list of Connections."""
151+
155152
root = ET.Element('datasource', caption=caption, version='10.0', inline='true')
156153
outer_connection = ET.SubElement(root, 'connection')
157154
outer_connection.set('class', 'federated')
158155
named_conns = ET.SubElement(outer_connection, 'named-connections')
159156
for conn in connections:
160157
nc = ET.SubElement(named_conns,
161158
'named-connection',
162-
name=make_unique_name(conn.dbclass),
159+
name=_make_unique_name(conn.dbclass),
163160
caption=conn.server)
164161
nc.append(conn._connectionXML)
165162
return cls(root)
@@ -194,16 +191,10 @@ def save_as(self, new_filename):
194191

195192
xfile._save_file(self._filename, self._datasourceTree, new_filename)
196193

197-
###########
198-
# name
199-
###########
200194
@property
201195
def name(self):
202196
return self._name
203197

204-
###########
205-
# version
206-
###########
207198
@property
208199
def version(self):
209200
return self._version
@@ -222,9 +213,6 @@ def caption(self):
222213
del self._datasourceXML.attrib['caption']
223214
self._caption = ''
224215

225-
###########
226-
# connections
227-
###########
228216
@property
229217
def connections(self):
230218
return self._connections
@@ -234,16 +222,15 @@ def clear_repository_location(self):
234222
if tag is not None:
235223
self._datasourceXML.remove(tag)
236224

237-
###########
238-
# fields
239-
###########
240225
@property
241226
def fields(self):
242227
if not self._fields:
243228
self._fields = self._get_all_fields()
244229
return self._fields
245230

246231
def _get_all_fields(se 10000 lf):
232+
# Some columns are represented by `column` tags and others as `metadata-record` tags
233+
# Find them all and chain them into one dictionary
247234
column_field_objects = self._get_column_objects()
248235
existing_column_fields = [x.id for x in column_field_objects]
249236
metadata_only_field_objects = (x for x in self._get_metadata_objects() if x.id not in existing_column_fields)

tableaudocumentapi/workbook.py

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
###############################################################################
2-
#
3-
# Workbook - A class for writing Tableau workbook files
4-
#
5-
###############################################################################
61
import weakref
72

83

@@ -11,25 +6,18 @@
116

127

138
class Workbook(object):
14-
"""
15-
A class for writing Tableau workbook files.
9+
"""A class for writing Tableau workbook files."""
1610

17-
"""
18-
19-
###########################################################################
20-
#
21-
# Public API.
22-
#
23-
###########################################################################
2411
def __init__(self, filename):
25-
"""
26-
Constructor.
12+
"""Open the workbook at `filename`. This will handle packaged and unpacked
13+
workbook files automatically. This will also parse Data Sources and Worksheets
14+
for access.
2715
2816
"""
2917

3018
self._filename = filename
3119

32-
self._workbookTree = xml_open(self._filename, self.__class__.__name__.lower())
20+
self._workbookTree = xml_open(self._filename, 'workbook')
3321

3422
self._workbookRoot = self._workbookTree.getroot()
3523
# prepare our datasource objects
@@ -42,23 +30,14 @@ def __init__(self, filename):
4230
self._workbookRoot, self._datasource_index
4331
)
4432

45-
###########
46-
# datasources
47-
###########
4833
@property
4934
def datasources(self):
5035
return self._datasources
5136

52-
###########
53-
# worksheets
54-
###########
5537
@property
5638
def worksheets(self):
5739
return self._worksheets
5840

59-
###########
60-
# filename
61-
###########
6241
@property
6342
def filename(self):
6443
return self._filename
@@ -92,11 +71,6 @@ def save_as(self, new_filename):
9271
xfile._save_file(
9372
self._filename, self._workbookTree, new_filename)
9473

95-
###########################################################################
96-
#
97-
# Private API.
98-
#
99-
###########################################################################
10074
@staticmethod
10175
def _prepare_datasource_index(datasources):
10276
retval = weakref.WeakValueDictionary()

0 commit comments

Comments
 (0)
0