FlightRadarAPI 1.5.0__tar.gz → 1.5.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.
Files changed (21) hide show
  1. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/.gitignore +5 -0
  2. flightradarapi-1.5.2/FlightRadar24/__init__.py +37 -0
  3. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/__init__.py +1 -1
  4. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/api.py +44 -20
  5. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/request.py +12 -1
  6. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/Makefile +125 -73
  7. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/PKG-INFO +4 -4
  8. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/README.md +1 -1
  9. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/pyproject.toml +8 -3
  10. flightradarapi-1.5.0/.tool-versions +0 -1
  11. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/core.py +0 -0
  12. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/entities/__init__.py +0 -0
  13. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/entities/airport.py +0 -0
  14. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/entities/entity.py +0 -0
  15. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/entities/flight.py +0 -0
  16. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/errors.py +0 -0
  17. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/flight_tracker_config.py +0 -0
  18. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/parsers.py +0 -0
  19. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/py.typed +0 -0
  20. {flightradarapi-1.5.0/FlightRadar24 → flightradarapi-1.5.2/FlightRadarAPI}/zones.py +0 -0
  21. {flightradarapi-1.5.0 → flightradarapi-1.5.2}/LICENSE +0 -0
@@ -19,6 +19,11 @@ coverage.xml
19
19
  # Node.js
20
20
  node_modules/
21
21
 
22
+ # Version managers (local dev only)
23
+ .tool-versions
24
+ .python-version
25
+ .nvmrc
26
+
22
27
  # Editors / OS
23
28
  .idea/
24
29
  .vscode/
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ Deprecated import alias for the FlightRadarAPI SDK.
5
+
6
+ The package was renamed to ``FlightRadarAPI`` so the Python import name
7
+ matches the PyPI distribution name and the Node.js package name. This
8
+ module re-exports the public API and aliases every submodule so legacy
9
+ imports such as ``from FlightRadar24 import FlightRadar24API`` or
10
+ ``from FlightRadar24.errors import CloudflareError`` keep working, but a
11
+ ``DeprecationWarning`` is emitted on import.
12
+ """
13
+
14
+ import importlib
15
+ import pkgutil
16
+ import sys
17
+ import warnings
18
+
19
+ import FlightRadarAPI as _pkg
20
+
21
+ warnings.warn(
22
+ "Importing from 'FlightRadar24' is deprecated and will be removed in a "
23
+ "future release. Import from 'FlightRadarAPI' instead "
24
+ "(e.g. 'from FlightRadarAPI import FlightRadar24API').",
25
+ DeprecationWarning,
26
+ stacklevel=2,
27
+ )
28
+
29
+ # Mirror every submodule of FlightRadarAPI under the legacy FlightRadar24
30
+ # namespace so dotted imports keep resolving without touching disk.
31
+ for _info in pkgutil.walk_packages(_pkg.__path__, prefix=f"{_pkg.__name__}."):
32
+ _mod = importlib.import_module(_info.name)
33
+ sys.modules[_info.name.replace(_pkg.__name__, __name__, 1)] = _mod
34
+ del _info, _mod
35
+
36
+ from FlightRadarAPI import * # noqa: E402, F401, F403
37
+ from FlightRadarAPI import __all__, __author__, __version__ # noqa: E402, F401
@@ -12,7 +12,7 @@ https://www.flightradar24.com/terms-and-conditions
12
12
  """
13
13
 
14
14
  __author__ = "Jean Loui Bernard Silva de Jesus"
15
- __version__ = "1.5.0"
15
+ __version__ = "1.5.2"
16
16
 
17
17
  from .api import FlightRadar24API
18
18
  from .core import Countries
@@ -14,6 +14,13 @@ from .flight_tracker_config import FlightTrackerConfig
14
14
  from .parsers import parse_airlines_html, parse_airports_html
15
15
  from .request import APIClient, RetryPolicy
16
16
 
