pyopensky 2.8__tar.gz → 2.10__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.
@@ -0,0 +1,34 @@
1
+ .vscode/
2
+ .DS_Store
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ .pytest_cache/
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ env/
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
@@ -1,28 +1,25 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pyopensky
3
- Version: 2.8
3
+ Version: 2.10
4
4
  Summary: A Python interface for OpenSky database
5
- Home-page: https://github.com/open-aviation/pyopensky/
6
- License: MIT
7
- Author: Xavier Olive
8
- Author-email: git@xoolive.org
9
- Requires-Python: >=3.9,<4.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
- Classifier: Programming Language :: Python :: 3.12
16
- Requires-Dist: appdirs (>=1.4.4)
17
- Requires-Dist: httpx (>=0.27.0,<0.28.0)
18
- Requires-Dist: minio (>=7.1)
19
- Requires-Dist: pandas (>=1.5)
20
- Requires-Dist: pyarrow (>=11.0.0)
21
- Requires-Dist: pyjwt (>=2.7.0)
22
- Requires-Dist: tqdm (>=4.65.0)
23
- Requires-Dist: trino[sqlalchemy] (>=0.322)
24
- Requires-Dist: typing-extensions (>=4.5.0)
25
5
  Project-URL: Repository, https://github.com/open-aviation/pyopensky/
6
+ Author-email: Xavier Olive <git@xoolive.org>, Junzi Sun <j.sun-1@tudelft.nl>
7
+ License-Expression: MIT
8
+ Requires-Python: >=3.9
9
+ Requires-Dist: appdirs>=1.4.4
10
+ Requires-Dist: httpx>=0.27.2
11
+ Requires-Dist: minio>=7.2.8
12
+ Requires-Dist: pandas>=2.2.2
13
+ Requires-Dist: pyarrow>=17.0.0
14
+ Requires-Dist: pyjwt>=2.9.0
15
+ Requires-Dist: tqdm>=4.66.5
16
+ Requires-Dist: trino[sqlalchemy]>=0.329.0
17
+ Requires-Dist: typing-extensions>=4.12.2
18
+ Provides-Extra: cartes
19
+ Requires-Dist: cartes>=0.8.1; extra == 'cartes'
20
+ Provides-Extra: decoding
21
+ Requires-Dist: pymodes>=2.18; extra == 'decoding'
22
+ Requires-Dist: rs1090>=0.3.8; extra == 'decoding'
26
23
  Description-Content-Type: text/markdown
27
24
 
28
25
  # pyopensky
@@ -43,12 +40,12 @@ The library is also available on conda-forge:
43
40
  conda install -c conda-forge pyopensky
44
41
  ```
45
42
 
46
- Development mode (with poetry):
43
+ Development mode (with uv):
47
44
 
48
45
  ```sh
49
- git clone https://github.com/open-aviation/pyopensky
50
- cd pyopensky
51
- poetry install
46
+ curl -LsSf https://astral.sh/uv/install.sh | sh # Linux and MacOS
47
+ irm https://astral.sh/uv/install.ps1 | iex # Windows
48
+ uv sync --dev
52
49
  ```
53
50
 
54
51
  ## Credentials
@@ -86,4 +83,3 @@ See details in the [documentation](https://open-aviation.github.io/pyopensky/cre
86
83
  trino.history(start, stop, *, callsign, icao24, bounds)
87
84
  trino.rawdata(start, stop, *, callsign, icao24, bounds)
88
85
  ```
