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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/ISSUE_TEMPLATE/bug_report.yml +1 -1
- data/.github/PULL_REQUEST_TEMPLATE.md +13 -0
- data/.github/workflows/ci.yml +9 -9
- data/.github/workflows/release-please.yml +6 -6
- data/.github/workflows/semantic-pr.yml +34 -0
- data/.github/workflows/semantic-pull-request.yml +12 -2
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +20 -1
- data/CODE_OF_CONDUCT.md +6 -6
- data/CONTRIBUTING.md +1 -1
- data/Gemfile.lock +4 -1
- data/README.md +21 -3
- data/SECURITY.md +1 -1
- data/altertable-lakehouse.gemspec +1 -0
- data/lib/altertable/lakehouse/adapters.rb +17 -9
- data/lib/altertable/lakehouse/client.rb +28 -10
- data/lib/altertable/lakehouse/version.rb +1 -1
- data/rbi/altertable/lakehouse.rbi +26 -13
- data/sig/altertable/lakehouse/adapters.rbs +6 -4
- data/sig/altertable/lakehouse/client.rbs +14 -3
- metadata +18 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 730648db52f373495553ad9179f698b55a1bc309e5e5465a3e39733bc4659ab4
|
|
4
|
+
data.tar.gz: 0adb085fa50da366e377cb1b847273c0020ef058b871a143866b4c2d1558e106
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cde4636923e138c259a738f96d84305ff6a8aa929dc12e49f792989da2ee0a2394db20f2a37f80dcda21b304ebb7c3860122bd46b6cc4a01ca0ddadd805bc38
|
|
7
|
+
data.tar.gz: baffcdd22da74b9006f153f41b87703f93ba0351f3edcc2082576472b3ef52451656ee0bdc2afe72e79ff6835d10a1049ccc6555bc92c1bf23b82184e65cd54a
|
data/.github/FUNDING.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github: [altertable-ai]
|
|
@@ -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
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -6,7 +6,7 @@ on:
|
|
|
6
6
|
pull_request: {}
|
|
7
7
|
jobs:
|
|
8
8
|
test:
|
|
9
|
-
runs-on: ubuntu-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
20
|
+
runs-on: ubuntu-24.04
|
|
21
|
+
timeout-minutes: 5
|
|
13
22
|
steps:
|
|
14
|
-
-
|
|
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:
|
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), `
|
|
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
|
|
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
|
|
81
|
-
[Mozilla CoC]: https://github.com/mozilla/
|
|
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
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
altertable-lakehouse (0.
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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:,
|
|
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
|
|
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
|
|
@@ -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:,
|
|
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
|
-
?
|
|
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.
|
|
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"
|