pyopensky 2.16__tar.gz → 2.18__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.
- pyopensky-2.18/.gitattributes +4 -0
- {pyopensky-2.16 → pyopensky-2.18}/.github/workflows/build-docs.yml +3 -3
- {pyopensky-2.16 → pyopensky-2.18}/.github/workflows/pypi_publish.yml +3 -3
- pyopensky-2.18/.github/workflows/run_tests.yml +123 -0
- {pyopensky-2.16 → pyopensky-2.18}/.gitignore +1 -0
- {pyopensky-2.16 → pyopensky-2.18}/PKG-INFO +31 -3
- {pyopensky-2.16 → pyopensky-2.18}/agents.md +1 -1
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/credentials.rst +3 -3
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/trino_advanced.rst +154 -3
- {pyopensky-2.16 → pyopensky-2.18}/pyproject.toml +18 -18
- {pyopensky-2.16 → pyopensky-2.18}/readme.md +27 -0
- pyopensky-2.18/scripts/benchmark_trino_routes.py +214 -0
- pyopensky-2.18/src/pyopensky/api.py +77 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/config.py +5 -5
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/decoders/pymodes.py +1 -1
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/rebuild.py +21 -21
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/rest.py +41 -36
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/s3.py +11 -8
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/schema.py +4 -2
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/time.py +13 -12
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/trino.py +268 -141
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/tzdata.py +10 -2
- {pyopensky-2.16 → pyopensky-2.18}/tests/test_s3.py +2 -1
- {pyopensky-2.16 → pyopensky-2.18}/tests/test_trino.py +14 -4
- pyopensky-2.18/tests/test_trino_offline.py +642 -0
- pyopensky-2.18/uv.lock +4735 -0
- pyopensky-2.16/.github/workflows/run_tests.yml +0 -83
- pyopensky-2.16/src/pyopensky/api.py +0 -76
- pyopensky-2.16/uv.lock +0 -4675
- {pyopensky-2.16 → pyopensky-2.18}/.github/dependabot.yml +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/.github/renovate.json5 +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/.gitignore +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/Makefile +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/make.bat +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/_static/main_stylesheet.css +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/conf.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/index.rst +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/installation.rst +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/rebuild.rst +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/rest.rst +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/docs/source/trino.rst +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/license.txt +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/scripts/decode_pymodes.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/scripts/decode_rs1090.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/__init__.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/decoders/__init__.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/decoders/base.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/decoders/rs1090.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/src/pyopensky/py.typed +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/tests/test_rebuild.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/tests/test_rest.py +0 -0
- {pyopensky-2.16 → pyopensky-2.18}/tests/test_tzdata.py +0 -0
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
UV_CACHE_DIR: /tmp/.uv-cache
|
|
16
16
|
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
19
|
with:
|
|
20
20
|
fetch-depth: 0
|
|
21
21
|
|
|
@@ -23,13 +23,13 @@ jobs:
|
|
|
23
23
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
24
24
|
|
|
25
25
|
- name: Set up Python
|
|
26
|
-
uses: actions/setup-python@
|
|
26
|
+
uses: actions/setup-python@v7.1.0
|
|
27
27
|
with:
|
|
28
28
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
- name: Cache folder for uv
|
|
32
|
-
uses: actions/cache@
|
|
32
|
+
uses: actions/cache@v6
|
|
33
33
|
with:
|
|
34
34
|
path: /tmp/.uv-cache
|
|
35
35
|
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
@@ -9,16 +9,16 @@ jobs:
|
|
|
9
9
|
deploy:
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
steps:
|
|
12
|
-
- uses: actions/checkout@
|
|
12
|
+
- uses: actions/checkout@v7
|
|
13
13
|
|
|
14
14
|
- name: Set up uv
|
|
15
15
|
run: curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
16
16
|
|
|
17
17
|
- name: Set up Python
|
|
18
|
-
uses: actions/setup-python@
|
|
18
|
+
uses: actions/setup-python@v7.1.0
|
|
19
19
|
|
|
20
20
|
- name: Cache folder for uv
|
|
21
|
-
uses: actions/cache@
|
|
21
|
+
uses: actions/cache@v6
|
|
22
22
|
with:
|
|
23
23
|
path: /tmp/.uv-cache
|
|
24
24
|
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request_target:
|
|
6
|
+
schedule: # keep the cache warm
|
|
7
|
+
- cron: "42 3 * * 0" # every Sunday morning
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: lint and format
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
|
|
17
|
+
- uses: astral-sh/setup-uv@v10.3.2
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
|
|
21
|
+
- run: uv sync --dev --extra rs1090 --extra cartes
|
|
22
|
+
- run: uv run ruff check
|
|
23
|
+
- run: uv run ruff format --check
|
|
24
|
+
- run: uv cache prune --ci
|
|
25
|
+
|
|
26
|
+
typing:
|
|
27
|
+
name: type checking
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v7
|
|
31
|
+
|
|
32
|
+
- uses: astral-sh/setup-uv@v10.3.2
|
|
33
|
+
with:
|
|
34
|
+
enable-cache: true
|
|
35
|
+
|
|
36
|
+
- run: uv sync --dev --extra rs1090 --extra cartes
|
|
37
|
+
- run: uv run ty check src tests
|
|
38
|
+
- run: uv cache prune --ci
|
|
39
|
+
|
|
40
|
+
fill_cache:
|
|
41
|
+
name: fill trino cache
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v7
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 0
|
|
47
|
+
|
|
48
|
+
- uses: astral-sh/setup-uv@v10.3.2
|
|
49
|
+
with:
|
|
50
|
+
enable-cache: true
|
|
51
|
+
|
|
52
|
+
- uses: actions/cache@v6
|
|
53
|
+
id: cache
|
|
54
|
+
with:
|
|
55
|
+
path: cache_opensky
|
|
56
|
+
enableCrossOsArchive: true
|
|
57
|
+
key: opensky-${{ hashFiles('uv.lock') }}
|
|
58
|
+
|
|
59
|
+
- run: uv sync --dev --extra rs1090 --extra cartes
|
|
60
|
+
|
|
61
|
+
- name: Fill cache with Trino queries
|
|
62
|
+
if: steps.cache.outputs.cache-hit != 'true'
|
|
63
|
+
env:
|
|
64
|
+
OPENSKY_USERNAME: ${{ secrets.OPENSKY_USERNAME }}
|
|
65
|
+
OPENSKY_PASSWORD: ${{ secrets.OPENSKY_PASSWORD }}
|
|
66
|
+
OPENSKY_CACHE: ${{ github.workspace }}/cache_opensky
|
|
67
|
+
run: uv run pytest tests/test_trino.py tests/test_rebuild.py
|
|
68
|
+
|
|
69
|
+
- run: uv cache prune --ci
|
|
70
|
+
|
|
71
|
+
tests:
|
|
72
|
+
name: python-${{ matrix.python-version }} on ${{ matrix.os }}
|
|
73
|
+
needs: fill_cache
|
|
74
|
+
runs-on: ${{ matrix.os }}
|
|
75
|
+
strategy:
|
|
76
|
+
fail-fast: false
|
|
77
|
+
matrix:
|
|
78
|
+
os:
|
|
79
|
+
- ubuntu-latest
|
|
80
|
+
- windows-latest
|
|
81
|
+
- macos-latest
|
|
82
|
+
python-version:
|
|
83
|
+
- "3.10"
|
|
84
|
+
- "3.11"
|
|
85
|
+
- "3.12"
|
|
86
|
+
- "3.13"
|
|
87
|
+
- "3.14"
|
|
88
|
+
# `trino` (v0.336.0) depends on `orjson` (v3.11.5)
|
|
89
|
+
# which does not support Python 3.14t
|
|
90
|
+
# https://github.com/ijl/orjson/issues/591#issuecomment-3160351169
|
|
91
|
+
# - "3.14t"
|
|
92
|
+
exclude:
|
|
93
|
+
# greenlet v3.2.4 is not available for Python 3.14t on Windows
|
|
94
|
+
# and fails to compile there. Not much we can do about that right now.
|
|
95
|
+
- os: windows-latest
|
|
96
|
+
python-version: "3.14t"
|
|
97
|
+
include:
|
|
98
|
+
- os: ubuntu-latest
|
|
99
|
+
python-version: "3.13"
|
|
100
|
+
rest: true
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v7
|
|
103
|
+
with:
|
|
104
|
+
fetch-depth: 0
|
|
105
|
+
|
|
106
|
+
- uses: astral-sh/setup-uv@v10.3.2
|
|
107
|
+
with:
|
|
108
|
+
enable-cache: true
|
|
109
|
+
|
|
110
|
+
- uses: actions/cache@v6
|
|
111
|
+
with:
|
|
112
|
+
path: cache_opensky
|
|
113
|
+
enableCrossOsArchive: true
|
|
114
|
+
key: opensky-${{ hashFiles('uv.lock') }}
|
|
115
|
+
|
|
116
|
+
- run: uv sync --dev --python ${{ matrix.python-version }} --extra rs1090 --extra cartes
|
|
117
|
+
|
|
118
|
+
- name: Run tests
|
|
119
|
+
env:
|
|
120
|
+
OPENSKY_CACHE: ${{ github.workspace }}/cache_opensky
|
|
121
|
+
run: uv run pytest ${{ ! matrix.rest && '--ignore=tests/test_rest.py' || '' }}
|
|
122
|
+
|
|
123
|
+
- run: uv cache prune --ci
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: pyopensky
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.18
|
|
4
4
|
Summary: A Python interface for OpenSky database
|
|
5
5
|
Project-URL: Repository, https://github.com/open-aviation/pyopensky/
|
|
6
6
|
Author-email: Xavier Olive <git@xoolive.org>, Junzi Sun <j.sun-1@tudelft.nl>
|
|
7
7
|
License-Expression: MIT
|
|
8
|
-
Requires-Python: >=3.
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
9
|
Requires-Dist: appdirs>=1.4.4
|
|
10
10
|
Requires-Dist: httpx>=0.27.2
|
|
11
11
|
Requires-Dist: minio>=7.2.8
|
|
@@ -14,6 +14,7 @@ Requires-Dist: pandas>=2.2.2
|
|
|
14
14
|
Requires-Dist: pyarrow>=17.0.0
|
|
15
15
|
Requires-Dist: pyjwt>=2.9.0
|
|
16
16
|
Requires-Dist: python-dotenv>=1.0.1
|
|
17
|
+
Requires-Dist: stamina>=25.1.0
|
|
17
18
|
Requires-Dist: tqdm>=4.66.5
|
|
18
19
|
Requires-Dist: trino[sqlalchemy]>=0.329.0
|
|
19
20
|
Requires-Dist: typing-extensions>=4.12.2
|
|
@@ -137,5 +138,32 @@ trino.history(start, stop, *, callsign, icao24, bounds)
|
|
|
137
138
|
trino.rebuild(start, stop, *, icao24, bounds)
|
|
138
139
|
```
|
|
139
140
|
|
|
141
|
+
For several routes in the same time window, use one query with exact directed
|
|
142
|
+
airport pairs:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
df = trino.history(
|
|
146
|
+
"2025-01-01",
|
|
147
|
+
"2025-01-02",
|
|
148
|
+
routes=[("KJFK", "EGLL"), ("KMIA", "EIDW"), ("LFPG", "KJFK")],
|
|
149
|
+
selected_columns=("time", "icao24", "callsign", "lat", "lon"),
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The same `routes` filter is available in `flightlist()` for metadata queries and
|
|
154
|
+
`rawdata()` for raw messages.
|
|
155
|
+
`history()` clips trajectories to the requested time window, including flights
|
|
156
|
+
that cross midnight.
|
|
157
|
+
|
|
158
|
+
Optional Trino session settings apply to all queries on a client. For selective
|
|
159
|
+
flight joins whose filtered flight table fits in each worker's memory:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
trino = Trino(session_properties={"join_distribution_type": "BROADCAST"})
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`Trino()` uses the server's default settings. Use `cached=False` on each call when
|
|
166
|
+
benchmarking query performance.
|
|
167
|
+
|
|
140
168
|
> [!IMPORTANT]
|
|
141
169
|
> Refer to the [documentation](https://mode-s.org/pyopensky) for advanced usage and parameter details.
|
|
@@ -5,9 +5,9 @@ Apply for access
|
|
|
5
5
|
----------------
|
|
6
6
|
|
|
7
7
|
Access to the Trino database will be granted provided you meet the `conditions
|
|
8
|
-
defined by The OpenSky Network <https://opensky-network.org/about/faq
|
|
9
|
-
https://trino.opensky-network.org, and then apply at https://opensky-network.org/data
|
|
10
|
-
|
|
8
|
+
defined by The OpenSky Network <https://opensky-network.org/about/faq>`_. Please create an account on
|
|
9
|
+
https://trino.opensky-network.org, and then apply at https://opensky-network.org/my-opensky/request-data
|
|
10
|
+
to request activation.
|
|
11
11
|
|
|
12
12
|
Configuration
|
|
13
13
|
-------------
|
|
@@ -70,6 +70,155 @@ Use ``with_only_columns()`` to reduce data transfer and improve query performanc
|
|
|
70
70
|
- Schema attribute: ``StateVectorsData4.lat``
|
|
71
71
|
- Qualified string: ``"StateVectorsData4.lat"`` or ``"FlightsData4.estdepartureairport"``
|
|
72
72
|
|
|
73
|
+
Configuring Trino sessions
|
|
74
|
+
---------------------------
|
|
75
|
+
|
|
76
|
+
Pass ``session_properties`` to ``Trino`` to configure each connection opened by
|
|
77
|
+
that client. Names and values are strings. For example, a broadcast join can
|
|
78
|
+
reduce CPU and worker network traffic for selective flight queries:
|
|
79
|
+
|
|
80
|
+
.. code-block:: python
|
|
81
|
+
|
|
82
|
+
from pyopensky.trino import Trino
|
|
83
|
+
|
|
84
|
+
trino = Trino(
|
|
85
|
+
session_properties={"join_distribution_type": "BROADCAST"}
|
|
86
|
+
)
|
|
87
|
+
df = trino.history(
|
|
88
|
+
"2025-06-01 12:00",
|
|
89
|
+
"2025-06-01 13:00",
|
|
90
|
+
routes=[("EGLL", "KJFK"), ("LFPG", "KJFK"), ("EHAM", "KJFK")],
|
|
91
|
+
selected_columns=("time", "icao24", "callsign", "lat", "lon"),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
``Trino()`` uses the server's default session settings. Broadcast joins are
|
|
95
|
+
optional: the filtered build table must fit in each worker's memory. For large
|
|
96
|
+
flight selections, let the server choose the join strategy or choose another
|
|
97
|
+
session configuration. See `Trino join distribution selection
|
|
98
|
+
<https://trino.io/docs/current/optimizer/cost-based-optimizations.html#join-distribution-selection>`_.
|
|
99
|
+
|
|
100
|
+
Session properties apply to ``query()``, ``history()``, ``flightlist()``, and
|
|
101
|
+
``rawdata()`` on that client. The constructor copies the supplied mapping.
|
|
102
|
+
Result-cache keys include configured properties, so different configurations do
|
|
103
|
+
not reuse each other's results. To measure query performance, pass
|
|
104
|
+
``cached=False`` to every measured call.
|
|
105
|
+
|
|
106
|
+
Batching directed routes
|
|
107
|
+
------------------------
|
|
108
|
+
|
|
109
|
+
Use ``routes`` to retrieve several directed airport pairs in one query for the
|
|
110
|
+
same time window. This avoids submitting one state-vector query per route.
|
|
111
|
+
|
|
112
|
+
.. code-block:: python
|
|
113
|
+
|
|
114
|
+
from pyopensky.trino import Trino
|
|
115
|
+
|
|
116
|
+
trino = Trino()
|
|
117
|
+
routes = [
|
|
118
|
+
("KJFK", "EGLL"),
|
|
119
|
+
("KMIA", "EIDW"),
|
|
120
|
+
("LFPG", "KJFK"),
|
|
121
|
+
]
|
|
122
|
+
df = trino.history(
|
|
123
|
+
"2025-01-01",
|
|
124
|
+
"2025-01-02",
|
|
125
|
+
routes=routes,
|
|
126
|
+
selected_columns=(
|
|
127
|
+
"time", "icao24", "callsign", "lat", "lon", "baroaltitude",
|
|
128
|
+
"FlightsData4.firstseen", "FlightsData4.lastseen",
|
|
129
|
+
"FlightsData4.estdepartureairport",
|
|
130
|
+
"FlightsData4.estarrivalairport",
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
Each pair contains the estimated departure and arrival ICAO identifiers, in that
|
|
135
|
+
order. Only the listed pairs match. For example, ``[("KJFK", "EGLL"),
|
|
136
|
+
("KMIA", "EIDW")]`` does not include KJFK to EIDW or the reverse directions.
|
|
137
|
+
Separate ``departure_airport`` and ``arrival_airport`` lists select every
|
|
138
|
+
combination between those lists.
|
|
139
|
+
|
|
140
|
+
Route identifiers match exactly; SQL wildcards are not expanded. An empty route
|
|
141
|
+
list selects no flights. Repeating a pair does not duplicate its results. Other
|
|
142
|
+
filters, such as ``icao24``, ``callsign``, bounds and airport filters, further
|
|
143
|
+
restrict the selected routes.
|
|
144
|
+
|
|
145
|
+
For long periods, loop over time windows and include all required routes in each
|
|
146
|
+
call. Select the columns needed for the analysis. Actual scan savings depend on
|
|
147
|
+
the Trino query plan and table layout.
|
|
148
|
+
|
|
149
|
+
If only flight metadata is needed, use the same route list with
|
|
150
|
+
``trino.flightlist(start, stop, routes=routes)``. With routes alone,
|
|
151
|
+
``flightlist()`` filters by ``lastseen``. Setting ``departure_airport`` also
|
|
152
|
+
selects its existing departure-time behavior.
|
|
153
|
+
|
|
154
|
+
.. note::
|
|
155
|
+
|
|
156
|
+
``history()`` returns state vectors within ``start`` and ``stop``. These
|
|
157
|
+
timestamps do not select flights by their departure or arrival time. A flight
|
|
158
|
+
that crosses midnight can be partial in a daily result. ``time_buffer``
|
|
159
|
+
extends the bounds around each flight's ``firstseen`` and ``lastseen`` but
|
|
160
|
+
does not extend the requested state-vector window. Each call submits one
|
|
161
|
+
query; pyopensky does not split that window automatically.
|
|
162
|
+
|
|
163
|
+
Filtering flight metadata in history queries
|
|
164
|
+
--------------------------------------------
|
|
165
|
+
|
|
166
|
+
``history()`` accepts ``FlightsData4`` conditions alongside state-vector
|
|
167
|
+
conditions. Flight columns refer to the flight table joined to the state vectors.
|
|
168
|
+
A flight condition also enables this join when no airport or route is specified.
|
|
169
|
+
Selecting flight columns also enables this join. Flight schema attributes can
|
|
170
|
+
be used directly in ``selected_columns``.
|
|
171
|
+
|
|
172
|
+
.. code-block:: python
|
|
173
|
+
|
|
174
|
+
from pyopensky.schema import FlightsData4, StateVectorsData4
|
|
175
|
+
from pyopensky.trino import Trino
|
|
176
|
+
|
|
177
|
+
df = Trino().history(
|
|
178
|
+
"2025-01-01",
|
|
179
|
+
"2025-01-02",
|
|
180
|
+
FlightsData4.estarrivalairporthorizdistance < 5000,
|
|
181
|
+
routes=[("KJFK", "EGLL"), ("LFPG", "KJFK")],
|
|
182
|
+
selected_columns=(
|
|
183
|
+
StateVectorsData4.time,
|
|
184
|
+
StateVectorsData4.icao24,
|
|
185
|
+
FlightsData4.estdepartureairport,
|
|
186
|
+
FlightsData4.estarrivalairport,
|
|
187
|
+
),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
Raw messages for directed routes
|
|
191
|
+
--------------------------------
|
|
192
|
+
|
|
193
|
+
``rawdata()`` also accepts exact ``routes``. It joins raw messages to matching
|
|
194
|
+
flights by aircraft address and the flight's ``firstseen``/``lastseen`` interval,
|
|
195
|
+
then clips messages to the requested time window. FlightsData4 conditions and
|
|
196
|
+
extra columns use this joined flight table.
|
|
197
|
+
|
|
198
|
+
.. code-block:: python
|
|
199
|
+
|
|
200
|
+
from pyopensky.schema import FlightsData4, PositionData4
|
|
201
|
+
from pyopensky.trino import Trino
|
|
202
|
+
|
|
203
|
+
df = Trino().rawdata(
|
|
204
|
+
"2025-01-01",
|
|
205
|
+
"2025-01-02",
|
|
206
|
+
FlightsData4.estarrivalairporthorizdistance < 5000,
|
|
207
|
+
routes=[("KJFK", "EGLL"), ("LFPG", "KJFK")],
|
|
208
|
+
Table=PositionData4,
|
|
209
|
+
extra_columns=(FlightsData4.estdepartureairport,),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
An empty route list selects no messages. Repeated pairs do not duplicate results.
|
|
213
|
+
Airport filters and ``icao24`` further restrict the selected routes. Flight
|
|
214
|
+
conditions or flight extra columns enable a flight join even without an airport
|
|
215
|
+
or route argument.
|
|
216
|
+
|
|
217
|
+
``rawdata()`` supports one selection mode per call: flight metadata (airports,
|
|
218
|
+
routes, flight conditions or flight extra columns), geographic bounds, or
|
|
219
|
+
callsign. These modes cannot be combined. Conditions on the raw table can
|
|
220
|
+
further restrict any mode. Its existing raw-column output is preserved.
|
|
221
|
+
|
|
73
222
|
|
|
74
223
|
Spatial queries with bounds
|
|
75
224
|
---------------------------
|
|
@@ -181,7 +330,8 @@ Filter by sensor serial numbers to get data from specific ground stations:
|
|
|
181
330
|
Extending temporal range for airport queries
|
|
182
331
|
--------------------------------------------
|
|
183
332
|
|
|
184
|
-
Use ``time_buffer`` to include
|
|
333
|
+
Use ``time_buffer`` to include state vectors just before a flight's ``firstseen``
|
|
334
|
+
or after its ``lastseen``, within the requested time window:
|
|
185
335
|
|
|
186
336
|
.. code-block:: python
|
|
187
337
|
|
|
@@ -189,7 +339,7 @@ Use ``time_buffer`` to include aircraft that departed/arrived slightly outside t
|
|
|
189
339
|
|
|
190
340
|
trino = Trino()
|
|
191
341
|
|
|
192
|
-
#
|
|
342
|
+
# Allow samples up to 30 minutes before/after each flight's time bounds
|
|
193
343
|
df = trino.history(
|
|
194
344
|
start="2024-03-16 09:00",
|
|
195
345
|
stop="2024-03-16 11:00",
|
|
@@ -197,7 +347,8 @@ Use ``time_buffer`` to include aircraft that departed/arrived slightly outside t
|
|
|
197
347
|
time_buffer="30m", # Also accepts "1h", "45min", etc.
|
|
198
348
|
)
|
|
199
349
|
|
|
200
|
-
|
|
350
|
+
The result remains clipped to 09:00 through 11:00. To retrieve samples outside
|
|
351
|
+
that window, extend ``start`` or ``stop`` explicitly.
|
|
201
352
|
|
|
202
353
|
Filtering with boolean expressions
|
|
203
354
|
----------------------------------
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pyopensky"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.18"
|
|
4
4
|
description = "A Python interface for OpenSky database"
|
|
5
5
|
authors = [{ name = "Xavier Olive", email = "git@xoolive.org" }, { name = "Junzi Sun", email = "j.sun-1@tudelft.nl" }]
|
|
6
6
|
license = "MIT"
|
|
7
7
|
readme = "readme.md"
|
|
8
|
-
requires-python = ">=3.
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
9
|
dependencies = [
|
|
10
10
|
"appdirs >= 1.4.4",
|
|
11
11
|
"httpx >= 0.27.2",
|
|
@@ -15,6 +15,7 @@ dependencies = [
|
|
|
15
15
|
"pyarrow >= 17.0.0",
|
|
16
16
|
"pyjwt >= 2.9.0",
|
|
17
17
|
"python-dotenv>=1.0.1",
|
|
18
|
+
"stamina>=25.1.0",
|
|
18
19
|
"tqdm >= 4.66.5",
|
|
19
20
|
"trino[sqlalchemy] >= 0.329.0",
|
|
20
21
|
"typing-extensions >= 4.12.2",
|
|
@@ -35,8 +36,6 @@ build-backend = "hatchling.build"
|
|
|
35
36
|
|
|
36
37
|
[dependency-groups]
|
|
37
38
|
dev = [
|
|
38
|
-
"pre-commit >= 3.8.0",
|
|
39
|
-
"mypy >= 1.11.2",
|
|
40
39
|
"ruff >= 0.6.3",
|
|
41
40
|
"pytest >= 8.3.2",
|
|
42
41
|
"ipykernel >= 7.1.0; python_version>='3.10'",
|
|
@@ -44,6 +43,7 @@ dev = [
|
|
|
44
43
|
"sphinx-design >= 0.6.1; python_version>'3.11'",
|
|
45
44
|
"sphinx-rtd-theme >= 2.0.0; python_version>'3.11'",
|
|
46
45
|
"sphinx-autodoc-typehints >= 2.3.0; python_version>'3.11'",
|
|
46
|
+
"ty>=0.0.17",
|
|
47
47
|
]
|
|
48
48
|
|
|
49
49
|
[tool.ruff]
|
|
@@ -58,21 +58,21 @@ lint.select = [
|
|
|
58
58
|
"RUF",
|
|
59
59
|
]
|
|
60
60
|
line-length = 80
|
|
61
|
-
target-version = "
|
|
61
|
+
target-version = "py310"
|
|
62
62
|
|
|
63
63
|
[tool.ruff.lint.isort]
|
|
64
64
|
known-first-party = ["numpy", "pandas"]
|
|
65
65
|
|
|
66
|
-
[tool.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
[tool.ty.src]
|
|
67
|
+
exclude = ["src/pyopensky/decoders/pymodes.py"]
|
|
68
|
+
|
|
69
|
+
[[tool.ty.overrides]]
|
|
70
|
+
# SQLAlchemy models expose their columns dynamically. Ty cannot verify these
|
|
71
|
+
# attributes for the heterogeneous raw-message table union.
|
|
72
|
+
include = ["src/pyopensky/rest.py", "src/pyopensky/trino.py"]
|
|
73
|
+
rules = { "unresolved-attribute" = "ignore" }
|
|
74
|
+
|
|
75
|
+
[tool.pytest.ini_options]
|
|
76
|
+
log_cli = true
|
|
77
|
+
log_cli_level = "DEBUG"
|
|
78
|
+
log_cli_format = "%(levelname)s %(name)s:%(filename)s:%(lineno)d %(message)s"
|
|
@@ -109,5 +109,32 @@ trino.history(start, stop, *, callsign, icao24, bounds)
|
|
|
109
109
|
trino.rebuild(start, stop, *, icao24, bounds)
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
For several routes in the same time window, use one query with exact directed
|
|
113
|
+
airport pairs:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
df = trino.history(
|
|
117
|
+
"2025-01-01",
|
|
118
|
+
"2025-01-02",
|
|
119
|
+
routes=[("KJFK", "EGLL"), ("KMIA", "EIDW"), ("LFPG", "KJFK")],
|
|
120
|
+
selected_columns=("time", "icao24", "callsign", "lat", "lon"),
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The same `routes` filter is available in `flightlist()` for metadata queries and
|
|
125
|
+
`rawdata()` for raw messages.
|
|
126
|
+
`history()` clips trajectories to the requested time window, including flights
|
|
127
|
+
that cross midnight.
|
|
128
|
+
|
|
129
|
+
Optional Trino session settings apply to all queries on a client. For selective
|
|
130
|
+
flight joins whose filtered flight table fits in each worker's memory:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
trino = Trino(session_properties={"join_distribution_type": "BROADCAST"})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`Trino()` uses the server's default settings. Use `cached=False` on each call when
|
|
137
|
+
benchmarking query performance.
|
|
138
|
+
|
|
112
139
|
> [!IMPORTANT]
|
|
113
140
|
> Refer to the [documentation](https://mode-s.org/pyopensky) for advanced usage and parameter details.
|