altertable-lakehouse 0.5.1 → 0.7.0

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: 5a603bff18558e212586e0bb27016f56c832266d7dedce34ee0a7cf5a6b820a5
4
- data.tar.gz: 4203dd0b9b090439722b8f51c8ad931048689e37ab1078738b541b0644f07427
3
+ metadata.gz: 730648db52f373495553ad9179f698b55a1bc309e5e5465a3e39733bc4659ab4
4
+ data.tar.gz: 0adb085fa50da366e377cb1b847273c0020ef058b871a143866b4c2d1558e106
5
5
  SHA512:
6
- metadata.gz: 48b6b338259bdfa8ef5b65f967b76ec8ef79b48bba966eff4cd32c123c16ad94c7e3bb90d30ea09325d9b96f4313ea193f5e9bf639207f1969d0f640e869f44a
7
- data.tar.gz: 3459d13102d1a68eb09aaa8cdb969d0bb0ec7157061ceb83873eea9af545e0414f4702939d693eb32bcbe8a7c4208379041cb971b02de261f735801851304895
6
+ metadata.gz: 1cde4636923e138c259a738f96d84305ff6a8aa929dc12e49f792989da2ee0a2394db20f2a37f80dcda21b304ebb7c3860122bd46b6cc4a01ca0ddadd805bc38
7
+ data.tar.gz: baffcdd22da74b9006f153f41b87703f93ba0351f3edcc2082576472b3ef52451656ee0bdc2afe72e79ff6835d10a1049ccc6555bc92c1bf23b82184e65cd54a
@@ -0,0 +1 @@
1
+ github: [altertable-ai]
@@ -37,7 +37,7 @@ body:
37
37
  - type: input
38
38
  id: runtime
39
39
  attributes:
40
- label: "{language} Version"
40
+ label: "Ruby Version"
41
41
  validations:
42
42
  required: true
43
43
  - type: dropdown
@@ -0,0 +1,13 @@
1
+ ## What
2
+
3
+ <!-- What does this PR do? One sentence is fine. -->
4
+
5
+ ## Why
6
+
7
+ <!-- Link an issue or explain the motivation. -->
8
+
9
+ ## Checklist
10
+
11
+ - [ ] Tests added or updated
12
+ - [ ] `CHANGELOG.md` updated (skip for docs/CI-only changes)
13
+ - [ ] Breaking change noted in commit footer (`BREAKING CHANGE: …`) and changelog
@@ -6,7 +6,7 @@ on:
6
6
  pull_request: {}
7
7
  jobs:
8
8
  test:
9
- runs-on: ubuntu-latest
9
+ runs-on: ubuntu-24.04
10
10
  strategy:
11
11
  matrix:
12
12
  ruby-version: ["3.2", "3.3", "3.4", "4.0"]
@@ -26,12 +26,12 @@ jobs:
26
26
  --health-start-period 10s
27
27
 
28
28
  steps:
29
- - uses: actions/checkout@v4
29
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
30
30
  with:
31
31
  submodules: recursive
32
32
 
33
33
  - name: Set up Ruby
34
- uses: ruby/setup-ruby@v1
34
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
35
35
  with:
36
36
  ruby-version: ${{ matrix.ruby-version }}
37
37
  bundler-cache: true
@@ -40,11 +40,11 @@ jobs:
40
40
  run: bundle exec rake spec
41
41
 
42
42
  lint:
43
- runs-on: ubuntu-latest
43
+ runs-on: ubuntu-24.04
44
44
  steps:
45
- - uses: actions/checkout@v4
45
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
46
46
  - name: Set up Ruby
47
- uses: ruby/setup-ruby@v1
47
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
48
48
  with:
49
49
  ruby-version: "3.4"
50
50
  bundler-cache: true
@@ -53,11 +53,11 @@ jobs:
53
53
 
54
54
  typing:
55
55
  name: "Typing"
56
- runs-on: ubuntu-latest
56
+ runs-on: ubuntu-24.04
57
57
  steps:
58
- - uses: actions/checkout@v4
58
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
59
59
  - name: Set up Ruby
