pyopensky 2.1__tar.gz → 2.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyopensky
3
- Version: 2.1
3
+ Version: 2.2
4
4
  Summary: A Python interface for OpenSky database
5
5
  License: MIT
6
6
  Author: Xavier Olive
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.8
12
12
  Classifier: Programming Language :: Python :: 3.9
13
13
  Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
15
16
  Requires-Dist: appdirs (>=1.4.4)
16
17
  Requires-Dist: minio (>=7.1)
17
18
  Requires-Dist: pandas (>=1.5)
@@ -27,6 +28,8 @@ Description-Content-Type: text/markdown
27
28
 
28
29
  The `pyopensky` Python library provides functions to download data from the OpenSky Network live API and historical databases. It aims at making ADS-B and Mode S data from OpenSky easily accessible in the Python programming environment.
29
30
 
31
+ Full documentation on https://open-aviation.github.io/pyopensky
32
+
30
33
  ## Installation
31
34
 
32
35
  ```sh
@@ -72,7 +75,7 @@ print(opensky_config_dir)
72
75
 
73
76
  ## Usage
74
77
 
75
- - from the REST API:
78
+ - from the [REST API](https://open-aviation.github.io/pyopensky/rest.html):
76
79
 
77
80
  ```python
78
81
  from pyopensky.rest import REST
@@ -87,7 +90,7 @@ print(opensky_config_dir)
87
90
  rest.departure(airport, begin, end)
88
91
  ```
89
92
 
90
- - from the Impala shell (requires authentication):
93
+ - from the [Impala](https://open-aviation.github.io/pyopensky/impala.html) shell (requires authentication):
91
94
 
92
95
  ```python
93
96
  from pyopensky.impala import Impala
@@ -99,7 +102,7 @@ print(opensky_config_dir)
99
102
  impala.rawdata(start, stop, *, callsign, icao24, bounds)
100
103
  ```
101
104
 
102
- - from the Trino shell (requires authentication):
105
+ - from the [Trino](https://open-aviation.github.io/pyopensky/trino.html) database (requires authentication):
103
106
 
104
107
  ```python
105
108
  from pyopensky.trino import Trino
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pyopensky"
3
- version = "2.1"
3
+ version = "2.2"
4
4
  description = "A Python interface for OpenSky database"
5
5
  authors = ["Xavier Olive <git@xoolive.org>", "Junzi Sun <j.sun-1@tudelft.nl>"]
6
6
  license = "MIT"
@@ -24,13 +24,16 @@ paramiko = ">=2.7"
24
24
 
25
25
  [tool.poetry.group.dev.dependencies]
26
26
  pre-commit = ">=3.1.1"
27
- black = ">=23.1.0"
28
27
  mypy = ">=1.0.1"
29
28
  ruff = ">=0.0.253"
30
29
  pytest = ">=7.2.1"
31
30
  ipykernel = ">=6.21.2"
32
31
  types-requests = ">=2.28.11.15"
33
32
  types-paramiko = ">=3.3.0.0"
33
+ Sphinx = ">=5.1"
34
+ sphinx-design = ">=0.4.1"
35
+ sphinx-rtd-theme = ">=0.5.2"
36
+ sphinx-autodoc-typehints = ">=1.17,!=1.21.4"
34
37
 
35
38
  [build-system]
36
39
  requires = ["poetry-core"]
@@ -2,6 +2,8 @@
2
2
 
3
3
  The `pyopensky` Python library provides functions to download data from the OpenSky Network live API and historical databases. It aims at making ADS-B and Mode S data from OpenSky easily accessible in the Python programming environment.
4
4
 
5
+ Full documentation on https://open-aviation.github.io/pyopensky
6
+
5
7
  ## Installation
6
8
 
7
9
  ```sh
@@ -47,7 +49,7 @@ print(opensky_config_dir)
47
49
 
48
50
  ## Usage
49
51
 
50
- - from the REST API:
52
+ - from the [REST API](https://open-aviation.github.io/pyopensky/rest.html):
51
53
 
52
54
  ```python
