superset 0.2.6 → 0.2.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddf012f64fba5d3e1fe7584f41fc5ddcbdf9b20dea686efca47ae99e9e228c58
4
- data.tar.gz: 9295923ac58ea7f24d92e978f94d8bbcbb6c06dd4cc821de4d67c3b57ebd08d0
3
+ metadata.gz: c6b2b4cb255df5113b61de937f565c6f004c5df347bb047f0c47e6f1c06eadd2
4
+ data.tar.gz: a34377f58a2dbbfc0bcbcf7a897bee918760707c01b33c41d1119af0d940840d
5
5
  SHA512:
6
- metadata.gz: 563f5e16113862396196f5b0bbfe8fc96b2edce69d14089e464592f3770a9da156d50ebacc2098e6b4fc1a7766c568571d25a33507db86c2641d92ac5f518ea7
7
- data.tar.gz: 8a02610f9d42328bff42753363ddb651924af87da82abfcd9311a16dd8ab9293e1f035d4f6e60e097e7f82c1b28165d5a009dfae4de0b1c0b1d8b16a2f00f704
6
+ metadata.gz: c734a5177395f6981fa7733ee0a6c44c1839ca080eb18ad9c4c6e8d12f7adb2948f7710c5d5d2c13015c855cce03169b0ddf5b93254e17929173e3a81503501b
7
+ data.tar.gz: 3db00f88ca7dd063ace17729b41cc5c5c7e30b3b77ef37a15ccee83873cbe02caf1460bd30b397a4d28a7d3971179f57d9b0194a186ebf05b194e90a050ed650
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## Change Log
2
2
 
3
+ ## 0.2.7 - 2025-10-16
4
+ * add to_h method to list classes for Hash output
5
+ * add ids method to list classes for array of ids output
6
+ * add ability to over ride default page_size
7
+ * add ruby console auto timeout set to 30 mins by default
8
+ * add GetCatalogs endpoint caller
9
+ * fix catalog bug related to dashboard export and import across env
10
+ * add tag_equals param to dashboard list class
11
+
3
12
  ## 0.2.6 - 2025-08-05
4
13
  * Bump terminal-table from 1.8.0 to 4.0.0
5
14
 
@@ -2,13 +2,13 @@ module Superset
2
2
  module Chart
3
3
  class List < Superset::Request
4
4
 
5
- attr_reader :name_contains, :dashboard_id_eq, :dataset_id_eq
5
+ attr_reader :title_contains, :dashboard_id_eq, :dataset_id_eq
6
6
 
7
- def initialize(page_num: 0, name_contains: '', dashboard_id_eq: '', dataset_id_eq: '')
8
- @name_contains = name_contains
7
+ def initialize(title_contains: '', dashboard_id_eq: '', dataset_id_eq: '', **kwargs)
8
+ @title_contains = title_contains
9
9
  @dashboard_id_eq = dashboard_id_eq
10
10
  @dataset_id_eq = dataset_id_eq
11
- super(page_num: page_num)
11
+ super(**kwargs)
12
12
  end
13
13
 
14
14
  def self.call
@@ -38,7 +38,7 @@ module Superset
38
38
  def filters
39
39
  # TODO filtering across all classes needs a refactor to support multiple options in a more flexible way
40
40
  filter_set = []
41
- filter_set << "(col:slice_name,opr:ct,value:'#{name_contains}')" if name_contains.present?
41
+ filter_set << "(col:slice_name,opr:ct,value:'#{title_contains}')" if title_contains.present?
42
42
  filter_set << "(col:dashboards,opr:rel_m_m,value:#{dashboard_id_eq})" if dashboard_id_eq.present? # rel many to many
43
43
  filter_set << "(col:datasource_id,opr:eq,value:#{dataset_id_eq})" if dataset_id_eq.present?
44
44
 
@@ -5,15 +5,18 @@
5
5
  module Superset
6
6
  module Dashboard
7
7
  class List < Superset::Request
8
- attr_reader :title_contains, :title_equals, :tags_equal, :ids_not_in, :include_filter_dataset_schemas
8
+ attr_reader :title_contains, :title_equals,
9
+ :tags_contain, :tags_equal,
10
+ :ids_not_in, :include_filter_dataset_schemas
9
11
 