60
- uses: ruby/setup-ruby@v1
60
+ uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
61
61
  with:
62
62
  ruby-version: "3.4"
63
63
  bundler-cache: true
@@ -7,14 +7,14 @@ on:
7
7
 
8
8
  jobs:
9
9
  check:
10
- runs-on: ubuntu-latest
10
+ runs-on: ubuntu-24.04
11
11
 
12
12
  permissions:
13
13
  contents: write
14
14
  pull-requests: write
15
15
 
16
16
  steps:
17
- - uses: googleapis/release-please-action@v4
17
+ - uses: googleapis/release-please-action@8b8fd2cc23b2e18957157a9d923d75aa0c6f6ad5 # v4
18
18
  id: release
19
19
  with:
20
20
  token: ${{ secrets.GITHUB_TOKEN }}
@@ -29,7 +29,7 @@ jobs:
29
29
 
30
30
  if: ${{ needs.check.outputs.release_created }}
31
31
 
32
- runs-on: ubuntu-latest
32
+ runs-on: ubuntu-24.04
33
33
 
34
34
  permissions:
35
35
  contents: write
@@ -37,11 +37,11 @@ jobs:
37
37
  id-token: write
38
38
 
39
39
  steps:
40
- - uses: actions/checkout@v4
40
+ - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
41
41
  with:
42
42
  persist-credentials: false
43
- - uses: ruby/setup-ruby@v1
43
+ - uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
44
44
  with:
45
45
  ruby-version: 3.4
46
46
  bundler-cache: true
47
- - uses: rubygems/release-gem@v1
47
+ - uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1
@@ -0,0 +1,34 @@
1
+ name: Semantic Pull Request
2
+
3
+ on:
4
+ pull_request_target:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - synchronize
9
+
10
+ permissions:
11
+ pull-requests: read
12
+
13
+ jobs:
14
+ semantic-pr:
15
+ name: Validate PR title
16
+ runs-on: ubuntu-24.04
17
+ steps:
18
+ - name: Validate title
19
+ uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5
20
+ env:
21
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22
+ with:
23
+ types: |
24
+ feat
25
+ fix
26
+ perf
27
+ revert
28
+ docs
29
+ style
30
+ chore
31
+ refactor
32
+ test
33
+ build
34
+ ci
@@ -1,4 +1,5 @@
1
1
  name: Semantic Pull Request
2
+
2
3
  on:
3
4
  pull_request_target:
4
5
  types:
@@ -6,12 +7,21 @@ on:
6
7
  - edited
7
8
  - synchronize
8
9
 
10
+ permissions:
11
+ pull-requests: read
12
+
13
+ concurrency:
14
+ group: semantic-pr-${{ github.event.pull_request.number }}
15
+ cancel-in-progress: true
16
+
9
17
  jobs:
10
18
  main:
11
19
  name: Validate PR title
12
- runs-on: ubuntu-latest
20
+ runs-on: ubuntu-24.04
21
+ timeout-minutes: 5
13
22
  steps:
14
- - uses: amannn/action-semantic-pull-request@v5
23
+ - name: Validate pull request title
24
+ uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
15
25
  env:
16
26
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17
27
  with:
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.5.1"
2
+ ".": "0.7.0"
3
3
  }
