Flyan 0.1.0__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,282 @@
1
+ Metadata-Version: 2.4
2
+ Name: Flyan
3
+ Version: 0.1.0
4
+ Summary: Open source unofficial API wrappper to get flight data from RyanAir.
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: fake-useragent>=1.5.1
8
+ Requires-Dist: httpx>=0.27.2
9
+ Requires-Dist: pydantic>=2.9.2
10
+ Requires-Dist: tenacity>=9.0.0
11
+
12
+ # Flyan SDK
13
+
14
+ An open-source unofficial API wrapper to get flight data from Ryanair.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install flyan
20
+ ```
21
+
22
+ Or using uv:
23
+
24
+ ```bash
25
+ uv add flyan
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```python
31
+ from datetime import datetime
32
+ from flyan import RyanAir, FlightSearchParams
33
+
34
+ # Initialize the client
35
+ client = RyanAir(currency="EUR")
36
+
37
+ # Set up search parameters
38
+ search_params = FlightSearchParams(
39
+ from_airport="DUB", # Dublin
40
+ to_airport="BCN", # Barcelona
41
+ from_date=datetime(2025, 8, 15),
42
+ to_date=datetime(2025, 8, 20),
43
+ max_price=200
44
+ )
45
+
46
+ # Search for one-way flights
47
+ flights = client.get_oneways(search_params)
48
+
49
+ # Display results
50
+ for flight in flights:
51
+ print(f"Flight {flight.flight_number}: {flight.departure_airport.name} → {flight.arrival_airport.name}")
52
+ print(f"Departure: {flight.departure_date}")
53
+ print(f"Price: {flight.price} {flight.currency}")
54
+ print("---")
55
+ ```
56
+
57
+ ## API Reference
58
+
59
+ ### RyanAir Class
60
+
61
+ #### Constructor
62
+
63
+ ```python
64
+ RyanAir(currency: str = "EUR")
65
+ ```
66
+
67
+ Creates a new RyanAir client instance.
68
+
69
+ **Parameters:**
70
+
71
+ - `currency` (str, optional): Preferred currency for pricing. Defaults to "EUR". Must be a valid currency code from the supported currencies list.
72
+
73
+ **Example:**
74
+
75
+ ```python
76
+ # Default EUR currency
77
+ client = RyanAir()
78
+
79
+ # Specific currency
80
+ client = RyanAir(currency="USD")
81
+ ```
82
+
83
+ #### Methods
84
+
85
+ ##### `get_oneways(params: FlightSearchParams) -> list[Flight]`
86
+
87
+ Search for one-way flights.
88
+
89
+ **Parameters:**
90
+
91
+ - `params` (FlightSearchParams): Search parameters
92
+
93
+ **Returns:**
94
+
95
+ - `list[Flight]`: List of available flights
96
+
97
+ ### FlightSearchParams Class
98
+
99
+ Parameters for searching flights.
100
+
101
+ ```python
102
+ FlightSearchParams(
103
+ from_airport: str,
104
+ from_date: datetime,
105
+ to_date: datetime,
106
+ destination_country: Optional[str] = None,
107
+ max_price: Optional[int] = None,
108
+ to_airport: Optional[str] = None,
109
+ departure_time_from: Optional[str] = "00:00",
110
+ departure_time_to: Optional[str] = "23:59"
111
+ )
112
+ ```
113
+
114
+ **Parameters:**
115
+
116
+ - `from_airport` (str): IATA code of departure airport (e.g., "DUB")
117
+ - `from_date` (datetime): Earliest departure date
118
+ - `to_date` (datetime): Latest departure date
119
+ - `destination_country` (str, optional): Country code for destination
120
+ - `max_price` (int, optional): Maximum price filter
121
+ - `to_airport` (str, optional): IATA code of arrival airport
122
+ - `departure_time_from` (str, optional): Earliest departure time (HH:MM format)
123
+ - `departure_time_to` (str, optional): Latest departure time (HH:MM format)
124
+
125
+ **Example:**
126
+
127
+ ```python
128
+ from datetime import datetime
129
+
130
+ params = FlightSearchParams(
131
+ from_airport="DUB",
132
+ from_date=datetime(2025, 8, 15),
133
+ to_date=datetime(2025, 8, 20),
134
+ to_airport="BCN",
135
+ max_price=150,
136
+ departure_time_from="08:00",
137
+ departure_time_to="18:00"
138
+ )
139
+ ```
140
+
141
+ ### ReturnFlightSearchParams Class
142
+
143
+ Extended parameters for return flight searches.
144
+
145
+ ```python
146
+ ReturnFlightSearchParams(
147
+ # All FlightSearchParams fields plus:
148
+ return_date_from: datetime,
149
+ return_date_to: datetime,
150
+ inbound_departure_time_from: Optional[str] = "00:00",
151
+ inbound_departure_time_to: Optional[str] = "23:59"
152
+ )
153
+ ```
154
+
155
+ ## Data Models
156
+
157
+ ### Flight
158
+
159
+ Represents a single flight.
160
+
161
+ **Attributes:**
162
+
163
+ - `departure_airport` (Airport): Departure airport information
164
+ - `arrival_airport` (Airport): Arrival airport information
165
+ - `departure_date` (datetime): Departure date and time
166
+ - `arrival_date` (datetime): Arrival date and time
167
+ - `price` (float): Flight price
168
+ - `currency` (str): Price currency
169
+ - `flight_key` (str): Unique flight identifier
170
+ - `flight_number` (str): Flight number
171
+ - `previous_price` (Optional[str | float]): Previous price if available
172
+
173
+ ### Airport
174
+
175
+ Represents airport information.
176
+
177
+ **Attributes:**
178
+
179
+ - `country_name` (str): Country name
180
+ - `iata_code` (str): IATA airport code
181
+ - `name` (str): Airport name
182
+ - `seo_name` (str): SEO-friendly name
183
+ - `city_name` (str): City name
184
+ - `city_code` (str): City code
185
+ - `city_country_code` (str): Country code
186
+
187
+ ### ReturnFlight
188
+
189
+ Represents a return flight booking.
190
+
191
+ **Attributes:**
192
+
193
+ - `outbound` (Flight): Outbound flight
194
+ - `inbound` (Flight): Return flight
195
+ - `summary_price` (float): Total price for both flights
196
+ - `summary_currency` (str): Currency for total price
197
+ - `previous_price` (str | float): Previous total price if available
198
+
199
+ ## Examples
200
+
201
+ ### Search by Country
202
+
203
+ ```python
204
+ # Search flights to any airport in Spain
205
+ params = FlightSearchParams(
206
+ from_airport="DUB",
207
+ destination_country="ES",
208
+ from_date=datetime(2025, 9, 1),
209
+ to_date=datetime(2025, 9, 7)
210
+ )
211
+
212
+ flights = client.get_oneways(params)
213
+ ```
214
+
215
+ ### Filter by Time and Price
216
+
217
+ ```python
218
+ # Morning flights under €100
219
+ params = FlightSearchParams(
220
+ from_airport="STN", # London Stansted
221
+ to_airport="DUB", # Dublin
222
+ from_date=datetime(2025, 8, 1),
223
+ to_date=datetime(2025, 8, 5),
224
+ max_price=100,
225
+ departure_time_from="06:00",
226
+ departure_time_to="12:00"
227
+ )
228
+
229
+ flights = client.get_oneways(params)
230
+ ```
231
+
232
+ ### Error Handling
233
+
234
+ ```python
235
+ from flyan import RyanairException
236
+
237
+ try:
238
+ flights = client.get_oneways(params)
239
+ if not flights:
240
+ print("No flights found for the given criteria")
241
+ except RyanairException as e:
242
+ print(f"Ryanair API error: {e}")
243
+ except Exception as e:
244
+ print(f"Unexpected error: {e}")
245
+ ```
246
+
247
+ ## Supported Airports
248
+
249
+ The SDK supports all airports in Ryanair's network. Airport codes must be valid 3-letter IATA codes. You can find the complete list of supported airports in the `stations.json` file.
250
+
251
+ Popular airports include:
252
+
253
+ - **DUB** - Dublin
254
+ - **STN** - London Stansted
255
+ - **BCN** - Barcelona
256
+ - **MAD** - Madrid
257
+ - **FCO** - Rome Fiumicino
258
+ - **BRU** - Brussels
259
+ - **AMS** - Amsterdam
260
+
261
+ ## Supported Currencies
262
+
263
+ The SDK supports multiple currencies. Some popular ones include:
264
+
265
+ - **EUR** - Euro
266
+ - **USD** - US Dollar
267
+ - **GBP** - British Pound
268
+ - **CHF** - Swiss Franc
269
+
270
+ See `currencies.json` for the complete list.
271
+
272
+ ## Rate Limiting
273
+
274
+ The SDK includes automatic retry logic with exponential backoff to handle rate limiting and temporary API issues. It will retry failed requests up to 5 times before giving up.
275
+
276
+ ## Contributing
277
+
278
+ This is an open-source project. Contributions are welcome!
279
+
280
+ ## Disclaimer
281
+
282
+ This is an unofficial API wrapper and is not affiliated with Ryanair. Use at your own risk and ensure you comply with Ryanair's terms of service.
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ Flyan.egg-info/PKG-INFO
4
+ Flyan.egg-info/SOURCES.txt
5
+ Flyan.egg-info/dependency_links.txt
6
+ Flyan.egg-info/requires.txt
7
+ Flyan.egg-info/top_level.txt
8
+ flyan/__init__.py
9
+ flyan/misc.py
10
+ flyan/ryanair.py
@@ -0,0 +1,4 @@
1
+ fake-useragent>=1.5.1
2
+ httpx>=0.27.2
3
+ pydantic>=2.9.2
4
+ tenacity>=9.0.0
@@ -0,0 +1 @@
1
+ flyan
flyan-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,282 @@
1
+ Metadata-Version: 2.4
2
+ Name: Flyan
3
+ Version: 0.1.0
4
+ Summary: Open source unofficial API wrappper to get flight data from RyanAir.
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: fake-useragent>=1.5.1
8
+ Requires-Dist: httpx>=0.27.2
9
+ Requires-Dist: pydantic>=2.9.2
10
+ Requires-Dist: tenacity>=9.0.0
11
+
12
+ # Flyan SDK
13
+
14
+ An open-source unofficial API wrapper to get flight data from Ryanair.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install flyan
20
+ ```
21
+
22
+ Or using uv:
23
+
24
+ ```bash
25
+ uv add flyan
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```python
31
+ from datetime import datetime
32
+ from flyan import RyanAir, FlightSearchParams
33
+
34
+ # Initialize the client
35
+ client = RyanAir(currency="EUR")
36
+
37
+ # Set up search parameters
38
+ search_params = FlightSearchParams(
39
+ from_airport="DUB", # Dublin
40
+ to_airport="BCN", # Barcelona
41
+ from_date=datetime(2025, 8, 15),
42
+ to_date=datetime(2025, 8, 20),
43
+ max_price=200
44
+ )
45
+
46
+ # Search for one-way flights
47
+ flights = client.get_oneways(search_params)
48
+
49
+ # Display results
50
+ for flight in flights:
51
+ print(f"Flight {flight.flight_number}: {flight.departure_airport.name} → {flight.arrival_airport.name}")
52
+ print(f"Departure: {flight.departure_date}")
53
+ print(f"Price: {flight.price} {flight.currency}")
54
+ print("---")
55
+ ```
56
+
57
+ ## API Reference
58
+
59
+ ### RyanAir Class
60
+
61
+ #### Constructor
62
+
63
+ ```python
64
+ RyanAir(currency: str = "EUR")
65
+ ```
66
+
67
+ Creates a new RyanAir client instance.
68
+
69
+ **Parameters:**
70
+
71
+ - `currency` (str, optional): Preferred currency for pricing. Defaults to "EUR". Must be a valid currency code from the supported currencies list.
72
+
73
+ **Example:**
74
+
75
+ ```python
76
+ # Default EUR currency
77
+ client = RyanAir()
78
+
79
+ # Specific currency
80
+ client = RyanAir(currency="USD")
81
+ ```
82
+
83
+ #### Methods
84
+
85
+ ##### `get_oneways(params: FlightSearchParams) -> list[Flight]`
86
+
87
+ Search for one-way flights.
88
+
89
+ **Parameters:**
90
+
91
+ - `params` (FlightSearchParams): Search parameters
92
+
93
+ **Returns:**
94
+
95
+ - `list[Flight]`: List of available flights
96
+
97
+ ### FlightSearchParams Class
98
+
99
+ Parameters for searching flights.
100
+
101
+ ```python
102
+ FlightSearchParams(
103
+ from_airport: str,
104
+ from_date: datetime,
105
+ to_date: datetime,
106
+ destination_country: Optional[str] = None,
107
+ max_price: Optional[int] = None,
108
+ to_airport: Optional[str] = None,
109
+ departure_time_from: Optional[str] = "00:00",
110
+ departure_time_to: Optional[str] = "23:59"
111
+ )
112
+ ```
113
+
114
+ **Parameters:**
115
+
116
+ - `from_airport` (str): IATA code of departure airport (e.g., "DUB")
117
+ - `from_date` (datetime): Earliest departure date
118
+ - `to_date` (datetime): Latest departure date
119
+ - `destination_country` (str, optional): Country code for destination
120
+ - `max_price` (int, optional): Maximum price filter
121
+ - `to_airport` (str, optional): IATA code of arrival airport
122
+ - `departure_time_from` (str, optional): Earliest departure time (HH:MM format)
123
+ - `departure_time_to` (str, optional): Latest departure time (HH:MM format)
124
+
125
+ **Example:**
126
+
127
+ ```python
128
+ from datetime import datetime
129
+
130
+ params = FlightSearchParams(
131
+ from_airport="DUB",
132
+ from_date=datetime(2025, 8, 15),
133
+ to_date=datetime(2025, 8, 20),
134
+ to_airport="BCN",
135
+ max_price=150,
136
+ departure_time_from="08:00",
137
+ departure_time_to="18:00"
138
+ )
139
+ ```
140
+
141
+ ### ReturnFlightSearchParams Class
142
+
143
+ Extended parameters for return flight searches.
144
+
145
+ ```python
146
+ ReturnFlightSearchParams(
147
+ # All FlightSearchParams fields plus:
148
+ return_date_from: datetime,
149
+ return_date_to: datetime,
150
+ inbound_departure_time_from: Optional[str] = "00:00",
151
+ inbound_departure_time_to: Optional[str] = "23:59"
152
+ )
153
+ ```
154
+
155
+ ## Data Models
156
+
157
+ ### Flight
158
+
159
+ Represents a single flight.
160
+
161
+ **Attributes:**
162
+
163
+ - `departure_airport` (Airport): Departure airport information
164
+ - `arrival_airport` (Airport): Arrival airport information
165
+ - `departure_date` (datetime): Departure date and time
166
+ - `arrival_date` (datetime): Arrival date and time
167
+ - `price` (float): Flight price
168
+ - `currency` (str): Price currency
169
+ - `flight_key` (str): Unique flight identifier
170
+ - `flight_number` (str): Flight number
171
+ - `previous_price` (Optional[str | float]): Previous price if available
172
+
173
+ ### Airport
174
+
175
+ Represents airport information.
176
+
177
+ **Attributes:**
178
+
179
+ - `country_name` (str): Country name
180
+ - `iata_code` (str): IATA airport code
181
+ - `name` (str): Airport name
182
+ - `seo_name` (str): SEO-friendly name
183
+ - `city_name` (str): City name
184
+ - `city_code` (str): City code
185
+ - `city_country_code` (str): Country code
186
+
187
+ ### ReturnFlight
188
+
189
+ Represents a return flight booking.
190
+
191
+ **Attributes:**
192
+
193
+ - `outbound` (Flight): Outbound flight
194
+ - `inbound` (Flight): Return flight
195
+ - `summary_price` (float): Total price for both flights
196
+ - `summary_currency` (str): Currency for total price
197
+ - `previous_price` (str | float): Previous total price if available
198
+
199
+ ## Examples
200
+
201
+ ### Search by Country
202
+
203
+ ```python
204
+ # Search flights to any airport in Spain
205
+ params = FlightSearchParams(
206
+ from_airport="DUB",
207
+ destination_country="ES",
208
+ from_date=datetime(2025, 9, 1),
209
+ to_date=datetime(2025, 9, 7)
210
+ )
211
+
212
+ flights = client.get_oneways(params)
213
+ ```
214
+
215
+ ### Filter by Time and Price
216
+
217
+ ```python
218
+ # Morning flights under €100
219
+ params = FlightSearchParams(
220
+ from_airport="STN", # London Stansted
221
+ to_airport="DUB", # Dublin
222
+ from_date=datetime(2025, 8, 1),
223
+ to_date=datetime(2025, 8, 5),
224
+ max_price=100,
225
+ departure_time_from="06:00",
226
+ departure_time_to="12:00"
227
+ )
228
+
229
+ flights = client.get_oneways(params)
230
+ ```
231
+
232
+ ### Error Handling
233
+
234
+ ```python
235
+ from flyan import RyanairException
236
+
237
+ try:
238
+ flights = client.get_oneways(params)
239
+ if not flights:
240
+ print("No flights found for the given criteria")
241
+ except RyanairException as e:
242
+ print(f"Ryanair API error: {e}")
243
+ except Exception as e:
244
+ print(f"Unexpected error: {e}")
245
+ ```
246
+
247
+ ## Supported Airports
248
+
249
+ The SDK supports all airports in Ryanair's network. Airport codes must be valid 3-letter IATA codes. You can find the complete list of supported airports in the `stations.json` file.
250
+
251
+ Popular airports include:
252
+
253
+ - **DUB** - Dublin
254
+ - **STN** - London Stansted
255
+ - **BCN** - Barcelona
256
+ - **MAD** - Madrid
257
+ - **FCO** - Rome Fiumicino
258
+ - **BRU** - Brussels
259
+ - **AMS** - Amsterdam
260
+
261
+ ## Supported Currencies
262
+
263
+ The SDK supports multiple currencies. Some popular ones include:
264
+
265
+ - **EUR** - Euro
266
+ - **USD** - US Dollar
267
+ - **GBP** - British Pound
268
+ - **CHF** - Swiss Franc
269
+
270
+ See `currencies.json` for the complete list.
271
+
272
+ ## Rate Limiting
273
+
274
+ The SDK includes automatic retry logic with exponential backoff to handle rate limiting and temporary API issues. It will retry failed requests up to 5 times before giving up.
275
+
276
+ ## Contributing
277
+
278
+ This is an open-source project. Contributions are welcome!
279
+
280
+ ## Disclaimer
281
+
282
+ This is an unofficial API wrapper and is not affiliated with Ryanair. Use at your own risk and ensure you comply with Ryanair's terms of service.
flyan-0.1.0/README.md ADDED
@@ -0,0 +1,271 @@
1
+ # Flyan SDK
2
+
3
+ An open-source unofficial API wrapper to get flight data from Ryanair.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install flyan
9
+ ```
10
+
11
+ Or using uv:
12
+
13
+ ```bash
14
+ uv add flyan
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```python
20
+ from datetime import datetime
21
+ from flyan import RyanAir, FlightSearchParams
22
+
23
+ # Initialize the client
24
+ client = RyanAir(currency="EUR")
25
+
26
+ # Set up search parameters
27
+ search_params = FlightSearchParams(
28
+ from_airport="DUB", # Dublin
29
+ to_airport="BCN", # Barcelona
30
+ from_date=datetime(2025, 8, 15),
31
+ to_date=datetime(2025, 8, 20),
32
+ max_price=200
33
+ )
34
+
35
+ # Search for one-way flights
36
+ flights = client.get_oneways(search_params)
37
+
38
+ # Display results
39
+ for flight in flights:
40
+ print(f"Flight {flight.flight_number}: {flight.departure_airport.name} → {flight.arrival_airport.name}")
41
+ print(f"Departure: {flight.departure_date}")
42
+ print(f"Price: {flight.price} {flight.currency}")
43
+ print("---")
44
+ ```
45
+
46
+ ## API Reference
47
+
48
+ ### RyanAir Class
49
+
50
+ #### Constructor
51
+
52
+ ```python
53
+ RyanAir(currency: str = "EUR")
54
+ ```
55
+
56
+ Creates a new RyanAir client instance.
57
+
58
+ **Parameters:**
59
+
60
+ - `currency` (str, optional): Preferred currency for pricing. Defaults to "EUR". Must be a valid currency code from the supported currencies list.
61
+
62
+ **Example:**
63
+
64
+ ```python
65
+ # Default EUR currency
66
+ client = RyanAir()
67
+
68
+ # Specific currency
69
+ client = RyanAir(currency="USD")
70
+ ```
71
+
72
+ #### Methods
73
+
74
+ ##### `get_oneways(params: FlightSearchParams) -> list[Flight]`
75
+
76
+ Search for one-way flights.
77
+
78
+ **Parameters:**
79
+
80
+ - `params` (FlightSearchParams): Search parameters
81
+
82
+ **Returns:**
83
+
84
+ - `list[Flight]`: List of available flights
85
+
86
+ ### FlightSearchParams Class
87
+
88
+ Parameters for searching flights.
89
+
90
+ ```python
91
+ FlightSearchParams(
92
+ from_airport: str,
93
+ from_date: datetime,
94
+ to_date: datetime,
95
+ destination_country: Optional[str] = None,
96
+ max_price: Optional[int] = None,
97
+ to_airport: Optional[str] = None,
98
+ departure_time_from: Optional[str] = "00:00",
99
+ departure_time_to: Optional[str] = "23:59"
100
+ )
101
+ ```
102
+
103
+ **Parameters:**
104
+
105
+ - `from_airport` (str): IATA code of departure airport (e.g., "DUB")
106
+ - `from_date` (datetime): Earliest departure date
107
+ - `to_date` (datetime): Latest departure date
108
+ - `destination_country` (str, optional): Country code for destination
109
+ - `max_price` (int, optional): Maximum price filter
110
+ - `to_airport` (str, optional): IATA code of arrival airport
111
+ - `departure_time_from` (str, optional): Earliest departure time (HH:MM format)
112
+ - `departure_time_to` (str, optional): Latest departure time (HH:MM format)
113
+
114
+ **Example:**
115
+
116
+ ```python
117
+ from datetime import datetime
118
+
119
+ params = FlightSearchParams(
120
+ from_airport="DUB",
121
+ from_date=datetime(2025, 8, 15),
122
+ to_date=datetime(2025, 8, 20),
123
+ to_airport="BCN",
124
+ max_price=150,
125
+ departure_time_from="08:00",
126
+ departure_time_to="18:00"
127
+ )
128
+ ```
129
+
130
+ ### ReturnFlightSearchParams Class
131
+
132
+ Extended parameters for return flight searches.
133
+
134
+ ```python
135
+ ReturnFlightSearchParams(
136
+ # All FlightSearchParams fields plus:
137
+ return_date_from: datetime,
138
+ return_date_to: datetime,
139
+ inbound_departure_time_from: Optional[str] = "00:00",
140
+ inbound_departure_time_to: Optional[str] = "23:59"
141
+ )
142
+ ```
143
+
144
+ ## Data Models
145
+
146
+ ### Flight
147
+
148
+ Represents a single flight.
149
+
150
+ **Attributes:**
151
+
152
+ - `departure_airport` (Airport): Departure airport information
153
+ - `arrival_airport` (Airport): Arrival airport information
154
+ - `departure_date` (datetime): Departure date and time
155
+ - `arrival_date` (datetime): Arrival date and time
156
+ - `price` (float): Flight price
157
+ - `currency` (str): Price currency
158
+ - `flight_key` (str): Unique flight identifier
159
+ - `flight_number` (str): Flight number
160
+ - `previous_price` (Optional[str | float]): Previous price if available
161
+
162
+ ### Airport
163
+
164
+ Represents airport information.
165
+
166
+ **Attributes:**
167
+
168
+ - `country_name` (str): Country name
169
+ - `iata_code` (str): IATA airport code
170
+ - `name` (str): Airport name
171
+ - `seo_name` (str): SEO-friendly name
172
+ - `city_name` (str): City name
173
+ - `city_code` (str): City code
174
+ - `city_country_code` (str): Country code
175
+
176
+ ### ReturnFlight
177
+
178
+ Represents a return flight booking.
179
+
180
+ **Attributes:**
181
+
182
+ - `outbound` (Flight): Outbound flight
183
+ - `inbound` (Flight): Return flight
184
+ - `summary_price` (float): Total price for both flights
185
+ - `summary_currency` (str): Currency for total price
186
+ - `previous_price` (str | float): Previous total price if available
187
+
188
+ ## Examples
189
+
190
+ ### Search by Country
191
+
192
+ ```python
193
+ # Search flights to any airport in Spain
194
+ params = FlightSearchParams(
195
+ from_airport="DUB",
196
+ destination_country="ES",
197
+ from_date=datetime(2025, 9, 1),
198
+ to_date=datetime(2025, 9, 7)
199
+ )
200
+
201
+ flights = client.get_oneways(params)
202
+ ```
203
+
204
+ ### Filter by Time and Price
205
+
206
+ ```python
207
+ # Morning flights under €100
208
+ params = FlightSearchParams(
209
+ from_airport="STN", # London Stansted
210
+ to_airport="DUB", # Dublin
211
+ from_date=datetime(2025, 8, 1),
212
+ to_date=datetime(2025, 8, 5),
213
+ max_price=100,
214
+ departure_time_from="06:00",
215
+ departure_time_to="12:00"
216
+ )
217
+
218
+ flights = client.get_oneways(params)
219
+ ```
220
+
221
+ ### Error Handling
222
+
223
+ ```python
224
+ from flyan import RyanairException
225
+
226
+ try:
227
+ flights = client.get_oneways(params)
228
+ if not flights:
229
+ print("No flights found for the given criteria")
230
+ except RyanairException as e:
231
+ print(f"Ryanair API error: {e}")
232
+ except Exception as e:
233
+ print(f"Unexpected error: {e}")
234
+ ```
235
+
236
+ ## Supported Airports
237
+
238
+ The SDK supports all airports in Ryanair's network. Airport codes must be valid 3-letter IATA codes. You can find the complete list of supported airports in the `stations.json` file.
239
+
240
+ Popular airports include:
241
+
242
+ - **DUB** - Dublin
243
+ - **STN** - London Stansted
244
+ - **BCN** - Barcelona
245
+ - **MAD** - Madrid
246
+ - **FCO** - Rome Fiumicino
247
+ - **BRU** - Brussels
248
+ - **AMS** - Amsterdam
249
+
250
+ ## Supported Currencies
251
+
252
+ The SDK supports multiple currencies. Some popular ones include:
253
+
254
+ - **EUR** - Euro
255
+ - **USD** - US Dollar
256
+ - **GBP** - British Pound
257
+ - **CHF** - Swiss Franc
258
+
259
+ See `currencies.json` for the complete list.
260
+
261
+ ## Rate Limiting
262
+
263
+ The SDK includes automatic retry logic with exponential backoff to handle rate limiting and temporary API issues. It will retry failed requests up to 5 times before giving up.
264
+
265
+ ## Contributing
266
+
267
+ This is an open-source project. Contributions are welcome!
268
+
269
+ ## Disclaimer
270
+
271
+ This is an unofficial API wrapper and is not affiliated with Ryanair. Use at your own risk and ensure you comply with Ryanair's terms of service.
File without changes
@@ -0,0 +1,132 @@
1
+ import json
2
+ from datetime import datetime
3
+ from typing import Optional, Dict
4
+
5
+ from pydantic import BaseModel, field_validator
6
+
7
+ currencies: Dict[str, str] = json.load(open("./currencies.json", encoding="utf-8"))
8
+ stations: Dict[str, str] = json.load(open("./stations.json", encoding="utf-8"))
9
+
10
+
11
+ class Airport(BaseModel):
12
+ country_name: str
13
+ iata_code: str
14
+ name: str
15
+ seo_name: str
16
+ city_name: str
17
+ city_code: str
18
+ city_country_code: str
19
+
20
+
21
+ class Flight(BaseModel):
22
+ departure_airport: Airport
23
+ arrival_airport: Airport
24
+ departure_date: datetime
25
+ arrival_date: datetime
26
+ price: float
27
+ currency: str
28
+ flight_key: str
29
+ flight_number: str
30
+ previous_price: Optional[str | float]
31
+
32
+
33
+ class ReturnFlight(BaseModel):
34
+ outbound: Flight
35
+ inbound: Flight
36
+ summary_price: float
37
+ summary_currency: str
38
+ previous_price: str | float
39
+
40
+
41
+ class FlightSearchParams(BaseModel):
42
+ """Parameters for flight searches"""
43
+
44
+ from_airport: str
45
+ from_date: datetime
46
+ to_date: datetime
47
+ destination_country: Optional[str] = None
48
+ max_price: Optional[int] = None
49
+ to_airport: Optional[str] = None
50
+ departure_time_from: Optional[str] = "00:00"
51
+ departure_time_to: Optional[str] = "23:59"
52
+
53
+ @field_validator("from_airport")
54
+ def validate_airport(cls, v: str):
55
+
56
+ if v not in stations.keys():
57
+ raise ValueError("Airport code must be a 3-letter IATA code")
58
+
59
+ return v.upper()
60
+
61
+ @field_validator("from_date", "to_date")
62
+ def validate_dates(cls, v: datetime):
63
+ if v < datetime.now():
64
+ raise ValueError("Date from or to cannot be in the past")
65
+
66
+ return v
67
+
68
+ @field_validator("max_price")
69
+ def validate_price(cls, v: int | None):
70
+ if v is None:
71
+ return v
72
+
73
+ if v <= 0:
74
+ raise ValueError("Price can't be negative")
75
+
76
+ return v
77
+
78
+ def to_api_params(self) -> Dict[str, str | int]:
79
+ """Convert the parameters to the format expected by the Ryanair API"""
80
+ params: Dict[str, str | int] = {
81
+ "departureAirportIataCode": self.from_airport,
82
+ "outboundDepartureDateFrom": self.from_date.date().isoformat(),
83
+ "outboundDepartureDateTo": self.to_date.date().isoformat(),
84
+ "outboundDepartureTimeFrom": self.departure_time_from or "00:00",
85
+ "outboundDepartureTimeTo": self.departure_time_to or "23:59",
86
+ }
87
+
88
+ if self.destination_country:
89
+ params["arrivalCountryCode"] = self.destination_country
90
+
91
+ if self.max_price:
92
+ params["priceValueTo"] = self.max_price
93
+
94
+ if self.to_airport:
95
+ params["arrivalAirportIataCode"] = self.to_airport
96
+
97
+ return params
98
+
99
+
100
+ class ReturnFlightSearchParams(FlightSearchParams):
101
+ """Parameters for return flight searches"""
102
+
103
+ return_date_from: datetime
104
+ return_date_to: datetime
105
+ inbound_departure_time_from: Optional[str] = "00:00"
106
+ inbound_departure_time_to: Optional[str] = "23:59"
107
+
108
+ @field_validator("return_date_from", "return_date_to")
109
+ @classmethod
110
+ def validate_return_dates(cls, v: datetime) -> datetime:
111
+ # Note: In Pydantic v2, cross-field validation should be done with model_validator
112
+ # This is a simplified version - ideally use model_validator for cross-field validation
113
+ return v
114
+
115
+ def to_api_params(self) -> Dict[str, str | int]:
116
+ """Convert the parameters to the format expected by the Ryanair API"""
117
+ params = super().to_api_params()
118
+
119
+ additional_params = {
120
+ "inboundDepartureDateFrom": self.return_date_from.date().isoformat(),
121
+ "inboundDepartureDateTo": self.return_date_to.date().isoformat(),
122
+ }
123
+
124
+ if self.inbound_departure_time_from:
125
+ additional_params["inboundDepartureTimeFrom"] = (
126
+ self.inbound_departure_time_from
127
+ )
128
+ if self.inbound_departure_time_to:
129
+ additional_params["inboundDepartureTimeTo"] = self.inbound_departure_time_to
130
+
131
+ params.update(additional_params)
132
+ return params
@@ -0,0 +1,158 @@
1
+ import logging
2
+ from datetime import datetime
3
+ from typing import Dict, Any
4
+
5
+ import httpx
6
+ from fake_useragent.fake import UserAgent
7
+ from tenacity import (
8
+ retry,
9
+ retry_if_exception_type,
10
+ stop_after_attempt,
11
+ wait_exponential,
12
+ )
13
+
14
+ from flyan.misc import (
15
+ Airport,
16
+ Flight,
17
+ FlightSearchParams,
18
+ ReturnFlight,
19
+ currencies,
20
+ )
21
+
22
+ ua = UserAgent()
23
+ logger = logging.getLogger("Flyan")
24
+ if not logger.handlers:
25
+ logger.setLevel(logging.INFO)
26
+
27
+ console_handler = logging.StreamHandler()
28
+ formatter = logging.Formatter(
29
+ "%(asctime)s.%(msecs)03d %(levelname)s:%(message)s", datefmt="%Y-%m-%d %I:%M:%S"
30
+ )
31
+
32
+ console_handler.setFormatter(formatter)
33
+ logger.addHandler(console_handler)
34
+
35
+
36
+ class RyanairException(Exception):
37
+ def __init__(self, message: str):
38
+ super().__init__(f"Ryanair API: {message}")
39
+
40
+
41
+ class RyanAir:
42
+ """
43
+ Create a RyanAir instance
44
+
45
+ :param str currency: Preferred currency
46
+ """
47
+
48
+ BASE_SERVICES_API_URL = "https://services-api.ryanair.com/farfnd/v4"
49
+ AGGREGATE_URL = "https://www.ryanair.com/api/views/locate/3/aggregate/all/en"
50
+
51
+ def __init__(self, currency: str = "EUR"):
52
+ self.client = httpx.Client(
53
+ headers={
54
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
55
+ "Accept-Encoding": "gzip, deflate, br, zstd",
56
+ "Accept-Language": "en-GB,en;q=0.9",
57
+ "Cache-Control": "no-cache",
58
+ "Pragma": "no-cache",
59
+ "Priority": "u=0, i",
60
+ "Upgrade-Insecure-Requests": "1",
61
+ "User-Agent": ua.random,
62
+ },
63
+ follow_redirects=True,
64
+ )
65
+
66
+ self.__get("https://www.ryanair.com")
67
+
68
+ if currency in currencies.keys():
69
+ self.currency = currency
70
+
71
+ else:
72
+ self.currency = "EUR"
73
+
74
+ def __del__(self):
75
+ self.client.close()
76
+
77
+ @retry(
78
+ stop=stop_after_attempt(5), # Retry up to 5 times
79
+ wait=wait_exponential(),
80
+ retry=retry_if_exception_type(Exception),
81
+ reraise=True, # Raise the exception after retries are exhausted
82
+ )
83
+ def __get(self, url: str, params: dict[str, str] = {}) -> httpx.Response:
84
+ """
85
+ Send a GET request to url
86
+
87
+ :param str url: The url to GET
88
+ :param dict params: URL Parameters for the query
89
+ :return httpx.Response: Response object
90
+ :raises httpx.HTTPStatusError: If one occurred
91
+ """
92
+ response = self.client.get(url, params=params)
93
+ response.raise_for_status()
94
+ return response
95
+
96
+ def __parse_airport(self, airport: Dict[str, Any]) -> Airport:
97
+ return Airport(
98
+ country_name=airport["countryName"],
99
+ iata_code=airport["iataCode"],
100
+ name=airport["name"],
101
+ seo_name=airport["seoName"],
102
+ city_name=airport["city"]["name"],
103
+ city_code=airport["city"]["code"],
104
+ city_country_code=airport["city"]["countryCode"],
105
+ )
106
+
107
+ def __parse_fare(self, fare: Dict[str, Any], k: str = "outbound") -> Flight:
108
+ dep_date = datetime.fromisoformat(fare[k]["departureDate"])
109
+ arr_date = datetime.fromisoformat(fare[k]["arrivalDate"])
110
+
111
+ return Flight(
112
+ departure_airport=self.__parse_airport(fare[k]["departureAirport"]),
113
+ arrival_airport=self.__parse_airport(fare[k]["arrivalAirport"]),
114
+ departure_date=dep_date,
115
+ arrival_date=arr_date,
116
+ price=fare[k]["price"]["value"],
117
+ currency=fare[k]["price"]["currencyCode"],
118
+ flight_key=fare[k]["flightKey"],
119
+ flight_number=fare[k]["flightNumber"],
120
+ previous_price=fare[k].get("previousPrice", None),
121
+ )
122
+
123
+ def __parse_return_fare(self, fare: Dict[str, Any]) -> ReturnFlight:
124
+ outbound = self.__parse_fare(fare, "outbound")
125
+ inbound = self.__parse_fare(fare, "inbound")
126
+
127
+ return ReturnFlight(
128
+ outbound=outbound,
129
+ inbound=inbound,
130
+ summary_price=fare["summary"]["price"]["value"],
131
+ summary_currency=fare["summary"]["price"]["currencyCode"],
132
+ previous_price=fare.get("previousPrice") or 0,
133
+ )
134
+
135
+ def get_oneways(self, params: FlightSearchParams) -> list[Flight]:
136
+ """
137
+ Get oneways
138
+ """
139
+ print("Getting oneways")
140
+ url = f"{self.BASE_SERVICES_API_URL}/oneWayFares"
141
+
142
+ try:
143
+ r = self.__get(url, params.to_api_params())
144
+ if not r.is_success:
145
+ return []
146
+
147
+ fares = r.json()["fares"]
148
+ flights = [self.__parse_fare(f) for f in fares]
149
+
150
+ return flights
151
+
152
+ except httpx.HTTPError:
153
+ logger.error(f"A HTTP Error occured trying to get {url}", exc_info=True)
154
+ return []
155
+
156
+ except KeyError as KE:
157
+ print(KE)
158
+ return []
@@ -0,0 +1,12 @@
1
+ [project]
2
+ name = "Flyan"
3
+ version = "0.1.0"
4
+ description = "Open source unofficial API wrappper to get flight data from RyanAir."
5
+ readme = "README.md"
6
+ requires-python = ">=3.8"
7
+ dependencies = [
8
+ "fake-useragent>=1.5.1",
9
+ "httpx>=0.27.2",
10
+ "pydantic>=2.9.2",
11
+ "tenacity>=9.0.0",
12
+ ]
flyan-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+