10
- def initialize(page_num: 0, title_contains: '', title_equals: '', tags_equal: [], ids_not_in: [], include_filter_dataset_schemas: false)
12
+ def initialize(title_contains: '', title_equals: '', tags_contain: [], tags_equal: [], ids_not_in: [], include_filter_dataset_schemas: false, **kwargs)
11
13
  @title_contains = title_contains
12
14
  @title_equals = title_equals
15
+ @tags_contain = tags_contain
13
16
  @tags_equal = tags_equal
14
17
  @ids_not_in = ids_not_in
15
18
  @include_filter_dataset_schemas = include_filter_dataset_schemas
16
- super(page_num: page_num)
19
+ super(**kwargs)
17
20
  end
18
21
 
19
22
  def self.call
@@ -57,8 +60,16 @@ module Superset
57
60
  end
58
61
  end
59
62
 
63
+ def to_h
64
+ result.map do |d|
65
+ list_attributes.to_h do |la|
66
+ la == :url ? [la, "#{superset_host}#{d[la]}"] : [la, d[la]]
67
+ end
68
+ end
69
+ end
70
+
60
71
  def ids
61
- result.map { |d| d[:id] }
72
+ result.is_a?(Hash) ? [result[:id]] : result.map { |d| d[:id] }
62
73
  end
63
74
 
64
75
  private
@@ -72,15 +83,30 @@ module Superset
72
83
  filter_set = []
73
84
  filter_set << "(col:dashboard_title,opr:ct,value:'#{title_contains}')" if title_contains.present?
74
85
  filter_set << "(col:dashboard_title,opr:eq,value:'#{title_equals}')" if title_equals.present?
75
- filter_set << tag_filters if tags_equal.present?
86
+ filter_set << tags_contain_filters if tags_contain.present?
87
+ filter_set << tags_equal_filters if tags_equal.present?
76
88
  filter_set << ids_not_in_filters if ids_not_in.present?
89
+
77
90
  unless filter_set.empty?
78
91
  "filters:!(" + filter_set.join(',') + "),"
79
92
  end
80
93
  end
81
94
 
82
- def tag_filters
83
- tags_equal.map {|tag| "(col:tags,opr:dashboard_tags,value:'#{tag}')"}.join(',')
95
+ def tags_equal_filters
96
+ tags_equal_ids.map { |id| "(col:tags,opr:dashboard_tag_id,value:#{id})" }.join(',')
97
+ end
98
+
99
+ def tags_equal_ids
100
+ tags_equal.map do |tag_name|
101
+ ids = Superset::Tag::List.new(name_equals: tag_name).rows.map(&:first)
102
+ raise "No ID found for tag: #{tag_name}" if ids.empty?
103
+ raise "Multiple IDs found for tag: #{tag_name}" if ids.size > 1
104
+ ids.first
105
+ end
106
+ end
107
+
108
+ def tags_contain_filters
109
+ tags_contain.map {|tag| "(col:tags,opr:dashboard_tags,value:'#{tag}')"}.join(',')
84
110
  end
85
111
 
86
112
  def ids_not_in_filters
@@ -94,8 +120,8 @@ module Superset
94
120
  def validate_constructor_args
95
121
  raise InvalidParameterError, "title_contains must be a String type" unless title_contains.is_a?(String)
96
122
  raise InvalidParameterError, "title_equals must be a String type" unless title_equals.is_a?(String)
97
- raise InvalidParameterError, "tags_equal must be an Array type" unless tags_equal.is_a?(Array)
98
- raise InvalidParameterError, "tags_equal array must contain string only values" unless tags_equal.all? { |item| item.is_a?(String) }
123
+ raise InvalidParameterError, "tags_contain must be an Array type of String values" unless tags_contain.is_a?(Array) && tags_contain.all? { |item| item.is_a?(String) }
124
+ raise InvalidParameterError, "tags_equal must be an Array type of String values" unless tags_equal.is_a?(Array) && tags_equal.all? { |item| item.is_a?(String) }
99
125
  raise InvalidParameterError, "ids_not_in must be an Array type" unless ids_not_in.is_a?(Array)
