opensky-cli 0.1.0__tar.gz

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.
Files changed (40) hide show
  1. opensky_cli-0.1.0/.env.example +8 -0
  2. opensky_cli-0.1.0/.gitignore +16 -0
  3. opensky_cli-0.1.0/LICENSE +21 -0
  4. opensky_cli-0.1.0/PKG-INFO +231 -0
  5. opensky_cli-0.1.0/README.md +204 -0
  6. opensky_cli-0.1.0/create_video.py +747 -0
  7. opensky_cli-0.1.0/demo.gif +0 -0
  8. opensky_cli-0.1.0/opensky-demo.mp4 +0 -0
  9. opensky_cli-0.1.0/pyproject.toml +46 -0
  10. opensky_cli-0.1.0/src/opensky/__init__.py +3 -0
  11. opensky_cli-0.1.0/src/opensky/__main__.py +3 -0
  12. opensky_cli-0.1.0/src/opensky/_vendor/__init__.py +0 -0
  13. opensky_cli-0.1.0/src/opensky/_vendor/google_flights.py +489 -0
  14. opensky_cli-0.1.0/src/opensky/airports.py +183 -0
  15. opensky_cli-0.1.0/src/opensky/cache.py +49 -0
  16. opensky_cli-0.1.0/src/opensky/cli.py +690 -0
  17. opensky_cli-0.1.0/src/opensky/config.py +151 -0
  18. opensky_cli-0.1.0/src/opensky/data/conflict_zones.json +203 -0
  19. opensky_cli-0.1.0/src/opensky/data/demo_flights.json +3355 -0
  20. opensky_cli-0.1.0/src/opensky/display.py +358 -0
  21. opensky_cli-0.1.0/src/opensky/models.py +90 -0
  22. opensky_cli-0.1.0/src/opensky/providers/__init__.py +81 -0
  23. opensky_cli-0.1.0/src/opensky/providers/amadeus.py +150 -0
  24. opensky_cli-0.1.0/src/opensky/providers/duffel.py +122 -0
  25. opensky_cli-0.1.0/src/opensky/providers/google.py +111 -0
  26. opensky_cli-0.1.0/src/opensky/safety.py +138 -0
  27. opensky_cli-0.1.0/src/opensky/search.py +280 -0
  28. opensky_cli-0.1.0/tests/__init__.py +0 -0
  29. opensky_cli-0.1.0/tests/fixture_flights_blr_ham.json +3355 -0
  30. opensky_cli-0.1.0/tests/test_airports.py +73 -0
  31. opensky_cli-0.1.0/tests/test_cache.py +34 -0
  32. opensky_cli-0.1.0/tests/test_cli.py +160 -0
  33. opensky_cli-0.1.0/tests/test_config.py +96 -0
  34. opensky_cli-0.1.0/tests/test_dedup.py +76 -0
  35. opensky_cli-0.1.0/tests/test_display.py +192 -0
  36. opensky_cli-0.1.0/tests/test_integration.py +245 -0
  37. opensky_cli-0.1.0/tests/test_models.py +87 -0
  38. opensky_cli-0.1.0/tests/test_providers.py +300 -0
  39. opensky_cli-0.1.0/tests/test_safety.py +70 -0
  40. opensky_cli-0.1.0/tests/test_vendor.py +143 -0
