PyOpenMagnetics - Python Wrapper for OpenMagnetics
🤖 For AI Assistants: If you're an AI assistant helping with this library, please read AGENTS.md FIRST before continuing with this README. It contains essential information about:
- Correct import procedures (this package requires special handling)
- ⚠️ Using API methods instead of manual calculations (CRITICAL)
- Required field specifications for converter topologies
- Troubleshooting common API errors
- Complete working examples
⚠️ AVOID MANUAL MODE: Always use
process_flyback(),calculate_advised_magnetics(), and other API methods rather than doing manual calculations. The MKF engine handles complex magnetic effects that manual calculations cannot.
PyOpenMagnetics is a Python wrapper for MKF (Magnetics Knowledge Foundation), the simulation engine of OpenMagnetics, providing a comprehensive toolkit for designing and analyzing magnetic components such as transformers and inductors.
Features
- 🧲 Core Database: Access to extensive database of core shapes, materials, and manufacturers
- 🔌 Winding Design: Automatic winding calculations with support for various wire types (round, litz, rectangular, planar)
- 📊 Loss Calculations: Core losses (Steinmetz), winding losses (DC, skin effect, proximity effect)
- 🎯 Design Adviser: Automated recommendations for optimal magnetic designs
- 📈 Signal Processing: Harmonic analysis, waveform processing
- 🖼️ Visualization: SVG plotting of cores, windings, magnetic fields
- 🔧 SPICE Export: Export magnetic components as SPICE subcircuits
Installation
From PyPI (recommended)
pip install PyOpenMagnetics
From Source
git clone https://github.com/OpenMagnetics/PyOpenMagnetics.git
cd PyOpenMagnetics
pip install .
Build provenance
The build compiles MKF by globbing its .cpp files directly into the
extension, tracking MKF/MAS main, and builds the Kirchhoff converter-model
library (libKirchhoffApi.so) as an ExternalProject. The exact engine commits a
wheel was compiled from are baked into the package:
import PyOpenMagnetics
print(PyOpenMagnetics.__mkf_commit__) # MKF SHA this wheel was built from
print(PyOpenMagnetics.__mas_commit__) # MAS SHA this wheel was built from
A clean rebuild:
rm -rf build && pip install . --no-deps -v
Importing and error handling
import PyOpenMagnetics works like any other package. Since v1.7.0 every engine
failure raises PyOpenMagnetics.EngineError (a RuntimeError subclass) —
functions never return error strings or {"data": "<error>"} objects:
import PyOpenMagnetics
PyOpenMagnetics.load_databases({})
print(f"✓ Loaded {len(PyOpenMagnetics.get_core_materials())} materials")
print(f"✓ Loaded {len(PyOpenMagnetics.get_core_shapes())} shapes")
try:
PyOpenMagnetics.find_core_shape_by_name("No Such Shape")
except PyOpenMagnetics.EngineError as e:
print(f"Engine error: {e}")
The only exception is the plotting family, which returns a discriminated union
{"success": bool, "error": str, ...} that callers branch on.
See AGENTS.md for more usage guidance.
Quick Start
Basic Example: Creating a Core
import PyOpenMagnetics
# Find a core shape by name
shape = PyOpenMagnetics.find_core_shape_by_name("E 42/21/15")
# Find a core material by name
material = PyOpenMagnetics.find_core_material_by_name("3C95")
# Create a core with gapping. "type" is mandatory; shape/material accept
# either the objects fetched above or plain name strings.
core_data = {
"functionalDescription": {
"type": "two-piece set",
"shape": shape,
"material": material,
"gapping": [{"type": "subtractive", "length": 0.001}], # 1mm gap
"numberStacks": 1
}
}
# Calculate complete core data
core = PyOpenMagnetics.calculate_core_data(core_data, False)
print(f"Effective area: {core['processedDescription']['effectiveParameters']['effectiveArea']} m²")
Design Adviser: Get Magnetic Recommendations
import PyOpenMagnetics
# Define design requirements
inputs = {
"designRequirements": {
"magnetizingInductance": {
"minimum": 100e-6, # 100 µH minimum
"nominal": 110e-6 # 110 µH nominal
},
"turnsRatios": [{"nominal": 5.0}] # 5:1 turns ratio
},
"operatingPoints": [
{
"name": "Nominal",
"conditions": {"ambientTemperature": 25},
"excitationsPerWinding": [
{
"name": "Primary",
"frequency": 100000, # 100 kHz
"current": {
"waveform": {
"data": [0, 1.0, 0],
"time": [0, 5e-6, 10e-6]
}
},
"voltage": {
"waveform": {
"data": [50, 50, -50, -50],
"time": [0, 5e-6, 5e-6, 10e-6]
}
}
}
]
}
]
}
# Process inputs (adds harmonics and validation)
processed_inputs = PyOpenMagnetics.process_inputs(inputs)
# Get magnetic recommendations
# core_mode: "available cores" (stock cores) or "standard cores" (all standard shapes)
result = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
# Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
for i, item in enumerate(result["data"]):
mag = item["mas"]["magnetic"]
core = mag["core"]["functionalDescription"]
print(f"{i+1}. {core['shape']['name']} - {core['material']['name']} (score: {item['scoring']:.3f})")
Calculate Core Losses
import PyOpenMagnetics
# A complete core (see "Creating a Core" above)
core = PyOpenMagnetics.calculate_core_data({
"functionalDescription": {
"type": "two-piece set",
"shape": "E 42/21/15",
"material": "3C95",
"gapping": [{"type": "subtractive", "length": 0.0005}],
"numberStacks": 1
}
}, True)
# A wound coil on that core
bobbin = PyOpenMagnetics.create_basic_bobbin(core, True)
coil = PyOpenMagnetics.wind({
"bobbin": bobbin,
"functionalDescription": [{
"name": "Primary",
"numberTurns": 20,
"numberParallels": 1,
"isolationSide": "primary",
"wire": "Round 0.5 - Grade 1"
}]
}, 1, [1.0], [0], [])
# Inputs with the excitation waveforms (see the Design Adviser example)
inputs = PyOpenMagnetics.process_inputs({
"designRequirements": {
"magnetizingInductance": {"nominal": 100e-6},
"turnsRatios": []
},
"operatingPoints": [{
"name": "Nominal",
"conditions": {"ambientTemperature": 25},
"excitationsPerWinding": [{
"name": "Primary",
"frequency": 100000,
"current": {"waveform": {"data": [-1, 1, -1], "time": [0, 5e-6, 10e-6]}},
"voltage": {"waveform": {"data": [50, 50, -50, -50], "time": [0, 5e-6, 5e-6, 10e-6]}}
}]
}]
})
models = {"coreLosses": "IGSE", "reluctance": "ZHANG"}
losses = PyOpenMagnetics.calculate_core_losses(core, coil, inputs, models)
print(f"Core losses: {losses['coreLosses']} W")
Winding a Coil
import PyOpenMagnetics
# core from calculate_core_data(...) as above
bobbin = PyOpenMagnetics.create_basic_bobbin(core, True)
coil_spec = {
"bobbin": bobbin,
"functionalDescription": [
{
"name": "Primary",
"numberTurns": 50,
"numberParallels": 1,
"isolationSide": "primary",
"wire": "Round 0.5 - Grade 1"
},
{
"name": "Secondary",
"numberTurns": 10,
"numberParallels": 3,
"isolationSide": "secondary",
"wire": "Round 1.00 - Grade 1"
}
]
}
# wind(coil, repetitions, proportion_per_winding, pattern, margin_pairs)
coil = PyOpenMagnetics.wind(coil_spec, 1, [0.5, 0.5], [0, 1], [])
print(f"Wound {len(coil['turnsDescription'])} turns")
Converter-Based Design
The converter surface builds complete MAS Inputs straight from converter
specifications (the Kirchhoff topology designer sizes inductance, turns ratios
and waveforms). See examples/converter_design_example.py for the full flow:
import PyOpenMagnetics
flyback_specs = {
"inputVoltage": {"minimum": 185, "maximum": 265},
"desiredInductance": 800e-6, # optional pin; omit to let Kirchhoff size it
"desiredTurnsRatios": [13.5], # optional pin
"efficiency": 0.88,
"operatingPoints": [{
"outputVoltages": [12.0],
"outputCurrents": [2.0],
"switchingFrequency": 100000,
"ambientTemperature": 40
}]
}
inputs = PyOpenMagnetics.process_converter("flyback", flyback_specs)
processed = PyOpenMagnetics.process_inputs(inputs)
result = PyOpenMagnetics.calculate_advised_magnetics(processed, 5, "standard cores")
for item in result["data"]:
print(item["mas"]["magnetic"]["manufacturerInfo"]["reference"], item["scoring"])
A TAS-shaped spec (an object with designRequirements / operatingPoints[].outputs)
is also accepted and passed to Kirchhoff untouched.
API Reference
Database Access
| Function | Description |
|---|---|
get_core_materials() |
Get all available core materials |
get_core_shapes() |
Get all available core shapes |
get_wires() |
Get all available wires |
get_bobbins() |
Get all available bobbins |
find_core_material_by_name(name) |
Find core material by name |
find_core_shape_by_name(name) |
Find core shape by name |
find_wire_by_name(name) |
Find wire by name |
Core Calculations
| Function | Description |
|---|---|
calculate_core_data(core, process) |
Calculate complete core data |
calculate_core_gapping(core, gapping) |
Calculate gapping configuration |
calculate_inductance_from_number_turns_and_gapping(...) |
Calculate inductance |
calculate_core_losses(core, coil, inputs, models) |
Calculate core losses |
Winding Functions
| Function | Description |
|---|---|
wind(coil, repetitions, proportions, pattern, margins) |
Wind coils on a core |
calculate_winding_losses(...) |
Calculate total winding losses |
calculate_ohmic_losses(...) |
Calculate DC losses |
calculate_skin_effect_losses(...) |
Calculate skin effect losses |
calculate_proximity_effect_losses(...) |
Calculate proximity effect losses |
Design Adviser
| Function | Description |
|---|---|
calculate_advised_cores(inputs, max_results) |
Get recommended cores |
calculate_advised_magnetics(inputs, max, mode) |
Get complete designs |
process_inputs(inputs) |
Process and validate inputs |
Visualization
| Function | Description |
|---|---|
plot_core(core, ...) |
Generate SVG of core |
plot_sections(magnetic, ...) |
Plot winding sections |
plot_layers(magnetic, ...) |
Plot winding layers |
plot_turns(magnetic, ...) |
Plot individual turns |
plot_field(magnetic, ...) |
Plot magnetic field |
Settings
| Function | Description |
|---|---|
get_settings() |
Get current settings |
set_settings(settings) |
Configure settings |
reset_settings() |
Reset to defaults |
SPICE Export
| Function | Description |
|---|---|
export_magnetic_as_subcircuit(magnetic, ...) |
Export as SPICE model |
Converter Topologies
All 24 power topologies are exposed with a uniform API. Use the generic
process_converter("<topology>", converter, use_ngspice) (also accepts
"advanced_<topology>"), or the per-topology functions below. The converter
spec is either the legacy flat shape shown in "Converter-Based Design" above
(inputVoltage, optional desiredInductance/desiredTurnsRatios/efficiency/
currentRippleRatio, and operatingPoints[] with outputVoltages[]/
outputCurrents[]/switchingFrequency/ambientTemperature) or a TAS-shaped
spec, which is passed through untouched. Failures raise
PyOpenMagnetics.EngineError.
| Function family | Description |
|---|---|
process_converter(name, json, use_ngspice=True) |
Universal dispatch for every topology |
design_magnetics_from_converter(name, json, max_results, core_mode, ...) |
Converter → advised magnetic designs (single call) |
calculate_<t>_inputs(json) |
Build MAS inputs (basic mode) for topology <t> |
calculate_advanced_<t>_inputs(json) |
Build MAS inputs (advanced mode) |
simulate_<t>_ideal_waveforms(json) |
ngspice ideal-waveform simulation |
generate_<t>_ngspice_circuit(json, input_voltage_index=0, operating_point_index=0) |
Generate ngspice netlist |
<t> ∈ flyback, buck, boost, single_switch_forward, two_switch_forward, active_clamp_forward, push_pull, isolated_buck, isolated_buck_boost, cuk, sepic, zeta, four_switch_buck_boost, weinberg, llc, cllc, clllc, src, dab, psfb, pshb, ahb, vienna. PFC is basic-only (calculate_pfc_inputs,
generate_pfc_ngspice_circuit(json, dc_resistance=0.1, simulation_time=0.02, time_step=1e-8)); common-/differential-mode chokes use the cmc / dmc
families. See AGENTS.md §11 for the full per-topology parity matrix.
Core Materials
PyOpenMagnetics includes materials from major manufacturers:
- TDK/EPCOS: N27, N49, N87, N95, N97, etc.
- Ferroxcube: 3C90, 3C94, 3C95, 3F3, 3F4, etc.
- Fair-Rite: Various ferrite materials
- Magnetics Inc.: Powder cores (MPP, High Flux, Kool Mu)
- Micrometals: Iron powder cores
Core Shapes
Supported shape families include:
- E cores: E, EI, EFD, EQ, ER
- ETD/EC cores: ETD, EC
- PQ/PM cores: PQ, PM
- RM cores: RM, RM/ILP
- Toroidal: Various sizes
- Pot cores: P, PT
- U/UI cores: U, UI, UR
- Planar: E-LP, EQ-LP, etc.
Wire Types
- Round enamelled wire: Various AWG and IEC sizes
- Litz wire: Multiple strand configurations
- Rectangular wire: For high-current applications
- Foil: For planar magnetics
- Planar PCB: For integrated designs
Configuration
Use set_settings() to configure:
settings = PyOpenMagnetics.get_settings()
settings["coilAllowMarginTape"] = True
settings["coilWindEvenIfNotFit"] = False
settings["painterNumberPointsX"] = 50
PyOpenMagnetics.set_settings(settings)
Contributing
Contributions are welcome! Please see the OpenMagnetics organization for contribution guidelines.
Documentation
Quick Start
- llms.txt - Comprehensive API reference optimized for AI assistants and quick lookup
- examples/ - Practical example scripts for common design workflows
- PyOpenMagnetics.pyi - Type stubs for IDE autocompletion
Tutorials
- notebooks/ - Interactive Jupyter notebook tutorials with visualizations
- Getting Started - Introduction to PyOpenMagnetics
- Buck Inductor - Complete inductor design workflow
- Core Losses - In-depth core loss analysis
Reference
- docs/errors.md - Common errors and solutions
- docs/performance.md - Performance optimization guide
- docs/compatibility.md - Python/platform version compatibility
Validation
- api/validation.py - Runtime JSON schema validation for inputs
License
This project is licensed under the MIT License - see the LICENSE file for details.
Related Projects
- MKF - C++ magnetics library
- MAS - Magnetic Agnostic Structure schema
- OpenMagnetics Web - Online design tool
References
- Maniktala, S. "Switching Power Supplies A-Z", 2nd Edition
- Basso, C. "Switch-Mode Power Supplies", 2nd Edition
- McLyman, C. "Transformer and Inductor Design Handbook"
Support
For questions and support:
- 🐛 GitHub Issues
- 💬 Discussions
- 📧 Contact the maintainers
Release files for PyOpenMagnetics 1.7.18
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyopenmagnetics-1.7.18.tar.gz | 692.2 kB | Details |
Built distributions (wheels)
Total release size: 136.3 MB
Release files / pyopenmagnetics-1.7.18.tar.gz
| Download URL | pyopenmagnetics-1.7.18.tar.gz |
|---|---|
| Size | 692.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
30a5c859159db8d5044a39f2ea06c1347e540e8048375e263ad2843b27911db2
|
|
BLAKE2b-256 checksum How to use checksums |
f1c5076783ede9457aa989b060c715e8862c683f3880703af917098c87524823
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyopenmagnetics-1.7.18-cp314-cp314-win_amd64.whl
| Download URL | pyopenmagnetics-1.7.18-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 12.2 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0f1fff7ee090876c61c0c1ddb99374004c9e8881523cd81be87bb4ae59c51bd0
|
|
BLAKE2b-256 checksum How to use checksums |
8b58fdd6cee2c44d4ff6794725c2c0aceaa615a8d38f1a3d3d66c2d865f676ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / pyopenmagnetics-1.7.18-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pyopenmagnetics-1.7.18-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 15.0 MB |
| Tags | CPython 3.14 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
ccbe346d8dd05fd7ceed4be27d4bac46570eb36163d8ef7c163abff94373809e
|
|
BLAKE2b-256 checksum How to use checksums |
7be58c552dc7bb231e8439e915ac88d7951de9a41b687c7cf9a78c144f8b6f5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyopenmagnetics-1.7.18-cp313-cp313-win_amd64.whl
| Download URL | pyopenmagnetics-1.7.18-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 12.2 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c1fc5c4a11a6714b256c74a726b056010dca4c2f8ae06adcebdbbf4d0ba95e01
|
|
BLAKE2b-256 checksum How to use checksums |
abe613a6685809edf14de03b144fbae0ebc399a668e819d846b30363f8489199
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / pyopenmagnetics-1.7.18-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pyopenmagnetics-1.7.18-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 15.0 MB |
| Tags | CPython 3.13 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
8ce1b2cfb5b98df7eac48b78523586871e35cf874c68ca82b355292d941e88de
|
|
BLAKE2b-256 checksum How to use checksums |
06af00c164acd13ffa9653c9cf0981d956bd9b84974b2e7419a314e2338e515d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyopenmagnetics-1.7.18-cp312-cp312-win_amd64.whl
| Download URL | pyopenmagnetics-1.7.18-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 12.2 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
7051af91f678799cab43648bb3943459887af90a3448bdcfa41ce93551563c89
|
|
BLAKE2b-256 checksum How to use checksums |
1bd29fcd4dd72b549dea3ae774a97276317c598d7eafb9c2c8ac068099b2d82f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / pyopenmagnetics-1.7.18-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pyopenmagnetics-1.7.18-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 15.0 MB |
| Tags | CPython 3.12 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
70665c697f29eb8fb90cd028687794a18946b1355631c24eb6c90401a44defb3
|
|
BLAKE2b-256 checksum How to use checksums |
22cb031633fea4204069a55b4e52997f0499f9e7ca56da1cbc690a2105de3f29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyopenmagnetics-1.7.18-cp311-cp311-win_amd64.whl
| Download URL | pyopenmagnetics-1.7.18-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 12.2 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
098e2972d70d9b13e02dd99bc258836b0346b0359741fc8db5d155253b3c3bed
|
|
BLAKE2b-256 checksum How to use checksums |
716e8cd029ac609c35e96a7bb9d1cd27f976bbede88f3a68bf7519d494196920
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / pyopenmagnetics-1.7.18-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pyopenmagnetics-1.7.18-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.9 MB |
| Tags | CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
3e5451bc6f048dab576cb413dd26466e403dedd927225e4a2119b739557bb1f7
|
|
BLAKE2b-256 checksum How to use checksums |
3b735c50d9be581cf9ac4a61c6feb46e02fc129d8dc14b4b0cdd87b08c5a68a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyopenmagnetics-1.7.18-cp310-cp310-win_amd64.whl
| Download URL | pyopenmagnetics-1.7.18-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 12.2 MB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e48ec01a79ad53f18f9b5354b47bae290a53661b0149bf4b44275d7564d03020
|
|
BLAKE2b-256 checksum How to use checksums |
91fd1aa0bac6d62d94b890dbd3fd67eda6f723b37d679b7672482241c00ecd56
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / pyopenmagnetics-1.7.18-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | pyopenmagnetics-1.7.18-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 14.9 MB |
| Tags | CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
e99d9e7fc826c736ec6741da2084c050a9cc42160aae6158f0d0663a45bebb78
|
|
BLAKE2b-256 checksum How to use checksums |
9e739c3c9b3cd84405937b3712c9718c6c0f9f69efac424a47be25dfc7a9a504
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|