tableau_server_client 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 492e70dc7a49eb33db9318b3ace0065b36cdb19d
4
+ data.tar.gz: d0bddfa685157808e77380898bc05d74bedacd89
5
+ SHA512:
6
+ metadata.gz: 311e2452bd507ab1359e22bf690f835f6849e26bc7b689efd6e0c386e4cfadaf2952b5528189d474368d772193fd963386b686965f74f8ab0a4f8988a11e29e2
7
+ data.tar.gz: 17f5966cfb76ef52acb0748ff98209a279a951eb6bffd2416e6e6d6ef66648216afb2c2abe1e52d993a5b0ccaa850cfe4cac94fe6e96cd9953a0abb10ac2c4aa
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pipelined_my_import.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tableau_server_client (0.0.1)
5
+ faraday (>= 0.14.0)
6
+ nokogiri (>= 1.8.2)
7
+ pry (>= 0.11.3)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ byebug (10.0.2)
13
+ coderay (1.1.2)
14
+ diff-lcs (1.3)
15
+ faraday (0.14.0)
16
+ multipart-post (>= 1.2, < 3)
17
+ method_source (0.9.0)
18
+ mini_portile2 (2.3.0)
19
+ multipart-post (2.0.0)
20
+ nokogiri (1.8.2)
21
+ mini_portile2 (~> 2.3.0)
22
+ pry (0.11.3)
23
+ coderay (~> 1.1.0)
24
+ method_source (~> 0.9.0)
25
+ rake (10.5.0)
26
+ rspec (3.7.0)
27
+ rspec-core (~> 3.7.0)
28
+ rspec-expectations (~> 3.7.0)
29
+ rspec-mocks (~> 3.7.0)
30
+ rspec-core (3.7.1)
31
+ rspec-support (~> 3.7.0)
32
+ rspec-expectations (3.7.0)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.7.0)
35
+ rspec-mocks (3.7.0)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.7.0)
38
+ rspec-support (3.7.1)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ bundler (~> 1.13)
45
+ byebug
46
+ rake (~> 10.0)
47
+ rspec (~> 3.0)
48
+ tableau_server_client!
49
+
50
+ BUNDLED WITH
51
+ 1.16.0.pre.3
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # tableau-client
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tableau-server-client/server'
4
+
5
+ # You can add fixtures and/or initialization code here to make experimenting
6
+ # with your gem easier. You can also use a different console, if you like.
7
+
8
+ require 'pry'
9
+ Pry.start
@@ -0,0 +1,120 @@
1
+ require 'uri'
2
+ require 'faraday'
3
+ require 'nokogiri'
4
+ require 'tableau-server-client/request_url'
5
+ require 'tableau-server-client/request_builder'
6
+ require 'tableau-server-client/token'
7
+ require 'tableau-server-client/paginatable_response'
8
+
9
+ module TableauServerClient
10
+
11
+ class Client
12
+ include RequestBuilder
13
+
14
+ def initialize(server_url, username, password, site_name, api_version, token_lifetime, logger)
15
+ @server_url = server_url
16
+ @username = username
17
+ @password = password
18
+ @site_name = site_name
19
+ @api_version = api_version
20
+ @token_lifetime = token_lifetime
21
+ @logger
22
+ end
23
+
24
+ attr_reader :site_name, :username, :api_version, :token_lifetime, :logger
25
+
26
+ def server_url
27
+ @_server_url ||= URI(@server_url.chomp("/"))
28
+ end
29
+
30
+ def get_collection(resource_location, &block)
31
+ return self.to_enum(:get_collection, resource_location) unless block
32
+ req_url = request_url(resource_location.path, resource_location.query_params)
33
+ response = session.get req_url.to_s
34
+ TableauServerClient::PaginatableResponse.new(self, req_url, response).each_body do |b|
35
+ resource_location.klass.from_collection_response(self, resource_location.path, b) {|r| yield r }
36
+ end
37
+ end
38
+
39
+ def get(resource_location)
40
+ req_url = request_url(resource_location.path)
41
+ response = session.get req_url.to_s
42
+ resource_location.klass.from_response(self, resource_location.path, Nokogiri::XML(response.body))
43
+ end
44
+
45
+ def create(resource)
46
+ end
47
+
48
+ def delete(resource)
49
+ end
50
+
51
+ def update(resource)
52
+ session.put do |req|
53
+ req.url request_url(resource.path).to_s
54
+ req.body = resource.to_request
55
+ end
56
+ end
57
+
58
+ def session
59
+ faraday.headers['X-Tableau-Auth'] = token.to_s
60
+ faraday
61
+ end
62
+
63
+ def token
64
+ unless @token and @token.valid?
65
+ @token = signin
66
+ end
67
+ @token
68
+ end
69
+
70
+ private
71
+
72
+ attr_reader :password
73
+
74
+ def request_url(path, query_params={})
75
+ RequestUrl.new(server_url, api_version, path, query_params)
76
+ end
77
+
78
+ def request_body(&block)
79
+ build_request &block
80
+ end
81
+
82
+ def signin
83
+ request = request_body {|b|
84
+ b.credentials(name: username, password: password) {
85
+ b.site(contentUrl: content_url)
86
+ }
87
+ }
88
+ # POST without Token
89
+ res = faraday.post do |req|
90
+ req.url request_url("auth/signin").to_s
91
+ req.body = request
92
+ end
93
+ @token = TableauServerClient::Token.parse(res.body, token_lifetime)
94
+ end
95
+
96
+ def content_url
97
+ site_name == 'default' ? "" : site_name
98
+ end
99
+
100
+ def faraday
101
+ @faraday ||= Faraday.new(request: {params_encoder: EmptyEncoder.new}, headers: {'Content-Type' => 'application/xml'}) do |f|
102
+ f.response :raise_error
103
+ #TODO Cannot set log level (always print debug log)
104
+ #f.response :logger, logger
105
+ f.adapter Faraday.default_adapter
106
+ end
107
+ end
108
+
109
+ class EmptyEncoder
110
+ def encode(hash)
111
+ hash.keys.map {|k| "#{k}=#{hash[k]}" }.join('&')
112
+ end
113
+
114
+ def decode(str)
115
+ str.split('&').map {|p| p.split('=') }.to_h
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,73 @@
1
+ require 'nokogiri'
2
+
3
+ module TableauServerClient
4
+ class PaginatableResponse
5
+ include Enumerable
6
+
7
+ def initialize(client, request_url, response)
8
+ @client = client
9
+ @request_url = request_url
10
+ @response = response
11
+ end
12
+
13
+ def each
14
+ yield @response
15
+ return unless paginated?
16
+ res = @response.dup
17
+ url = @request_url.dup
18
+ while true
19
+ pgn = Pagination.parse(res.body)
20
+ break unless pgn.next_page?
21
+ res = @client.session.get url.merge_params!(pgn.request_params).to_s
22
+ yield res
23
+ end
24
+ end
25
+
26
+ def each_body
27
+ each do |res|
28
+ yield Nokogiri::XML(res.body)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def paginated?
35
+ @paginated ||= !Pagination.parse(@response.body).nil?
36
+ end
37
+
38
+ class Pagination
39
+ def initialize(page_number, page_size, total_available)
40
+ @page_numner = page_number
41
+ @page_size = page_size
42
+ @total_available = total_available
43
+ end
44
+
45
+ def page_number
46
+ @page_number.to_i
47
+ end
48
+
49
+ def page_size
50
+ @page_size.to_i
51
+ end
52
+
53
+ def total_available
54
+ @total_available.to_i
55
+ end
56
+
57
+ def self.parse(xml)
58
+ pg = Nokogiri::XML(xml).xpath("//xmlns:pagination")[0]
59
+ return nil unless pg
60
+ Pagination.new(pg['pageNumber'], pg['pageSize'], pg['totalAvailable'])
61
+ end
62
+
63
+ def next_page?
64
+ page_number * page_size > total_available
65
+ end
66
+
67
+ def request_params
68
+ { pageSize: page_size, pageNumber: page_number + 1 }
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+ require 'nokogiri'
2
+
3
+ module TableauServerClient
4
+ module RequestBuilder
5
+
6
+ def build_request
7
+ builder = Nokogiri::XML::Builder.new do |xml|
8
+ xml.tsRequest {
9
+ yield xml
10
+ }
11
+ end
12
+ builder.to_xml
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ require 'uri'
2
+
3
+ module TableauServerClient
4
+ class RequestUrl
5
+ def initialize(url, api_version, path, params)
6
+ @url = url
7
+ @api_version = api_version
8
+ @path = path
9
+ @params = params
10
+ end
11
+
12
+ attr_reader :url, :api_version
13
+ attr_accessor :path, :params
14
+
15
+ def merge_params!(params)
16
+ @params.merge!(params)
17
+ self
18
+ end
19
+
20
+ def to_s
21
+ URI("#{url}/api/#{api_version}/#{path}?#{query_params}").to_s
22
+ end
23
+
24
+ def query_params
25
+ return "" if params.empty?
26
+ params.keys.map {|k| URI.encode("#{k}=#{params[k]}") }.join("&")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ require 'tableau-server-client/resources/resource'
2
+
3
+ module TableauServerClient
4
+ module Resources
5
+
6
+ class Connection < Resource
7
+
8
+ attr_reader :id, :type, :server_address, :server_port, :user_name, :password, :embed_password
9
+ attr_writer :user_name, :password, :embed_password
10
+
11
+ def self.from_response(client, path, xml)
12
+ attrs = extract_attributes(xml)
13
+ new(client, path, attrs)
14
+ end
15
+
16
+ def self.from_collection_response(client, path, xml)
17
+ xml.xpath("//xmlns:connections/xmlns:connection").each do |s|
18
+ id = s['id']
19
+ yield from_response(client, "#{path}/#{id}", s)
20
+ end
21
+ end
22
+
23
+ def to_request
24
+ request = build_request {|b|
25
+ b.connection(serverAddress: server_address, serverPort: server_port,
26
+ userName: user_name, password: password, embedPassword: embed_password)
27
+ }
28
+ end
29
+
30
+ def update!
31
+ @client.update self
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ require 'tableau-server-client/resources/resource'
2
+ require 'tableau-server-client/resources/project'
3
+ require 'tableau-server-client/resources/connection'
4
+
5
+ module TableauServerClient
6
+ module Resources
7
+
8
+ class Datasource < Resource
9
+
10
+ attr_reader :id, :name, :content_url, :type, :created_at, :updated_at, :is_certified, :project, :owner
11
+
12
+ def self.from_response(client, path, xml)
13
+ attrs = extract_attributes(xml)
14
+ project = xml.xpath("xmlns:project")[0]
15
+ site_path = extract_site_path(path)
16
+ project_path = "#{site_path}/projects/#{project['id']}"
17
+ attrs['project'] = Project.from_response(client, project_path, project)
18
+ #TODO add owner
19
+ new(client, path, attrs)
20
+ end
21
+
22
+ def self.from_collection_response(client, path, xml)
23
+ xml.xpath("//xmlns:datasources/xmlns:datasource").each do |s|
24
+ id = s['id']
25
+ yield from_response(client, "#{path}/#{id}", s)
26
+ end
27
+ end
28
+
29
+ def connections
30
+ @client.get_collection Connection.location(path)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'tableau-server-client/resources/resource'
2
+
3
+ module TableauServerClient
4
+ module Resources
5
+
6
+ class Project < Resource
7
+
8
+ attr_reader :id, :name, :description, :content_permissions
9
+
10
+ def self.from_response(client, path, xml)
11
+ attrs = extract_attributes(xml)
12
+ new(client, path, attrs)
13
+ end
14
+
15
+ def self.from_collection_response(client, path, xml)
16
+ xml.xpath("//xmlns:projects/xmlns:project").each do |s|
17
+ id = s['id']
18
+ yield from_response(client, "#{path}/#{id}", s)
19
+ end
20
+ end
21
+
22
+ def reload
23
+ prjs = @client.get_collection Project.location(site_path, filter: ["name:eq:#{name}"])
24
+ prjs.select {|p| p.id == id }.first
25
+ end
26
+
27
+ def redshift_username
28
+ if md = description.match(/^REDSHIFT_USERNAME: (.+)$/)
29
+ return md[1]
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,88 @@
1
+ module TableauServerClient
2
+ module Resources
3
+
4
+ class Resource
5
+ include RequestBuilder
6
+
7
+ def initialize(client, path, attributes)
8
+ @client = client
9
+ @path = path
10
+ attributes.each {|k,v| instance_variable_set("@#{k}",v) }
11
+ end
12
+
13
+ def self.attr_reader(*vars)
14
+ @attributes ||= []
15
+ @attributes.concat (vars.map { |v| Attribute.new(v.to_s) })
16
+ super(*vars)
17
+ end
18
+
19
+ def self.attributes
20
+ @attributes
21
+ end
22
+
23
+ def self.resource_name
24
+ self.name.split("::").last.downcase
25
+ end
26
+
27
+ def self.location(prefix, id=nil, filter: [])
28
+ path = [prefix, "#{resource_name}s", id].compact.join("/")
29
+ Location.new(self, path, filter)
30
+ end
31
+
32
+ def self.extract_attributes(xml)
33
+ unless xml.name == resource_name
34
+ raise "Element name (#{xml.name}) does not match with resource name (#{resource_name})"
35
+ end
36
+ attributes.select {|a| xml.key?(a.camelCase) }.map {|a| [a.to_sym, xml[a.camelCase]] }.to_h
37
+ end
38
+
39
+ def self.extract_site_path(path)
40
+ p = path.split('/')
41
+ p.slice(p.index('sites'),2).join('/')
42
+ end
43
+
44
+ def attributes
45
+ self.class.attributes
46
+ end
47
+
48
+ def path
49
+ @path
50
+ end
51
+
52
+ def site_path
53
+ self.class.extract_site_path(path)
54
+ end
55
+
56
+ class Location
57
+
58
+ def initialize(klass, path, filter)
59
+ @klass = klass
60
+ @path = path
61
+ @filter = filter
62
+ end
63
+
64
+ attr_reader :klass, :path
65
+
66
+ def filter
67
+ @filter.empty? ? {} : {filter: @filter.join(",")}
68
+ end
69
+
70
+ def query_params
71
+ filter
72
+ end
73
+ end
74
+
75
+ class Attribute < String
76
+
77
+ def camelCase
78
+ atr = self.split("_").map{ |w| w.capitalize }.join
79
+ atr[0] = atr[0].downcase
80
+ atr
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,24 @@
1
+ require 'tableau-server-client/resources/resource'
2
+
3
+ module TableauServerClient
4
+ module Resources
5
+
6
+ class Schedule < Resource
7
+
8
+ attr_reader :id, :name, :state, :priority, :created_at, :updated_at, :type, :frequency, :next_run_at
9
+
10
+ def self.from_response(client, path, xml)
11
+ attrs = extract_attributes(xml)
12
+ new(client, path, attrs)
13
+ end
14
+
15
+ def self.from_collection_response(client, path, xml)
16
+ xml.xpath("//xmlns:schedules/xmlns:schedule").each do |s|
17
+ id = s.xpath("//xmlns:schedule/@id")[0].value
18
+ yield from_response(client, path, s)
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ require 'tableau-server-client/resources/resource'
2
+ require 'tableau-server-client/resources/datasource'
3
+ require 'tableau-server-client/resources/workbook'
4
+
5
+ module TableauServerClient
6
+ module Resources
7
+
8
+ class Site < Resource
9
+
10
+ attr_reader :id, :name, :content_url, :admin_mode, :storage_quota, :state
11
+
12
+ def self.from_response(client, path, xml)
13
+ attrs = extract_attributes(xml)
14
+ new(client, path, attrs)
15
+ end
16
+
17
+ def self.from_collection_response(client, path, xml)
18
+ xml.xpath("//xmlns:sites/xmlns:site").each do |s|
19
+ id = s['id']
20
+ yield from_response(client, "#{path}/#{id}", s)
21
+ end
22
+ end
23
+
24
+ def datasources(filter: [])
25
+ @client.get_collection Datasource.location(path, filter: filter)
26
+ end
27
+
28
+ def datasource(id)
29
+ @client.get Datasource.location(path, id)
30
+ end
31
+
32
+ def workbooks(filter: [])
33
+ @client.get_collection Workbook.location(path, filter: filter)
34
+ end
35
+
36
+ def workbook(id)
37
+ @client.get Workbook.location(path, id)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ require 'tableau-server-client/resources/resource'
2
+ require 'tableau-server-client/resources/project'
3
+ require 'tableau-server-client/resources/connection'
4
+
5
+ module TableauServerClient
6
+ module Resources
7
+
8
+ class Workbook < Resource
9
+
10
+ attr_reader :id, :name, :content_url, :show_tabs, :size, :created_at, :updated_at, :project, :owner
11
+
12
+ def self.from_response(client, path, xml)
13
+ attrs = extract_attributes(xml)
14
+ project = xml.xpath("xmlns:project")[0]
15
+ site_path = extract_site_path(path)
16
+ project_path = "#{site_path}/projects/#{project['id']}"
17
+ attrs['project'] = Project.from_response(client, project_path, project)
18
+ #TODO add owner
19
+ new(client, path, attrs)
20
+ end
21
+
22
+ def self.from_collection_response(client, path, xml)
23
+ xml.xpath("//xmlns:workbooks/xmlns:workbook").each do |s|
24
+ id = s['id']
25
+ yield from_response(client, "#{path}/#{id}", s)
26
+ end
27
+ end
28
+
29
+ def connections
30
+ @client.get_collection Connection.location(path)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ require 'tableau-server-client/client'
2
+ require 'tableau-server-client/resources/site'
3
+ require 'tableau-server-client/resources/schedule'
4
+ require 'logger'
5
+
6
+ module TableauServerClient
7
+ class Server
8
+
9
+ def initialize(server_url, username, password,
10
+ site_name: "default", api_version: "2.8", token_lifetime: 240)
11
+ @logger = ::Logger.new(STDOUT)
12
+ @logger.level = ::Logger::INFO
13
+ @client = Client.new(server_url, username, password, site_name, api_version, token_lifetime, @logger)
14
+ end
15
+
16
+ def sites
17
+ client.get_collection Resources::Site.location(path)
18
+ end
19
+
20
+ def site(id)
21
+ client.get Resources::Site.location(path, id)
22
+ end
23
+
24
+ def schedules
25
+ client.get_collection Resources::Schedule.location(path)
26
+ end
27
+
28
+ def path
29
+ nil
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :client
35
+
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ require 'nokogiri'
2
+
3
+ module TableauServerClient
4
+
5
+ class Token
6
+
7
+ def initialize(site_id, user_id, token, lifetime, created_at = Time.now)
8
+ @site_id = site_id
9
+ @user_id = user_id
10
+ @token = token
11
+ @lifetime = lifetime
12
+ @created_at = created_at
13
+ end
14
+
15
+ attr_reader :site_id, :user_id, :token
16
+
17
+ def self.parse(xml, lifetime)
18
+ cred = Nokogiri::XML(xml).xpath("//xmlns:credentials")
19
+ sid = cred.xpath("//xmlns:site")[0]['id']
20
+ uid = cred.xpath("//xmlns:user")[0]['id']
21
+ new(sid, uid, cred[0]['token'], lifetime)
22
+ end
23
+
24
+ SAFETY_BUFFER_MIN = 10
25
+
26
+ def valid?
27
+ Time.now < @created_at + (@lifetime + SAFETY_BUFFER_MIN) * 60
28
+ end
29
+
30
+ def to_s
31
+ @token
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,3 @@
1
+ module TableauServerClient
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tableau-server-client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tableau_server_client"
8
+ spec.version = TableauServerClient::VERSION
9
+ spec.authors = ["shimpeko"]
10
+ spec.email = ["shimpeko@swimmingpython.com"]
11
+
12
+ spec.summary = %q{Tableau Server REST API Client}
13
+ spec.description = %q{REST API Client for Tableau Server.}
14
+ spec.homepage = "https://github.com/shimpeko/tableau-server-client"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "bin"
21
+ spec.executables = ["console"]
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.13"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "byebug"
28
+
29
+ spec.add_dependency 'faraday', '>= 0.14.0'
30
+ spec.add_dependency 'nokogiri', '>= 1.8.2'
31
+ spec.add_dependency 'pry', '>= 0.11.3'
32
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tableau_server_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - shimpeko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.14.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.14.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: nokogiri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.8.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.8.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.11.3
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.11.3
111
+ description: REST API Client for Tableau Server.
112
+ email:
113
+ - shimpeko@swimmingpython.com
114
+ executables:
115
+ - console
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - Gemfile
120
+ - Gemfile.lock
121
+ - README.md
122
+ - Rakefile
123
+ - bin/console
124
+ - lib/tableau-server-client/client.rb
125
+ - lib/tableau-server-client/paginatable_response.rb
126
+ - lib/tableau-server-client/request_builder.rb
127
+ - lib/tableau-server-client/request_url.rb
128
+ - lib/tableau-server-client/resources/connection.rb
129
+ - lib/tableau-server-client/resources/datasource.rb
130
+ - lib/tableau-server-client/resources/project.rb
131
+ - lib/tableau-server-client/resources/resource.rb
132
+ - lib/tableau-server-client/resources/schedule.rb
133
+ - lib/tableau-server-client/resources/site.rb
134
+ - lib/tableau-server-client/resources/workbook.rb
135
+ - lib/tableau-server-client/server.rb
136
+ - lib/tableau-server-client/token.rb
137
+ - lib/tableau-server-client/version.rb
138
+ - tableau_server_client.gemspec
139
+ homepage: https://github.com/shimpeko/tableau-server-client
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.6.8
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Tableau Server REST API Client
163
+ test_files: []