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)