pyopensky 2.10__tar.gz → 2.12__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 (38) hide show
  1. pyopensky-2.12/.github/dependabot.yml +11 -0
  2. pyopensky-2.12/.github/renovate.json5 +6 -0
  3. pyopensky-2.12/.github/workflows/build-docs.yml +56 -0
  4. pyopensky-2.12/.github/workflows/pypi_publish.yml +39 -0
  5. pyopensky-2.12/.github/workflows/run_tests.yml +82 -0
  6. {pyopensky-2.10 → pyopensky-2.12}/PKG-INFO +2 -2
  7. pyopensky-2.12/docs/.gitignore +1 -0
  8. pyopensky-2.12/docs/Makefile +20 -0
  9. pyopensky-2.12/docs/make.bat +35 -0
  10. pyopensky-2.12/docs/source/_static/main_stylesheet.css +17 -0
  11. pyopensky-2.12/docs/source/api_reference.rst +8 -0
  12. pyopensky-2.12/docs/source/conf.py +47 -0
  13. pyopensky-2.12/docs/source/credentials.rst +65 -0
  14. pyopensky-2.12/docs/source/index.rst +30 -0
  15. pyopensky-2.12/docs/source/installation.rst +27 -0
  16. pyopensky-2.12/docs/source/rest.rst +8 -0
  17. pyopensky-2.12/docs/source/trino.rst +8 -0
  18. {pyopensky-2.10 → pyopensky-2.12}/pyproject.toml +2 -4
  19. pyopensky-2.12/scripts/decode_pymodes.py +89 -0
  20. pyopensky-2.12/scripts/decode_rs1090.py +31 -0
  21. pyopensky-2.12/src/pyopensky/__init__.py +13 -0
  22. pyopensky-2.12/src/pyopensky/api.py +76 -0
  23. pyopensky-2.12/src/pyopensky/config.py +210 -0
  24. pyopensky-2.12/src/pyopensky/rest.py +499 -0
  25. pyopensky-2.12/src/pyopensky/s3.py +157 -0
  26. pyopensky-2.12/src/pyopensky/schema.py +530 -0
  27. pyopensky-2.12/src/pyopensky/time.py +46 -0
  28. pyopensky-2.12/src/pyopensky/trino.py +981 -0
  29. pyopensky-2.12/src/pyopensky/tzdata.py +48 -0
  30. pyopensky-2.12/tests/test_rest.py +8 -0
  31. pyopensky-2.12/tests/test_s3.py +28 -0
  32. pyopensky-2.12/tests/test_trino.py +326 -0
  33. pyopensky-2.12/tests/test_tzdata.py +13 -0
  34. pyopensky-2.12/uv.lock +3233 -0
  35. {pyopensky-2.10 → pyopensky-2.12}/.gitignore +0 -0
  36. {pyopensky-2.10 → pyopensky-2.12}/license.txt +0 -0
  37. {pyopensky-2.10 → pyopensky-2.12}/readme.md +0 -0
  38. {pyopensky-2.10 → pyopensky-2.12}/src/pyopensky/py.typed +0 -0
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ updates:
3
+ # - package-ecosystem: "pip"
4
+ # directory: "/"
5
+ # schedule:
6
+ # interval: "monthly"
7
+
8
+ - package-ecosystem: "github-actions"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "monthly"
@@ -0,0 +1,6 @@
1
+ {
2
+ $schema: "https://docs.renovatebot.com/renovate-schema.json",
3
+ lockFileMaintenance: {
4
+ enabled: true,
5
+ },
6
+ }
@@ -0,0 +1,56 @@
1
+ name: docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ documentation:
11
+ runs-on: ubuntu-latest
12
+
13
+ env:
14
+ PYTHON_VERSION: "3.12"
15
+ UV_CACHE_DIR: /tmp/.uv-cache
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+
22
+ - name: Set up uv
23
+ run: curl -LsSf https://astral.sh/uv/install.sh | sh
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: ${{ env.PYTHON_VERSION }}
29
+
30
+
31
+ - name: Cache folder for uv
32
+ uses: actions/cache@v4
33
+ with:
34
+ path: /tmp/.uv-cache
35
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
36
+ restore-keys: |
37
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
38
+ uv-${{ runner.os }}
39
+
40
+ - name: Install dependencies
41
+ run: |
42
+ uv sync --all-extras --dev
43
+
44
+ - name: Build pages
45
+ working-directory: docs
46
+ run: |
47
+ uv run make html
48
+
49
+ - name: Minimize uv cache
50
+ run: uv cache prune --ci
51
+
52
+ - name: Deploy pages
53
+ uses: peaceiris/actions-gh-pages@v4
54
+ with:
55
+ github_token: ${{ secrets.GITHUB_TOKEN }}
56
+ publish_dir: docs/build/html
@@ -0,0 +1,39 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up uv
15
+ run: curl -LsSf https://astral.sh/uv/install.sh | sh
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+
20
+ - name: Cache folder for uv
21
+ uses: actions/cache@v4
22
+ with:
23
+ path: /tmp/.uv-cache
24
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
25
+ restore-keys: |
26
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
27
+ uv-${{ runner.os }}
28
+
29
+ - name: Build packages
30
+ run: uvx hatch build
31
+
32
+ - name: Minimize uv cache
33
+ run: uv cache prune --ci
34
+
35
+ - name: Publish a Python distribution to PyPI
36
+ uses: pypa/gh-action-pypi-publish@release/v1
37
+ with:
38
+ user: __token__
39
+ password: ${{ secrets.PYPI_PASSWORD }}
@@ -0,0 +1,82 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ pull_request_target:
6
+ schedule: # This is useful for keeping the cache fit and ready
7
+ - cron: "42 3 * * 0" # Every Sunday morning when I am fast asleep :)
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ deploy:
12
+ name: python-${{ matrix.python-version }} on ${{ matrix.os }}
13
+
14
+ strategy:
15
+ matrix:
16
+ os:
17
+ - ubuntu-latest
18
+ - windows-latest
19
+ - macos-latest
20
+ python-version:
21
+ - "3.9"
22
+ - "3.10"
23
+ - "3.11"
24
+ - "3.12"
25
+ - "3.13"
26
+
27
+ fail-fast: false
28
+
29
+ runs-on: ${{ matrix.os }}
30
+
31
+ env:
32
+ UV_CACHE_DIR: /tmp/.uv-cache
33
+
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0
38
+
39
+ - name: Set up uv
40
+ if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' }}
41
+ run: curl -LsSf https://astral.sh/uv/install.sh | sh
42
+
43
+ - name: Set up uv
44
+ if: ${{ matrix.os == 'windows-latest' }}
45
+ run: irm https://astral.sh/uv/install.ps1 | iex
46
+ shell: powershell
47
+
48
+ - name: Cache folder for uv
49
+ uses: actions/cache@v4
50
+ with:
51
+ path: /tmp/.uv-cache
52
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
53
+ restore-keys: |
54
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
55
+ uv-${{ runner.os }}
56
+
57
+ - name: Cache folder for data
58
+ uses: actions/cache@v4
59
+ id: cache-folder
60
+ with:
61
+ path: |
62
+ ${{ github.workspace }}/cache_opensky
63
+ key: opensky-${{ runner.os }}-${{ hashFiles('uv.lock') }}
64
+
65
+ - name: Install the project
66
+ run: uv sync --all-extras --dev --python ${{ matrix.python-version }}
67
+
68
+ - name: Linting and formatting
69
+ run: |
70
+ uv run ruff check
71
+ uv run ruff format --check
72
+
73
+ - name: Run tests
74
+ if: ${{ matrix.python-version == '3.12' || steps.cache-folder.outputs.cache-hit == 'true' }}
75
+ env:
76
+ OPENSKY_USERNAME: ${{ secrets.OPENSKY_USERNAME }}
77
+ OPENSKY_PASSWORD: ${{ secrets.OPENSKY_PASSWORD }}
78
+ OPENSKY_CACHE: ${{ github.workspace }}/cache_opensky
79
+ run: uv run pytest
80
+
81
+ - name: Minimize uv cache
82
+ run: uv cache prune --ci
@@ -1,10 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyopensky
3
- Version: 2.10
3
+ Version: 2.12
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
- License-Expression: MIT
8
7
  Requires-Python: >=3.9
