fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42551?usp=email )
Change subject: docs: auto-generate Card Filesystem Reference
......................................................................
docs: auto-generate Card Filesystem Reference
Add a Sphinx extension (docs/pysim_fs_sphinx.py) that hooks into the
builder-inited event and generates docs/filesystem.rst before Sphinx
reads any source files.
The generated page contains a hierarchical listing of all implemented
EFs and DFs, organised by application/specification (UICC/TS 102 221,
ADF.USIM/TS 31.102, ADF.ISIM/TS 31.103, SIM/TS 51.011). For each file,
the class docstring and any _test_de_encode / _test_decode vectors
are included as an encoding/decoding example table.
docs/filesystem.rst is fully generated at build time and is therefore
added to .gitignore.
Change-Id: I06ddeefc6c11e04d7c24e116f3f39c8a6635856f
Related: OS#6316
---
M .gitignore
M docs/conf.py
M docs/index.rst
A docs/pysim_fs_sphinx.py
4 files changed, 253 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/51/42551/1
diff --git a/.gitignore b/.gitignore
index 0cd5b14..3f1f645 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
/docs/_*
/docs/generated
+/docs/filesystem.rst
/.cache
/.local
/build
diff --git a/docs/conf.py b/docs/conf.py
index 165d235..2a6bbd3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,6 +13,7 @@
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
+sys.path.insert(0, os.path.abspath('.')) # for local extensions (pysim_fs_sphinx, …)
# -- Project information -----------------------------------------------------
@@ -39,7 +40,8 @@
"sphinx.ext.autodoc",
"sphinxarg.ext",
"sphinx.ext.autosectionlabel",
- "sphinx.ext.napoleon"
+ "sphinx.ext.napoleon",
+ "pysim_fs_sphinx",
]
# Add any paths that contain templates here, relative to this directory.
@@ -81,8 +83,13 @@
# reader", "decode_hex", etc.) still slip through. Suppress the residual
# warnings per-file; cross-references into these sections are not a supported
# use-case.
+#
+# filesystem.rst is auto-generated and intentionally repeats DF names across
+# different application sections (e.g. DF.PHONEBOOK in both ADF.USIM and
+# DF.GSM); suppress its duplicate-label warnings for the same reason.
autosectionlabel_maxdepth = 3
suppress_warnings = [
+ 'autosectionlabel.filesystem',
'autosectionlabel.saip-tool',
'autosectionlabel.shell',
'autosectionlabel.smpp2sim',
diff --git a/docs/index.rst b/docs/index.rst
index a6ed7b9..8908c4e 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -39,6 +39,7 @@
:caption: Contents:
shell
+ filesystem
trace
legacy
smpp2sim
diff --git a/docs/pysim_fs_sphinx.py b/docs/pysim_fs_sphinx.py
new file mode 100644
index 0000000..37f3577
--- /dev/null
+++ b/docs/pysim_fs_sphinx.py
@@ -0,0 +1,243 @@
+"""
+Sphinx extension: auto-generate docs/filesystem.rst from the pySim EF class hierarchy.
+
+Hooked into Sphinx's ``builder-inited`` event so the file is always regenerated
+from the live Python classes before Sphinx reads any source files.
+
+The table of root objects to document is in SECTIONS near the top of this file.
+"""
+
+import importlib
+import inspect
+import json
+import os
+import sys
+import textwrap
+
+# Ensure pySim is importable when this module is loaded as a Sphinx extension
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+
+from pySim.filesystem import (CardApplication, CardDF, CardMF, CardEF, # noqa: E402
+ TransparentEF, TransRecEF, LinFixedEF, CyclicEF, BerTlvEF)
+from pySim.profile import CardProfile # noqa: E402
+
+
+# Generic EF base classes whose docstrings describe the *type* of file
+# (Transparent, LinFixed, ...) rather than a specific file's content.
+# Suppress those boilerplate texts in the per-EF entries; they are only
+# useful once, at the top of the document or in a dedicated glossary.
+_EF_BASE_TYPES = frozenset([TransparentEF,
+ TransRecEF,
+ LinFixedEF,
+ CyclicEF,
+ BerTlvEF])
+
+
+# ---------------------------------------------------------------------------
+# Sections: (heading, module, class-name)
+# The class must be either a CardProfile (uses .files_in_mf) or a CardDF
+# subclass (uses .children).
+# ---------------------------------------------------------------------------
+SECTIONS = [
+ ('MF / TS 102 221 (UICC)',
+ 'pySim.ts_102_221', 'CardProfileUICC'),
+ ('ADF.USIM / TS 31.102',
+ 'pySim.ts_31_102', 'ADF_USIM'),
+ ('ADF.ISIM / TS 31.103',
+ 'pySim.ts_31_103', 'ADF_ISIM'),
+ ('ADF.HPSIM / TS 31.104',
+ 'pySim.ts_31_104', 'ADF_HPSIM'),
+ ('DF.GSM + DF.TELECOM / TS 51.011 (SIM)',
+ 'pySim.ts_51_011', 'CardProfileSIM'),
+ ('CDMA / IS-820 (RUIM)',
+ 'pySim.cdma_ruim', 'CardProfileRUIM'),
+ ('DF.EIRENE / GSM-R',
+ 'pySim.gsm_r', 'DF_EIRENE'),
+ ('DF.SYSTEM / sysmocom SJA2+SJA5',
+ 'pySim.sysmocom_sja2', 'DF_SYSTEM'),
+ # pySim.ara_m / ADF_ARAM: ARA-M has no EF/DF children defined in pySim.
+ # pySim.euicc / CardProfileEuiccSGP{02,22,32}: no MF-level files beyond base UICC.
+ # pySim.euicc / CardApplicationISDR, CardApplicationECASD: no EF/DF children.
+ # pySim.ts_102_310 / DF_EAP: skipped due to a NameError bug in the module (EF_EAPKEYS
+ # self-references its own class name during class body evaluation).
+]
+
+# RST underline characters ordered by nesting depth
+_HEADING_CHARS = ['=', '=', '-', '~', '^', '"']
+# Level 0 uses '=' with overline (page title).
+# Level 1 uses '=' without overline (major sections).
+# Levels 2+ use the remaining characters for DFs.
+
+
+# ---------------------------------------------------------------------------
+# RST formatting helpers
+# ---------------------------------------------------------------------------
+
+def _heading(title: str, level: int) -> str:
+ """Return an RST heading string. Level 0 gets an overline."""
+ char = _HEADING_CHARS[level]
+ rule = char * len(title)
+ if level == 0:
+ return f'{rule}\n{title}\n{rule}\n\n'
+ return f'{title}\n{rule}\n\n'
+
+
+def _json_default(obj):
+ """Fallback serialiser: bytes -> hex, anything else -> repr."""
+ if isinstance(obj, (bytes, bytearray)):
+ return obj.hex()
+ return repr(obj)
+
+
+def _examples_block(cls) -> str:
+ """Return RST code-block examples (one per vector), or '' if none exist.
+
+ Each example is rendered as a ``json5`` code-block with the hex-encoded
+ binary as a ``// comment`` on the first line, followed by the decoded JSON.
+ ``json5`` is used instead of ``json`` so that Pygments does not flag the
+ ``//`` comment as a syntax error.
+ """
+ vectors = []
+ for attr in ('_test_de_encode', '_test_decode'):
+ v = getattr(cls, attr, None)
+ if v:
+ vectors.extend(v)
+ if not vectors:
+ return ''
+
+ lines = ['**Examples**\n\n']
+
+ for t in vectors:
+ # 2-tuple: (encoded, decoded)
+ # 3-tuple: (encoded, record_nr, decoded) — LinFixedEF
+ encoded = t[0]
+ decoded = t[2] if len(t) >= 3 else t[1]
+
+ json_str = json.dumps(decoded, default=_json_default, indent=2)
+ json_indented = textwrap.indent(json_str, ' ')
+
+ lines.append('.. code-block:: json5\n\n')
+ lines.append(f' // {encoded.lower()}\n')
+ lines.append(json_indented + '\n')
+ lines.append('\n')
+
+ return ''.join(lines)
+
+
+def _document_ef(ef: CardEF) -> str:
+ """Return RST for a single EF. Uses ``rubric`` to stay out of the TOC."""
+ cls = type(ef)
+
+ parts = [ef.fully_qualified_path_str()]
+ if ef.fid:
+ parts.append(f'({ef.fid.upper()})')
+ if ef.desc:
+ parts.append(f'\u2014 {ef.desc}') # em-dash
+ title = ' '.join(parts)
+
+ lines = [f'.. rubric:: {title}\n\n']
+
+ # Only show a docstring if it is specific to this class. EFs that are
+ # direct instances of a base type (TransparentEF, LinFixedEF, …) carry
+ # only the generic "what is a TransparentEF" boilerplate; named subclasses
+ # without their own __doc__ have cls.__dict__['__doc__'] == None. Either
+ # way, suppress the text here — it belongs at the document level, not
+ # repeated for every single EF entry.
+ doc = None if cls in _EF_BASE_TYPES else cls.__dict__.get('__doc__')
+ if doc:
+ lines.append(inspect.cleandoc(doc) + '\n\n')
+
+ examples = _examples_block(cls)
+ if examples:
+ lines.append(examples)
+
+ return ''.join(lines)
+
+
+def _document_df(df: CardDF, level: int) -> str:
+ """Return RST for a DF section and all its children, recursively."""
+ parts = [df.fully_qualified_path_str()]
+ if df.fid:
+ parts.append(f'({df.fid.upper()})')
+ if df.desc:
+ parts.append(f'\u2014 {df.desc}') # em-dash
+ title = ' '.join(parts)
+
+ lines = [_heading(title, level)]
+
+ cls = type(df)
+ doc = None if cls in (CardDF, CardMF) else cls.__dict__.get('__doc__')
+ if doc:
+ lines.append(inspect.cleandoc(doc) + '\n\n')
+
+ for child in df.children.values():
+ if isinstance(child, CardDF):
+ lines.append(_document_df(child, level + 1))
+ elif isinstance(child, CardEF):
+ lines.append(_document_ef(child))
+
+ return ''.join(lines)
+
+
+# ---------------------------------------------------------------------------
+# Top-level generator
+# ---------------------------------------------------------------------------
+
+def generate_filesystem_rst() -> str:
+ """Walk all registered sections and return the full RST document as a string."""
+ out = [
+ '.. This file is auto-generated by docs/pysim_fs_sphinx.py — do not edit.\n\n',
+ _heading('Card Filesystem Reference', 0),
+ 'This page documents all Elementary Files (EFs) and Dedicated Files (DFs) '
+ 'implemented in pySim, organised by their location in the card filesystem.\n\n',
+ ]
+
+ # Track already-documented classes so that DFs/EFs shared between profiles
+ # (e.g. DF.TELECOM / DF.GSM present in both CardProfileSIM and CardProfileRUIM)
+ # are only emitted once.
+ seen_types: set = set()
+
+ for section_title, module_path, class_name in SECTIONS:
+ module = importlib.import_module(module_path)
+ cls = getattr(module, class_name)
+ obj = cls()
+
+ if isinstance(obj, CardProfile):
+ files = obj.files_in_mf
+ elif isinstance(obj, CardApplication):
+ files = list(obj.adf.children.values())
+ elif isinstance(obj, CardDF):
+ files = list(obj.children.values())
+ else:
+ continue
+
+ # Filter out files whose class was already documented in an earlier section.
+ files = [f for f in files if type(f) not in seen_types]
+ if not files:
+ continue
+
+ out.append(_heading(section_title, 1))
+
+ for f in files:
+ seen_types.add(type(f))
+ if isinstance(f, CardDF):
+ out.append(_document_df(f, level=2))
+ elif isinstance(f, CardEF):
+ out.append(_document_ef(f))
+
+ return ''.join(out)
+
+
+# ---------------------------------------------------------------------------
+# Sphinx integration
+# ---------------------------------------------------------------------------
+
+def _on_builder_inited(app):
+ output_path = os.path.join(app.srcdir, 'filesystem.rst')
+ with open(output_path, 'w') as fh:
+ fh.write(generate_filesystem_rst())
+
+
+def setup(app):
+ app.connect('builder-inited', _on_builder_inited)
+ return {'version': '0.1', 'parallel_read_safe': True}
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42551?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I06ddeefc6c11e04d7c24e116f3f39c8a6635856f
Gerrit-Change-Number: 42551
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42548?usp=email
to look at the new patch set (#2).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
Change subject: stp: m3ua: Introduce test TC_adm_block_act_err
......................................................................
stp: m3ua: Introduce test TC_adm_block_act_err
Related: OS#6752
Related: libosmo-sigtran.git Change-Id I23851fe05c06b6bf59b902632029a2382231427e
Change-Id: I9869ec2b71a3f6814340e181d67bab4c9266a2f4
---
M stp/STP_Tests_M3UA.ttcn
M stp/expected-results.xml
2 files changed, 22 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/48/42548/2
--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/42548?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I9869ec2b71a3f6814340e181d67bab4c9266a2f4
Gerrit-Change-Number: 42548
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sigtran/+/42549?usp=email )
Change subject: xua asp block: SGP/IPSP: Answer ASPAC with Err if blocked
......................................................................
xua asp block: SGP/IPSP: Answer ASPAC with Err if blocked
Reject received ASPACs when the asp is administratively blocked.
Moving an already active ASP into inactive state upon user applies
adminsitrative block is not covered in this commit; it will be
implementer later.
This commit doesn't yet implement asp blocking in ASP role nor
(ASP-side) IPSP role.
Related: OS#6752
Change-Id: I23851fe05c06b6bf59b902632029a2382231427e
---
M src/ss7_asp.c
M src/ss7_asp.h
M src/ss7_asp_vty.c
M src/xua_asp_fsm.c
M tests/vty/osmo_stp_test.vty
M tests/vty/ss7_asp_test.vty
6 files changed, 66 insertions(+), 7 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/49/42549/1
diff --git a/src/ss7_asp.c b/src/ss7_asp.c
index ba3b95c..96e8759 100644
--- a/src/ss7_asp.c
+++ b/src/ss7_asp.c
@@ -1530,6 +1530,18 @@
return -1;
}
+/* Change adminsitrative state "block" of an ASP.
+ * A blocked ASP can't stay nor be turned into ACTIVE state. */
+void ss7_asp_set_blocked(struct osmo_ss7_asp *asp, bool blocked)
+{
+ if (asp->cfg.adm_state.blocked == blocked)
+ return;
+ LOGPASP(asp, DLSS7, LOGL_NOTICE, "Applying Adm State change: '%sblock' -> '%sblock'\n",
+ asp->cfg.adm_state.blocked ? "" : "no ",
+ blocked ? "" : "no ");
+ asp->cfg.adm_state.blocked = blocked;
+}
+
/* Apply sane configs for unconfigured options and restart the ASP. */
void ss7_asp_restart_after_reconfigure(struct osmo_ss7_asp *asp)
{
diff --git a/src/ss7_asp.h b/src/ss7_asp.h
index 6b8e974..3012e5e 100644
--- a/src/ss7_asp.h
+++ b/src/ss7_asp.h
@@ -192,6 +192,7 @@
int ss7_asp_apply_new_local_address(const struct osmo_ss7_asp *asp, unsigned int loc_idx);
int ss7_asp_apply_drop_local_address(const struct osmo_ss7_asp *asp, unsigned int loc_idx);
+void ss7_asp_set_blocked(struct osmo_ss7_asp *asp, bool blocked);
void ss7_asp_restart_after_reconfigure(struct osmo_ss7_asp *asp);
unsigned int ss7_asp_get_all_rctx(const struct osmo_ss7_asp *asp, uint32_t *rctx, unsigned int rctx_size,
diff --git a/src/ss7_asp_vty.c b/src/ss7_asp_vty.c
index 3cae016..e3c82fe 100644
--- a/src/ss7_asp_vty.c
+++ b/src/ss7_asp_vty.c
@@ -705,9 +705,33 @@
"Allows a SCTP Association with ASP, but doesn't let it become active\n",
CMD_ATTR_NODE_EXIT)
{
- /* TODO */
- vty_out(vty, "Not supported yet%s", VTY_NEWLINE);
- return CMD_WARNING;
+ struct osmo_ss7_asp *asp = vty->index;
+
+ if (asp->cfg.proto != OSMO_SS7_ASP_PROT_M3UA &&
+ asp->cfg.proto != OSMO_SS7_ASP_PROT_SUA) {
+ vty_out(vty, "%% 'block' not supported for ASP protocol %s%s",
+ osmo_ss7_asp_protocol_name(asp->cfg.proto), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (asp->cfg.role == OSMO_SS7_ASP_ROLE_ASP) {
+ vty_out(vty, "%% 'block' not yet implemented in 'role asp'%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ss7_asp_set_blocked(asp, true);
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(asp_no_block, asp_no_block_cmd,
+ "no block",
+ NO_STR "Allows a SCTP Association with ASP, but doesn't let it become active\n",
+ CMD_ATTR_NODE_EXIT)
+{
+ struct osmo_ss7_asp *asp = vty->index;
+
+ ss7_asp_set_blocked(asp, false);
+ return CMD_SUCCESS;
}
DEFUN_ATTR(asp_shutdown, asp_shutdown_cmd,
@@ -1492,6 +1516,7 @@
gen_asp_timer_lm_cmd_strs(&asp_timer_lm_cmd);
install_lib_element(L_CS7_ASP_NODE, &asp_timer_lm_cmd);
install_lib_element(L_CS7_ASP_NODE, &asp_block_cmd);
+ install_lib_element(L_CS7_ASP_NODE, &asp_no_block_cmd);
install_lib_element(L_CS7_ASP_NODE, &asp_shutdown_cmd);
install_lib_element(L_CS7_ASP_NODE, &asp_no_shutdown_cmd);
}
diff --git a/src/xua_asp_fsm.c b/src/xua_asp_fsm.c
index 8524c4d..7ee3fd1 100644
--- a/src/xua_asp_fsm.c
+++ b/src/xua_asp_fsm.c
@@ -655,7 +655,7 @@
struct xua_msg_part *asp_id_ie;
struct xua_msg *xua_in;
uint32_t traf_mode = 0;
- struct xua_msg_part *part;
+ struct xua_msg_part *rctx_ie;
uint32_t asp_id;
int i;
@@ -711,9 +711,9 @@
return;
}
}
- if ((part = xua_msg_find_tag(xua_in, M3UA_IEI_ROUTE_CTX))) {
- for (i = 0; i < part->len / sizeof(uint32_t); i++) {
- uint8_t *rctx_raw = &part->dat[i * sizeof(uint32_t)];
+ if ((rctx_ie = xua_msg_find_tag(xua_in, M3UA_IEI_ROUTE_CTX))) {
+ for (i = 0; i < rctx_ie->len / sizeof(uint32_t); i++) {
+ uint8_t *rctx_raw = &rctx_ie->dat[i * sizeof(uint32_t)];
uint32_t rctx = osmo_load32be(rctx_raw);
as = ss7_asp_find_as_by_rctx(asp, rctx);
if (!as) {
@@ -726,6 +726,23 @@
}
}
+ if (asp->cfg.adm_state.blocked) {
+ /* RFC4666 (M3UA) 3.8.1: The "Refused - Management Blocking" error is sent
+ * when an ASP Up or ASP Active message is received and the request is refused
+ * for management reasons (e.g., management lockout). If this error is in
+ * response to an ASP Active message, the Routing Context(s) in the ASP Active
+ * message SHOULD be included in the Error message."
+ * RC4666 (M3UA) 4.3.4.3: "If for any local reason (e.g., management lockout)
+ * the SGP responds to an ASP Active message with an Error message with reason
+ * Refused Management Blocking".
+ */
+ LOGPFSML(fi, LOGL_INFO, "ASPAC: Reject due to ASP in administrative state 'block'\n");
+ peer_send_error_ext(fi, SUA_ERR_REFUSED_MGMT_BLOCKING,
+ rctx_ie ? rctx_ie->dat : NULL,
+ rctx_ie ? rctx_ie->len : 0);
+ return;
+ }
+
if (traf_mode) { /* if the peer has specified a traffic mode at all */
/* First validate peer not trying to establish an incompatible traffic mode: */
llist_for_each_entry(assoc, &asp->assoc_as_list, asp_entry) {
diff --git a/tests/vty/osmo_stp_test.vty b/tests/vty/osmo_stp_test.vty
index 561fc39..3c6e466 100644
--- a/tests/vty/osmo_stp_test.vty
+++ b/tests/vty/osmo_stp_test.vty
@@ -303,6 +303,7 @@
timer xua (ack|beat) <1-999999>
timer lm (wait_asp_up|wait_notify|wait_notify_rkm|wait_rk_reg_resp) <1-999999>
block
+ no block
shutdown
no shutdown
...
@@ -332,6 +333,7 @@
tcp-param Configure TCP parameters
destination-audit Configure ASP Auditing (xUA DAUD)
quirk Disable quirk to work around interop issues
+ block Allows a SCTP Association with ASP, but doesn't let it become active
shutdown Terminates SCTP association; New associations will be rejected
...
diff --git a/tests/vty/ss7_asp_test.vty b/tests/vty/ss7_asp_test.vty
index 62b7aa3..0b8f4fd 100644
--- a/tests/vty/ss7_asp_test.vty
+++ b/tests/vty/ss7_asp_test.vty
@@ -299,6 +299,7 @@
timer xua (ack|beat) <1-999999>
timer lm (wait_asp_up|wait_notify|wait_notify_rkm|wait_rk_reg_resp) <1-999999>
block
+ no block
shutdown
no shutdown
...
@@ -330,6 +331,7 @@
tcp-param Configure TCP parameters
destination-audit Configure ASP Auditing (xUA DAUD)
quirk Disable quirk to work around interop issues
+ block Allows a SCTP Association with ASP, but doesn't let it become active
shutdown Terminates SCTP association; New associations will be rejected
...
--
To view, visit https://gerrit.osmocom.org/c/libosmo-sigtran/+/42549?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I23851fe05c06b6bf59b902632029a2382231427e
Gerrit-Change-Number: 42549
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42546?usp=email )
Change subject: docs/conf.py: add autodoc_mock_imports for klein and twisted
......................................................................
docs/conf.py: add autodoc_mock_imports for klein and twisted
The eSIM SM-DP+ server modules (`pySim.esim.es2p`, `pySim.esim.es9p`,
`pySim.esim.http_json_api`) unconditionally import optional server-side
dependencies at module level:
pySim.esim.es2p -- from klein import Klein
pySim.esim.http_json_api -- from twisted.web.server import Request
Both imports fail during a docs build if the packages are absent or
broken, causing three "autodoc: failed to import" warnings and three
missing chapters in the generated manual.
Even when klein and twisted are installed, twisted 23.10.0 (the
version pulled in transitively by smpp.twisted3's `Twisted~=23.10.0`
constraint) is incompatible with Python 3.13+ because twisted.web.http
unconditionally executes `import cgi`, a module that was removed from
the standard library in Python 3.13.
Fix: add `autodoc_mock_imports = ['klein', 'twisted']` to conf.py.
Sphinx inserts mock entries into sys.modules before each autodoc import
attempt, so the modules can be imported and documented without requiring
the real packages to be importable at build time.
Change-Id: I71650466f02a6a6d150650deed167c05d2cb6e64
---
M docs/conf.py
1 file changed, 6 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/46/42546/1
diff --git a/docs/conf.py b/docs/conf.py
index 99107e2..165d235 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -65,6 +65,12 @@
autoclass_content = 'both'
+# es2p and http_json_api/es9p use optional server-side deps (klein, twisted.web)
+# that may be absent or Python-version-incompatible (twisted 23.x uses the
+# `cgi` stdlib module removed in Python 3.13). Mock them so autodoc can still
+# import and document those modules.
+autodoc_mock_imports = ['klein', 'twisted']
+
# sphinxarg.ext generates generic sub-headings ("Named arguments",
# "Positional arguments", "Sub-commands", "General options", ...) for every
# argparse command/tool. These repeat across many files and trigger tons
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42546?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I71650466f02a6a6d150650deed167c05d2cb6e64
Gerrit-Change-Number: 42546
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>