data/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.7.0](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.6.0...altertable-lakehouse/v0.7.0) (2026-08-26)
6
+
7
+
8
+ ### Features
9
+
10
+ * pass proxy through as a raw options override ([#50](https://github.com/altertable-ai/altertable-lakehouse-ruby/issues/50)) ([f2af534](https://github.com/altertable-ai/altertable-lakehouse-ruby/commit/f2af53452b42b8421f6529d532e23546ffe80c16))
11
+
12
+ ## [0.6.0](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.5.1...altertable-lakehouse/v0.6.0) (2026-06-30)
13
+
14
+
15
+ ### Features
16
+
17
+ * add configurable open timeout ([#41](https://github.com/altertable-ai/altertable-lakehouse-ruby/issues/41)) ([f568a96](https://github.com/altertable-ai/altertable-lakehouse-ruby/commit/f568a96a4fcc59dd91a622c6119779e1e9171bda))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **api:** expose upsert API ([#42](https://github.com/altertable-ai/altertable-lakehouse-ruby/issues/42)) ([fcda808](https://github.com/altertable-ai/altertable-lakehouse-ruby/commit/fcda808db2c52a526d848f56fa3509bdb2738310))
23
+
5
24
  ## [0.5.1](https://github.com/altertable-ai/altertable-lakehouse-ruby/compare/altertable-lakehouse/v0.5.0...altertable-lakehouse/v0.5.1) (2026-05-29)
6
25
 
7
26
 
@@ -66,7 +85,7 @@ All notable changes to this project will be documented in this file.
66
85
 
67
86
  ### Added
68
87
  - Initial implementation of Altertable Lakehouse Ruby Client.
69
- - Support for `append`, `query` (streamed/accumulated), `upload`, `validate`.
88
+ - Support for `append`, `query` (streamed/accumulated), `upsert`, `validate`.
70
89
  - Support for `get_query`, `cancel_query`.
71
90
  - Typed request/response models.
72
91
  - Faraday-based HTTP client with retries.
data/CODE_OF_CONDUCT.md CHANGED
@@ -70,14 +70,14 @@ Community leaders will follow these Community Impact Guidelines in determining t
70
70
 
71
71
  ## Attribution
72
72
 
73
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
73
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][v2.1].
74
74
 
75
75
  Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
76
76
 
77
- For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
77
+ For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq/][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations/][translations].
78
78
 
79
79
  [homepage]: https://www.contributor-covenant.org
80
- [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
81
- [Mozilla CoC]: https://github.com/mozilla/diversity
82
- [FAQ]: https://www.contributor-covenant.org/faq
83
- [translations]: https://www.contributor-covenant.org/translations
80
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
81
+ [Mozilla CoC]: https://github.com/mozilla/inclusion
82
+ [FAQ]: https://www.contributor-covenant.org/faq/
83
+ [translations]: https://www.contributor-covenant.org/translations/
data/CONTRIBUTING.md CHANGED
@@ -1,4 +1,4 @@
1
- # Contributing to altertable-lakehouse-ruby
1
+ # Contributing to altertable-lakehouse
2
2
 
3
3
  ## Development Setup
4
4
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- altertable-lakehouse (0.5.1)
4
+ altertable-lakehouse (0.7.0)
5
5
  base64
6
6
 
7
7
  GEM
@@ -108,6 +108,8 @@ GEM
108
108
  rexml (>= 3.2.6)
109
109
  sorbet-static-and-runtime (>= 0.5.10187)
110
110
  thor (>= 0.19.2)
111
+ stub_env (1.0.4)
112
+ rspec (>= 2.0, < 4.0)
111
113
  tapioca (0.17.7)
112
114
  benchmark
113
115
  bundler (>= 2.2.25)
@@ -150,6 +152,7 @@ DEPENDENCIES
150
152
  rubocop (~> 1.50)
151
153
  sorbet
152
154
  sorbet-runtime
155
+ stub_env
153
156
  tapioca
154
157
  testcontainers
155
158
 
data/README.md CHANGED
@@ -57,7 +57,9 @@ client = Altertable::Lakehouse::Client.new(
57
57
  username: "your_username",
58
58
  password: "your_password",
59
59
  base_url: "https://api.altertable.ai", # Optional
60
- timeout: 10 # Optional
60
+ timeout: 10, # Optional
61
+ open_timeout: 5, # Optional
62
+ proxy: nil # Optional; omit to honor HTTP(S)_PROXY, or pass nil/a custom proxy URL to override
61
63
  )
62
64
 
63
65
  # 2. Pre-encoded Basic Auth Token
@@ -144,7 +146,7 @@ end
144
146
 
145
147
  ### `upload`
146
148
 
147
- Uploads a file (CSV, Parquet, etc.) to a table.
149
+ Uploads a file (CSV, Parquet, etc.) to create, append, or overwrite a table.
148
150
 
149
151
  ```ruby
150
152
  File.open("data.csv", "rb") do |file|
@@ -152,13 +154,28 @@ File.open("data.csv", "rb") do |file|
152
154
  catalog: "main",
153
155
  schema: "public",
154
156
  table: "events",
155
- format: "csv",
156
157
  mode: "append",
157
158
  file_io: file
158
159
  )
159
160
  end
160
161
  ```
161
162
 
163
+ ### `upsert`
164
+
165
+ Upserts a file by matching rows on a primary key.
166
+
167
+ ```ruby
168
+ File.open("updates.csv", "rb") do |file|
169
+ client.upsert(
170
+ catalog: "main",
171
+ schema: "public",
172
+ table: "events",
173
+ primary_key: "id",
174
+ file_io: file
175
+ )
176
+ end
177
+ ```
178
+
162
179
  ### `get_query`
163
180
 
164
181
  Retrieves information about a query execution.
@@ -234,6 +251,7 @@ end
234
251
  | `basic_auth_token` | String | `ENV["ALTERTABLE_BASIC_AUTH_TOKEN"]` | Pre-encoded Basic Auth token |
235
252
  | `base_url` | String | `https://api.altertable.ai` | API base URL |
236
253
  | `timeout` | Integer | `10` | Request timeout in seconds |
254
+ | `open_timeout` | Integer | `5` | Connection timeout in seconds |
237
255
  | `user_agent` | String | `nil` | Custom User-Agent suffix |
238
256
 
239
257
  ## License
data/SECURITY.md CHANGED
@@ -8,7 +8,7 @@ Only the latest minor release receives security patches.
8
8
 
9
9
  **Do not open a public issue.**
10
10
 
11
- Email security@altertable.ai with:
11
+ Email <security@altertable.ai> with:
12
12
 
13
13
  1. Description of the vulnerability
14
14
  2. Steps to reproduce
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "rake", "~> 13.0"
35
35
  spec.add_development_dependency "rspec", "~> 3.0"
36
36
  spec.add_development_dependency "rubocop", "~> 1.50"
37
+ spec.add_development_dependency "stub_env"
37
38
  spec.add_development_dependency "testcontainers"
38
39
  spec.add_development_dependency "rbs"
39
40
  spec.add_development_dependency "sorbet"
@@ -4,10 +4,12 @@ module Altertable
4
4
  Response = Struct.new(:status, :body, :headers)
5
5
 
6
6
  class Base
7
- def initialize(base_url:, timeout:, headers: {})
7
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options)
8
8
  @base_url = base_url
9
9
  @timeout = timeout
10
+ @open_timeout = open_timeout
10
11
  @headers = headers
12
+ @options = options
11
13
  end
12
14
 
13
15
  def get(path, body: nil, params: {}, headers: {}, &_block)
@@ -24,16 +26,18 @@ module Altertable
24
26
  end
25
27
 
26
28
  class FaradayAdapter < Base
27
- def initialize(base_url:, timeout:, headers: {})
29
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options)
28
30
  super
29
31
  require "faraday"
30
32
  require "faraday/retry"
31
33
  require "faraday/net_http"
32
-
34
+
33
35
  @conn = Faraday.new(url: @base_url) do |f|
34
36
  @headers.each { |k, v| f.headers[k] = v }
35
37
  f.options.timeout = @timeout
38
+ f.options.open_timeout = @open_timeout
36
39
  f.request :retry, max: 3, interval: 0.05, backoff_factor: 2
40
+ f.proxy = options[:proxy] if options.key?(:proxy)
37
41
  f.adapter Faraday.default_adapter
38
42
  end
39
43
  end
@@ -78,16 +82,18 @@ module Altertable
78
82
  end
79
83
 
80
84
  class HttpxAdapter < Base
81
- def initialize(base_url:, timeout:, headers: {})
85
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options)
82
86
  super
