Skip to content

Commit

Permalink
Implement call to move to highest supported REST API version
Browse files Browse the repository at this point in the history
  • Loading branch information
t8y8 committed Nov 8, 2016
1 parent 39f4b22 commit c93fea4
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 7 deletions.
6 changes: 4 additions & 2 deletions samples/initialize_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import logging
import glob


def main():
parser = argparse.ArgumentParser(description='Initialize a server with content.')
parser.add_argument('--server', '-s', required=True, help='server address')
Expand Down Expand Up @@ -47,12 +48,12 @@ def main():
# Create the site if it doesn't exist
if existing_site is None:
print("Site not found: {0} Creating it...").format(args.site)
new_site = TSC.SiteItem(name=args.site, content_url=args.site.replace(" ", ""), admin_mode=TSC.SiteItem.AdminMode.ContentAndUsers)
new_site = TSC.SiteItem(name=args.site, content_url=args.site.replace(" ", ""),
admin_mode=TSC.SiteItem.AdminMode.ContentAndUsers)
server.sites.create(new_site)
else:
print("Site {0} exists. Moving on...").format(args.site)


################################################################################
# Step 3: Sign-in to our target site
################################################################################
Expand Down Expand Up @@ -82,6 +83,7 @@ def main():
publish_datasources_to_site(server_upload, project, args.datasources_folder)
publish_workbooks_to_site(server_upload, project, args.workbooks_folder)


def publish_datasources_to_site(server_object, project, folder):
path = folder + '/*.tds*'

Expand Down
2 changes: 1 addition & 1 deletion tableauserverclient/server/endpoint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .auth_endpoint import Auth
from .datasources_endpoint import Datasources
from .endpoint import Endpoint
from .exceptions import ServerResponseError, MissingRequiredFieldError
from .exceptions import ServerResponseError, MissingRequiredFieldError, ServerInfoEndpointNotFoundError
from .groups_endpoint import Groups
from .projects_endpoint import Projects
from .schedules_endpoint import Schedules
Expand Down
4 changes: 4 additions & 0 deletions tableauserverclient/server/endpoint/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ def from_response(cls, resp):

class MissingRequiredFieldError(Exception):
pass


class ServerInfoEndpointNotFoundError(Exception):
pass
8 changes: 7 additions & 1 deletion tableauserverclient/server/endpoint/server_info_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .endpoint import Endpoint
from .exceptions import ServerResponseError, ServerInfoEndpointNotFoundError
from ...models import ServerInfoItem
import logging

Expand All @@ -12,6 +13,11 @@ def baseurl(self):

def get(self):
""" Retrieve the server info for the server. This is an unauthenticated call """
server_response = self.get_unauthenticated_request(self.baseurl)
try:
server_response = self.get_unauthenticated_request(self.baseurl)
except ServerResponseError as e:
if e.code == "404003":
raise ServerInfoEndpointNotFoundError

server_info = ServerInfoItem.from_response(server_response.content)
return server_info
36 changes: 35 additions & 1 deletion tableauserverclient/server/server.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
import xml.etree.ElementTree as ET

from .exceptions import NotSignedInError
from .endpoint import Sites, Views, Users, Groups, Workbooks, Datasources, Projects, Auth, Schedules, ServerInfo
from .endpoint import Sites, Views, Users, Groups, Workbooks, Datasources, Projects, Auth, \
Schedules, ServerInfo, ServerInfoEndpointNotFoundError

import requests

_PRODUCT_TO_REST_VERSION = {
'10.0': '2.3',
'9.3': '2.2',
'9.2': '2.1',
'9.1': '2.0',
'9.0': '2.0'
}


class Server(object):
class PublishMode:
Expand Down Expand Up @@ -47,6 +58,29 @@ def _set_auth(self, site_id, user_id, auth_token):
self._user_id = user_id
self._auth_token = auth_token