17
+ # Some FR24 live-feed backends answer 200 with a well-formed envelope but no
18
+ # flight entries -- indistinguishable from a legitimately empty result. The
19
+ # "AWSALB" cookie then pins the session to that backend, so dropping it is what
20
+ # makes the load balancer re-roll on retry.
21
+ FEED_STICKY_COOKIES = ("AWSALB", "AWSALBCORS")
22
+ FEED_EMPTY_RETRIES = 4
23
+
17
24
 
18
25
  class FlightRadar24API:
19
26
  """
@@ -38,7 +45,7 @@ class FlightRadar24API:
38
45
  :param max_workers: Maximum threads used when fetching flight details concurrently
39
46
  :param impersonate: TLS impersonation profile (curl_cffi). Override when FR24
40
47
  updates its Cloudflare bot mitigation faster than this library releases.
41
- See ``FlightRadar24.request.DEFAULT_IMPERSONATE`` for the current default.
48
+ See ``FlightRadarAPI.request.DEFAULT_IMPERSONATE`` for the current default.
42
49
  :param retry: Optional :class:`RetryPolicy` applied to transient failures
43
50
  (``CloudflareError`` and curl_cffi network errors). Defaults to no retry.
44
51
  """
@@ -230,30 +237,39 @@ class FlightRadar24API:
230
237
  lon = math.radians(longitude)
231
238
 
232
239
  approx_earth_radius = 6371
240
+
241
+ # Distance from the centre to a corner of the bounding square.
233
242
  hypotenuse_distance = math.sqrt(2 * (math.pow(half_side_in_km, 2)))
234
243
 
244
+ # The two diagonal bearings (in radians) used below are 225° (SW corner,
245
+ # yields the min lat/lon) and 45° (NE corner, yields the max lat/lon).
246
+ bearing_sw = math.radians(225)
247
+ bearing_ne = math.radians(45)
248
+
249
+ # Destination-point formula along the SW bearing → south-west corner.
235
250
  lat_min = math.asin(
236
251
  math.sin(lat) * math.cos(hypotenuse_distance / approx_earth_radius)
237
252
  + math.cos(lat)
238
253
  * math.sin(hypotenuse_distance / approx_earth_radius)
239
- * math.cos(225 * (math.pi / 180)),
254
+ * math.cos(bearing_sw),
240
255
  )
241
256
  lon_min = lon + math.atan2(
242
- math.sin(225 * (math.pi / 180))
257
+ math.sin(bearing_sw)
243
258
  * math.sin(hypotenuse_distance / approx_earth_radius)
244
259
  * math.cos(lat),
245
260
  math.cos(hypotenuse_distance / approx_earth_radius)
246
261
  - math.sin(lat) * math.sin(lat_min),
247
262
  )
248
263
 
264
+ # Same formula along the NE bearing → north-east corner.
249
265
  lat_max = math.asin(
250
266
  math.sin(lat) * math.cos(hypotenuse_distance / approx_earth_radius)
251
267
  + math.cos(lat)
252
268
  * math.sin(hypotenuse_distance / approx_earth_radius)
253
- * math.cos(45 * (math.pi / 180)),
269
+ * math.cos(bearing_ne),
254
270
  )