83
87
  require "httpx"
84
88
  # Configure retries plugin if available or implement manual retries?
85
89
  # Httpx has built-in retries via plugin.
86
- @client = HTTPX.plugin(:retries).with(
87
- timeout: { operation_timeout: @timeout },
90
+ http_options = {
91
+ timeout: { operation_timeout: @timeout, connect_timeout: @open_timeout },
88
92
  headers: @headers,
89
93
  base_url: @base_url
90
- )
94
+ }
95
+ http_options[:proxy] = options[:proxy] if options.key?(:proxy)
96
+ @client = HTTPX.plugin(:retries).with(**http_options)
91
97
  end
92
98
 
93
99
  def get(path, body: nil, params: {}, headers: {}, &_block) # rubocop:disable Lint/UnusedMethodArgument
@@ -133,7 +139,7 @@ module Altertable
133
139
  end
134
140
 
135
141
  class NetHttpAdapter < Base
136
- def initialize(base_url:, timeout:, headers: {})
142
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options)
137
143
  super
138
144
  require "net/http"
139
145
  require "uri"
@@ -164,7 +170,9 @@ module Altertable
164
170
  req.body = body if body
165
171
 
166
172
  # Net::HTTP start
167
- Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", open_timeout: @timeout, read_timeout: @timeout) do |http|
173
+ start_args = [uri.host, uri.port]
174
+ start_args << @options[:proxy] if @options.key?(:proxy)
175
+ Net::HTTP.start(*start_args, use_ssl: uri.scheme == "https", open_timeout: @open_timeout, read_timeout: @timeout) do |http|
168
176
  if block_given?