100
126
  end
101
127
  end
@@ -0,0 +1,38 @@
1
+ module Superset
2
+ module Database
3
+ class GetCatalogs < Superset::Request
4
+
5
+ attr_reader :id, :include_system_catalogs
6
+
7
+ def initialize(id, include_system_catalogs: false)
8
+ @id = id
9
+ @include_system_catalogs = include_system_catalogs
10
+ end
11
+
12
+ def self.call(id)
13
+ self.new(id).catalogs
14
+ end
15
+
16
+ def catalogs
17
+ return result if include_system_catalogs
18
+
19
+ remove_system_catalogs
20
+ end
21
+
22
+ private
23
+
24
+ def route
25
+ "database/#{id}/catalogs/"
26
+ end
27
+
28
+ # exclude system catalog values for certain databases that support them
29
+ def remove_system_catalogs
30
+ result - postgres_system_catalogs
31
+ end
32
+
33
+ def postgres_system_catalogs
34
+ %w(postgres rdsadmin template1 template0)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -6,10 +6,10 @@ module Superset
6
6
  class List < Superset::Request
7
7
  attr_reader :title_contains, :uuid_equals
8
8
 
9
- def initialize(page_num: 0, title_contains: '', uuid_equals: '')
9
+ def initialize(title_contains: '', uuid_equals: '', **kwargs)
10
10
  @title_contains = title_contains
11
11
  @uuid_equals = uuid_equals
12
- super(page_num: page_num)
12
+ super(**kwargs)
13
13
  end
14
14
 
15
15
  def self.call
@@ -18,7 +18,11 @@ module Superset
18
18
  end
19
19
 
20
20
  def rows
21
- [ [title, schema, database_name, database_id] ]
21
+ [to_h.values]
22
+ end
23
+
24
+ def to_h
25
+ list_attributes.to_h { |a| [a, send(a)] }
22
26
  end
23
27
 
24
28
  def schema
@@ -26,7 +30,7 @@ module Superset
26
30
  end
27
31
 
28
32
  def title
29
- result['name']
33
+ result['table_name']
30
34
  end
31
35
 
32
36
  def database_name
@@ -47,8 +51,8 @@ module Superset
47
51
  "dataset/#{id}"
48
52
  end
49
53
 
50
- def display_headers
51
- %w[title schema database_name, database_id]
54
+ def list_attributes
55
+ [:title, :schema, :database_name, :database_id]
52
56
  end
53
57
  end
54
58
  end
@@ -3,12 +3,12 @@ module Superset
3
3
  class List < Superset::Request
4
4
  attr_reader :title_contains, :title_equals, :schema_equals, :database_id_eq
5
5
 
6
- def initialize(page_num: 0, title_contains: '', title_equals: '', schema_equals: '', database_id_eq: '')
6
+ def initialize(title_contains: '', title_equals: '', schema_equals: '', database_id_eq: '', **kwargs)
7
7
  @title_contains = title_contains
8
8
  @title_equals = title_equals
9
9
  @schema_equals = schema_equals
10
10
  @database_id_eq = database_id_eq
11
- super(page_num: page_num)
11
+ super(**kwargs)
12
12
  end
13
13
 
14
14
  def self.call
@@ -2,12 +2,13 @@ module Superset
2
2
  module Dataset
3
3
  class UpdateSchema < Superset::Request
4
4
 
5
- attr_reader :source_dataset_id, :target_database_id, :target_schema, :remove_copy_suffix
5
+ attr_reader :source_dataset_id, :target_database_id, :target_schema, :target_catalog, :remove_copy_suffix
6
6
 
7
- def initialize(source_dataset_id: , target_database_id: , target_schema: , remove_copy_suffix: false)
7
+ def initialize(source_dataset_id: , target_database_id: , target_schema: , target_catalog: nil, remove_copy_suffix: false)
8
8
  @source_dataset_id = source_dataset_id
9
9
  @target_database_id = target_database_id
