Attention is currently required from: daniel.
pespin has posted comments on this change by daniel. ( https://gerrit.osmocom.org/c/python/pyosmocom/+/42555?usp=email )
Change subject: tlv: Remove unused branch
......................................................................
Patch Set 1: Code-Review+1
--
To view, visit https://gerrit.osmocom.org/c/python/pyosmocom/+/42555?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: Ia6a0656721a1fcaf5f16526fefe62c30b0ddb664
Gerrit-Change-Number: 42555
Gerrit-PatchSet: 1
Gerrit-Owner: daniel <dwillmann(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-CC: Jenkins Builder
Gerrit-Attention: daniel <dwillmann(a)sysmocom.de>
Gerrit-Comment-Date: Tue, 31 Mar 2026 07:54:04 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Jenkins Builder has posted comments on this change by daniel. ( https://gerrit.osmocom.org/c/python/pyosmocom/+/42556?usp=email )
Change subject: tlv: Allow control over comprehension bit in COMPR_TLV_IE
......................................................................
Patch Set 1:
(1 comment)
File src/osmocom/tlv.py:
Robot Comment from checkpatch (run ID ):
https://gerrit.osmocom.org/c/python/pyosmocom/+/42556/comment/739cc2de_ba5d… :
PS1, Line 64: # This happens if the class is created in code. In that case the
trailing whitespace
--
To view, visit https://gerrit.osmocom.org/c/python/pyosmocom/+/42556?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: I9ca689b9b51152f3907ea470c7b42a0b12208459
Gerrit-Change-Number: 42556
Gerrit-PatchSet: 1
Gerrit-Owner: daniel <dwillmann(a)sysmocom.de>
Gerrit-CC: Jenkins Builder
Gerrit-Comment-Date: Tue, 31 Mar 2026 07:48:20 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
daniel has uploaded this change for review. ( https://gerrit.osmocom.org/c/python/pyosmocom/+/42556?usp=email )
Change subject: tlv: Allow control over comprehension bit in COMPR_TLV_IE
......................................................................
tlv: Allow control over comprehension bit in COMPR_TLV_IE
This allows construction of a comprehension TLV with the bit set or
cleared. The default is comprehension=True to not break existing code.
```
>>> foo = Foo(decoded=b"2342", comprehension=True)
>>> bar = Foo(decoded=b"2342", comprehension=False)
```
Related: OS#6989
Change-Id: I9ca689b9b51152f3907ea470c7b42a0b12208459
---
M src/osmocom/tlv.py
1 file changed, 6 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/python/pyosmocom refs/changes/56/42556/1
diff --git a/src/osmocom/tlv.py b/src/osmocom/tlv.py
index ada7380..07adfb9 100644
--- a/src/osmocom/tlv.py
+++ b/src/osmocom/tlv.py
@@ -58,11 +58,12 @@
compr = bool(binary[0] & 0x80)
return ({'comprehension': compr, 'tag': tag}, binary[1:])
-def comprehensiontlv_encode_tag(tag) -> bytes:
+def comprehensiontlv_encode_tag(tag, comprehension: bool = True) -> bytes:
"""Encode a single Tag according to ETSI TS 101 220 Section 7.1.1"""
# permit caller to specify tag also as integer value
+ # This happens if the class is created in code. In that case the
if isinstance(tag, int):
- compr = bool(tag < 0xff and tag & 0x80)
+ compr = comprehension
tag = {'tag': tag, 'comprehension': compr}
compr = tag.get('comprehension', False)
if tag['tag'] in [0x00, 0x80, 0xff] or tag['tag'] > 0xff:
@@ -74,7 +75,7 @@
return b'\x7f' + byte2.to_bytes(1, 'big') + byte3.to_bytes(1, 'big')
else:
# 1-byte format
- ret = tag['tag']
+ ret = tag['tag'] & 0x7f
if compr:
ret |= 0x80
return ret.to_bytes(1, 'big')
@@ -648,7 +649,7 @@
def __init__(self, **kwargs):
super().__init__(**kwargs)
- self.comprehension = False
+ self.comprehension = kwargs.get("comprehension", True)
@classmethod
def _decode_tag(cls, do: bytes) -> Tuple[dict, bytes]:
@@ -672,7 +673,7 @@
return ctag & 0x7f == rawtag & 0x7f
def _encode_tag(self) -> bytes:
- return comprehensiontlv_encode_tag(self._compute_tag())
+ return comprehensiontlv_encode_tag(self._compute_tag(), self.comprehension)
def _encode_len(self, val: bytes) -> bytes:
return bertlv_encode_len(len(val))
--
To view, visit https://gerrit.osmocom.org/c/python/pyosmocom/+/42556?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: I9ca689b9b51152f3907ea470c7b42a0b12208459
Gerrit-Change-Number: 42556
Gerrit-PatchSet: 1
Gerrit-Owner: daniel <dwillmann(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42554?usp=email )
Change subject: filesystem: JsonEditor: offer interactive retry on error
......................................................................
filesystem: JsonEditor: offer interactive retry on error
When json.loads() fails (e.g. the user made a syntax mistake), prompt
the user with "Re-open file for editing? [y]es/[n]o:" and loop back to
the editor if they answer 'y' or 'yes'. If the user declines, return
the original unmodified value so no write is attempted; the temp file
is still cleaned up by __exit__() in that case.
Change-Id: I9161b7becea0d8dfd3f5f740fbb253da2f061a1d
Related: OS#6899
---
M pySim/filesystem.py
1 file changed, 13 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/54/42554/1
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index d62e71a..d8b7df0 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -598,16 +598,24 @@
def __enter__(self) -> object:
"""Write JSON + examples to a temp file, run the editor, return parsed result.
- The temp file is kept on JSONDecodeError so the user can correct and
- re-open it manually. It is removed by __exit__() on success."""
+ On JSONDecodeError the user is offered the option to re-open the file
+ and fix the mistake interactively. The temp file is removed by __exit__()
+ on success, or when the user declines to retry."""
self._file = tempfile.NamedTemporaryFile(prefix='pysim', suffix='.json',
mode='w', delete=False)
json.dump(self._orig_json, self._file, indent=4, cls=JsonEncoder)
self._append_examples_as_comments(self._file)
self._file.close()
- self._cmd.run_editor(self._file.name)
- with open(self._file.name, 'r') as text_file:
- return json.loads(self._strip_comments(text_file.read()))
+ while True:
+ self._cmd.run_editor(self._file.name)
+ try:
+ with open(self._file.name, 'r') as f:
+ return json.loads(self._strip_comments(f.read()))
+ except json.JSONDecodeError as e:
+ self._cmd.perror(f'Invalid JSON: {e}')
+ answer = self._cmd.read_input('Re-open file for editing? [y]es/[n]o: ')
+ if answer not in ('y', 'yes'):
+ return self._orig_json
def __exit__(self, *args):
os.unlink(self._file.name)
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42554?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: I9161b7becea0d8dfd3f5f740fbb253da2f061a1d
Gerrit-Change-Number: 42554
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42553?usp=email )
Change subject: filesystem: JsonEditor: use NamedTemporaryFile
......................................................................
filesystem: JsonEditor: use NamedTemporaryFile
A plain NamedTemporaryFile is sufficient here: we only need a single
file, not a directory to hold it. Using NamedTemporaryFile is simpler
(no subdirectory to manage) and gives us a .json suffix for free,
which editors use for syntax highlighting.
Change-Id: If3b0bd0fcc90732407dbd03b9cc883f7abeb948e
---
M pySim/filesystem.py
1 file changed, 14 insertions(+), 10 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/53/42553/1
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index 626bace..d62e71a 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -30,6 +30,7 @@
import json
import abc
import inspect
+import os
import cmd2
from cmd2 import CommandSet, with_default_category
@@ -567,7 +568,7 @@
self._cmd = cmd
self._orig_json = orig_json
self._ef = ef
- self._tmpdir = None
+ self._file = None
@staticmethod
def _strip_comments(text: str) -> str:
@@ -595,18 +596,21 @@
text_file.write(f'// {line}\n')
def __enter__(self) -> object:
- """Write JSON + examples to a temp file, run the editor, return parsed result."""
- self._tmpdir = tempfile.TemporaryDirectory(prefix='pysim_')
- filename = '%s/file' % self._tmpdir.name
- with open(filename, 'w') as text_file:
- json.dump(self._orig_json, text_file, indent=4, cls=JsonEncoder)
- self._append_examples_as_comments(text_file)
- self._cmd.run_editor(filename)
- with open(filename, 'r') as text_file:
+ """Write JSON + examples to a temp file, run the editor, return parsed result.
+
+ The temp file is kept on JSONDecodeError so the user can correct and
+ re-open it manually. It is removed by __exit__() on success."""
+ self._file = tempfile.NamedTemporaryFile(prefix='pysim', suffix='.json',
+ mode='w', delete=False)
+ json.dump(self._orig_json, self._file, indent=4, cls=JsonEncoder)
+ self._append_examples_as_comments(self._file)
+ self._file.close()
+ self._cmd.run_editor(self._file.name)
+ with open(self._file.name, 'r') as text_file:
return json.loads(self._strip_comments(text_file.read()))
def __exit__(self, *args):
- self._tmpdir.cleanup()
+ os.unlink(self._file.name)
class CardEF(CardFile):
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42553?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: If3b0bd0fcc90732407dbd03b9cc883f7abeb948e
Gerrit-Change-Number: 42553
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>
fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/42552?usp=email )
Change subject: filesystem: edit_{binary,record}_decoded: add encode/decode examples
......................................................................
filesystem: edit_{binary,record}_decoded: add encode/decode examples
When invoking `edit_binary_decoded` or `edit_record_decoded`, the
temp file opened in the editor now contains the EF's encode/decode
test vectors as //-comment lines below the JSON content, similar to
how 'git commit' appends comments to the commit message template.
The comment block is stripped before JSON parsing on save,
so it has no effect on the written data.
The feature is implemented via a new module-level JsonEditor context
manager class that encapsulates the full edit cycle:
* write JSON + examples to a TemporaryDirectory
* invoke the editor
* read back, strip //-comments, parse and return the result
Change-Id: I5a046a9c7ba7e08a98cf643d5a26bc669539b38f
Related: OS#6900
---
M pySim/filesystem.py
1 file changed, 61 insertions(+), 18 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/52/42552/1
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index b5d1868..626bace 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -552,6 +552,63 @@
return lchan.selected_file.application.export(as_json, lchan)
+class JsonEditor:
+ """Context manager for editing a JSON-encoded EF value in an external editor.
+
+ Writes the current JSON value (plus encode/decode examples as //-comments)
+ to a temporary file, opens the user's editor, then reads the result back
+ (stripping comment lines) and returns it as the context variable::
+
+ with JsonEditor(self._cmd, orig_json, ef) as edited_json:
+ if edited_json != orig_json:
+ ...write back...
+ """
+ def __init__(self, cmd, orig_json, ef):
+ self._cmd = cmd
+ self._orig_json = orig_json
+ self._ef = ef
+ self._tmpdir = None
+
+ @staticmethod
+ def _strip_comments(text: str) -> str:
+ """Strip //-comment lines from text before JSON parsing."""
+ return '\n'.join(line for line in text.splitlines() if not line.lstrip().startswith('//'))
+
+ def _append_examples_as_comments(self, text_file) -> None:
+ """Append encode/decode test vectors as //-comment lines to an open file.
+ The examples are taken from _test_de_encode and _test_decode class
+ attributes (same source as the auto-generated filesystem documentation).
+ The comment block is intentionally ignored on read-back by _strip_comments."""
+ vectors = []
+ for attr in ('_test_de_encode', '_test_decode'):
+ v = getattr(type(self._ef), attr, None)
+ if v:
+ vectors.extend(v)
+ if not vectors:
+ return
+ text_file.write('\n\n// Examples (ignored on save):\n')
+ for t in vectors:
+ encoded = t[0]
+ decoded = t[2] if len(t) >= 3 else t[1]
+ text_file.write(f'// {encoded}\n')
+ for line in json.dumps(decoded, indent=4, cls=JsonEncoder).splitlines():
+ text_file.write(f'// {line}\n')
+
+ def __enter__(self) -> object:
+ """Write JSON + examples to a temp file, run the editor, return parsed result."""
+ self._tmpdir = tempfile.TemporaryDirectory(prefix='pysim_')
+ filename = '%s/file' % self._tmpdir.name
+ with open(filename, 'w') as text_file:
+ json.dump(self._orig_json, text_file, indent=4, cls=JsonEncoder)
+ self._append_examples_as_comments(text_file)
+ self._cmd.run_editor(filename)
+ with open(filename, 'r') as text_file:
+ return json.loads(self._strip_comments(text_file.read()))
+
+ def __exit__(self, *args):
+ self._tmpdir.cleanup()
+
+
class CardEF(CardFile):
"""EF (Entry File) in the smart card filesystem"""
@@ -657,15 +714,8 @@
def do_edit_binary_decoded(self, _opts):
"""Edit the JSON representation of the EF contents in an editor."""
(orig_json, _sw) = self._cmd.lchan.read_binary_dec()
- with tempfile.TemporaryDirectory(prefix='pysim_') as dirname:
- filename = '%s/file' % dirname
- # write existing data as JSON to file
- with open(filename, 'w') as text_file:
- json.dump(orig_json, text_file, indent=4, cls=JsonEncoder)
- # run a text editor
- self._cmd.run_editor(filename)
- with open(filename, 'r') as text_file:
- edited_json = json.load(text_file)
+ ef = self._cmd.lchan.selected_file
+ with JsonEditor(self._cmd, orig_json, ef) as edited_json:
if edited_json == orig_json:
self._cmd.poutput("Data not modified, skipping write")
else:
@@ -959,15 +1009,8 @@
def do_edit_record_decoded(self, opts):
"""Edit the JSON representation of one record in an editor."""
(orig_json, _sw) = self._cmd.lchan.read_record_dec(opts.RECORD_NR)
- with tempfile.TemporaryDirectory(prefix='pysim_') as dirname:
- filename = '%s/file' % dirname
- # write existing data as JSON to file
- with open(filename, 'w') as text_file:
- json.dump(orig_json, text_file, indent=4, cls=JsonEncoder)
- # run a text editor
- self._cmd.run_editor(filename)
- with open(filename, 'r') as text_file:
- edited_json = json.load(text_file)
+ ef = self._cmd.lchan.selected_file
+ with JsonEditor(self._cmd, orig_json, ef) as edited_json:
if edited_json == orig_json:
self._cmd.poutput("Data not modified, skipping write")
else:
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42552?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: I5a046a9c7ba7e08a98cf643d5a26bc669539b38f
Gerrit-Change-Number: 42552
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de>