169
177
  http.request(req) do |response|
170
178
  # Stream the body if block is given
@@ -10,8 +10,9 @@ module Altertable
10
10
  class Client
11
11
  DEFAULT_BASE_URL = "https://api.altertable.ai"
12
12
  DEFAULT_TIMEOUT = 10
13
+ DEFAULT_OPEN_TIMEOUT = 5
13
14
 
14
- def initialize(username: nil, password: nil, basic_auth_token: nil, base_url: nil, timeout: nil, user_agent: nil, adapter: nil, headers: {})
15
+ def initialize(username: nil, password: nil, basic_auth_token: nil, base_url: nil, timeout: nil, open_timeout: nil, user_agent: nil, adapter: nil, headers: {}, **options)
15
16
  # 1. Try passed basic_auth_token
16
17
  # 2. Try passed username/password
17
18
  # 3. Try ENV["ALTERTABLE_BASIC_AUTH_TOKEN"]
@@ -31,15 +32,15 @@ module Altertable
31
32
 
32
33
  @base_url = base_url || DEFAULT_BASE_URL
33
34
  @timeout = timeout || DEFAULT_TIMEOUT
35
+ @open_timeout = open_timeout || DEFAULT_OPEN_TIMEOUT
34
36
  @user_agent = user_agent ? "AltertableRuby/#{VERSION} #{user_agent}" : "AltertableRuby/#{VERSION}"
35
37
 
36
38
  default_headers = {
37
39
  "Authorization" => @auth_header,
38
- "User-Agent" => @user_agent,
39
- "Content-Type" => "application/json"
40
+ "User-Agent" => @user_agent
40
41
  }
41
42
 
42
- @adapter = select_adapter(adapter, base_url: @base_url, timeout: @timeout, headers: default_headers.merge(headers))
43
+ @adapter = select_adapter(adapter, base_url: @base_url, timeout: @timeout, open_timeout: @open_timeout, headers: default_headers.merge(headers), **options)
43
44
  end
44
45
 
45
46
  # POST /append
@@ -65,7 +66,7 @@ module Altertable
65
66
  buffer = ""
66
67
 
67
68
  # Use adapter's stream capability
68
- resp = @adapter.post("/query", body: req_body, headers: headers) do |chunk, _|
69
+ resp = @adapter.post("/query", body: req_body, headers: json_headers(headers)) do |chunk, _|
69
70
  buffer << chunk
70
71
  end
71
72
 
@@ -87,19 +88,32 @@ module Altertable
87
88
  end
88
89
 
89
90
  # POST /upload