9
8
  Requires-Dist: appdirs>=1.4.4
10
9
  Requires-Dist: httpx>=0.27.2
@@ -15,6 +14,7 @@ Requires-Dist: pyjwt>=2.9.0
15
14
  Requires-Dist: tqdm>=4.66.5
16
15
  Requires-Dist: trino[sqlalchemy]>=0.329.0
17
16
  Requires-Dist: typing-extensions>=4.12.2
17
+ Requires-Dist: tzdata>=2024.2
18
18
  Provides-Extra: cartes
19
19
  Requires-Dist: cartes>=0.8.1; extra == 'cartes'
20
20
  Provides-Extra: decoding
@@ -0,0 +1 @@
1
+ build/
@@ -0,0 +1,20 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line, and also
5
+ # from the environment for the first two.
6
+ SPHINXOPTS ?=
7
+ SPHINXBUILD ?= sphinx-build
8
+ SOURCEDIR = source
9
+ BUILDDIR = build
10
+
11
+ # Put it first so that "make" without argument is like "make help".
12
+ help:
13
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14
+
15
+ .PHONY: help Makefile
16
+
17
+ # Catch-all target: route all unknown targets to Sphinx using the new
18
+ # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19
+ %: Makefile
20
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -0,0 +1,35 @@
1
+ @ECHO OFF
2
+
3
+ pushd %~dp0
4
+
5
+ REM Command file for Sphinx documentation
6
+
7
+ if "%SPHINXBUILD%" == "" (
8
+ set SPHINXBUILD=sphinx-build
9
+ )
10
+ set SOURCEDIR=source
11
+ set BUILDDIR=build
12
+
13
+ %SPHINXBUILD% >NUL 2>NUL
14
+ if errorlevel 9009 (
15
+ echo.
16
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17
+ echo.installed, then set the SPHINXBUILD environment variable to point
18
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
19
+ echo.may add the Sphinx directory to PATH.
20
+ echo.
21
+ echo.If you don't have Sphinx installed, grab it from
22
+ echo.https://www.sphinx-doc.org/
23
+ exit /b 1
24
+ )
25
+
26
+ if "%1" == "" goto help
27
+
28
+ %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29
+ goto end
30
+
31
+ :help
32
+ %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33
+
34
+ :end
35
+ popd
@@ -0,0 +1,17 @@
1
+ a.reference code.literal span {
2
+ font-family: Lato, proxima-nova, Helvetica Neue, Arial, sans-serif;
3
+ font-size: 16px;
4
+ font-weight: 500;
5
+ color: #2980b9;
6
+ }
7
+ .rst-content .document a {
8
+ text-decoration: underline;
9
+ text-underline-offset: 2pt;
10
+ }
11
+ .rst-content .document a code {
12
+ padding: 0
13
+ }
14
+ .rst-content code {
15
+ border: none;
16
+ background: none;
17
+ }
@@ -0,0 +1,8 @@
1
+ API reference
2
+ =============
3
+
4
+ .. toctree::
5
+ :maxdepth: 1
6
+
7
+ rest
8
+ trino
@@ -0,0 +1,47 @@
1
+ from typing import Any
2
+
3
+ # Configuration file for the Sphinx documentation builder.
4
+ #
5
+ # For the full list of built-in configuration values, see the documentation:
6
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
7
+ import pyopensky
8
+
9
+ # -- Project information -----------------------------------------------------
10
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
11
+
12
+ project = "pyopensky"
13
+ copyright = "2023, Xavier Olive, Junzi Sun"
14
+ author = "Xavier Olive, Junzi Sun"
15
+ release = pyopensky.__version__
16
+
17
+ # -- General configuration ---------------------------------------------------
18
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
19
+
20
+ extensions = [
21
+ "sphinx.ext.autodoc",
22
+ "sphinx.ext.autosectionlabel",
23
+ "sphinx.ext.githubpages",
24
+ "sphinx.ext.intersphinx",
25
+ "sphinx_autodoc_typehints",
26
+ ]
27
+
28
+ templates_path = ["_templates"]
29
+ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
30
+
31
+
32
+ # -- Options for HTML output -------------------------------------------------
33
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
34
+
35
+ html_theme = "sphinx_rtd_theme"
36
+ html_static_path = ["_static"]
37
+
38
+ intersphinx_mapping = {
39
+ "python": ("https://docs.python.org/3", None),
40
+ "pandas": ("https://pandas.pydata.org/pandas-docs/dev", None),
41
+ "traffic": ("https://traffic-viz.github.io", None),
42
+ }
43
+
44
+
45
+ def setup(app: Any) -> None:
46
+ # Specific stylesheet
47
+ app.add_css_file("main_stylesheet.css")
@@ -0,0 +1,65 @@
1
+ Credentials
2
+ ===========
3
+
4
+ Apply for access
5
+ ----------------
6
+
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#q5>`_. Please create an account on
9
+ https://trino.opensky-network.org, and then apply at https://opensky-network.org/data/apply
10
+ with your Trino username to request for activation.
11
+
12
+ Configuration
13
+ -------------
14
+
15
+ The first time you use the library, a configuration file named ``settings.conf``
16
+ is created, including the following content:
17
+
18
+ .. code::
19
+
20
+ [default]
21
+ username =
22
+ password =
23
+
24
+ If you use the same login for the OpenSky website (therefore the REST API) and
25
+ for Trino (it will be unified one day), just fill it here.
26
+
27
+ You will identify the folder where the ``settings.conf`` file is located:
28
+
29
+ .. code:: python
30
+
31
+ from pyopensky.config import opensky_config_dir
32
+
33
+ print(opensky_config_dir)
34
+
35
+
36
+ Different credentials per service
37
+ ---------------------------------
38
+
39
+ If you want to specify different credentials for the REST API and for the Trino
40
+ database, use the following sections in the configuration file.
41
+
42
+ .. code::
43
+
44
+ [opensky] # REST API
45
+ username =
46
+ password =
47
+
48
+ [trino] # Trino database
49
+ username =
50
+ password =
51
+
52
+ If these sections are commented, the library will use the credentials from the
53
+ [default] section.
54
+
55
+ Fallback configuration
56
+ ----------------------
57
+
58
+ If no username and password are specified in the `pyopensky` configuration file, the
59
+ following steps are performed in order:
60
+
61
+ - try to get the credentials from the `traffic <https://traffic-viz.github.io>`_
62
+ configuration file;
63
+ - get the credentials from ``$OPENSKY_USERNAME`` and ``$OPENSKY_PASSWORD``
64
+ environment variables;
65
+ - open a browser and log in on a dedicated webpage.
@@ -0,0 +1,30 @@
1
+ pyopensky
2
+ =========
3
+
4
+ .. toctree::
5
+ :maxdepth: 2
6
+ :caption: Contents:
7
+
8
+ Source code on `github <https://github.com/open-aviation/pyopensky>`_
9
+
10
+ The pyopensky library provides function to easily download data from
11
+ `The OpenSky Network <https://opensky-network.org/>`_ databases. This minimal
12
+ library is ideal for quickly downloading and locally saving data that you will
13
+ use in your future studies. All functions return pandas :class:`~pandas.DataFrame`.
14
+
15
+ .. hint::
16
+
17
+ If Python is your language of choice in general, and you are interested in
18
+ analysing aircraft trajectories, please refer to the following `section in
19
+ the traffic <https://traffic-viz.github.io/data_sources/opensky_db.html>`_
20
+ library. traffic wraps the same pyopensky queries and returns
21
+ :class:`~traffic.core.Traffic` and :class:`~traffic.core.Flight` objects.
22
+
23
+ .. toctree::
24
+ :maxdepth: 2
25
+ :caption: Contents
26
+
27
+ installation
28
+ credentials
29
+ api_reference
30
+
@@ -0,0 +1,27 @@
1
+ Installation
2
+ ============
3
+
4
+ pyopensky is available through pip:
5
+
6
+ .. code::
7
+
8
+ pip install pyopensky
9
+
10
+ The library is also available on conda-forge:
11
+
12
+ .. code::
13
+
14
+ conda install -c conda-forge pyopensky
15
+
16
+ Development mode (with uv):
17
+
18
+ .. code::
19
+
20
+ curl -LsSf https://astral.sh/uv/install.sh | sh # Linux and MacOS
21
+ irm https://astral.sh/uv/install.ps1 | iex # Windows
22
+ uv sync --dev
23
+
24
+ .. hint::
25
+
26
+ pyopensky is automatically installed as a dependency of the `traffic
27
+ <https://traffic-viz.github.io>`_ library.
@@ -0,0 +1,8 @@
1
+ The REST API
2
+ ------------
3
+
4
+ .. autoclass:: pyopensky.rest.REST
5
+ :members:
6
+ :inherited-members:
7
+ :no-undoc-members:
8
+ :show-inheritance:
@@ -0,0 +1,8 @@
1
+ The Trino database
2
+ -------------------
3
+
4
+ .. autoclass:: pyopensky.trino.Trino
5
+ :members:
6
+ :inherited-members:
7
+ :no-undoc-members:
8
+ :show-inheritance:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyopensky"
3
- version = "2.10"
3
+ version = "2.12"
4
4
  description = "A Python interface for OpenSky database"
