diff --git a/setup.py b/setup.py
index 27d6a73..998914e 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@
setup(
name='tableaudocumentapi',
version='0.3',
- author='Tableau Software',
+ author='Tableau',
author_email='github@tableau.com',
url='https://github.com/tableau/document-api-python',
packages=['tableaudocumentapi'],
diff --git a/tableaudocumentapi/datasource.py b/tableaudocumentapi/datasource.py
index dd3d5c5..69318ed 100644
--- a/tableaudocumentapi/datasource.py
+++ b/tableaudocumentapi/datasource.py
@@ -31,7 +31,7 @@
def _get_metadata_xml_for_field(root_xml, field_name):
if "'" in field_name:
field_name = sax.escape(field_name, {"'": "'"})
- xpath = ".//metadata-record[@class='column'][local-name='{}']".format(field_name)
+ xpath = u".//metadata-record[@class='column'][local-name='{}']".format(field_name)
return root_xml.find(xpath)
diff --git a/tableaudocumentapi/field.py b/tableaudocumentapi/field.py
index 63cc72c..65ce78d 100644
--- a/tableaudocumentapi/field.py
+++ b/tableaudocumentapi/field.py
@@ -199,4 +199,9 @@ def _read_description(xmldata):
if description is None:
return None
- return u'{}'.format(ET.tostring(description, encoding='utf-8')) # This is necessary for py3 support
+ description_string = ET.tostring(description, encoding='utf-8')
+ # Format expects a unicode string so in Python 2 we have to do the explicit conversion
+ if isinstance(description_string, bytes):
+ description_string = description_string.decode('utf-8')
+
+ return description_string
diff --git a/test/assets/CONNECTION.xml b/test/assets/CONNECTION.xml
index 392d112..6cce11f 100644
--- a/test/assets/CONNECTION.xml
+++ b/test/assets/CONNECTION.xml
@@ -1 +1 @@
-
+
diff --git a/test/assets/TABLEAU_10_TDS.tds b/test/assets/TABLEAU_10_TDS.tds
index 7a81784..01fe7c3 100644
--- a/test/assets/TABLEAU_10_TDS.tds
+++ b/test/assets/TABLEAU_10_TDS.tds
@@ -1 +1 @@
-
+
diff --git a/test/assets/unicode.tds b/test/assets/unicode.tds
new file mode 100644
index 0000000..6c6e764
--- /dev/null
+++ b/test/assets/unicode.tds
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+ a
+ 130
+ [a]
+ [xy]
+ a
+ 1
+ string
+ Count
+ 255
+ true
+
+ "SQL_WVARCHAR"
+ "SQL_C_WCHAR"
+ "true"
+
+
+
+ Today's Date
+ 130
+ [Today's Date]
+ [xy]
+ a
+ 1
+ string
+ Count
+ 255
+ true
+
+ "SQL_WVARCHAR"
+ "SQL_C_WCHAR"
+ "true"
+
+
+
+ x
+ 3
+ [x]
+ [xy]
+ x
+ 2
+ integer
+ Sum
+ 10
+ true
+
+ "SQL_INTEGER"
+ "SQL_C_SLONG"
+
+
+
+ y
+ 3
+ [y]
+ [xy]
+ y
+ 3
+ integer
+ Sum
+ 10
+ true
+
+ "SQL_INTEGER"
+ "SQL_C_SLONG"
+
+
+
+
+
+
+
+
+
+
+
+ año
+
Something will go here too, in a muted gray
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/bvt.py b/test/bvt.py
index 4ea3d11..60e42c3 100644
--- a/test/bvt.py
+++ b/test/bvt.py
@@ -42,7 +42,7 @@ def test_can_extract_federated_connections(self):
connections = parser.get_connections()
self.assertIsInstance(connections, list)
self.assertIsInstance(connections[0], Connection)
- self.assertEqual(connections[0].dbname, 'testv1')
+ self.assertEqual(connections[0].dbname, 'TestV1')
class ConnectionModelTests(unittest.TestCase):
@@ -54,18 +54,18 @@ def test_can_read_attributes_from_connection(self):
conn = Connection(self.connection)
self.assertEqual(conn.dbname, 'TestV1')
self.assertEqual(conn.username, '')
- self.assertEqual(conn.server, 'mssql2012.test.tsi.lan')
+ self.assertEqual(conn.server, 'mssql2012')
self.assertEqual(conn.dbclass, 'sqlserver')
self.assertEqual(conn.authentication, 'sspi')
def test_can_write_attributes_to_connection(self):
conn = Connection(self.connection)
conn.dbname = 'BubblesInMyDrink'
- conn.server = 'mssql2014.test.tsi.lan'
+ conn.server = 'mssql2014'
conn.username = 'bob'
self.assertEqual(conn.dbname, 'BubblesInMyDrink')
self.assertEqual(conn.username, 'bob')
- self.assertEqual(conn.server, 'mssql2014.test.tsi.lan')
+ self.assertEqual(conn.server, 'mssql2014')
def test_bad_dbclass_rasies_attribute_error(self):
conn = Connection(self.connection)
@@ -117,15 +117,15 @@ def test_can_extract_connection(self):
def test_can_save_tds(self):
original_tds = Datasource.from_file(self.tds_file.name)
- original_tds.connections[0].dbname = 'newdb.test.tsi.lan'
+ original_tds.connections[0].dbname = 'newdb'
original_tds.save()
new_tds = Datasource.from_file(self.tds_file.name)
- self.assertEqual(new_tds.connections[0].dbname, 'newdb.test.tsi.lan')
+ self.assertEqual(new_tds.connections[0].dbname, 'newdb')
def test_save_has_xml_declaration(self):
original_tds = Datasource.from_file(self.tds_file.name)
- original_tds.connections[0].dbname = 'newdb.test.tsi.lan'
+ original_tds.connections[0].dbname = 'newdb'
original_tds.save()
@@ -158,11 +158,11 @@ def test_can_extract_connection(self):
def test_can_save_tds(self):
original_tds = Datasource.from_file(self.tds_file.name)
- original_tds.connections[0].dbname = 'newdb.test.tsi.lan'
+ original_tds.connections[0].dbname = 'newdb'
original_tds.save()
new_tds = Datasource.from_file(self.tds_file.name)
- self.assertEqual(new_tds.connections[0].dbname, 'newdb.test.tsi.lan')
+ self.assertEqual(new_tds.connections[0].dbname, 'newdb')
class DatasourceModelV10TDSXTests(unittest.TestCase):
@@ -183,22 +183,22 @@ def test_can_open_tdsx(self):
def test_can_open_tdsx_and_save_changes(self):
original_tdsx = Datasource.from_file(self.tdsx_file.name)
- original_tdsx.connections[0].server = 'newdb.test.tsi.lan'
+ original_tdsx.connections[0].server = 'newdb'
original_tdsx.save()
new_tdsx = Datasource.from_file(self.tdsx_file.name)
self.assertEqual(new_tdsx.connections[
- 0].server, 'newdb.test.tsi.lan')
+ 0].server, 'newdb')
def test_can_open_tdsx_and_save_as_changes(self):
new_tdsx_filename = 'newtdsx.tdsx'
original_wb = Datasource.from_file(self.tdsx_file.name)
- original_wb.connections[0].server = 'newdb.test.tsi.lan'
+ original_wb.connections[0].server = 'newdb'
original_wb.save_as(new_tdsx_filename)
new_wb = Datasource.from_file(new_tdsx_filename)
self.assertEqual(new_wb.connections[
- 0].server, 'newdb.test.tsi.lan')
+ 0].server, 'newdb')
os.unlink(new_tdsx_filename)
@@ -230,12 +230,12 @@ def test_has_filename(self):
def test_can_update_datasource_connection_and_save(self):
original_wb = Workbook(self.workbook_file.name)
- original_wb.datasources[0].connections[0].dbname = 'newdb.test.tsi.lan'
+ original_wb.datasources[0].connections[0].dbname = 'newdb'
original_wb.save()
new_wb = Workbook(self.workbook_file.name)
self.assertEqual(new_wb.datasources[0].connections[
- 0].dbname, 'newdb.test.tsi.lan')
+ 0].dbname, 'newdb')
class WorkbookModelV10Tests(unittest.TestCase):
@@ -260,17 +260,17 @@ def test_can_extract_datasourceV10(self):
def test_can_update_datasource_connection_and_saveV10(self):
original_wb = Workbook(self.workbook_file.name)
- original_wb.datasources[0].connections[0].dbname = 'newdb.test.tsi.lan'
+ original_wb.datasources[0].connections[0].dbname = 'newdb'
original_wb.save()
new_wb = Workbook(self.workbook_file.name)
self.assertEqual(new_wb.datasources[0].connections[
- 0].dbname, 'newdb.test.tsi.lan')
+ 0].dbname, 'newdb')
def test_save_has_xml_declaration(self):
original_wb = Workbook(self.workbook_file.name)
- original_wb.datasources[0].connections[0].dbname = 'newdb.test.tsi.lan'
+ original_wb.datasources[0].connections[0].dbname = 'newdb'
original_wb.save()
@@ -298,22 +298,22 @@ def test_can_open_twbx(self):
def test_can_open_twbx_and_save_changes(self):
original_wb = Workbook(self.workbook_file.name)
- original_wb.datasources[0].connections[0].server = 'newdb.test.tsi.lan'
+ original_wb.datasources[0].connections[0].server = 'newdb'
original_wb.save()
new_wb = Workbook(self.workbook_file.name)
self.assertEqual(new_wb.datasources[0].connections[
- 0].server, 'newdb.test.tsi.lan')
+ 0].server, 'newdb')
def test_can_open_twbx_and_save_as_changes(self):
new_twbx_filename = 'newtwbx.twbx'
original_wb = Workbook(self.workbook_file.name)
- original_wb.datasources[0].connections[0].server = 'newdb.test.tsi.lan'
+ original_wb.datasources[0].connections[0].server = 'newdb'
original_wb.save_as(new_twbx_filename)
new_wb = Workbook(new_twbx_filename)
self.assertEqual(new_wb.datasources[0].connections[
- 0].server, 'newdb.test.tsi.lan')
+ 0].server, 'newdb')
os.unlink(new_twbx_filename)
diff --git a/test/test_field.py b/test/test_field.py
index 7cbe885..b222e81 100644
--- a/test/test_field.py
+++ b/test/test_field.py
@@ -12,6 +12,10 @@
TEST_ASSET_DIR,
'datasource_test.tds'
)
+TEST_UNICODE_FILE = os.path.join(
+ TEST_ASSET_DIR,
+ 'unicode.tds'
+)
class FieldsUnitTest(unittest.TestCase):
@@ -27,3 +31,9 @@ def find(self, *args, **kwargs):
def test_find_metadata_record_returns_none(self):
self.assertIsNone(_find_metadata_record(self.MockXmlWithNoFind(), 'foo'))
+
+
+class FieldsHandleUnicode(unittest.TestCase):
+ def test_description_unicode(self):
+ ds = Datasource.from_file(TEST_UNICODE_FILE)
+ self.assertIsNotNone(ds.fields['A'].description)