def _get_legacy_version(self):
response = self._session.get(self.server_address + "/auth?format=xml")
info_xml = ET.fromstring(response.content)
prod_version = info_xml.find('.//product_version').text
version = _PRODUCT_TO_REST_VERSION.get(prod_version, '2.1') # 2.1
return version

def _determine_highest_version(self):
try:
old_version = self.version
self.version = "2.4"
version = self.server_info.get().rest_api_version
except ServerInfoEndpointNotFoundError:
version = self._get_legacy_version()

finally:
self.version = old_version

return version

def use_highest_version(self):
self.version = self._determine_highest_version()

@property
def baseurl(self):
return "{0}/api/{1}".format(self._server_address, str(self.version))
Expand Down
7 changes: 7 additions & 0 deletions test/assets/server_info_404.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<tsResponse xmlns="http://tableau.com/api" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tableau.com/api http://tableau.com/api/ts-api-2.3.xsd">
<error code="404003">
<summary>Resource Not Found</summary>
<detail>Unknown resource '/2.4/serverInfo' specified in URI.</detail>
</error>
</tsResponse>
12 changes: 12 additions & 0 deletions test/assets/server_info_auth_info.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<authinfo>
<version version="0.31">
<api_version>0.31</api_version>
<server_api_version>0.31</server_api_version>
<document_version>9.2</document_version>
<product_version>9.3</product_version>
<external_version>9.3.4</external_version>
<build>hello.16.1106.2025</build>
<publishing_method>unrestricted</publishing_method>
<mobile_api_version>2.6</mobile_api_version>
</version>
</authinfo>
31 changes: 29 additions & 2 deletions test/test_server_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,48 @@
TEST_ASSET_DIR = os.path.join(os.path.dirname(__file__), 'assets')

SERVER_INFO_GET_XML = os.path.join(TEST_ASSET_DIR, 'server_info_get.xml')
SERVER_INFO_404 = os.path.join(TEST_ASSET_DIR, 'server_info_404.xml')
SERVER_INFO_AUTH_INFO_XML = os.path.join(TEST_ASSET_DIR, 'server_info_auth_info.xml')


class ServerInfoTests(unittest.TestCase):
def setUp(self):
self.server = TSC.Server('http://test')
self.server.version = '2.4'
self.baseurl = self.server.server_info.baseurl

def test_server_info_get(self):
with open(SERVER_INFO_GET_XML, 'rb') as f:
response_xml = f.read().decode('utf-8')
with requests_mock.mock() as m:
m.get(self.baseurl, text=response_xml)
self.server.version = '2.4'
m.get(self.server.server_info.baseurl, text=response_xml)
actual = self.server.server_info.get()

self.assertEqual('10.1.0', actual.product_version)
self.assertEqual('10100.16.1024.2100', actual.build_number)
self.assertEqual('2.4', actual.rest_api_version)

def test_server_info_use_highest_version_downgrades(self):
with open(SERVER_INFO_AUTH_INFO_XML, 'rb') as f:
# This is the auth.xml endpoint present back to 9.0 Servers
auth_response_xml = f.read().decode('utf-8')
with open(SERVER_INFO_404, 'rb') as f:
# 10.1 serverInfo response
si_response_xml = f.read().decode('utf-8')
with requests_mock.mock() as m:
# Return a 404 for serverInfo so we can pretend this is an old Server
m.get(self.server.server_address + "/api/2.4/serverInfo", text=si_response_xml, status_code=404)
m.get(self.server.server_address + "/auth?format=xml", text=auth_response_xml)
self.server.use_highest_version()
self.assertEqual(self.server.version, '2.2')

def test_server_info_use_highest_version_upgrades(self):
with open(SERVER_INFO_GET_XML, 'rb') as f:
si_response_xml = f.read().decode('utf-8')
with requests_mock.mock() as m:
m.get(self.server.server_address + "/api/2.4/serverInfo", text=si_response_xml)
# Pretend we're old
self.server.version = '2.0'
self.server.use_highest_version()
# Did we upgrade to 2.4?
self.assertEqual(self.server.version, '2.4')

0 comments on commit c93fea4

Please sign in to comment.