10
10
  @target_schema = target_schema
11
+ @target_catalog = target_catalog
11
12
  @remove_copy_suffix = remove_copy_suffix
12
13
  end
13
14
 
@@ -37,6 +38,7 @@ module Superset
37
38
 
38
39
  # primary database and schema changes
39
40
  new_params.merge!("database_id": target_database_id) # add the target database id
41
+ new_params['catalog'] = target_catalog
40
42
  new_params['schema'] = target_schema
41
43
  new_params['owners'] = new_params['owners'].map {|o| o['id'] } # expects an array of user ids
42
44
  new_params['table_name'] = new_params['table_name'].gsub(/ \(COPY\)/, '') if remove_copy_suffix
@@ -7,28 +7,37 @@ module Superset
7
7
  def table
8
8
  Terminal::Table.new(
9
9
  title: title,
10
- headings: headings,
10
+ headings: list_attributes.map(&:to_s).map(&:humanize),
11
11
  rows: rows
12
12
  )
13
13
  end
14
14
 
15
15
  def rows
16
- result.map do |d|
17
- list_attributes.map { |la| d[la].to_s }
16
+ if result.is_a?(Hash)
17
+ list_attributes.map { |la| result[la].to_s }
18
+ else
19
+ result.map do |d|
20
+ list_attributes.map { |la| d[la].to_s }
21
+ end
18
22
  end
19
23
  end
20
24
 
21
- def title
22
- self.class.to_s
25
+ def to_h
26
+ if result.is_a?(Hash)
27
+ list_attributes.to_h { |la| [la, result[la]] }
28
+ else
29
+ result.map do |d|
30
+ list_attributes.to_h { |la| [la, d[la]] }
31
+ end
32
+ end
23
33
  end
24
34
 
25
- def headings
26
- headings = display_headers ? display_headers : list_attributes
27
- headings.map(&:to_s).map(&:humanize)
35
+ def ids
36
+ result.map { |d| d[:id] }
28
37
  end
29
38
 
30
- def display_headers
31
- # optionally override this method to display custom headers
39
+ def title
40
+ self.class.to_s
32
41
  end
33
42
 
34
43
  def list_attributes
@@ -5,12 +5,13 @@ module Superset
5
5
  class InvalidParameterError < StandardError; end
6
6
  class ValidationError < StandardError; end
7
7
 
8
- PAGE_SIZE = 100
8
+ DEFAULT_PAGE_SIZE = 100
9
9
 
10
- attr_accessor :page_num
10
+ attr_accessor :page_num, :page_size
11
11
 
12
- def initialize(page_num: 0)
12
+ def initialize(page_num: 0, page_size: nil)
13
13
  @page_num = page_num
14
+ @page_size = page_size || DEFAULT_PAGE_SIZE
14
15
  end
15
16
 
16
17
  def self.call
@@ -51,7 +52,8 @@ module Superset
51
52
  end
52
53
 
53
54
  def pagination
54
- "page:#{page_num},page_size:#{PAGE_SIZE}"
55
+ raise InvalidParameterError, "page_size max is 1000 records" if page_size.to_i > 1000
56
+ "page:#{page_num},page_size:#{page_size}"
55
57
  end
56
58
 
57
59
  def filters
@@ -3,8 +3,8 @@ module Superset
3
3
  module PermissionsResources
4
4
  class List < Superset::Request
5
5
 
6
- def initialize(page_num: 0)
7
- super(page_num: page_num)
6
+ def initialize(**kwargs)
7
+ super(**kwargs)
8
8
  end
9
9
 
10
10
  private
@@ -4,10 +4,10 @@ module Superset
4
4
  class List < Superset::Request
5
5
  attr_reader :email_contains, :username_equals
6
6
 
7
- def initialize(page_num: 0, email_contains: '', username_equals: '')
7
+ def initialize(email_contains: '', username_equals: '', **kwargs)
8
8
  @email_contains = email_contains
9
9
  @username_equals = username_equals
10
- super(page_num: page_num)
10
+ super(**kwargs)
11
11
  end
12
12
 
13
13
  private