53
55
  from pyopensky.rest import REST
@@ -62,7 +64,7 @@ print(opensky_config_dir)
62
64
  rest.departure(airport, begin, end)
63
65
  ```
64
66
 
65
- - from the Impala shell (requires authentication):
67
+ - from the [Impala](https://open-aviation.github.io/pyopensky/impala.html) shell (requires authentication):
66
68
 
67
69
  ```python
68
70
  from pyopensky.impala import Impala
@@ -74,7 +76,7 @@ print(opensky_config_dir)
74
76
  impala.rawdata(start, stop, *, callsign, icao24, bounds)
75
77
  ```
76
78
 
77
- - from the Trino shell (requires authentication):
79
+ - from the [Trino](https://open-aviation.github.io/pyopensky/trino.html) database (requires authentication):
78
80
 
79
81
  ```python
80
82
  from pyopensky.trino import Trino
@@ -0,0 +1,3 @@
1
+ from importlib.metadata import version
2
+
3
+ __version__ = version("pyopensky")
@@ -50,6 +50,7 @@ class OpenSkyDBAPI(Protocol):
50
50
  departure_airport: None | str = None,
51
51
  arrival_airport: None | str = None,
52
52
  airport: None | str = None,
53
+ time_buffer: None | str | pd.Timedelta = None,
53
54
  cached: bool = True,
54
55
  compress: bool = False,
55
56
  limit: None | int = None,
@@ -656,12 +656,12 @@ class Impala(OpenSkyDBAPI):
656
656
  departure_airport: None | str = None,
657
657
  arrival_airport: None | str = None,
658
658
  airport: None | str = None,
659
+ time_buffer: None | str | pd.Timedelta = None,
659
660
  cached: bool = True,
660
661
  compress: bool = False,
661
662
  limit: None | int = None,
662
663
  other_tables: str = "",
663
664
  other_params: str = "",
664
- time_buffer: None | str | pd.Timedelta = None,
665
665
  progressbar: bool | ProgressbarType[Any] = True,
666
666
  date_delta: timedelta = timedelta(hours=1),
667
667
  count: bool = False,
@@ -711,6 +711,10 @@ class Impala(OpenSkyDBAPI):
711
711
  :param airport: a string for the ICAO identifier of the airport. Selects
712
712
  flights departing from or arriving at the airport between the two
713
713
  timestamps;
714
+ :param time_buffer: (default: None) time buffer used to extend time
715
+ bounds for flights in the OpenSky flight tables: requests will get
716
+ flights between ``start - time_buffer`` and ``stop + time_buffer``.
717
+ If no airport is specified, the parameter is ignored.
714
718
 
715
719
  .. warning::
716
720
 
@@ -728,10 +732,6 @@ class Impala(OpenSkyDBAPI):
728
732
  received each record;
729
733
  :param nautical_units: (default: True) convert data stored in Impala to
730
734
  standard nautical units (ft, ft/min, knots).
731
- :param time_buffer: (default: None) time buffer used to extend time
732
- bounds for flights in the OpenSky flight tables: requests will get
733
- flights between ``start - time_buffer`` and ``stop + time_buffer``.
734
- If no airport is specified, the parameter is ignored.
735
735
  :param cached: (default: True) switch to False to force a new request to
736
736
  the database regardless of the cached files. This option also
737
737
  deletes previous cache files;
@@ -804,7 +804,7 @@ class Impala(OpenSkyDBAPI):
804
804
  else:
805
805
  other_params += f"and RTRIM(callsign) REGEXP('{callsign}') "
806
806
 
807
- elif callsign.find("%") > 0 or callsign.find("_") > 0:
807
+ elif callsign.find("%") >= 0 or callsign.find("_") >= 0:
808
808
  other_params += "and callsign ilike '{}' ".format(callsign)
809
809
  else:
810
810
  other_params += "and callsign='{:<8s}' ".format(callsign)
@@ -1010,7 +1010,7 @@ class Impala(OpenSkyDBAPI):
1010
1010
  other_params += "and not typeogn "
1011
1011
 