90
- def upload(catalog:, schema:, table:, format:, mode:, file_io:, primary_key: nil, headers: {})
91
+ def upload(catalog:, schema:, table:, mode:, file_io:, headers: {})
91
92
  params = {
92
93
  catalog: catalog,
93
94
  schema: schema,
94
95
  table: table,
95
- format: format,
96
96
  mode: mode
97
97
  }
98
- params[:primary_key] = primary_key if primary_key
99
98
 
100
99
  body = file_io.respond_to?(:read) ? file_io.read : file_io
101
100
 
102
- resp = @adapter.post("/upload", body: body, params: params, headers: headers.merge("Content-Type" => "application/octet-stream"))
101
+ resp = @adapter.post("/upload", body: body, params: params, headers: headers)
102
+ handle_response(resp)
103
+ end
104
+
105
+ # POST /upsert
106
+ def upsert(catalog:, schema:, table:, primary_key:, file_io:, headers: {})
107
+ params = {
108
+ catalog: catalog,
109
+ schema: schema,
110
+ table: table,
111
+ primary_key: primary_key
112
+ }
113
+
114
+ body = file_io.respond_to?(:read) ? file_io.read : file_io
115
+
116
+ resp = @adapter.post("/upsert", body: body, params: params, headers: headers)
103
117
  handle_response(resp)
104
118
  end
105
119
 
@@ -187,11 +201,15 @@ module Altertable
187
201
  method, path,
188
202
  body: encode_request_body(body),
189
203
  params: query || {},
190
- headers: headers
204
+ headers: body.nil? ? headers : json_headers(headers)
191
205
  )
192
206
  handle_response(resp)
193
207
  end
194
208
 
209
+ def json_headers(headers)
210
+ { "Content-Type" => "application/json" }.merge(headers)
211
+ end
212
+
195
213
  def encode_request_body(body)
196
214
  case body
197
215
  when Hash, Array
@@ -1,5 +1,5 @@
1
1
  module Altertable
2
2
  module Lakehouse
3
- VERSION = "0.5.1"
3
+ VERSION = "0.7.0"
4
4
  end
5
5
  end
@@ -53,6 +53,7 @@ module Altertable
53
53
  class Client
54
54
  DEFAULT_BASE_URL = T.let(T.unsafe(nil), String)
55
55
  DEFAULT_TIMEOUT = T.let(T.unsafe(nil), Integer)
56
+ DEFAULT_OPEN_TIMEOUT = T.let(T.unsafe(nil), Integer)
56
57
 
57
58
  sig do
58
59
  params(
@@ -61,12 +62,14 @@ module Altertable
61
62
  basic_auth_token: T.nilable(String),
62
63
  base_url: T.nilable(String),
63
64
  timeout: T.nilable(T.any(Integer, Float)),
65
+ open_timeout: T.nilable(T.any(Integer, Float)),
64
66
  user_agent: T.nilable(String),
65
67
  adapter: T.nilable(Symbol),
66
- headers: T::Hash[String, String]
68
+ headers: T::Hash[String, String],
69
+ options: T.untyped
67
70
  ).void
68
71
  end
69
- def initialize(username: nil, password: nil, basic_auth_token: nil, base_url: nil, timeout: nil, user_agent: nil, adapter: nil, headers: {}); end
72
+ def initialize(username: nil, password: nil, basic_auth_token: nil, base_url: nil, timeout: nil, open_timeout: nil, user_agent: nil, adapter: nil, headers: {}, **options); end
70
73
 
71
74
  sig do
72
75
  params(
@@ -94,14 +97,24 @@ module Altertable
94
97
  catalog: String,
95
98
  schema: String,
96
99
  table: String,
97
- format: String,
98
100
  mode: String,
99
101
  file_io: T.untyped,
100
- primary_key: T.nilable(String),
101
102
  headers: T::Hash[String, String]
102
103
  ).returns(T.untyped)
103
104
  end