@@ -0,0 +1,8 @@
1
+ # Optional: Duffel API (free unlimited searches)
2
+ # Sign up at https://duffel.com
3
+ # OPENSKY_DUFFEL_TOKEN=duffel_test_xxxxx
4
+
5
+ # Optional: Amadeus API (free tier: 2,000 calls/month)
6
+ # Sign up at https://developers.amadeus.com
7
+ # OPENSKY_AMADEUS_KEY=your_api_key
8
+ # OPENSKY_AMADEUS_SECRET=your_api_secret
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .venv/
10
+ venv/
11
+ .env
12
+ *.so
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ WORKPLAN-*.md
16
+ demo.tape
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Federico De Ponte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: opensky-cli
3
+ Version: 0.1.0
4
+ Summary: The first agentic flight search engine. Searches hundreds of routes in minutes, not hours.
5
+ Project-URL: Homepage, https://github.com/federicodeponte/opensky
6
+ Project-URL: Repository, https://github.com/federicodeponte/opensky
7
+ Author: Federico De Ponte
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: cli,flight-search,flights,google-flights,price-comparison,travel
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Internet
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: airportsdata>=20240101
19
+ Requires-Dist: curl-cffi>=0.7
20
+ Requires-Dist: diskcache>=5.6
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: pydantic>=2.10
23
+ Requires-Dist: ratelimit>=2.2
24
+ Requires-Dist: rich>=13.0
25
+ Requires-Dist: typer>=0.15
26
+ Description-Content-Type: text/markdown
27
+
28
+ # opensky
29
+
30
+ The first agentic flight search engine. Define your origins, destinations, and dates, and opensky searches every combination for you, in minutes instead of hours.
31
+
32
+ ```
33
+ $ opensky scan --config scan.toml
34
+
35
+ Scanning 6 origins x 6 destinations x 10 dates = 360 combos via google
36
+
37
+ Best per Destination
38
+ Destination Price Date Duration Route
39
+ Amsterdam €289 Tue Mar 17 11h 20m Bangkok → Amsterdam
40
+ Berlin €312 Thu Mar 12 12h 45m Kuala Lumpur → Berlin
41
+ Frankfurt €298 Wed Mar 11 11h 50m Bangkok → Frankfurt
42
+ Hamburg €357 Tue Mar 10 13h 10m Bangalore → Dubai → Hamburg
43
+ Munich €315 Fri Mar 13 12h 30m Delhi → Munich
44
+ Copenhagen €345 Mon Mar 16 13h 10m Singapore → Copenhagen
45
+ ```
46
+
47
+ Doing this manually on Google Flights would take 360 individual searches. opensky does it in one command.
48
+
49
+ ## How it works
50
+
51
+ 1. You define a search space: origins, destinations, date range
52
+ 2. opensky searches every combination across up to three providers (Google Flights, Duffel, Amadeus)
53
+ 3. Results are deduplicated, scored, and presented as a price matrix with the cheapest options highlighted
54
+
55
+ It also works for single route searches:
56
+
57
+ ```bash
58
+ opensky search bangalore hamburg tomorrow
59
+ opensky search BLR HAM next monday
60
+ opensky search BLR HAM mar 15
61
+ ```
62
+
63
+ ## Install
64
+
65
+ Requires Python 3.11+.
66
+
67
+ ```bash
68
+ pip install opensky
69
+ ```
70
+
71
+ Or from source:
72
+
73
+ ```bash
74
+ git clone https://github.com/federicodeponte/opensky.git
75
+ cd opensky
76
+ python -m venv .venv && source .venv/bin/activate
77
+ pip install -e .
78
+ ```
79
+
80
+ Copy `.env.example` to `.env` and fill in any API keys you have (optional, Google Flights works without any keys).
81
+
82
+ ## Quick demo
83
+
84
+ See what opensky does without any API keys or network calls:
85
+
86
+ ```bash
87
+ opensky demo
88
+ ```
89
+
90
+ ![opensky demo](demo.gif)
91
+
92
+ ## Usage
93
+
94
+ ### Multi-route scan (the power feature)
95
+
96
+ Search every combination of origins, destinations, and dates at once.
97
+
98
+ #### Interactive setup
99
+
100
+ ```bash
101
+ opensky config init
102
+ ```
103
+
104
+ ```
105
+ opensky config init
106
+
107
+ Where are you flying from? (comma-separated cities or codes): bangalore, delhi, bangkok
108
+ → BLR (Bangalore), DEL (Delhi), BKK (Bangkok)
109
+ Where to? (comma-separated cities or codes): hamburg, frankfurt, amsterdam
110
+ → HAM (Hamburg), FRA (Frankfurt), AMS (Amsterdam)
111
+ Start date (YYYY-MM-DD): mar 15
112
+ End date (YYYY-MM-DD): mar 25
113
+ Currency [EUR]:
114
+
115
+ Created scan.toml. Next: opensky scan --config scan.toml
116
+ ```
117
+
118
+ Then run:
119
+
120
+ ```bash
121
+ opensky scan --config scan.toml
122
+ ```
123
+
124
+ #### Quick template
125
+
126
+ ```bash
127
+ opensky config init --quick # dumps template, no prompts
128
+ # edit scan.toml with your routes and dates
129
+ opensky scan --config scan.toml
130
+ ```
131
+
132
+ 6 origins x 6 destinations x 10 dates = 360 searches, one command. You get:
133
+ - **Best per destination**: cheapest flight to each city, with date and route
134
+ - **Price matrix**: prices across all dates, cheapest highlighted
135
+ - **Stats**: total flights found, price range
136
+
137
+ ```bash
138
+ opensky scan --config scan.toml --all-flights # show every flight, not just summary
139
+ opensky scan --config scan.toml --workers 5 # parallel workers (default: 3)
140
+ opensky scan --config scan.toml --json -o results.json
141
+ ```
142
+
143
+ Scans are cached. If interrupted, re-run the same command to resume where it left off.
144
+
145
+ #### Scan config
146
+
147
+ ```toml
148
+ [search]
149
+ origins = ["BLR", "DEL", "BOM", "KUL", "BKK", "SIN"]
150
+ destinations = ["HAM", "FRA", "MUC", "BER", "AMS", "CPH"]
151
+ cabin = "economy"
152
+ currency = "EUR"
153
+ stops = "any"
154
+
155
+ [search.date_range]
156
+ start = "2026-03-10"
157
+ end = "2026-03-20"
158
+
159
+ [scoring]
160
+ price_weight = 1.0
161
+ duration_weight = 0.5
162
+
163
+ # Optional: add ground transit time for scoring
164
+ [connections]
165
+ final_destination = "Hamburg"
166
+
167
+ [connections.transit_hours]
168
+ HAM = 0
169
+ BER = 2
170
+ FRA = 4
171
+
172
+ [safety]
173
+ risk_threshold = "high_risk"
174
+ ```
175
+
176
+ ### Single route search
177
+
178
+ Use city names, IATA codes, or friendly dates:
179
+
180
+ ```bash
181
+ opensky search bangalore hamburg tomorrow
182
+ opensky search BLR HAM next monday
183
+ opensky search BLR HAM mar 15 --class business
184
+ opensky search BLR HAM 2026-03-10 --source duffel
185
+ opensky search BLR HAM 2026-03-10 --json
186
+ opensky search BLR HAM 2026-03-10 --fresh
187
+ ```
188
+
189
+ Options:
190
+ - `--class` / `--cabin`: Travel class (economy, premium, business, first)
191
+ - `--stops`: Max stops (nonstop, 1, 2, or any)
192
+ - `--max-price`: Maximum price (0 = no limit)
193
+ - `--fresh` / `--no-cache`: Skip cached results
194
+ - `--source` / `--provider`: Flight data source (google, duffel, amadeus)
195
+ - `--include-risky`: Include flights through conflict zones
196
+ - `--json` / `--csv`: Machine-readable output
197
+ - `--output` / `-o`: Save results to file
198
+ - `--currency` / `-c`: Currency code (EUR, USD, GBP, etc.)
199
+
200
+ ## Providers
201
+
202
+ opensky aggregates results from up to three flight data sources. When multiple providers are configured, results are deduplicated (same flight from two sources keeps the cheapest price).
203
+
204
+ | Provider | Env vars | Notes |
205
+ |----------|----------|-------|
206
+ | Google Flights | none (default) | Scrapes Google Flights. Needs residential IP. |
207
+ | [Duffel](https://duffel.com) | `OPENSKY_DUFFEL_TOKEN` | Free unlimited searches. |
208
+ | [Amadeus](https://developers.amadeus.com) | `OPENSKY_AMADEUS_KEY` + `OPENSKY_AMADEUS_SECRET` | Free tier: 2,000 calls/month. |
209
+
210
+ ## Conflict zones
211
+
212
+ opensky ships with a conflict zone database. By default, flights through high-risk airspace are filtered out. Use `--include-risky` to see all options.
213
+
214
+ ```bash
215
+ opensky zones # list active conflict zones
216
+ opensky zones --update # fetch latest data
217
+ ```
218
+
219
+ ## Limitations
220
+
221
+ - **Residential IP required**: Google Flights blocks datacenter IPs. Use `--proxy` on servers. Duffel and Amadeus work from any IP.
222
+ - **Rate limits**: All providers rate-limited to 10 req/sec. Default scan settings (3 workers, 1s delay) are conservative.
223
+ - **Price accuracy**: Prices may differ from airline websites. Always verify before booking.
224
+
225
+ ## Credits
226
+
227
+ Flight data API based on [fli](https://github.com/punitarani/fli) by Punit Arani (MIT license). Airport metadata from [airportsdata](https://github.com/mborsetti/airportsdata).
228
+
229
+ ## License
230
+
231
+ MIT
@@ -0,0 +1,204 @@
1
+ # opensky
2
+
3
+ The first agentic flight search engine. Define your origins, destinations, and dates, and opensky searches every combination for you, in minutes instead of hours.
4
+
5
+ ```
6
+ $ opensky scan --config scan.toml
7
+
8
+ Scanning 6 origins x 6 destinations x 10 dates = 360 combos via google
9
+
10
+ Best per Destination
11
+ Destination Price Date Duration Route
12
+ Amsterdam €289 Tue Mar 17 11h 20m Bangkok → Amsterdam
13
+ Berlin €312 Thu Mar 12 12h 45m Kuala Lumpur → Berlin
14
+ Frankfurt €298 Wed Mar 11 11h 50m Bangkok → Frankfurt
15
+ Hamburg €357 Tue Mar 10 13h 10m Bangalore → Dubai → Hamburg
16
+ Munich €315 Fri Mar 13 12h 30m Delhi → Munich
17
+ Copenhagen €345 Mon Mar 16 13h 10m Singapore → Copenhagen
18
+ ```
19
+
20
+ Doing this manually on Google Flights would take 360 individual searches. opensky does it in one command.
21
+
22
+ ## How it works
23
+
24
+ 1. You define a search space: origins, destinations, date range
25
+ 2. opensky searches every combination across up to three providers (Google Flights, Duffel, Amadeus)
26
+ 3. Results are deduplicated, scored, and presented as a price matrix with the cheapest options highlighted
27
+
28
+ It also works for single route searches:
29
+
30
+ ```bash
31
+ opensky search bangalore hamburg tomorrow
32
+ opensky search BLR HAM next monday
33
+ opensky search BLR HAM mar 15
34
+ ```
35
+
36
+ ## Install
37
+
38
+ Requires Python 3.11+.
39
+
40
+ ```bash
41
+ pip install opensky
42
+ ```
43
+
44
+ Or from source:
45
+
46
+ ```bash
47
+ git clone https://github.com/federicodeponte/opensky.git
48
+ cd opensky
49
+ python -m venv .venv && source .venv/bin/activate
50
+ pip install -e .
51
+ ```
52
+
53
+ Copy `.env.example` to `.env` and fill in any API keys you have (optional, Google Flights works without any keys).
54
+
55
+ ## Quick demo
56
+
57
+ See what opensky does without any API keys or network calls:
58
+
59
+ ```bash
60
+ opensky demo
61
+ ```
62
+
63
+ ![opensky demo](demo.gif)
64
+
65
+ ## Usage
66
+
67
+ ### Multi-route scan (the power feature)
68
+
69
+ Search every combination of origins, destinations, and dates at once.
70
+
71
+ #### Interactive setup
72
+
73
+ ```bash
74
+ opensky config init
75
+ ```
76
+
77
+ ```
78
+ opensky config init
79
+
80
+ Where are you flying from? (comma-separated cities or codes): bangalore, delhi, bangkok
81
+ → BLR (Bangalore), DEL (Delhi), BKK (Bangkok)
82
+ Where to? (comma-separated cities or codes): hamburg, frankfurt, amsterdam
83
+ → HAM (Hamburg), FRA (Frankfurt), AMS (Amsterdam)
84
+ Start date (YYYY-MM-DD): mar 15
85
+ End date (YYYY-MM-DD): mar 25
86
+ Currency [EUR]:
87
+
88
+ Created scan.toml. Next: opensky scan --config scan.toml
89
+ ```
90
+
91
+ Then run:
92
+
93
+ ```bash
94
+ opensky scan --config scan.toml
95
+ ```
96
+
97
+ #### Quick template
98
+
99
+ ```bash
100
+ opensky config init --quick # dumps template, no prompts
101
+ # edit scan.toml with your routes and dates
102
+ opensky scan --config scan.toml
103
+ ```
104
+
105
+ 6 origins x 6 destinations x 10 dates = 360 searches, one command. You get:
106
+ - **Best per destination**: cheapest flight to each city, with date and route
107
+ - **Price matrix**: prices across all dates, cheapest highlighted
108
+ - **Stats**: total flights found, price range
109
+
110
+ ```bash
111
+ opensky scan --config scan.toml --all-flights # show every flight, not just summary
112
+ opensky scan --config scan.toml --workers 5 # parallel workers (default: 3)
113
+ opensky scan --config scan.toml --json -o results.json
114
+ ```
115
+
116
+ Scans are cached. If interrupted, re-run the same command to resume where it left off.
117
+
118
+ #### Scan config
119
+
120
+ ```toml
121
+ [search]
122
+ origins = ["BLR", "DEL", "BOM", "KUL", "BKK", "SIN"]
123
+ destinations = ["HAM", "FRA", "MUC", "BER", "AMS", "CPH"]
124
+ cabin = "economy"
125
+ currency = "EUR"
126
+ stops = "any"
127
+
128
+ [search.date_range]
129
+ start = "2026-03-10"
130
+ end = "2026-03-20"
131
+
132
+ [scoring]
133
+ price_weight = 1.0
134
+ duration_weight = 0.5
135
+
136
+ # Optional: add ground transit time for scoring
137
+ [connections]
138
+ final_destination = "Hamburg"
139
+
140
+ [connections.transit_hours]
141
+ HAM = 0
142
+ BER = 2
143
+ FRA = 4
144
+
145
+ [safety]
146
+ risk_threshold = "high_risk"
147
+ ```
148
+
149
+ ### Single route search
150
+
151
+ Use city names, IATA codes, or friendly dates:
152
+
153
+ ```bash
154
+ opensky search bangalore hamburg tomorrow
155
+ opensky search BLR HAM next monday
156
+ opensky search BLR HAM mar 15 --class business
157
+ opensky search BLR HAM 2026-03-10 --source duffel
158
+ opensky search BLR HAM 2026-03-10 --json
159
+ opensky search BLR HAM 2026-03-10 --fresh
160
+ ```
161
+
162
+ Options:
163
+ - `--class` / `--cabin`: Travel class (economy, premium, business, first)
164
+ - `--stops`: Max stops (nonstop, 1, 2, or any)
165
+ - `--max-price`: Maximum price (0 = no limit)
166
+ - `--fresh` / `--no-cache`: Skip cached results
167
+ - `--source` / `--provider`: Flight data source (google, duffel, amadeus)
168
+ - `--include-risky`: Include flights through conflict zones
169
+ - `--json` / `--csv`: Machine-readable output
170
+ - `--output` / `-o`: Save results to file
171
+ - `--currency` / `-c`: Currency code (EUR, USD, GBP, etc.)
172
+
173
+ ## Providers
174
+
175
+ opensky aggregates results from up to three flight data sources. When multiple providers are configured, results are deduplicated (same flight from two sources keeps the cheapest price).
176
+
177
+ | Provider | Env vars | Notes |
178
+ |----------|----------|-------|
179
+ | Google Flights | none (default) | Scrapes Google Flights. Needs residential IP. |
180
+ | [Duffel](https://duffel.com) | `OPENSKY_DUFFEL_TOKEN` | Free unlimited searches. |
181
+ | [Amadeus](https://developers.amadeus.com) | `OPENSKY_AMADEUS_KEY` + `OPENSKY_AMADEUS_SECRET` | Free tier: 2,000 calls/month. |
182
+
183
+ ## Conflict zones
184
+
185
+ opensky ships with a conflict zone database. By default, flights through high-risk airspace are filtered out. Use `--include-risky` to see all options.
186
+
187
+ ```bash
188
+ opensky zones # list active conflict zones
189
+ opensky zones --update # fetch latest data
190
+ ```
191
+
192
+ ## Limitations
193
+
194
+ - **Residential IP required**: Google Flights blocks datacenter IPs. Use `--proxy` on servers. Duffel and Amadeus work from any IP.
195
+ - **Rate limits**: All providers rate-limited to 10 req/sec. Default scan settings (3 workers, 1s delay) are conservative.
196
+ - **Price accuracy**: Prices may differ from airline websites. Always verify before booking.
197
+
198
+ ## Credits
199
+
200
+ Flight data API based on [fli](https://github.com/punitarani/fli) by Punit Arani (MIT license). Airport metadata from [airportsdata](https://github.com/mborsetti/airportsdata).
201
+
202
+ ## License
203
+
204
+ MIT