255
271
  lon_max = lon + math.atan2(
256
- math.sin(45 * (math.pi / 180))
272
+ math.sin(bearing_ne)
257
273
  * math.sin(hypotenuse_distance / approx_earth_radius)
258
274
  * math.cos(lat),
259
275
  math.cos(hypotenuse_distance / approx_earth_radius)
@@ -276,7 +292,8 @@ class FlightRadar24API:
276
292
 
277
293
  :param country: Country name
278
294
  """
279
- flag_url = Core.country_flag_url.format(country.lower().replace(" ", "-"))
295
+ slug = country.lower().replace(" ", "-")
296
+ flag_url = Core.country_flag_url.format(slug)
280
297
  headers = Core.image_headers.copy()
281
298
 
282
299
  headers.pop("origin", None) # Does not work for this request.
@@ -332,24 +349,31 @@ class FlightRadar24API:
332
349
  if registration is not None: request_params["reg"] = registration
333
350
  if aircraft_type is not None: request_params["type"] = aircraft_type
334
351
 
335
- # Get all flights from Data Live FlightRadar24.
336
- response = self.__client.request(
337
- Core.real_time_flight_tracker_data_url,
338
- params=request_params,
339
- headers=Core.json_headers,
340
- timeout=self.timeout,
341
- )
342
- content = response.get_json_content()
343
-
344
352
  flights: List[Flight] = list()
345
353
 
346
- for flight_id, flight_info in content.items():
354
+ for _ in range(FEED_EMPTY_RETRIES + 1):
355
+ # Get all flights from Data Live FlightRadar24.
356
+ response = self.__client.request(
357
+ Core.real_time_flight_tracker_data_url,
358
+ params=request_params,
359
+ headers=Core.json_headers,
360
+ timeout=self.timeout,
361
+ )
362
+ content = response.get_json_content()
347
363
 
348
364
  # Get flights only.
349
- if not flight_id[0].isnumeric():
350
- continue
351
-
352
- flights.append(Flight(flight_id, flight_info))
365
+ flights = [
366
+ Flight(flight_id, flight_info)
367
+ for flight_id, flight_info in content.items()
368
+ if flight_id[0].isnumeric()
369
+ ]
370
+
371
+ # "full_count": 0 means the feed really has nothing to report.
372
+ if flights or not content.get("full_count"):
373
+ break
374
+
375
+ for cookie_name in FEED_STICKY_COOKIES:
376
+ self.__client.delete_cookie(cookie_name)
353
377
 
354
378
  if details:
355
379
  with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
@@ -76,7 +76,7 @@ def _run_with_retry(fn, retry: Optional[RetryPolicy]):
76
76
 
77
77
  class APIClient:
78
78
  """
79
- Central HTTP client for the FlightRadar24 package.
79
+ Central HTTP client for the FlightRadarAPI package.
80
80
 
81
81
  Owns the persistent session (cookie jar, TLS fingerprint, future bypass logic)
82
82
  so that the rest of the codebase never has to deal with those concerns directly.
@@ -122,6 +122,17 @@ class APIClient:
122
122
  """Clear all cookies from the session."""
123
123
  self.__session.cookies.clear()
124
124
 
125
+ def delete_cookie(self, name: str) -> None:
126
+ """Drop a single cookie, leaving the rest of the jar intact.
127
+
128
+ Sheds load-balancer stickiness without discarding the login session,
129
+ which lives in the same jar.
130
+ """
131
+ try:
132
+ del self.__session.cookies[name]
133
+ except KeyError:
134
+ pass
135
+
125
136
 
126
137
  class APIRequest:
127
138
  """
@@ -1,20 +1,41 @@
1
1
  # Makefile for FlightRadarAPI Python package
2
2
 
3
3
  # Variables
4
- PACKAGE_NAME = FlightRadar24
5
- PYTHON = python3
6
- PIP = pip3
4
+ PACKAGE_NAME = FlightRadarAPI
7
5
  BUILD_DIR = build
8
6
  DIST_DIR = dist
9
7
  EGG_INFO = $(PACKAGE_NAME).egg-info
10
8
  VENV_DIR = venv
11
9
  TEST_DIR = tests
12
10
 
11
+ # Minimum offline coverage required by `test-coverage` and by the CI workflow.
12
+ # Keep this single source-of-truth in sync with `.github/workflows/python-package.yml`
13
+ # (raise both together when the offline suite grows).
14
+ COVERAGE_MIN = 60
15
+
16
+ # Dev tooling installed by `install-dev` / `dev-setup` on top of `.[tests]`.
17
+ # Centralised so the two targets do not drift.
18
+ DEV_TOOLS = pytest-cov flake8 black mypy twine build hatch pip-audit
19
+
20
+ # Auto-detect virtualenv. When `venv/` already exists, every target uses its
21
+ # interpreter so `make test` / `make lint` / etc. work without first running
22
+ # `source venv/bin/activate`. Otherwise we fall back to the system python.
23
+ #
24
+ # Targets that *create* the venv (notably `dev-setup`) must call
25
+ # `$(VENV_DIR)/bin/pip` directly — variable expansion happens at parse time,
26
+ # so the auto-detection below cannot pick up a venv created later in the
27
+ # same `make` invocation.
28
+ ifneq ($(wildcard $(VENV_DIR)/bin/python),)
29
+ PYTHON := $(VENV_DIR)/bin/python
30
+ PIP := $(VENV_DIR)/bin/pip
31
+ else
32
+ PYTHON := python3
33
+ PIP := pip3
34
+ endif
35
+
13
36
  # Colors for output
14
37
  GREEN = \033[0;32m
15
38
  YELLOW = \033[0;33m
16
- RED = \033[0;31m
17
- BLUE = \033[0;34m
18
39
  NC = \033[0m # No Color
19
40
 
20
41
  # Default target
@@ -43,47 +64,49 @@ help:
43
64
  @echo " $(YELLOW)check-deps$(NC) - Check for outdated dependencies"
44
65
  @echo " $(YELLOW)update-deps$(NC) - Update dependencies"
45
66
  @echo " $(YELLOW)security$(NC) - Run security audit"
46
- @echo " $(YELLOW)docs$(NC) - Generate documentation"
67
+ @echo " $(YELLOW)docs$(NC) - Build the MkDocs site (output in ../site/)"
68
+ @echo " $(YELLOW)docs-serve$(NC) - Serve the MkDocs site locally with auto-reload"
47
69
  @echo " $(YELLOW)venv$(NC) - Create virtual environment"
48
- @echo " $(YELLOW)venv-activate$(NC) - Show command to activate venv"
49
70
  @echo " $(YELLOW)all$(NC) - Run full pipeline (install, lint, test, build)"
50
71
 
51
- # Create virtual environment
72
+ # Create virtual environment.
73
+ #
74
+ # Uses `python3` literally rather than `$(PYTHON)`: when this target runs with
75
+ # an existing venv on disk the auto-detection at the top would point at
76
+ # `venv/bin/python` and we'd be asking the venv to recreate itself, which is
77
+ # both confusing and unreliable on Python builds with restricted `venv`
78
+ # support. The system python3 is the right bootstrap interpreter.
52
79
  .PHONY: venv
53
80
  venv:
54
81
  @echo "$(GREEN)Creating virtual environment...$(NC)"
55
- $(PYTHON) -m venv $(VENV_DIR)
82
+ python3 -m venv $(VENV_DIR)
56
83
  @echo "$(GREEN)Virtual environment created in $(VENV_DIR)$(NC)"
57
84
  @echo "$(YELLOW)To activate: source $(VENV_DIR)/bin/activate$(NC)"
58
85
 
59
- # Show activation command
60
- .PHONY: venv-activate
61
- venv-activate:
62
- @echo "$(YELLOW)To activate virtual environment run:$(NC)"
63
- @echo "source $(VENV_DIR)/bin/activate"
86
+ # Install package in editable mode (no dev tools).
87
+ .PHONY: install
88
+ install:
89
+ @echo "$(GREEN)Installing package in editable mode...$(NC)"
90
+ $(PIP) install -e .
91
+ @echo "$(GREEN)Package installed successfully!$(NC)"
64
92
 
65
- # Install dependencies
93
+ # Backwards-compatible alias for `install`. Kept so older docs / muscle memory
94
+ # referencing `make install-deps` keep working; consolidating eliminated the
95
+ # old redundant double `pip install -e .` between `install-deps` and `install`.
66
96
  .PHONY: install-deps
67
- install-deps:
68
- @echo "$(GREEN)Installing dependencies...$(NC)"
69
- $(PIP) install -e .
70
- @echo "$(GREEN)Dependencies installed successfully!$(NC)"
97
+ install-deps: install
71
98
 
72
- # Install development dependencies
99
+ # Install everything needed for development: package (editable) + test extras
100
+ # + the tooling used by other Makefile targets (lint, type-check, security,
101
+ # build). Dev tools are defined once in `$(DEV_TOOLS)` so this target and
102
+ # `dev-setup` cannot drift.
73
103
  .PHONY: install-dev
74
104
  install-dev:
75
105
  @echo "$(GREEN)Installing development dependencies...$(NC)"
76
106
  $(PIP) install -e ".[tests]"
77
- $(PIP) install pytest-cov flake8 black mypy twine build hatch
107
+ $(PIP) install $(DEV_TOOLS)
78
108
  @echo "$(GREEN)Development dependencies installed successfully!$(NC)"
79
109
 
80
- # Install package in development mode
81
- .PHONY: install
82
- install: install-deps
83
- @echo "$(GREEN)Installing package in development mode...$(NC)"
84
- $(PIP) install -e .
85
- @echo "$(GREEN)Package installed successfully!$(NC)"
86
-
87
110
  # Run tests
88
111
  .PHONY: test
89
112
  test:
@@ -98,11 +121,12 @@ test-verbose:
98
121
  $(PYTHON) -m pytest $(TEST_DIR) -v -s
99
122
  @echo "$(GREEN)Verbose tests completed!$(NC)"
100
123
 
101
- # Run tests with coverage
124
+ # Run tests with coverage. Threshold lives in $(COVERAGE_MIN) so it stays in
125
+ # sync with the CI workflow — bump both together.
102
126
  .PHONY: test-coverage
103
127
  test-coverage:
104
- @echo "$(GREEN)Running tests with coverage...$(NC)"
105
- $(PYTHON) -m pytest $(TEST_DIR) --cov=$(PACKAGE_NAME) --cov-report=html --cov-report=term
128
+ @echo "$(GREEN)Running tests with coverage (min $(COVERAGE_MIN)%)...$(NC)"
129
+ $(PYTHON) -m pytest $(TEST_DIR) --cov=$(PACKAGE_NAME) --cov-report=html --cov-report=term --cov-fail-under=$(COVERAGE_MIN)
106
130
  @echo "$(GREEN)Coverage report generated!$(NC)"
107
131
  @echo "$(YELLOW)HTML report available at htmlcov/index.html$(NC)"
108
132
 
@@ -127,41 +151,43 @@ type-check:
127
151
  $(PYTHON) -m mypy $(PACKAGE_NAME) --ignore-missing-imports
128
152
  @echo "$(GREEN)Type checking completed!$(NC)"
129
153
 
130
- # Clean build artifacts
131
- .PHONY: clean
132
- clean:
154
+ # Clean *build* artifacts only. Kept narrow so that `build` (and everything
155
+ # that depends on it: `validate`, `publish`, `release`) does not silently
156
+ # wipe coverage reports or pytest/mypy caches that the developer just ran.
157
+ .PHONY: clean-build
158
+ clean-build:
133
159
  @echo "$(GREEN)Cleaning build artifacts...$(NC)"
134
- rm -rf $(BUILD_DIR)
135
- rm -rf $(DIST_DIR)
136
- rm -rf $(EGG_INFO)
137
- rm -rf .pytest_cache
138
- rm -rf htmlcov
139
- rm -rf .coverage
140
- rm -rf .mypy_cache
160
+ rm -rf $(BUILD_DIR) $(DIST_DIR) $(EGG_INFO)
161
+
162
+ # Full clean: build artifacts + caches + coverage reports. Use this between
163
+ # branches or before publishing. Note that `build` no longer depends on
164
+ # `clean` — call `make clean build` if you want a fully scrubbed build.
165
+ .PHONY: clean
166
+ clean: clean-build
167
+ @echo "$(GREEN)Cleaning caches and coverage reports...$(NC)"
168
+ rm -rf .pytest_cache htmlcov .coverage .mypy_cache
141
169
  find . -type d -name "__pycache__" -exec rm -rf {} +
142
- find . -type f -name "*.pyc" -delete
143
- find . -type f -name "*.pyo" -delete
144
- find . -type f -name "*.pyd" -delete
145
- find . -type f -name ".coverage" -delete
170
+ find . -type f \( -name "*.pyc" -o -name "*.pyo" -o -name "*.pyd" \) -delete
146
171
  @echo "$(GREEN)Cleanup completed!$(NC)"
147
172
 
148
- # Build package
173
+ # Build package. Depends on `clean-build` (not `clean`) so coverage / cache
174
+ # files survive — see the comment on `clean-build` for motivation.
149
175
  .PHONY: build
150
- build: clean
176
+ build: clean-build
151
177
  @echo "$(GREEN)Building package...$(NC)"
152
178
  $(PYTHON) -m build
153
179
  @echo "$(GREEN)Package built successfully!$(NC)"
154
180
 
155
181
  # Build wheel package only
156
182
  .PHONY: build-wheel
157
- build-wheel: clean
183
+ build-wheel: clean-build
158
184
  @echo "$(GREEN)Building wheel package...$(NC)"
159
185
  $(PYTHON) -m build --wheel
160
186
  @echo "$(GREEN)Wheel package built successfully!$(NC)"
161
187
 
162
188
  # Build source distribution only
163
189
  .PHONY: build-sdist
164
- build-sdist: clean
190
+ build-sdist: clean-build
165
191
  @echo "$(GREEN)Building source distribution...$(NC)"
166
192
  $(PYTHON) -m build --sdist
167
193
  @echo "$(GREEN)Source distribution built successfully!$(NC)"
@@ -200,43 +226,65 @@ check-deps:
200
226
  @echo "$(GREEN)Checking for outdated dependencies...$(NC)"
201
227
  $(PIP) list --outdated
202
228
 
203
- # Update dependencies
229
+ # Update every dependency that `install-dev` installs — the package itself
230
+ # (editable, with test extras) AND the dev tools. Updating only the extras
231
+ # (the previous behaviour) silently drifted flake8/mypy/etc. behind.
204
232
  .PHONY: update-deps
205
233
  update-deps:
206
234
  @echo "$(GREEN)Updating dependencies...$(NC)"
207
235
  $(PIP) install --upgrade -e ".[tests]"
236
+ $(PIP) install --upgrade $(DEV_TOOLS)
208
237
  @echo "$(GREEN)Dependencies updated!$(NC)"
209
238
 
210
- # Security audit
239
+ # Security audit. Uses `pip-audit` to match the CI workflow (the older
240
+ # `safety` CLI was retired upstream and is no longer the recommended tool).
241
+ # Assumes `make install-dev` already installed `pip-audit`.
211
242
  .PHONY: security
212
243
  security:
213
- @echo "$(GREEN)Running security audit...$(NC)"
214
- $(PIP) install safety
215
- safety check
244
+ @echo "$(GREEN)Running security audit (pip-audit)...$(NC)"
245
+ $(PYTHON) -m pip_audit
216
246
  @echo "$(GREEN)Security audit completed!$(NC)"
217
247
 
218
- # Generate documentation
248
+ # Build the MkDocs site. The configuration (`mkdocs.yml`) and the `docs/`
249
+ # directory live in the repository root, so we invoke MkDocs from one level
250
+ # up. Requires `mkdocs-material` (install with `pip install mkdocs-material`
251
+ # — kept out of `install-dev` because the docs site is rebuilt by CI, not
252
+ # every developer needs the dependency locally).
219
253
  .PHONY: docs
220
254
  docs:
221
- @echo "$(GREEN)Generating documentation...$(NC)"
222
- @if [ -d "docs" ]; then \
223
- cd docs && make html; \
224
- echo "$(GREEN)Documentation generated in docs/_build/html/$(NC)"; \
225
- else \
226
- echo "$(YELLOW)No docs directory found. Skipping documentation generation.$(NC)"; \
227
- fi
228
-
229
- # Full development pipeline
255
+ @echo "$(GREEN)Building MkDocs site...$(NC)"
256
+ cd .. && mkdocs build
257
+ @echo "$(GREEN)Site generated in ../site/$(NC)"
258
+
259
+ # Serve the MkDocs site locally with auto-reload.
260
+ .PHONY: docs-serve
261
+ docs-serve:
262
+ @echo "$(GREEN)Serving MkDocs site at http://127.0.0.1:8000 ...$(NC)"
263
+ cd .. && mkdocs serve
264
+
265
+ # Full development pipeline. Uses `install-dev` (not `install`) so that
266
+ # `lint`, `type-check`, and `test` have flake8 / mypy / pytest available
267
+ # when this is run from a fresh checkout.
230
268
  .PHONY: all
231
- all: install lint type-check test build validate
269
+ all: install-dev lint type-check test build validate
232
270
  @echo "$(GREEN)Full pipeline completed successfully!$(NC)"
233
271
 
234
- # Development workflow targets
272
+ # Development workflow target.
273
+ #
274
+ # Installs every dev dependency *into the venv* using `$(VENV_DIR)/bin/pip`
275
+ # directly — do not rely on `$(PIP)` here, because Make resolves variables at
276
+ # parse time and the venv may not have existed yet when this Makefile was
277
+ # read.
235
278
  .PHONY: dev-setup
236
- dev-setup: venv install-dev install
279
+ dev-setup: venv
280
+ @echo "$(GREEN)Installing project (editable) + dev dependencies into $(VENV_DIR)/...$(NC)"
281
+ $(VENV_DIR)/bin/pip install --upgrade pip
282
+ $(VENV_DIR)/bin/pip install -e ".[tests]"
283
+ $(VENV_DIR)/bin/pip install $(DEV_TOOLS)
237
284
  @echo "$(GREEN)Development environment setup completed!$(NC)"
238
- @echo "$(YELLOW)Don't forget to activate the virtual environment:$(NC)"
239
- @echo "source $(VENV_DIR)/bin/activate"
285
+ @echo ""
286
+ @echo "$(YELLOW)You can now run targets directly — they auto-detect $(VENV_DIR)/.$(NC)"
287
+ @echo "$(YELLOW)To activate the venv in your shell anyway:$(NC) source $(VENV_DIR)/bin/activate"
240
288
 
241
289
  .PHONY: pre-commit
242
290
  pre-commit: lint type-check test
@@ -246,12 +294,16 @@ pre-commit: lint type-check test
246
294
  pre-publish: all security
247
295
  @echo "$(GREEN)Pre-publish checks completed!$(NC)"
248
296
 
249
- # CI/CD targets
297
+ # CI/CD target. `install-dev` already installs the package in editable mode
298
+ # via `pip install -e ".[tests]"`, so a separate `install` step would be
299
+ # redundant.
250
300
  .PHONY: ci
251
- ci: install-dev install lint type-check test build validate
301
+ ci: install-dev lint type-check test build validate
252
302
  @echo "$(GREEN)CI pipeline completed!$(NC)"
253
303
 
254
- # Show package info
304
+ # Show package info. The grep filter lists every tool in $(DEV_TOOLS) plus
305
+ # the package itself and `pytest` (installed via the `[tests]` extra). Keep
306
+ # the regex in sync if $(DEV_TOOLS) changes.
255
307
  .PHONY: info
256
308
  info:
257
309
  @echo "$(GREEN)Package Information:$(NC)"
@@ -261,7 +313,7 @@ info:
261
313
  @echo "Pip: $(shell $(PIP) --version)"
262
314
  @echo ""
263
315
  @echo "$(GREEN)Installed packages:$(NC)"
264
- @$(PIP) list | grep -E "($(PACKAGE_NAME)|pytest|flake8|black|mypy|twine|build)"
316
+ @$(PIP) list | grep -E "($(PACKAGE_NAME)|pytest|pytest-cov|flake8|black|mypy|twine|build|hatch|pip-audit)"
265
317
 
266
318
  # Quick release workflow
267
319
  .PHONY: release
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: FlightRadarAPI
3
- Version: 1.5.0
3
+ Version: 1.5.2
4
4
  Summary: SDK for FlightRadar24
5
5
  Project-URL: Homepage, https://github.com/JeanExtreme002/FlightRadarAPI
6
6
  Project-URL: Source Code, https://github.com/JeanExtreme002/FlightRadarAPI
7
7
  Project-URL: Documentation, https://jeanextreme002.github.io/FlightRadarAPI/
8
8
  Project-URL: Bug Reports, https://github.com/JeanExtreme002/FlightRadarAPI/issues
9
- Author-email: Jean Loui Bernard Silva de Jesus <jeanextreme002@gmail.com>
9
+ Author-email: Jean Loui Bernard Silva de Jesus <contact@jeanloui.dev>
10
10
  License-Expression: MIT
11
11
  License-File: LICENSE
12
12
  Keywords: aircraft,airlines,airports,api,aviation,flightradar24,flights,radar
@@ -47,7 +47,7 @@ $ pip install FlightRadarAPI
47
47
  ## Basic Usage:
48
48
  Import the class `FlightRadar24API` and create an instance of it.
49
49
  ```py
50
- from FlightRadar24 import FlightRadar24API
50
+ from FlightRadarAPI import FlightRadar24API
51
51
  fr_api = FlightRadar24API()
52
52
  ```
53
53
 
@@ -21,7 +21,7 @@ $ pip install FlightRadarAPI
21
21
  ## Basic Usage:
22
22
  Import the class `FlightRadar24API` and create an instance of it.
23
23
  ```py
24
- from FlightRadar24 import FlightRadar24API
24
+ from FlightRadarAPI import FlightRadar24API
25
25
  fr_api = FlightRadar24API()
26
26
  ```
27
27
 
@@ -3,7 +3,7 @@ name = "FlightRadarAPI"
3
3
  dynamic = ["version"]
4
4
  description = "SDK for FlightRadar24"
5
5
  authors = [
6
- { name = "Jean Loui Bernard Silva de Jesus", email = "jeanextreme002@gmail.com" },
6
+ { name = "Jean Loui Bernard Silva de Jesus", email = "contact@jeanloui.dev" },
7
7
  ]
8
8
  license = "MIT"
9
9
  readme = "README.md"
@@ -27,7 +27,12 @@ dependencies = [
27
27
  exclude = ["tests", ".flake8"]
28
28
 
29
29
  [tool.hatch.build.targets.wheel]
30
- packages = ["FlightRadar24"]
30
+ packages = ["FlightRadarAPI", "FlightRadar24"]
31
+
32
+ # Force-include the PEP 561 marker so downstream type checkers always see it,
33
+ # regardless of future changes to the global exclude list above.
34
+ [tool.hatch.build.targets.wheel.force-include]
35
+ "FlightRadarAPI/py.typed" = "FlightRadarAPI/py.typed"
31
36
 
32
37
  [project.optional-dependencies]
33
38
  tests = [
@@ -41,7 +46,7 @@ tests = [
41
46
  "Bug Reports" = "https://github.com/JeanExtreme002/FlightRadarAPI/issues"
42
47
 
43
48
  [tool.hatch.version]
44
- path = "FlightRadar24/__init__.py"
49
+ path = "FlightRadarAPI/__init__.py"
45
50
 
46
51
  [tool.pytest.ini_options]
47
52
  testpaths = ["tests"]
@@ -1 +0,0 @@
1
- python 3.11.0
File without changes