104
- def upload(catalog:, schema:, table:, format:, mode:, file_io:, primary_key: nil, headers: {}); end
105
+ def upload(catalog:, schema:, table:, mode:, file_io:, headers: {}); end
106
+
107
+ sig do
108
+ params(
109
+ catalog: String,
110
+ schema: String,
111
+ table: String,
112
+ primary_key: String,
113
+ file_io: T.untyped,
114
+ headers: T::Hash[String, String]
115
+ ).returns(T.untyped)
116
+ end
117
+ def upsert(catalog:, schema:, table:, primary_key:, file_io:, headers: {}); end
105
118
 
106
119
  sig { params(query_id: String, headers: T::Hash[String, String]).returns(::Altertable::Lakehouse::Models::QueryLogResponse) }
107
120
  def get_query(query_id, headers: {}); end
@@ -664,8 +677,8 @@ module Altertable
664
677
  end
665
678
 
666
679
  class Base
667
- sig { params(base_url: String, timeout: T.any(Integer, Float), headers: T::Hash[String, String]).void }
668
- def initialize(base_url:, timeout:, headers: {}); end
680
+ sig { params(base_url: String, timeout: T.any(Integer, Float), open_timeout: T.any(Integer, Float), headers: T::Hash[String, String], options: T.untyped).void }
681
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options); end
669
682
 
670
683
  sig do
671
684
  params(
@@ -702,8 +715,8 @@ module Altertable
702
715
  end
703
716
 
704
717
  class FaradayAdapter < Base
705
- sig { params(base_url: String, timeout: T.any(Integer, Float), headers: T::Hash[String, String]).void }
706
- def initialize(base_url:, timeout:, headers: {}); end
718
+ sig { params(base_url: String, timeout: T.any(Integer, Float), open_timeout: T.any(Integer, Float), headers: T::Hash[String, String], options: T.untyped).void }
719
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options); end
707
720
 
708
721
  sig do
709
722
  params(
@@ -745,8 +758,8 @@ module Altertable
745
758
  end
746
759
 
747
760
  class HttpxAdapter < Base
748
- sig { params(base_url: String, timeout: T.any(Integer, Float), headers: T::Hash[String, String]).void }
749
- def initialize(base_url:, timeout:, headers: {}); end
761
+ sig { params(base_url: String, timeout: T.any(Integer, Float), open_timeout: T.any(Integer, Float), headers: T::Hash[String, String], options: T.untyped).void }
762
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options); end
750
763
 
751
764
  sig do