5
5
  authors = [
6
6
  { name = "Xavier Olive", email = "git@xoolive.org" },
@@ -19,6 +19,7 @@ dependencies = [
19
19
  "tqdm >= 4.66.5",
20
20
  "trino[sqlalchemy] >= 0.329.0",
21
21
  "typing-extensions >= 4.12.2",
22
+ "tzdata>=2024.2",
22
23
  ]
23
24
 
24
25
  [project.urls]
@@ -32,9 +33,6 @@ decoding = ["pymodes>=2.18", "rs1090>=0.3.8"]
32
33
  requires = ["hatchling"]
33
34
  build-backend = "hatchling.build"
34
35
 
35
- [tool.hatch.build.targets.sdist]
36
- include = ["license.txt", "py.typed"]
37
-
38
36
  [tool.uv]
39
37
  dev-dependencies = [
40
38
  "pre-commit >= 3.8.0",
@@ -0,0 +1,89 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import pyModeS as pms
6
+
7
+ import pandas as pd
8
+
9
+
10
+ def decode_row(row: pd.Series) -> dict[str, Any]:
11
+ bds = row["bds"]
12
+ msg = row["rawmsg"]
13
+
14
+ decoded = {
15
+ "time": row["mintime"],
16
+ "icao24": row["icao24"],
17
+ "bds": bds,
18
+ "rawmsg": row["rawmsg"],
19
+ "altitude": row["altitude"],
20
+ "squawk": row["squawk"],
21
+ }
22
+
23
+ if bds == "BDS40":
24
+ selalt40mcp = pms.commb.selalt40mcp(msg)
25
+ selalt40fms = pms.commb.selalt40fms(msg)
26
+ p40baro = pms.commb.p40baro(msg)
27
+
28
+ decoded.update(
29
+ {
30
+ "selalt40mcp": selalt40mcp,
31
+ "selalt40fms": selalt40fms,
32
+ "p40baro": p40baro,
33
+ }
34
+ )
35
+
36
+ if bds == "BDS50":
37
+ roll50 = pms.commb.roll50(msg)
38
+ trk50 = pms.commb.trk50(msg)
39
+ rtrk50 = pms.commb.rtrk50(msg)
40
+ gs50 = pms.commb.gs50(msg)
41
+ tas50 = pms.commb.tas50(msg)
42
+
43
+ decoded.update(
44
+ {
45
+ "roll50": roll50,
46
+ "trk50": trk50,
47
+ "rtrk50": rtrk50,
48
+ "gs50": gs50,
49
+ "tas50": tas50,
50
+ }
51
+ )
52
+
53
+ if bds == "BDS60":
54
+ ias60 = pms.commb.ias60(msg)
55
+ hdg60 = pms.commb.hdg60(msg)
56
+ mach60 = pms.commb.mach60(msg)
57
+ vr60baro = pms.commb.vr60baro(msg)
58
+ vr60ins = pms.commb.vr60ins(msg)
59
+
60
+ decoded.update(
61
+ {
62
+ "ias60": ias60,
63
+ "hdg60": hdg60,
64
+ "mach60": mach60,
65
+ "vr60baro": vr60baro,
66
+ "vr60ins": vr60ins,
67
+ }
68
+ )
69
+ return decoded
70
+
71
+
72
+ def decode(df: pd.DataFrame) -> pd.DataFrame:
73
+ commb = (
74
+ df.assign(DF=lambda df: df["rawmsg"].apply(pms.df))
75
+ .query("DF in [20, 21]")
76
+ .assign(bds=lambda df: df["rawmsg"].apply(pms.bds.infer))
77
+ .query('bds in ["BDS40", "BDS50", "BDS60"]')
78
+ .drop_duplicates(["icao24", "mintime"])
79
+ )
80
+
81
+ altcode = commb.loc[commb.DF == 20, "rawmsg"].apply(pms.altcode)
82
+ commb.loc[commb.DF == 20, "altitude"] = altcode
83
+
84
+ idcode = commb.loc[commb.DF == 21, "rawmsg"].apply(pms.idcode)
85
+ commb.loc[commb.DF == 21, "squawk"] = idcode
86
+
87
+ return pd.DataFrame.from_records(
88
+ decode_row(row) for _i, row in commb.sort_values("mintime").iterrows()
89
+ )
@@ -0,0 +1,31 @@
1
+ # ruff: noqa: E741
2
+
3
+ import sys
4
+
5
+ import rs1090
6
+
7
+ import pandas as pd
8
+
9
+ if sys.version_info < (3, 12):
10
+ from typing import Iterator, Tuple, TypeVar
11
+
12
+ T = TypeVar("T", covariant=True)
13
+
14
+ def batched(
15
+ iterable: Iterator[Tuple[T, ...]], n: int = 1
16
+ ) -> Iterator[Tuple[T, ...]]:
17
+ l = len(iterable) # type: ignore
18
+ for ndx in range(0, l, n):
19
+ yield iterable[ndx : min(ndx + n, l)] # type: ignore
20
+
21
+ else:
22
+ from itertools import batched
23
+
24
+
25
+ def decode(df: pd.DataFrame) -> pd.DataFrame:
26
+ decoded = rs1090.decode(df["rawmsg"], df["mintime"])
27
+
28
+ # 5000 is (empirically) the fastest batch size I found
29
+ df = pd.concat(pd.DataFrame.from_records(d) for d in batched(decoded, 5000))
30
+ df = df.assign(timestamp=pd.to_datetime(df.timestamp, unit="s", utc=True))
31
+ return df
@@ -0,0 +1,13 @@
1
+ import sys
2
+ from importlib.metadata import version
3
+
4
+ from .tzdata import download_tzdata_windows
5
+
6
+ __version__ = version("pyopensky")
7
+
8
+ # Despite the 'win32' string, this value is returned on all versions of Windows,
9
+ # including both 32-bit and 64-bit. The 'win32' identifier is a historical
10
+ # artifact that has been retained for compatibility with older versions of
11
+ # Python.
12
+ if sys.platform == "win32":
13
+ download_tzdata_windows(year=2022)