89
-
@@ -0,0 +1,80 @@
1
+ [project]
2
+ name = "pyopensky"
3
+ version = "2.10"
4
+ description = "A Python interface for OpenSky database"
5
+ authors = [
6
+ { name = "Xavier Olive", email = "git@xoolive.org" },
7
+ { name = "Junzi Sun", email = "j.sun-1@tudelft.nl" },
8
+ ]
9
+ license = "MIT"
10
+ readme = "readme.md"
11
+ requires-python = ">=3.9"
12
+ dependencies = [
13
+ "appdirs >= 1.4.4",
14
+ "httpx >= 0.27.2",
15
+ "minio >= 7.2.8",
16
+ "pandas >= 2.2.2",
17
+ "pyarrow >= 17.0.0",
18
+ "pyjwt >= 2.9.0",
19
+ "tqdm >= 4.66.5",
20
+ "trino[sqlalchemy] >= 0.329.0",
21
+ "typing-extensions >= 4.12.2",
22
+ ]
23
+
24
+ [project.urls]
25
+ Repository = "https://github.com/open-aviation/pyopensky/"
26
+
27
+ [project.optional-dependencies]
28
+ cartes = ["cartes>=0.8.1"]
29
+ decoding = ["pymodes>=2.18", "rs1090>=0.3.8"]
30
+
31
+ [build-system]
32
+ requires = ["hatchling"]
33
+ build-backend = "hatchling.build"
34
+
35
+ [tool.hatch.build.targets.sdist]
36
+ include = ["license.txt", "py.typed"]
37
+
38
+ [tool.uv]
39
+ dev-dependencies = [
40
+ "pre-commit >= 3.8.0",
41
+ "mypy >= 1.11.2",
42
+ "ruff >= 0.6.3",
43
+ "pytest >= 8.3.2",
44
+ "ipykernel >= 6.29.5",
45
+ "sphinx >= 7.4.7; python_version>'3.11'",
46
+ "sphinx-design >= 0.6.1; python_version>'3.11'",
47
+ "sphinx-rtd-theme >= 2.0.0; python_version>'3.11'",
48
+ "sphinx-autodoc-typehints >= 2.3.0; python_version>'3.11'",
49
+ ]
50
+
51
+ [tool.ruff]
52
+ lint.select = [
53
+ "E",
54
+ "W", # pycodestyle
55
+ "F", # pyflakes
56
+ "I", # isort
57
+ "NPY", # numpy
58
+ # "PD", # pandas
59
+ "DTZ", # flake8-datetimez
60
+ "RUF",
61
+ ]
62
+ line-length = 80
63
+ target-version = "py39"
64
+
65
+ [tool.ruff.lint.isort]
66
+ known-first-party = ["numpy", "pandas"]
67
+
68
+ [tool.mypy]
69
+ python_version = "3.9"
70
+ platform = "posix"
71
+ color_output = true
72
+ pretty = true
73
+ show_column_numbers = true
74
+ strict = true
75
+ check_untyped_defs = true
76
+ ignore_missing_imports = true
77
+ warn_no_return = true
78
+ warn_redundant_casts = true
79
+ warn_unused_configs = true
80
+ warn_unused_ignores = true
@@ -16,12 +16,12 @@ The library is also available on conda-forge:
16
16
  conda install -c conda-forge pyopensky
17
17
  ```
18
18
 
19
- Development mode (with poetry):
19
+ Development mode (with uv):
20
20
 
21
21
  ```sh
