roto-api-native 0.2.1__tar.gz → 0.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.
Files changed (24) hide show
  1. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/.gitignore +55 -55
  2. roto_api_native-0.2.2/API.md +446 -0
  3. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/Cargo.lock +1 -1
  4. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/Cargo.toml +1 -1
  5. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/LICENSE +30 -30
  6. roto_api_native-0.2.2/PKG-INFO +220 -0
  7. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/PUBLISHING.md +1 -1
  8. roto_api_native-0.2.2/README.md +193 -0
  9. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/pyproject.toml +1 -1
  10. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/python/roto_api/__init__.py +26 -6
  11. roto_api_native-0.2.1/scripts/bootstrap_data.py → roto_api_native-0.2.2/python/roto_api/data.py +60 -17
  12. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/rustfmt.toml +1 -1
  13. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/scripts/query_ips_native.py +5 -10
  14. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/tests/conftest.py +0 -3
  15. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/tests/test_api.py +27 -2
  16. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/tests/test_data.py +4 -4
  17. roto_api_native-0.2.1/API.md +0 -141
  18. roto_api_native-0.2.1/PKG-INFO +0 -264
  19. roto_api_native-0.2.1/README.md +0 -237
  20. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/.github/workflows/pkg.yml +0 -0
  21. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/.github/workflows/publish.yml +0 -0
  22. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/build.rs +0 -0
  23. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/src/lib.rs +0 -0
  24. {roto_api_native-0.2.1 → roto_api_native-0.2.2}/src/python.rs +0 -0
@@ -1,58 +1,58 @@
1
- ## File system
2
- .DS_Store
3
- desktop.ini
4
-
5
- ## Editor
6
- *.swp
7
- *.swo
8
- Session.vim
9
- .cproject
10
- .idea
11
- *.iml
12
- .vscode
13
- .project
14
- .favorites.json
15
- .settings/
16
-
17
- ## Tool
18
- .valgrindrc
19
- .cargo
20
-
21
- ## Configuration
22
- /config.toml
23
- /Makefile
24
- config.mk
25
- config.stamp
26
- no_llvm_build
27
-
28
- ## Build
29
- /dl/
30
- /doc/
31
- /inst/
32
- /llvm/
33
- /mingw-build/
34
- /build/
35
- /dist/
36
- /unicode-downloads
37
- /target
38
- /src/tools/x/target
39
- # Generated by compiletest for incremental
40
- /tmp/
41
- # Created by default with `src/ci/docker/run.sh`
42
- /obj/
43
-
44
- ## Temporary files
45
- *~
46
- \#*
47
- \#*\#
48
- .#*
49
-
50
- ## Tags
51
- tags
52
- tags.*
53
- TAGS
54
- TAGS.*
55
-
1
+ ## File system
2
+ .DS_Store
3
+ desktop.ini
4
+
5
+ ## Editor
6
+ *.swp
7
+ *.swo
8
+ Session.vim
9
+ .cproject
10
+ .idea
11
+ *.iml
12
+ .vscode
13
+ .project
14
+ .favorites.json
15
+ .settings/
16
+
17
+ ## Tool
18
+ .valgrindrc
19
+ .cargo
20
+
21
+ ## Configuration
22
+ /config.toml
23
+ /Makefile
24
+ config.mk
25
+ config.stamp
26
+ no_llvm_build
27
+
28
+ ## Build
29
+ /dl/
30
+ /doc/
31
+ /inst/
32
+ /llvm/
33
+ /mingw-build/
34
+ /build/
35
+ /dist/
36
+ /unicode-downloads
37
+ /target
38
+ /src/tools/x/target
39
+ # Generated by compiletest for incremental
40
+ /tmp/
41
+ # Created by default with `src/ci/docker/run.sh`
42
+ /obj/
43
+
44
+ ## Temporary files
45
+ *~
46
+ \#*
47
+ \#*\#
48
+ .#*
49
+
50
+ ## Tags
51
+ tags
52
+ tags.*
53
+ TAGS
54
+ TAGS.*
55
+
56
56
  ## Python
57
57
  __pycache__/
58
58
  *.py[cod]
@@ -0,0 +1,446 @@
1
+ # API Reference
2
+
3
+ Install name:
4
+ - `roto-api-native`
5
+
6
+ Import name:
7
+ - `roto_api`
8
+
9
+ ## Package Functions
10
+
11
+ ### `ensure_data`
12
+
13
+ Download and build the local routing snapshot if needed.
14
+
15
+ `ensure_data(data_dir, refresh=False, del_ext_sources=None, riswhois_sources=None)`
16
+
17
+ Parameters
18
+
19
+ `data_dir`
20
+
21
+ - Directory where the snapshot files and cached downloads are stored
22
+
23
+ Type: `str | os.PathLike`
24
+
25
+ `refresh`
26
+
27
+ - Re-download upstream sources and rebuild the snapshot even if the expected files already exist
28
+
29
+ Type: `bool`
30
+ Default: `False`
31
+
32
+ `del_ext_sources`
33
+
34
+ - Optional delegated-extended source URL overrides
35
+ - Keys typically include:
36
+ - `afrinic`
37
+ - `apnic`
38
+ - `arin`
39
+ - `lacnic`
40
+ - `ripencc`
41
+
42
+ Type: `Mapping[str, str] | None`
43
+ Default: `None`
44
+
45
+ `riswhois_sources`
46
+
47
+ - Optional RIS Whois source URL overrides
48
+ - Keys typically include:
49
+ - `riswhois4`
50
+ - `riswhois6`
51
+
52
+ Type: `Mapping[str, str] | None`
53
+ Default: `None`
54
+
55
+ Return value
56
+
57
+ - A `pathlib.Path` pointing to the prepared data directory
58
+
59
+ Exceptions
60
+
61
+ - `OSError`
62
+ - If files cannot be created, replaced, or written
63
+ - `urllib.error.URLError`
64
+ - If an upstream download fails
65
+ - Other parse/build exceptions can surface if upstream content is malformed
66
+
67
+ Example
68
+
69
+ ```python
70
+ from roto_api import ensure_data
71
+
72
+ data_dir = ensure_data("./data")
73
+ ```
74
+
75
+ Refresh example:
76
+
77
+ ```python
78
+ from roto_api import ensure_data
79
+
80
+ data_dir = ensure_data("./data", refresh=True)
81
+ ```
82
+
83
+ ### `load_lookup`
84
+
85
+ Load the native lookup engine from a prepared local data directory.
86
+
87
+ `load_lookup(data_dir)`
88
+
89
+ Parameters
90
+
91
+ `data_dir`
92
+
93
+ - The path to a directory containing a prepared routing snapshot.
94
+ - Required files:
95
+ - `delegated_all.csv`
96
+ - at least one of `pfx_asn_dfz_v4.csv` or `pfx_asn_dfz_v6.csv`
97
+ - Optional files:
98
+ - `del_ext.timestamps.json`
99
+ - `riswhois.timestamps.json`
100
+
101
+ Type: `str | os.PathLike`
102
+
103
+ Filename behavior:
104
+
105
+ - `load_lookup(data_dir)` expects those exact filenames inside `data_dir`
106
+ - It does not search for alternate names
107
+ - If you need custom filenames, use `RotoLookup(prefixes_file, ris_files, timestamps_dir=None)` instead
108
+
109
+ Return value
110
+
111
+ - A `RotoLookup` object
112
+
113
+ Exceptions
114
+
115
+ - `RuntimeError`
116
+ - If the delegated file cannot be opened or parsed
117
+ - If the RIS Whois file cannot be opened or parsed
118
+ - If timestamp metadata exists but is malformed
119
+ - `ValueError`
120
+ - If no RIS Whois CSV files are present in the data directory
121
+
122
+ Example
123
+
124
+ ```python
125
+ from roto_api import load_lookup
126
+
127
+ lookup = load_lookup("./data")
128
+ ```
129
+
130
+ ### `open_lookup`
131
+
132
+ Ensure the snapshot exists, then load the native lookup engine.
133
+
134
+ `open_lookup(data_dir, refresh=False, del_ext_sources=None, riswhois_sources=None)`
135
+
136
+ Parameters
137
+
138
+ `data_dir`
139
+
140
+ - Same target data directory used by `ensure_data(...)`
141
+
142
+ Type: `str | os.PathLike`
143
+
144
+ `refresh`
145
+
146
+ - Re-download upstream sources before loading
147
+
148
+ Type: `bool`
149
+ Default: `False`
150
+
151
+ `del_ext_sources`
152
+
153
+ - Optional delegated-extended source URL overrides
154
+
155
+ Type: `Mapping[str, str] | None`
156
+ Default: `None`
157
+
158
+ `riswhois_sources`
159
+
160
+ - Optional RIS Whois source URL overrides
161
+
162
+ Type: `Mapping[str, str] | None`
163
+ Default: `None`
164
+
165
+ Return value
166
+
167
+ - A `RotoLookup` object
168
+
169
+ Example
170
+
171
+ ```python
172
+ from roto_api import open_lookup
173
+
174
+ lookup = open_lookup("./data")
175
+ ```
176
+
177
+ Refresh example:
178
+
179
+ ```python
180
+ lookup = open_lookup("./data", refresh=True)
181
+ ```
182
+
183
+ ## Class `RotoLookup`
184
+
185
+ ### `RotoLookup`
186
+
187
+ Build a lookup object from explicit file paths.
188
+
189
+ `RotoLookup(prefixes_file, ris_files, timestamps_dir=None)`
190
+
191
+ Parameters
192
+
193
+ `prefixes_file`
194
+
195
+ - Path to the delegated allocations file
196
+ - Normally this is `delegated_all.csv`
197
+
198
+ Type: `str`
199
+
200
+ `ris_files`
201
+
202
+ - One or more RIS Whois CSV files
203
+ - Typically one or both of:
204
+ - `pfx_asn_dfz_v4.csv`
205
+ - `pfx_asn_dfz_v6.csv`
206
+
207
+ Type: `list[str]`
208
+
209
+ `timestamps_dir`
210
+
211
+ - Directory containing optional timestamp metadata files
212
+ - Defaults to the parent directory of `prefixes_file`
213
+
214
+ Type: `str | None`
215
+ Default: `None`
216
+
217
+ Return value
218
+
219
+ - A `RotoLookup` object
220
+
221
+ Exceptions
222
+
223
+ - `RuntimeError`
224
+ - If a required file cannot be opened or parsed
225
+ - `ValueError`
226
+ - If `ris_files` is empty
227
+
228
+ Example
229
+
230
+ ```python
231
+ from roto_api import RotoLookup
232
+
233
+ lookup = RotoLookup(
234
+ prefixes_file="./data/delegated_all.csv",
235
+ ris_files=[
236
+ "./data/pfx_asn_dfz_v4.csv",
237
+ "./data/pfx_asn_dfz_v6.csv",
238
+ ],
239
+ timestamps_dir="./data",
240
+ )
241
+ ```
242
+
243
+ ### `RotoLookup.from_data_dir`
244
+
245
+ Build a lookup object from a prepared data directory.
246
+
247
+ `RotoLookup.from_data_dir(data_dir)`
248
+
249
+ Parameters
250
+
251
+ `data_dir`
252
+
253
+ - Directory containing:
254
+ - `delegated_all.csv`
255
+ - at least one of `pfx_asn_dfz_v4.csv` or `pfx_asn_dfz_v6.csv`
256
+ - May also contain:
257
+ - `del_ext.timestamps.json`
258
+ - `riswhois.timestamps.json`
259
+
260
+ Type: `str`
261
+
262
+ Filename behavior:
263
+
264
+ - `RotoLookup.from_data_dir(data_dir)` expects those exact filenames
265
+ - It automatically looks for:
266
+ - `delegated_all.csv`
267
+ - `pfx_asn_dfz_v4.csv`
268
+ - `pfx_asn_dfz_v6.csv`
269
+ - optional timestamp files in the same directory
270
+ - If your files have different names, use the explicit `RotoLookup(...)` constructor
271
+
272
+ Return value
273
+
274
+ - A `RotoLookup` object
275
+
276
+ Exceptions
277
+
278
+ - `RuntimeError`
279
+ - If the data files cannot be opened or parsed
280
+ - `ValueError`
281
+ - If no RIS Whois CSV files are found
282
+
283
+ Example
284
+
285
+ ```python
286
+ from roto_api import RotoLookup
287
+
288
+ lookup = RotoLookup.from_data_dir("./data")
289
+ ```
290
+
291
+ ### `RotoLookup.lookup_ip`
292
+
293
+ Run a single-IP longest-prefix lookup.
294
+
295
+ `lookup_ip(ip)`
296
+
297
+ Parameters
298
+
299
+ `ip`
300
+
301
+ - IPv4 or IPv6 address to look up
302
+
303
+ Type: `str`
304
+
305
+ Return value
306
+
307
+ A dictionary with these keys:
308
+
309
+ - `ip`
310
+ - The original input IP
311
+ - Type: `str`
312
+ - `prefix`
313
+ - The matched longest prefix
314
+ - Type: `str | None`
315
+ - `origin_asns`
316
+ - Origin ASNs attached to the matched RIS entry
317
+ - Type: `list[str]`
318
+ - `match_type`
319
+ - Match result type
320
+ - Type: `str`
321
+
322
+ Exceptions
323
+
324
+ - `ValueError`
325
+ - If `ip` is not a valid IPv4 or IPv6 address
326
+
327
+ Example
328
+
329
+ ```python
330
+ result = lookup.lookup_ip("8.8.8.8")
331
+ print(result["prefix"])
332
+ print(result["origin_asns"])
333
+ ```
334
+
335
+ ### `RotoLookup.lookup_ips`
336
+
337
+ Run longest-prefix lookup for multiple IPs in one Rust call.
338
+
339
+ `lookup_ips(ips)`
340
+
341
+ Parameters
342
+
343
+ `ips`
344
+
345
+ - IPv4 and/or IPv6 addresses to look up
346
+
347
+ Type: `list[str]`
348
+
349
+ Return value
350
+
351
+ - A list of dictionaries
352
+ - Each dictionary has the same schema as `lookup_ip`
353
+ - Result order matches input order
354
+
355
+ Exceptions
356
+
357
+ - `ValueError`
358
+ - If any input IP is invalid
359
+
360
+ Example
361
+
362
+ ```python
363
+ results = lookup.lookup_ips(["8.8.8.8", "1.1.1.1"])
364
+ for row in results:
365
+ print(row["ip"], row["prefix"], row["origin_asns"])
366
+ ```
367
+
368
+ ### `RotoLookup.source_status`
369
+
370
+ Return source metadata for the loaded snapshot.
371
+
372
+ `source_status()`
373
+
374
+ Return value
375
+
376
+ - A list of dictionaries with:
377
+ - `type`
378
+ - `rir-alloc` or `bgp`
379
+ - Type: `str`
380
+ - `id`
381
+ - Source identifier
382
+ - Type: `str`
383
+ - `serial`
384
+ - Source serial / file timestamp
385
+ - Type: `int`
386
+ - `last_updated`
387
+ - Last update timestamp in RFC3339 format
388
+ - Type: `str`
389
+
390
+ If the snapshot does not include timestamp metadata files, this returns an empty list.
391
+
392
+ Example
393
+
394
+ ```python
395
+ for source in lookup.source_status():
396
+ print(source["id"], source["serial"], source["last_updated"])
397
+ ```
398
+
399
+ ## Data Preparation
400
+
401
+ This package can explicitly prepare the snapshot through `ensure_data(...)`.
402
+
403
+ It does not download anything:
404
+
405
+ - at install time
406
+ - on plain `import roto_api`
407
+ - unless your code calls `ensure_data(...)` or `open_lookup(...)`
408
+
409
+ Typical patterns:
410
+
411
+ - explicit two-step flow:
412
+ - `ensure_data(...)`
413
+ - `load_lookup(...)`
414
+ - one-step convenience flow:
415
+ - `open_lookup(...)`
416
+
417
+ ## Manual Snapshot File Format
418
+
419
+ If you generate the snapshot yourself and then call `load_lookup(...)` or `RotoLookup.from_data_dir(...)`, the loader expects:
420
+
421
+ `delegated_all.csv`
422
+
423
+ - Pipe-delimited delegated-extended records
424
+ - No header row required
425
+ - The first row is treated as data
426
+
427
+ `pfx_asn_dfz_v4.csv`
428
+
429
+ - Comma-separated records
430
+ - Row format: `prefix,length,asn`
431
+ - No header row required
432
+ - The first row is treated as data
433
+
434
+ `pfx_asn_dfz_v6.csv`
435
+
436
+ - Comma-separated records
437
+ - Row format: `prefix,length,asn`
438
+ - No header row required
439
+ - The first row is treated as data
440
+
441
+ `del_ext.timestamps.json`
442
+ `riswhois.timestamps.json`
443
+
444
+ - Optional metadata files
445
+ - Despite the `.json` extension, these are CSV-formatted text files for compatibility
446
+ - If present, they should contain a header row and CSV records
@@ -388,7 +388,7 @@ dependencies = [
388
388
 
389
389
  [[package]]
390
390
  name = "roto-api-native"
391
- version = "0.2.1"
391
+ version = "0.2.2"
392
392
  dependencies = [
393
393
  "ansi_term",
394
394
  "chrono",
@@ -5,7 +5,7 @@ edition = "2018"
5
5
  keywords = ["routing", "bgp"]
6
6
  license = "BSD-3-Clause"
7
7
  name = "roto-api-native"
8
- version = "0.2.1"
8
+ version = "0.2.2"
9
9
  exclude = [".tmp/*", ".pkgtest/*", "target/*", "data/*"]
10
10
  readme = "README.md"
11
11
 
@@ -1,30 +1,30 @@
1
- Copyright (c) 2021, NLnet Labs. All rights reserved.
2
-
3
- This software is open source.
4
-
5
- Redistribution and use in source and binary forms, with or without
6
- modification, are permitted provided that the following conditions
7
- are met:
8
-
9
- Redistributions of source code must retain the above copyright notice,
10
- this list of conditions and the following disclaimer.
11
-
12
- Redistributions in binary form must reproduce the above copyright notice,
13
- this list of conditions and the following disclaimer in the documentation
14
- and/or other materials provided with the distribution.
15
-
16
- Neither the name of the NLNET LABS nor the names of its contributors may
17
- be used to endorse or promote products derived from this software without
18
- specific prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1
+ Copyright (c) 2021, NLnet Labs. All rights reserved.
2
+
3
+ This software is open source.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions and the following disclaimer.
11
+
12
+ Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ Neither the name of the NLNET LABS nor the names of its contributors may
17
+ be used to endorse or promote products derived from this software without
18
+ specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.