1012
1012
  if isinstance(sensor_name, str):
1013
- if sensor_name.find("%") > 0 or sensor_name.find("_") > 0:
1013
+ if sensor_name.find("%") > -1 or sensor_name.find("_") > -1:
1014
1014
  other_params += "and sensorname ilike '{}' ".format(sensor_name)
1015
1015
  else:
1016
1016
  other_params += "and sensorname='{:<8s}' ".format(sensor_name)
@@ -1241,7 +1241,7 @@ class Impala(OpenSkyDBAPI):
1241
1241
  "supported at the moment."
1242
1242
  )
1243
1243
  if isinstance(callsign, str):
1244
- if callsign.find("%") > 0 or callsign.find("_") > 0:
1244
+ if callsign.find("%") > -1 or callsign.find("_") > -1:
1245
1245
  callsigns = "and callsign ilike '{}' ".format(callsign)
1246
1246
  else:
1247
1247
  callsigns = "and callsign='{:<8s}' ".format(callsign)
@@ -64,6 +64,7 @@ class REST:
64
64
  | str
65
65
  | HasBounds
66
66
  | tuple[float, float, float, float] = None,
67
+ retry: int = 5,
67
68
  ) -> pd.DataFrame:
68
69
  """Returns the current state vectors from OpenSky REST API.
69
70
 
@@ -132,9 +133,12 @@ class REST:
132
133
  columns.append("_")
133
134
  r = pd.DataFrame.from_records(json["states"], columns=columns)
134
135
  except Exception:
135
- _log.warning("Error in received data, retrying in 10 seconds")
136
- time.sleep(10)
137
- return self.states(own, bounds)
136
+ if retry > 0:
137
+ retry = retry - 1
138
+ _log.warning("Retrying in 10 seconds... {retry} more time")
139
+ time.sleep(10)
140
+ return self.states(own, bounds, retry=retry)
141
+ raise
138
142
 
139
143
  return r.assign(
140
144
  timestamp=lambda df: pd.to_datetime(
@@ -210,7 +214,7 @@ class REST:
210
214
  c.raise_for_status()
211
215
  json = c.json()
212
216
 
213
- return tuple(json["route"]) # type: ignore
217
+ return tuple(json["route"])
214
218
 
215
219
  def aircraft(
216
220
  self,
@@ -31,6 +31,8 @@ class UTCTimestampInteger(TypeDecorator[pd.Timestamp]):
31
31
  value = pd.to_datetime(value, utc=True)
32
32
  if isinstance(value, pd.Timestamp):
33
33
  return int(value.timestamp())
34
+ if isinstance(value, pd.Timedelta):
35
+ return int(value.total_seconds())
34
36
  return super().process_bind_param(value, dialect)
35
37
 
36
38
  def process_result_value(
@@ -83,6 +85,7 @@ class CallsignString(TypeDecorator[str]):
83
85
  operator.ne, # !=
84
86
  sql_operators.eq,
85
87
  sql_operators.ne,
88
+ sql_operators.in_op,
86
89
  sql_operators.contains, # .in()
87
90
  ):
88
91
  return self
@@ -408,16 +411,22 @@ class PositionData4(Base):
408
411
  maxtime: Mapped[pd.Timestamp] = mapped_column(UTCTimestampFloat)
409
412
  msgcount: Mapped[int]
410
413
  icao24: Mapped[str]
411
- message: Mapped[str]
412
- isid: Mapped[bool]
413
- flightstatus: Mapped[int]
414
- downlinkrequest: Mapped[int]
415
- utilitymsg: Mapped[int]
416
- interrogatorid: Mapped[int]
417
- identifierdesignator: Mapped[int]
418
- valuecode: Mapped[int]
419
- altitude: Mapped[float]
420
- identity: Mapped[str]
414
+ nicsuppla: Mapped[bool]
415
+ hcr: Mapped[float]
416
+ nic: Mapped[int]
417
+ survstatus: Mapped[int]
418
+ nicsupplb: Mapped[bool]
419
+ odd: Mapped[bool]
420
+ baroalt: Mapped[bool]
421
+ lat: Mapped[float]
422
+ lon: Mapped[float]
423
+ alt: Mapped[float]
424
+ nicsupplc: Mapped[bool]
425
+ groundspeed: Mapped[float]
426
+ gsresolution: Mapped[float]
427
+ heading: Mapped[float]
428
+ timeflag: Mapped[bool]
429
+ surface: Mapped[bool]
421
430
 
422
431
  # Whatever, we pick this one as primary key BUT
423
432
  # - this is not true
@@ -22,6 +22,7 @@ from sqlalchemy import (
22
22
  )
23
23
  from sqlalchemy.orm import aliased
24
24
  from sqlalchemy.orm.attributes import InstrumentedAttribute
25
+ from sqlalchemy.sql import ColumnExpressionArgument
25
26
  from sqlalchemy.sql.expression import text
26
27
  from tqdm import tqdm
27
28
  from trino.auth import JWTAuthentication, OAuth2Authentication
@@ -224,7 +225,7 @@ class Trino(OpenSkyDBAPI):
224
225
  self,
225
226
  start: timelike,
226
227
  stop: None | timelike = None,
227
- *args: Any, # more reasonable to be explicit about arguments
228
+ *args: ColumnExpressionArgument[bool],
228
229
  departure_airport: None | str | list[str] = None,
229
230
  arrival_airport: None | str | list[str] = None,
230
231
  airport: None | str | list[str] = None,
@@ -345,6 +346,9 @@ class Trino(OpenSkyDBAPI):
345
346
  Table.day < stop_ts.ceil("1d"),
346
347
  )
347
348
 
349
+ for condition in args:
350
+ stmt = stmt.where(condition)
351
+
348
352
  if limit is not None:
349
353
  stmt = stmt.limit(limit)
350
354
 
@@ -364,7 +368,7 @@ class Trino(OpenSkyDBAPI):
364
368
  self,
365
369
  start: timelike,
366
370
  stop: None | timelike = None,
367
- *args: Any,
371
+ *args: ColumnExpressionArgument[bool],
368
372
  # date_delta: timedelta = timedelta(hours=1),
369
373
  callsign: None | str | list[str] = None,
370
374
  icao24: None | str | list[str] = None,
@@ -581,7 +585,7 @@ class Trino(OpenSkyDBAPI):
581
585
  self,
582
586
  start: timelike,
583
587
  stop: None | timelike = None,
584
- *args: Any, # more reasonable to be explicit about arguments
588
+ *args: ColumnExpressionArgument[bool],
585
589
  icao24: None | str | list[str] = None,
586
590
  serials: None | int | Iterable[int] = None,
587
591
  bounds: None | HasBounds | tuple[float, float, float, float] = None,
@@ -593,6 +597,7 @@ class Trino(OpenSkyDBAPI):
593
597
  compress: bool = False,
594
598
  limit: None | int = None,
595
599
  Table: Type[RawTable] = RollcallRepliesData4,
600
+ extra_columns: tuple[InstrumentedAttribute[Any], ...] = (),
596
601
  **kwargs: Any,
597
602
  ) -> None | pd.DataFrame:
598
603
  """Get raw message from the OpenSky Trino database.
@@ -687,11 +692,9 @@ class Trino(OpenSkyDBAPI):
687
692
  select(Table)
688
693
  .with_only_columns(
689
694
  Table.mintime,
690
- Table.maxtime,
691
695
  Table.rawmsg,
692
- Table.msgcount,
693
696
  Table.icao24,
694
- Table.sensors,
697
+ *extra_columns,
695
698
  )
696
699
  .where(Table.rawmsg.is_not(None))
697
700
  )
@@ -807,6 +810,9 @@ class Trino(OpenSkyDBAPI):
807
810
  )
808
811
  )
809
812
 
813
+ for condition in args:
814
+ stmt = stmt.where(condition)
815
+
810
816
  stmt = self.stmt_where_str(stmt, icao24, Table.icao24)
811
817
 
812
818
  stmt = stmt.where(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes