pktlib 0.2.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.
- pktlib-0.2.0/LICENSE +21 -0
- pktlib-0.2.0/PKG-INFO +124 -0
- pktlib-0.2.0/README.md +96 -0
- pktlib-0.2.0/pyproject.toml +153 -0
- pktlib-0.2.0/pyproject.toml.orig +114 -0
- pktlib-0.2.0/src/pktlib/__init__.py +104 -0
- pktlib-0.2.0/src/pktlib/__main__.py +5 -0
- pktlib-0.2.0/src/pktlib/_audit.py +178 -0
- pktlib-0.2.0/src/pktlib/_cli.py +125 -0
- pktlib-0.2.0/src/pktlib/_codec.py +64 -0
- pktlib-0.2.0/src/pktlib/_editions.py +62 -0
- pktlib-0.2.0/src/pktlib/_errors.py +38 -0
- pktlib-0.2.0/src/pktlib/_export.py +202 -0
- pktlib-0.2.0/src/pktlib/_iosconfig.py +367 -0
- pktlib-0.2.0/src/pktlib/_model.py +2178 -0
- pktlib-0.2.0/src/pktlib/_modules.py +134 -0
- pktlib-0.2.0/src/pktlib/_passwords.py +66 -0
- pktlib-0.2.0/src/pktlib/_ports.py +120 -0
- pktlib-0.2.0/src/pktlib/_shapes.py +174 -0
- pktlib-0.2.0/src/pktlib/_twofish.py +223 -0
- pktlib-0.2.0/src/pktlib/_xml.py +84 -0
- pktlib-0.2.0/src/pktlib/activity.py +610 -0
- pktlib-0.2.0/src/pktlib/data/activity.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/base.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-1841.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-1941.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2620XM.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2621XM.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2811.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2901.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2911.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2950-24.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2950T-24.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-2960-24TT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-3560-24PS.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-3650-24PS.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-3702i.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-5505.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-5506-X.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-7960.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-819HG-4G-IOX.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-819HGW.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-829.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-AccessPoint-PT-A.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-AccessPoint-PT-AC.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-AccessPoint-PT-N.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-AccessPoint-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Analog-Phone-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Bridge-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-CGR1240.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Cable-Modem-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Cell-Tower.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Central-Office-Server.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Cloud-PT-Empty.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Cloud-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-CoAxialSplitter-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-DLC100.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-DSL-Modem-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Home-VoIP-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-HomeRouter-PT-AC.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Hub-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-IE-2000.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-ISR4321.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-ISR4331.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-LAP-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Laptop-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Linksys-WRT300N.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Meraki-MX65W.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Meraki-Server.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-NetworkController.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-PC-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Printer-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Repeater-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Router-PT-Empty.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Router-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-SMARTPHONE-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Server-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Sniffer.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Switch-PT-Empty.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-Switch-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-TV-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-TabletPC-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-WLC-2504.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-WLC-3504.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-WLC-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-WiredEndDevice-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/model-WirelessEndDevice-PT.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/modules.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/data/router-1841-wic2t.xml.gz +0 -0
- pktlib-0.2.0/src/pktlib/lab.py +207 -0
- pktlib-0.2.0/src/pktlib/py.typed +0 -0
- pktlib-0.2.0/src/pktlib/spec/devices.json +2068 -0
pktlib-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Conor McShane
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pktlib-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pktlib
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Read, edit and write Cisco Packet Tracer .pkt files in Python
|
|
5
|
+
Keywords: cisco,packet-tracer,pkt,ccna,networking,network-labs,netacad
|
|
6
|
+
Author: Conor McShane
|
|
7
|
+
Author-email: Conor McShane <117556909+conor-sometimes@users.noreply.github.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Education
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Education
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Project-URL: Homepage, https://github.com/conor-sometimes/pktlib
|
|
26
|
+
Project-URL: Issues, https://github.com/conor-sometimes/pktlib/issues
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# pktlib
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/pktlib/)
|
|
32
|
+
[](https://pypi.org/project/pktlib/)
|
|
33
|
+
[](https://github.com/conor-sometimes/pktlib/actions/workflows/ci.yml)
|
|
34
|
+
[](https://github.com/conor-sometimes/pktlib/blob/main/LICENSE)
|
|
35
|
+
|
|
36
|
+
Read, edit and write Cisco Packet Tracer `.pkt` files (and `.pka` activities) from Python. Build a network in code,
|
|
37
|
+
open it in Packet Tracer, and it works.
|
|
38
|
+
|
|
39
|
+
Tested on **Packet Tracer 8.2.0** (build 8.2.0.0162). Plain Python 3.10+, no dependencies.
|
|
40
|
+
MIT licensed. Not affiliated with Cisco.
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
import pktlib
|
|
44
|
+
|
|
45
|
+
net = pktlib.new()
|
|
46
|
+
r1 = net.router("R1", "2911", at=(300, 200))
|
|
47
|
+
sw = net.switch("SW1", at=(300, 320))
|
|
48
|
+
pc = net.pc("PC1", at=(300, 440), ip="192.168.1.10/24", gateway="192.168.1.1")
|
|
49
|
+
|
|
50
|
+
pc["fa0"].connect(sw["fa0/1"]) # the right cable is picked for you
|
|
51
|
+
sw["fa0/2"].connect(r1["g0/0"])
|
|
52
|
+
r1["g0/0"].address = "192.168.1.1/24" # interface, ip address, no shutdown
|
|
53
|
+
r1.config("""
|
|
54
|
+
router ospf 1
|
|
55
|
+
network 192.168.1.0 0.0.0.255 area 0
|
|
56
|
+
""")
|
|
57
|
+
net.save("lab.pkt")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
pktlib is [on PyPI](https://pypi.org/project/pktlib/):
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
pip install pktlib
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
In a uv project, `uv add pktlib`. To use only the command line (`pktlib audit lab.pkt`,
|
|
69
|
+
`pktlib info`, `pktlib dump`) without installing anything into a project:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
pipx install pktlib
|
|
73
|
+
# or run it once with uv
|
|
74
|
+
uvx pktlib audit lab.pkt
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The latest unreleased version: `pip install git+https://github.com/conor-sometimes/pktlib`.
|
|
78
|
+
|
|
79
|
+
## What it does
|
|
80
|
+
|
|
81
|
+
- **Build** routers, switches, PCs, phones and any of the 64 models in the 8.2 palette;
|
|
82
|
+
cable them, address them, configure them with IOS text, fit modules, draw labels.
|
|
83
|
+
- **Read** any `.pkt`: devices, ports, cables, addresses, VLANs, config. Files from older
|
|
84
|
+
Packet Tracers (6.2 and up) load and save as 8.2.
|
|
85
|
+
- **Activities** (`.pka`, `pktlib.activity`): read one, score a network against it, or write
|
|
86
|
+
a new one from two networks that Packet Tracer grades with Check Results.
|
|
87
|
+
- **Check** a file before handing it in: `pktlib audit lab.pkt` finds duplicate addresses,
|
|
88
|
+
wrong gateways, shut ports, missing clock rates and config Packet Tracer drops.
|
|
89
|
+
- **Teach** with it: troubleshooting labs with planted faults, an answer key and grading
|
|
90
|
+
(`pktlib.lab`); ping checks students click in Packet Tracer.
|
|
91
|
+
- **Round-trip**: `pktlib dump lab.pkt` turns any file into a script that rebuilds it.
|
|
92
|
+
|
|
93
|
+
Every behaviour was seen in Packet Tracer before pktlib relied on it. Where Packet Tracer
|
|
94
|
+
does something surprising, pktlib handles it; [docs/packet-tracer.md](https://github.com/conor-sometimes/pktlib/blob/main/docs/packet-tracer.md)
|
|
95
|
+
lists what and how we know.
|
|
96
|
+
|
|
97
|
+
## Command line
|
|
98
|
+
|
|
99
|
+
| Command | What it does |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `pktlib info lab.pkt` | devices, links and addresses |
|
|
102
|
+
| `pktlib audit lab.pkt` | problems you can see without running the simulation; exit code 1 if any |
|
|
103
|
+
| `pktlib dump lab.pkt [out.py]` | a Python script that rebuilds the file |
|
|
104
|
+
| `pktlib decode lab.pkt [out.xml]` / `encode in.xml out.pkt` | the raw XML |
|
|
105
|
+
|
|
106
|
+
## Documentation
|
|
107
|
+
|
|
108
|
+
- [Guide](https://github.com/conor-sometimes/pktlib/blob/main/docs/guide.md): the API, with errors and warnings
|
|
109
|
+
- [For students](https://github.com/conor-sometimes/pktlib/blob/main/docs/students.md) and [for lecturers](https://github.com/conor-sometimes/pktlib/blob/main/docs/lecturers.md)
|
|
110
|
+
- [Packet Tracer notes](https://github.com/conor-sometimes/pktlib/blob/main/docs/packet-tracer.md): editions, device models, the quirks pktlib
|
|
111
|
+
handles, the file format
|
|
112
|
+
- [Examples](https://github.com/conor-sometimes/pktlib/blob/main/examples/README.md): every example, by folder; [which were opened in Packet Tracer](https://github.com/conor-sometimes/pktlib/blob/main/docs/examples.md)
|
|
113
|
+
- [Changelog](https://github.com/conor-sometimes/pktlib/blob/main/CHANGELOG.md)
|
|
114
|
+
|
|
115
|
+
## Development
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
uv sync
|
|
119
|
+
just check # ruff, the type checkers, then the tests (about a minute)
|
|
120
|
+
just soak 3 # every random test on every core but two for 3 hours, counted
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
[CLAUDE.md](https://github.com/conor-sometimes/pktlib/blob/main/CLAUDE.md) has the project's rules, starting with the main one: Packet Tracer is
|
|
124
|
+
the source of truth.
|
pktlib-0.2.0/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# pktlib
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pktlib/)
|
|
4
|
+
[](https://pypi.org/project/pktlib/)
|
|
5
|
+
[](https://github.com/conor-sometimes/pktlib/actions/workflows/ci.yml)
|
|
6
|
+
[](https://github.com/conor-sometimes/pktlib/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Read, edit and write Cisco Packet Tracer `.pkt` files (and `.pka` activities) from Python. Build a network in code,
|
|
9
|
+
open it in Packet Tracer, and it works.
|
|
10
|
+
|
|
11
|
+
Tested on **Packet Tracer 8.2.0** (build 8.2.0.0162). Plain Python 3.10+, no dependencies.
|
|
12
|
+
MIT licensed. Not affiliated with Cisco.
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import pktlib
|
|
16
|
+
|
|
17
|
+
net = pktlib.new()
|
|
18
|
+
r1 = net.router("R1", "2911", at=(300, 200))
|
|
19
|
+
sw = net.switch("SW1", at=(300, 320))
|
|
20
|
+
pc = net.pc("PC1", at=(300, 440), ip="192.168.1.10/24", gateway="192.168.1.1")
|
|
21
|
+
|
|
22
|
+
pc["fa0"].connect(sw["fa0/1"]) # the right cable is picked for you
|
|
23
|
+
sw["fa0/2"].connect(r1["g0/0"])
|
|
24
|
+
r1["g0/0"].address = "192.168.1.1/24" # interface, ip address, no shutdown
|
|
25
|
+
r1.config("""
|
|
26
|
+
router ospf 1
|
|
27
|
+
network 192.168.1.0 0.0.0.255 area 0
|
|
28
|
+
""")
|
|
29
|
+
net.save("lab.pkt")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
pktlib is [on PyPI](https://pypi.org/project/pktlib/):
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
pip install pktlib
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
In a uv project, `uv add pktlib`. To use only the command line (`pktlib audit lab.pkt`,
|
|
41
|
+
`pktlib info`, `pktlib dump`) without installing anything into a project:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
pipx install pktlib
|
|
45
|
+
# or run it once with uv
|
|
46
|
+
uvx pktlib audit lab.pkt
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The latest unreleased version: `pip install git+https://github.com/conor-sometimes/pktlib`.
|
|
50
|
+
|
|
51
|
+
## What it does
|
|
52
|
+
|
|
53
|
+
- **Build** routers, switches, PCs, phones and any of the 64 models in the 8.2 palette;
|
|
54
|
+
cable them, address them, configure them with IOS text, fit modules, draw labels.
|
|
55
|
+
- **Read** any `.pkt`: devices, ports, cables, addresses, VLANs, config. Files from older
|
|
56
|
+
Packet Tracers (6.2 and up) load and save as 8.2.
|
|
57
|
+
- **Activities** (`.pka`, `pktlib.activity`): read one, score a network against it, or write
|
|
58
|
+
a new one from two networks that Packet Tracer grades with Check Results.
|
|
59
|
+
- **Check** a file before handing it in: `pktlib audit lab.pkt` finds duplicate addresses,
|
|
60
|
+
wrong gateways, shut ports, missing clock rates and config Packet Tracer drops.
|
|
61
|
+
- **Teach** with it: troubleshooting labs with planted faults, an answer key and grading
|
|
62
|
+
(`pktlib.lab`); ping checks students click in Packet Tracer.
|
|
63
|
+
- **Round-trip**: `pktlib dump lab.pkt` turns any file into a script that rebuilds it.
|
|
64
|
+
|
|
65
|
+
Every behaviour was seen in Packet Tracer before pktlib relied on it. Where Packet Tracer
|
|
66
|
+
does something surprising, pktlib handles it; [docs/packet-tracer.md](https://github.com/conor-sometimes/pktlib/blob/main/docs/packet-tracer.md)
|
|
67
|
+
lists what and how we know.
|
|
68
|
+
|
|
69
|
+
## Command line
|
|
70
|
+
|
|
71
|
+
| Command | What it does |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `pktlib info lab.pkt` | devices, links and addresses |
|
|
74
|
+
| `pktlib audit lab.pkt` | problems you can see without running the simulation; exit code 1 if any |
|
|
75
|
+
| `pktlib dump lab.pkt [out.py]` | a Python script that rebuilds the file |
|
|
76
|
+
| `pktlib decode lab.pkt [out.xml]` / `encode in.xml out.pkt` | the raw XML |
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
- [Guide](https://github.com/conor-sometimes/pktlib/blob/main/docs/guide.md): the API, with errors and warnings
|
|
81
|
+
- [For students](https://github.com/conor-sometimes/pktlib/blob/main/docs/students.md) and [for lecturers](https://github.com/conor-sometimes/pktlib/blob/main/docs/lecturers.md)
|
|
82
|
+
- [Packet Tracer notes](https://github.com/conor-sometimes/pktlib/blob/main/docs/packet-tracer.md): editions, device models, the quirks pktlib
|
|
83
|
+
handles, the file format
|
|
84
|
+
- [Examples](https://github.com/conor-sometimes/pktlib/blob/main/examples/README.md): every example, by folder; [which were opened in Packet Tracer](https://github.com/conor-sometimes/pktlib/blob/main/docs/examples.md)
|
|
85
|
+
- [Changelog](https://github.com/conor-sometimes/pktlib/blob/main/CHANGELOG.md)
|
|
86
|
+
|
|
87
|
+
## Development
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
uv sync
|
|
91
|
+
just check # ruff, the type checkers, then the tests (about a minute)
|
|
92
|
+
just soak 3 # every random test on every core but two for 3 hours, counted
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
[CLAUDE.md](https://github.com/conor-sometimes/pktlib/blob/main/CLAUDE.md) has the project's rules, starting with the main one: Packet Tracer is
|
|
96
|
+
the source of truth.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pktlib"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Read, edit and write Cisco Packet Tracer .pkt files in Python"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
dependencies = []
|
|
10
|
+
keywords = [
|
|
11
|
+
"cisco",
|
|
12
|
+
"packet-tracer",
|
|
13
|
+
"pkt",
|
|
14
|
+
"ccna",
|
|
15
|
+
"networking",
|
|
16
|
+
"network-labs",
|
|
17
|
+
"netacad",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Education",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Programming Language :: Python :: 3.14",
|
|
31
|
+
"Topic :: Education",
|
|
32
|
+
"Topic :: System :: Networking",
|
|
33
|
+
"Typing :: Typed",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[project.authors]]
|
|
37
|
+
name = "Conor McShane"
|
|
38
|
+
email = "117556909+conor-sometimes@users.noreply.github.com"
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/conor-sometimes/pktlib"
|
|
42
|
+
Issues = "https://github.com/conor-sometimes/pktlib/issues"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
pktlib = "pktlib._cli:main"
|
|
46
|
+
|
|
47
|
+
[build-system]
|
|
48
|
+
requires = ["uv_build>=0.13.5,<0.14.0"]
|
|
49
|
+
build-backend = "uv_build"
|
|
50
|
+
|
|
51
|
+
[dependency-groups]
|
|
52
|
+
dev = [
|
|
53
|
+
"hypothesis>=6.168.5",
|
|
54
|
+
"mutmut>=3.8.0",
|
|
55
|
+
"mypy>=2.4.0",
|
|
56
|
+
"pyright>=1.1.414",
|
|
57
|
+
"pytest>=9.1.1",
|
|
58
|
+
"pytest-cov>=7.1.0",
|
|
59
|
+
"pytest-randomly>=5.0.0",
|
|
60
|
+
"pytest-xdist>=3.8.0",
|
|
61
|
+
"ruff>=0.17.2",
|
|
62
|
+
"ty>=0.0.92",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
addopts = [
|
|
68
|
+
"-n",
|
|
69
|
+
"auto",
|
|
70
|
+
"-ra",
|
|
71
|
+
"--strict-markers",
|
|
72
|
+
"--strict-config",
|
|
73
|
+
]
|
|
74
|
+
xfail_strict = true
|
|
75
|
+
filterwarnings = ["error"]
|
|
76
|
+
|
|
77
|
+
[tool.coverage.run]
|
|
78
|
+
source = ["pktlib"]
|
|
79
|
+
branch = true
|
|
80
|
+
|
|
81
|
+
[tool.coverage.report]
|
|
82
|
+
show_missing = true
|
|
83
|
+
skip_covered = true
|
|
84
|
+
fail_under = 95
|
|
85
|
+
|
|
86
|
+
[tool.ruff]
|
|
87
|
+
line-length = 120
|
|
88
|
+
target-version = "py310"
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint]
|
|
91
|
+
select = [
|
|
92
|
+
"E",
|
|
93
|
+
"W",
|
|
94
|
+
"F",
|
|
95
|
+
"I",
|
|
96
|
+
"UP",
|
|
97
|
+
"B",
|
|
98
|
+
"BLE",
|
|
99
|
+
"C4",
|
|
100
|
+
"SIM",
|
|
101
|
+
"FBT",
|
|
102
|
+
"ANN",
|
|
103
|
+
"RUF",
|
|
104
|
+
]
|
|
105
|
+
ignore = [
|
|
106
|
+
"RUF005",
|
|
107
|
+
"SIM108",
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
[tool.ruff.lint.per-file-ignores]
|
|
111
|
+
"tests/**" = [
|
|
112
|
+
"ANN",
|
|
113
|
+
"FBT",
|
|
114
|
+
"E741",
|
|
115
|
+
]
|
|
116
|
+
"{examples,stress,scripts}/**" = [
|
|
117
|
+
"ANN",
|
|
118
|
+
"FBT",
|
|
119
|
+
"E741",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[tool.ty.environment]
|
|
123
|
+
python-version = "3.10"
|
|
124
|
+
|
|
125
|
+
[tool.mutmut]
|
|
126
|
+
paths_to_mutate = ["src/pktlib/"]
|
|
127
|
+
also_copy = [
|
|
128
|
+
"src/pktlib/data/",
|
|
129
|
+
"src/pktlib/spec/",
|
|
130
|
+
"tests/",
|
|
131
|
+
"examples/",
|
|
132
|
+
"stress/",
|
|
133
|
+
"scripts/",
|
|
134
|
+
"docs/",
|
|
135
|
+
"README.md",
|
|
136
|
+
"CHANGELOG.md",
|
|
137
|
+
"CLAUDE.md",
|
|
138
|
+
"LICENSE",
|
|
139
|
+
"CITATION.cff",
|
|
140
|
+
]
|
|
141
|
+
pytest_add_cli_args = [
|
|
142
|
+
"-n0",
|
|
143
|
+
"-p",
|
|
144
|
+
"no:randomly",
|
|
145
|
+
"-x",
|
|
146
|
+
"-q",
|
|
147
|
+
]
|
|
148
|
+
pytest_add_cli_args_test_selection = [
|
|
149
|
+
"tests/",
|
|
150
|
+
"--deselect=tests/test_stateful.py",
|
|
151
|
+
"--deselect=tests/test_fuzz_files.py",
|
|
152
|
+
"--deselect=tests/test_properties.py",
|
|
153
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pktlib"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Read, edit and write Cisco Packet Tracer .pkt files in Python"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
dependencies = []
|
|
10
|
+
authors = [{ name = "Conor McShane", email = "117556909+conor-sometimes@users.noreply.github.com" }]
|
|
11
|
+
keywords = ["cisco", "packet-tracer", "pkt", "ccna", "networking", "network-labs", "netacad"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Education",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Education",
|
|
25
|
+
"Topic :: System :: Networking",
|
|
26
|
+
"Typing :: Typed",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://github.com/conor-sometimes/pktlib"
|
|
31
|
+
Issues = "https://github.com/conor-sometimes/pktlib/issues"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
pktlib = "pktlib._cli:main"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["uv_build>=0.13.5,<0.14.0"]
|
|
38
|
+
build-backend = "uv_build"
|
|
39
|
+
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
dev = [
|
|
42
|
+
"hypothesis>=6.168.5",
|
|
43
|
+
"mutmut>=3.8.0",
|
|
44
|
+
"mypy>=2.4.0",
|
|
45
|
+
"pyright>=1.1.414",
|
|
46
|
+
"pytest>=9.1.1",
|
|
47
|
+
"pytest-cov>=7.1.0",
|
|
48
|
+
"pytest-randomly>=5.0.0",
|
|
49
|
+
"pytest-xdist>=3.8.0",
|
|
50
|
+
"ruff>=0.17.2",
|
|
51
|
+
"ty>=0.0.92",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[tool.pytest.ini_options]
|
|
55
|
+
testpaths = ["tests"]
|
|
56
|
+
# every core (pytest-xdist), a fresh random order each run (pytest-randomly; -p no:randomly
|
|
57
|
+
# to turn it off, -p randomly -p "randomly_seed=N" to repeat one), and no surprises: an
|
|
58
|
+
# unexpected warning fails, a typo'd marker or setting is an error, an xfail that passes fails
|
|
59
|
+
addopts = ["-n", "auto", "-ra", "--strict-markers", "--strict-config"]
|
|
60
|
+
xfail_strict = true
|
|
61
|
+
filterwarnings = ["error"]
|
|
62
|
+
|
|
63
|
+
[tool.coverage.run]
|
|
64
|
+
source = ["pktlib"]
|
|
65
|
+
branch = true
|
|
66
|
+
|
|
67
|
+
[tool.coverage.report]
|
|
68
|
+
show_missing = true
|
|
69
|
+
skip_covered = true
|
|
70
|
+
fail_under = 95 # line and branch coverage of the package; CI fails below it
|
|
71
|
+
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
line-length = 120
|
|
74
|
+
target-version = "py310"
|
|
75
|
+
|
|
76
|
+
[tool.ruff.lint]
|
|
77
|
+
select = [
|
|
78
|
+
"E", "W", "F", # pycodestyle, pyflakes
|
|
79
|
+
"I", # import order
|
|
80
|
+
"UP", # pyupgrade, for the oldest supported Python
|
|
81
|
+
"B", # bugbear
|
|
82
|
+
"BLE", # blind except
|
|
83
|
+
"C4", # comprehensions
|
|
84
|
+
"SIM", # simplify
|
|
85
|
+
"FBT", # boolean positional arguments
|
|
86
|
+
"ANN", # annotations on the public API
|
|
87
|
+
"RUF",
|
|
88
|
+
]
|
|
89
|
+
ignore = [
|
|
90
|
+
"RUF005", # [*a, b] over a + [b] is taste, not correctness
|
|
91
|
+
"SIM108", # a ternary is not always clearer than an if/else
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
[tool.ruff.lint.per-file-ignores]
|
|
95
|
+
# scripts and tests: no annotations required; `l` for a line is left alone outside the package
|
|
96
|
+
"tests/**" = ["ANN", "FBT", "E741"]
|
|
97
|
+
"{examples,stress,scripts}/**" = ["ANN", "FBT", "E741"]
|
|
98
|
+
|
|
99
|
+
[tool.ty.environment]
|
|
100
|
+
python-version = "3.10"
|
|
101
|
+
|
|
102
|
+
[tool.mutmut]
|
|
103
|
+
# `just mutate`: plant small bugs in the package and check a test catches each one. Slow, so
|
|
104
|
+
# it isn't part of `just check`. The slow random suites are left out: the targeted tests are
|
|
105
|
+
# what should catch a planted bug.
|
|
106
|
+
paths_to_mutate = ["src/pktlib/"]
|
|
107
|
+
also_copy = ["src/pktlib/data/", "src/pktlib/spec/", "tests/", "examples/", "stress/", "scripts/", "docs/", "README.md", "CHANGELOG.md", "CLAUDE.md", "LICENSE", "CITATION.cff"]
|
|
108
|
+
pytest_add_cli_args = ["-n0", "-p", "no:randomly", "-x", "-q"]
|
|
109
|
+
pytest_add_cli_args_test_selection = [
|
|
110
|
+
"tests/",
|
|
111
|
+
"--deselect=tests/test_stateful.py",
|
|
112
|
+
"--deselect=tests/test_fuzz_files.py",
|
|
113
|
+
"--deselect=tests/test_properties.py",
|
|
114
|
+
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""pktlib: read, edit and write Cisco Packet Tracer .pkt files, in plain Python.
|
|
2
|
+
|
|
3
|
+
import pktlib
|
|
4
|
+
|
|
5
|
+
net = pktlib.new()
|
|
6
|
+
r1 = net.router("R1", "1841+WIC-2T", at=(200, 380))
|
|
7
|
+
sw = net.switch("SW0", at=(200, 260))
|
|
8
|
+
pc = net.pc("PC0", at=(200, 150), ip="192.168.1.10/24", gateway="192.168.1.1")
|
|
9
|
+
pc["fa0"].connect(sw["fa0/1"])
|
|
10
|
+
sw["fa0/2"].connect(r1["fa0/0"])
|
|
11
|
+
r1["fa0/0"].address = "192.168.1.1/24"
|
|
12
|
+
net.save("lab.pkt")
|
|
13
|
+
|
|
14
|
+
net = pktlib.load("lab.pkt")
|
|
15
|
+
print(pktlib.to_python(net)) # any .pkt -> a script that rebuilds it
|
|
16
|
+
|
|
17
|
+
Everything public is here, at the top level, and in pktlib.lab. Modules whose names
|
|
18
|
+
start with an underscore are pktlib's own and may change in any release.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import contextlib as _contextlib
|
|
22
|
+
from importlib import metadata as _metadata
|
|
23
|
+
|
|
24
|
+
from ._audit import Problem, audit
|
|
25
|
+
from ._codec import decode, encode
|
|
26
|
+
from ._editions import EDITIONS, LATEST
|
|
27
|
+
from ._errors import FileFormatError, NotFound, PktError, PktWarning, TagMismatch
|
|
28
|
+
from ._export import to_python
|
|
29
|
+
from ._iosconfig import refused
|
|
30
|
+
from ._model import (
|
|
31
|
+
Address,
|
|
32
|
+
Cable,
|
|
33
|
+
Device,
|
|
34
|
+
End,
|
|
35
|
+
Interface,
|
|
36
|
+
Link,
|
|
37
|
+
Network,
|
|
38
|
+
Pdu,
|
|
39
|
+
Port,
|
|
40
|
+
Ports,
|
|
41
|
+
Profile,
|
|
42
|
+
RsaKey,
|
|
43
|
+
load,
|
|
44
|
+
models,
|
|
45
|
+
new,
|
|
46
|
+
)
|
|
47
|
+
from ._modules import Slot, module_models
|
|
48
|
+
from ._passwords import matches as password_matches
|
|
49
|
+
from ._ports import canonical_port
|
|
50
|
+
from ._shapes import Note, Shape
|
|
51
|
+
from .lab import Fault, Lab, Result
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"EDITIONS",
|
|
55
|
+
"LATEST",
|
|
56
|
+
"Address",
|
|
57
|
+
"Cable",
|
|
58
|
+
"Device",
|
|
59
|
+
"End",
|
|
60
|
+
"Fault",
|
|
61
|
+
"FileFormatError",
|
|
62
|
+
"Interface",
|
|
63
|
+
"Lab",
|
|
64
|
+
"Link",
|
|
65
|
+
"Network",
|
|
66
|
+
"NotFound",
|
|
67
|
+
"Note",
|
|
68
|
+
"Pdu",
|
|
69
|
+
"PktError",
|
|
70
|
+
"PktWarning",
|
|
71
|
+
"Port",
|
|
72
|
+
"Ports",
|
|
73
|
+
"Problem",
|
|
74
|
+
"Profile",
|
|
75
|
+
"Result",
|
|
76
|
+
"RsaKey",
|
|
77
|
+
"Shape",
|
|
78
|
+
"Slot",
|
|
79
|
+
"TagMismatch",
|
|
80
|
+
"audit",
|
|
81
|
+
"canonical_port",
|
|
82
|
+
"decode",
|
|
83
|
+
"encode",
|
|
84
|
+
"load",
|
|
85
|
+
"models",
|
|
86
|
+
"module_models",
|
|
87
|
+
"new",
|
|
88
|
+
"password_matches",
|
|
89
|
+
"refused",
|
|
90
|
+
"to_python",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
# Public names say they're pktlib's, not a private module's: pktlib.NotFound in a
|
|
94
|
+
# traceback, and help(pktlib.Network) names the right place.
|
|
95
|
+
for _name in __all__:
|
|
96
|
+
_obj = globals()[_name]
|
|
97
|
+
if getattr(_obj, "__module__", "").startswith("pktlib."):
|
|
98
|
+
with _contextlib.suppress(AttributeError, TypeError): # typing aliases (Cable, Address) can't be
|
|
99
|
+
_obj.__module__ = __name__
|
|
100
|
+
|
|
101
|
+
try:
|
|
102
|
+
__version__ = _metadata.version("pktlib")
|
|
103
|
+
except _metadata.PackageNotFoundError: # running from a source tree that isn't installed
|
|
104
|
+
__version__ = "0+unknown"
|