752
765
  params(
@@ -788,8 +801,8 @@ module Altertable
788
801
  end
789
802
 
790
803
  class NetHttpAdapter < Base
791
- sig { params(base_url: String, timeout: T.any(Integer, Float), headers: T::Hash[String, String]).void }
792
- def initialize(base_url:, timeout:, headers: {}); end
804
+ sig { params(base_url: String, timeout: T.any(Integer, Float), open_timeout: T.any(Integer, Float), headers: T::Hash[String, String], options: T.untyped).void }
805
+ def initialize(base_url:, timeout:, open_timeout:, headers: {}, **options); end
793
806
 
794
807
  sig do
795
808
  params(
@@ -12,9 +12,11 @@ module Altertable
12
12
  class Base
13
13
  @base_url: String
14
14
  @timeout: Integer | Float
15
+ @open_timeout: Integer | Float
15
16
  @headers: ::Hash[String, String]
17
+ @options: ::Hash[Symbol, untyped]
16
18
 
17
- def initialize: (base_url: String, timeout: Integer | Float, ?headers: ::Hash[String, String]) -> void
19
+ def initialize: (base_url: String, timeout: Integer | Float, open_timeout: Integer | Float, ?headers: ::Hash[String, String], **untyped options) -> void
18
20
  def get: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
19
21
  def post: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
20
22
  def delete: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
@@ -23,7 +25,7 @@ module Altertable
23
25
  class FaradayAdapter < Base
24
26
  @conn: untyped
25
27
 
26
- def initialize: (base_url: String, timeout: Integer | Float, ?headers: ::Hash[String, String]) -> void
28
+ def initialize: (base_url: String, timeout: Integer | Float, open_timeout: Integer | Float, ?headers: ::Hash[String, String], **untyped options) -> void
27
29
  def get: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
28
30
  def post: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
29
31
  def delete: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
@@ -36,7 +38,7 @@ module Altertable
36
38
  class HttpxAdapter < Base
37
39
  @client: untyped
38
40
 
39
- def initialize: (base_url: String, timeout: Integer | Float, ?headers: ::Hash[String, String]) -> void
41
+ def initialize: (base_url: String, timeout: Integer | Float, open_timeout: Integer | Float, ?headers: ::Hash[String, String], **untyped options) -> void
40
42
  def get: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
41
43
  def post: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
42
44
  def delete: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
@@ -49,7 +51,7 @@ module Altertable
49
51
  class NetHttpAdapter < Base
50
52
  @uri: URI::HTTP | URI::HTTPS
51
53
 
52
- def initialize: (base_url: String, timeout: Integer | Float, ?headers: ::Hash[String, String]) -> void
54
+ def initialize: (base_url: String, timeout: Integer | Float, open_timeout: Integer | Float, ?headers: ::Hash[String, String], **untyped options) -> void
53
55
  def get: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
54
56
  def post: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
55
57
  def delete: (String path, ?body: String?, ?params: ::Hash[Symbol | String, untyped], ?headers: ::Hash[String, String]) -> Response
@@ -4,11 +4,13 @@ module Altertable
4
4
  @auth_header: String
5
5
  @base_url: String
6
6
  @timeout: Integer | Float
7
+ @open_timeout: Integer | Float
7
8
  @user_agent: String
8
9
  @adapter: untyped
9
10
 
10
11
  DEFAULT_BASE_URL: String
11
12
  DEFAULT_TIMEOUT: Integer
13
+ DEFAULT_OPEN_TIMEOUT: Integer
12
14
 
13
15
  def initialize: (
14
16
  ?username: String?,
@@ -16,9 +18,11 @@ module Altertable
16
18
  ?basic_auth_token: String?,
17
19
  ?base_url: String?,
18
20
  ?timeout: Integer | Float?,
21
+ ?open_timeout: Integer | Float?,
19
22
  ?user_agent: String?,
20
23
  ?adapter: Symbol?,
21
- ?headers: ::Hash[String, String]
24
+ ?headers: ::Hash[String, String],
25
+ **untyped options
22
26
  ) -> void
23
27
 
24
28
  def append: (
@@ -40,10 +44,17 @@ module Altertable
40
44
  catalog: String,
41
45
  schema: String,
42
46
  table: String,
43
- format: String,
44
47
  mode: String,
45
48
  file_io: untyped,
46
- ?primary_key: String?,
49
+ ?headers: ::Hash[String, String]
50
+ ) -> untyped
51
+
52
+ def upsert: (
53
+ catalog: String,
54
+ schema: String,
55
+ table: String,
56
+ primary_key: String,
57
+ file_io: untyped,
47
58
  ?headers: ::Hash[String, String]
48
59
  ) -> untyped
49
60
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: altertable-lakehouse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Altertable AI
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
123
  version: '1.50'
124
+ - !ruby/object:Gem::Dependency
125
+ name: stub_env
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
124
138
  - !ruby/object:Gem::Dependency
125
139
  name: testcontainers
126
140
  requirement: !ruby/object:Gem::Requirement
@@ -184,10 +198,13 @@ executables: []
184
198
  extensions: []
185
199
  extra_rdoc_files: []
186
200
  files:
201
+ - ".github/FUNDING.yml"
187
202
  - ".github/ISSUE_TEMPLATE/bug_report.yml"
188
203
  - ".github/ISSUE_TEMPLATE/feature_request.yml"
204
+ - ".github/PULL_REQUEST_TEMPLATE.md"
189
205
  - ".github/workflows/ci.yml"
190
206
  - ".github/workflows/release-please.yml"
207
+ - ".github/workflows/semantic-pr.yml"
191
208
  - ".github/workflows/semantic-pull-request.yml"
192
209
  - ".gitignore"
193
210
  - ".gitmodules"