@@ -100,8 +100,12 @@ module Superset
100
100
  new_dataset_id = existing_datasets[0]["id"] # assuming that we do not name multiple datasets with same name in a single schema
101
101
  else
102
102
  new_dataset_id = Superset::Dataset::Duplicate.new(source_dataset_id: dataset[:id], new_dataset_name: new_dataset_name).perform
103
- # update the new dataset with the target schema and target database
104
- Superset::Dataset::UpdateSchema.new(source_dataset_id: new_dataset_id, target_database_id: target_database_id, target_schema: target_schema).perform
103
+ # update the new dataset with the target schema, database, catalog
104
+ Superset::Dataset::UpdateSchema.new(
105
+ source_dataset_id: new_dataset_id,
106
+ target_database_id: target_database_id,
107
+ target_schema: target_schema,
108
+ target_catalog: target_database_catalog).perform
105
109
  end
106
110
  # keep track of the previous dataset and the matching new dataset_id
107
111
  dataset_duplication_tracker << { source_dataset_id: dataset[:id], new_dataset_id: new_dataset_id }
@@ -263,6 +267,13 @@ module Superset
263
267
  @filter_dataset_ids ||= source_dashboard.filter_configuration.map { |c| c['targets'] }.flatten.compact.map { |c| c['datasetId'] }.flatten.compact.uniq
264
268
  end
265
269
 
270
+ # currently does not support multiple catalogs, assumption is that 1 catalog is used per database
271
+ def target_database_catalog
272
+ catalogs = Superset::Database::GetCatalogs.new(target_database_id).catalogs
273
+ raise ValidationError, "Target Database #{target_database_id} has multiple catalogs" if catalogs.size > 1
274
+ catalogs.first
275
+ end
276
+
266
277
  # Primary Assumption is that all charts datasets on the source dashboard are pointing to the same database schema
267
278
  # An unpermitted filter will have a dataset that is pulling data from a datasource that is
268
279
  # different to the dashboard charts database schema
@@ -56,6 +56,7 @@ module Superset
56
56
 
57
57
  def remove_source_database_config
58
58
  return if dashboard_config[:databases].blank?
59
+
59
60
  previous_database_name = dashboard_config[:databases]&.first[:content][:database_name]
60
61
  File.delete(dashboard_config[:databases].first[:filename])
61
62
 
@@ -78,6 +79,8 @@ module Superset
78
79
  dashboard_config[:datasets].each do |dataset|
79
80
  dataset[:content][:database_uuid] = dashboard_config[:databases].first[:content][:uuid]
80
81
  dataset[:content][:schema] = target_database_schema
82
+ dataset[:content][:catalog] = nil # reset target to use default catalog if applicable
83
+
81
84
  stringified_content = deep_transform_keys_to_strings(dataset[:content])
82
85
  File.open(dataset[:filename], 'w') { |f| f.write stringified_content.to_yaml }
83
86
  end
@@ -23,7 +23,7 @@ module Superset
23
23
  # TODO filtering across all list classes can be refactored to support multiple options in a more flexible way
24
24
  filter_set = []
25
25
  filter_set << "(col:name,opr:ct,value:'#{name_contains}')" if name_contains.present?
26
- filter_set << "(col:name,opr:eq,value:#{name_equals})" if name_equals.present?
26
+ filter_set << "(col:name,opr:eq,value:'#{name_equals}')" if name_equals.present?
27
27
  unless filter_set.empty?
28
28
  "filters:!(" + filter_set.join(',') + "),"
29
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Superset
4
- VERSION = "0.2.6"
4
+ VERSION = "0.2.7"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superset
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - jbat
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-05 00:00:00.000000000 Z
11
+ date: 2025-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -249,6 +249,7 @@ files:
249
249
  - lib/superset/dashboard/warm_up_cache.rb
250
250
  - lib/superset/database/export.rb
251
251
  - lib/superset/database/get.rb
252
+ - lib/superset/database/get_catalogs.rb
252
253
  - lib/superset/database/get_schemas.rb
253
254
  - lib/superset/database/list.rb
254
255
  - lib/superset/dataset/bulk_delete.rb