22
- git clone https://github.com/open-aviation/pyopensky
23
- cd pyopensky
24
- poetry install
22
+ curl -LsSf https://astral.sh/uv/install.sh | sh # Linux and MacOS
23
+ irm https://astral.sh/uv/install.ps1 | iex # Windows
24
+ uv sync --dev
25
25
  ```
26
26
 
27
27
  ## Credentials
@@ -1,78 +0,0 @@
1
- [tool.poetry]
2
- name = "pyopensky"
3
- version = "2.8"
4
- description = "A Python interface for OpenSky database"
5
- repository = "https://github.com/open-aviation/pyopensky/"
6
- authors = [
7
- "Xavier Olive <git@xoolive.org>",
8
- "Junzi Sun <j.sun-1@tudelft.nl>"
9
- ]
10
- license = "MIT"
11
- readme = "readme.md"
12
- include = [
13
- "license.txt",
14
- "py.typed",
15
- ]
16
-
17
- [tool.poetry.dependencies]
18
- python = "^3.9"
19
- pandas = ">=1.5"
20
- trino = { version = ">=0.322", extras = ['sqlalchemy'] }
21
- minio = ">=7.1"
22
- appdirs = ">=1.4.4"
23
- tqdm = ">=4.65.0"
24
- pyarrow = ">=11.0.0"
25
- typing-extensions = ">=4.5.0"
26
- pyjwt = ">=2.7.0"
27
- httpx = "^0.27.0"
28
-
29
- [tool.poetry.group.dev.dependencies]
30
- pre-commit = ">=3.1.1"
31
- mypy = ">=1.0.1"
32
- ruff = ">=0.0.253"
33
- pytest = ">=7.2.1"
34
- ipykernel = ">=6.21.2"
35
- Sphinx = ">=5.1"
36
- sphinx-design = ">=0.4.1"
37
- sphinx-rtd-theme = ">=0.5.2"
38
- sphinx-autodoc-typehints = ">=1.17,!=1.21.4"
39
-
40
- [build-system]
41
- requires = ["poetry-core"]
42
- build-backend = "poetry.core.masonry.api"
43
-
44
- [tool.black]
45
- line-length = 80
46
- target_version = ['py38', 'py39', 'py310', 'py311']
47
- include = '\.pyi?$'
48
-
49
- [tool.ruff]
50
- lint.select = [
51
- "E", "W", # pycodestyle
52
- "F", # pyflakes
53
- "I", # isort
54
- "NPY", # numpy
55
- # "PD", # pandas
56
- "DTZ", # flake8-datetimez
57
- "RUF"
58
- ]
59
- line-length = 80
60
- target-version = "py38"
61
-
62
- [tool.ruff.lint.isort]
63
- known-first-party = ["numpy", "pandas"]
64
-
65
- [tool.mypy]
66
- python_version = 3.8
67
- platform = "posix"
68
-
69
- color_output = true
70
- pretty = true
71
- show_column_numbers = true
72
- strict = true
73
- check_untyped_defs = true
74
- ignore_missing_imports = true
75
- warn_no_return = true
76
- warn_redundant_casts = true
77
- warn_unused_configs = true
78
- warn_unused_ignores = true
@@ -1,3 +0,0 @@
1
- from importlib.metadata import version
2
-
3
- __version__ = version("pyopensky")
@@ -1,76 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any, Callable, Iterable, TypeVar
4
-
5
- from typing_extensions import Protocol
6
-
7
- import pandas as pd
8
-
9
- from .time import timelike
10
-
11
- T = TypeVar("T")
12
- ProgressbarType = Callable[[Iterable[T]], Iterable[T]]
13
-
14
-
15
- class HasBounds(Protocol):
16
- @property
17
- def bounds(self) -> tuple[float, float, float, float]: ...
18
-
19
-
20
- class OpenSkyDBAPI(Protocol):
21
- def flightlist(
22
- self,
23
- start: timelike,
24
- stop: None | timelike = None,
25
- *args: Any, # more reasonable to be explicit about arguments
26
- departure_airport: None | str | list[str] = None,
27
- arrival_airport: None | str | list[str] = None,
28
- airport: None | str | list[str] = None,
29
- callsign: None | str | list[str] = None,
30
- icao24: None | str | list[str] = None,
31
- cached: bool = True,
32
- compress: bool = False,
33
- limit: None | int = None,
34
- **kwargs: Any,
35
- ) -> None | pd.DataFrame: ...
36
-
37
- def history(
38
- self,
39
- start: timelike,
40
- stop: None | timelike = None,
41
- *args: Any,
42
- # date_delta: timedelta = timedelta(hours=1),
43
- callsign: None | str | list[str] = None,
44
- icao24: None | str | list[str] = None,
45
- serials: None | int | Iterable[int] = None,
46
- bounds: None
47
- | str
48
- | HasBounds
49
- | tuple[float, float, float, float] = None,
50
- departure_airport: None | str = None,
51
- arrival_airport: None | str = None,
52
- airport: None | str = None,
53
- time_buffer: None | str | pd.Timedelta = None,
54
- cached: bool = True,
55
- compress: bool = False,
56
- limit: None | int = None,
57
- **kwargs: Any,
58
- ) -> None | pd.DataFrame: ...
59
-
60
- def rawdata(
61
- self,
62
- start: timelike,
63
- stop: None | timelike = None,
64
- *args: Any, # more reasonable to be explicit about arguments
65
- icao24: None | str | list[str] = None,
66
- serials: None | int | Iterable[int] = None,
67
- bounds: None | HasBounds | tuple[float, float, float, float] = None,
68
- callsign: None | str | list[str] = None,
69
- departure_airport: None | str = None,
70
- arrival_airport: None | str = None,
71
- airport: None | str = None,
72
- cached: bool = True,
73
- compress: bool = False,
74
- limit: None | int = None,
75
- **kwargs: Any,
76
- ) -> None | pd.DataFrame: ...
@@ -1,210 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import configparser
4
- import logging
5
- import os
6
- from pathlib import Path
7
- from typing import TypedDict
8
-
9
- from appdirs import user_cache_dir, user_config_dir
10
-
11
- import pandas as pd
12
-
13
- _log = logging.getLogger(__name__)
14
-
15
-
16
- DEFAULT_CONFIG = """
17
- [default]
18
- username =
19
- password =
20
-
21
- # Uncomment the following if you have access to the s3 server
22
- # secret_key =
23
- # access_key =
24
-
25
- # If you need a different account on Trino, uncomment the following
26
- # [trino]
27
- # username =
28
- # password =
29
-
30
- [cache]
31
- ## You may set a different cache folder here if you have a preferred space
32
- ## for storing possibly large files.
33
- ## Default settings:
34
- ## - $HOME/.cache/opensky (Linux)
35
- ## - $HOME/Library/Caches/opensky (MacOS)
36
- ## - C:\\Users\\<username>\\AppData\\Local\\opensky\\Cache (Windows)
37
- ##
38
- # path =
39
-
40
- ## The purge parameter refers to the cache folder containing data from the
41
- ## Opensky databases. Cache files tend to take space so you may want to let
42
- ## the library delete older files.
43
- ## Files are removed when the library is imported.
44
- purge = 90 days
45
- """
46
-
47
- opensky_config_dir = Path(user_config_dir("pyopensky"))
48
- opensky_config = configparser.ConfigParser()
49
-
50
- if (opensky_config_file := opensky_config_dir / "settings.conf").exists():
51
- opensky_config.read(opensky_config_file.as_posix())
52
- elif (previous_config_file := opensky_config_dir / "secret.conf").exists():
53
- previous_config_file.rename(opensky_config_file)
54
- opensky_config.read(opensky_config_file.as_posix())
55
- else:
56
- if not opensky_config_dir.exists():
57
- opensky_config_dir.mkdir(parents=True)
58
- opensky_config_file.write_text(DEFAULT_CONFIG)
59
-
60
- traffic_config_dir = Path(user_config_dir("traffic"))
61
- traffic_config = configparser.ConfigParser()
62
-
63
- if (traffic_config_file := traffic_config_dir / "traffic.conf").exists():
64
- traffic_config.read(traffic_config_file.as_posix())
65
-
66
-
67
- def purge_cache(cache_path: Path) -> None:
68
- cache_no_expire = False
69
- cache_no_expire |= bool(os.environ.get("TRAFFIC_CACHE_NO_EXPIRE"))
70
- cache_no_expire |= bool(os.environ.get("OPENSKY_CACHE_NO_EXPIRE"))
71
-
72
- cache_purge = "90 days"
73
- if purge := traffic_config.get("cache", "purge", fallback=None):
74
- if purge.strip() != "":
75
- cache_purge = purge
76
- if purge := opensky_config.get("cache", "purge", fallback=None):
77
- if purge.strip() != "":
78
- cache_purge = purge
79
-
80
- if not cache_no_expire: # coverage: ignore
81
- expiration = pd.Timestamp("now") - pd.Timedelta(cache_purge)
82
-
83
- for cache_file in cache_path.glob("*"):
84
- ctime = cache_file.stat().st_ctime
85
- if ctime < expiration.timestamp():
86
- _log.warn(f"Removing {cache_file} created on {ctime}")
87
- cache_file.unlink()
88
-
89
-
90
- class Resolution(TypedDict, total=False):
91
- opensky_category: str
92
- opensky_name: str
93
- traffic_category: str
94
- traffic_name: str
95
- environment_variable: str
96
-
97
-
98
- NAME_RESOLUTION: dict[str, Resolution] = {
99
- # Cache configuration
100
- "cache_dir": dict(
101
- environment_variable="OPENSKY_CACHE",
102
- opensky_category="cache",
103
- opensky_name="path",
104
- traffic_category="cache",
105
- traffic_name="path",
106
- ),
107
- # Network configuration
108
- "http_proxy": dict(
109
- environment_variable="http_proxy",
110
- opensky_category="default",
111
- opensky_name="http_proxy",
112
- traffic_category="network",
113
- traffic_name="http_proxy",
114
- ),
115
- # Credentials configuration
116
- "access_key": dict(
117
- opensky_category="s3",
118
- opensky_name="access_key",
119
- traffic_category="opensky",
120
- traffic_name="access_key",
121
- ),
122
- "secret_key": dict(
123
- opensky_category="s3",
124
- opensky_name="secret_key",
125
- traffic_category="opensky",
126
- traffic_name="secret_key",
127
- ),
128
- "username": dict(
129
- environment_variable="OPENSKY_USERNAME",
130
- opensky_category="default",
131
- opensky_name="username",
132
- traffic_category="opensky",
133
- traffic_name="username",
134
- ),
135
- "password": dict(
136
- environment_variable="OPENSKY_PASSWORD",
137
- opensky_category="default",
138
- opensky_name="password",
139
- traffic_category="opensky",
140
- traffic_name="password",
141
- ),
142
- "trino_username": dict(
143
- environment_variable="OPENSKY_TRINO_USERNAME",
144
- opensky_category="trino",
145
- opensky_name="username",
146
- ),
147
- "trino_password": dict(
148
- environment_variable="OPENSKY_TRINO_PASSWORD",
149
- opensky_category="trino",
150
- opensky_name="password",
151
- ),
152
- }
153
-
154
- __all__ = list(NAME_RESOLUTION.keys())
155
-
156
-
157
- def get_config(
158
- opensky_category: str,
159
- opensky_name: str,
160
- traffic_category: None | str = None,
161
- traffic_name: None | str = None,
162
- environment_variable: None | str = None,
163
- ) -> None | str:
164
- if opensky_value := opensky_config.get(
165
- opensky_category, opensky_name, fallback=None
166
- ):
167
- return opensky_value
168
-
169
- if traffic_category is not None and traffic_name is not None:
170
- if traffic_value := traffic_config.get(
171
- traffic_category, traffic_name, fallback=None
172
- ):
173
- return traffic_value
174
-
175
- if environment_variable is not None:
176
- return os.environ.get(environment_variable)
177
-
178
- return None
179
-
180
-
181
- cache_dir = get_config(**NAME_RESOLUTION["cache_dir"])
182
- if cache_dir is None:
183
- cache_dir = user_cache_dir("opensky")
184
- cache_path = Path(cache_dir)
185
- if not cache_path.exists():
186
- cache_path.mkdir(parents=True)
187
-
188
- purge_cache(cache_path)
189
-
190
-
191
- def __getattr__(name: str) -> None | str:
192
- # Pick in order:
193
- # 1. pyopensky -> settings.conf
194
- # 2. traffic -> traffic.conf
195
- # 3. environment variables
196
-
197
- if name == "trino_username":
198
- if value := get_config(**NAME_RESOLUTION[name]):
199
- return value
200
- return get_config(**NAME_RESOLUTION["username"])
201
-
202
- if name == "trino_password":
203
- if value := get_config(**NAME_RESOLUTION[name]):
204
- return value
205
- return get_config(**NAME_RESOLUTION["password"])
206
-
207
- if name in __all__:
208
- return get_config(**NAME_RESOLUTION[name])
209
-
210
- raise AttributeError