openbadgeslib 3.0.0__tar.gz → 3.0.1__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.
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/Changelog.txt +8 -0
- {openbadgeslib-3.0.0/openbadgeslib.egg-info → openbadgeslib-3.0.1}/PKG-INFO +1 -1
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/openbadges_signer.py +13 -7
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/util.py +1 -1
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1/openbadgeslib.egg-info}/PKG-INFO +1 -1
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_cli_smoke.py +31 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/LICENSE.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/MANIFEST.in +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/README.md +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/docs/README.md +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/__init__.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/_jws/__init__.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/_jws/exceptions.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/_jws/utils.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/badge.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/baking.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/config.ini.example +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/confparser.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/errors.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/keys.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/logs.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/mail.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob1/__init__.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob1/badge.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob1/signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob1/verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob2/__init__.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob2/models.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob2/signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob2/verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/__init__.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/credential.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/did.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/status.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/ob3/verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/openbadges_init.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/openbadges_keygenerator.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/openbadges_publish.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/openbadges_verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/py.typed +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib/verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib.egg-info/SOURCES.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib.egg-info/dependency_links.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib.egg-info/entry_points.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib.egg-info/requires.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/openbadgeslib.egg-info/top_level.txt +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/pyproject.toml +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/setup.cfg +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/config1.ini +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/conftest.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/images/sample1.png +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/images/sample1.svg +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/images/userimage01.svg +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/logo Python Espan/314/203a.svg" +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/logo Python Espa/303/261a.svg" +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/runtests.sh +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_cli_json.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_confparser.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_docs.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_eddsa.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_jws.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_key_operation.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob1_badge_io.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob1_signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob1_verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob2_cli.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob2_models.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob2_signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob2_verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob3_credential.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob3_did.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob3_signer.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob3_status.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_ob3_verifier.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_sign_ecc.pem +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_sign_rsa.pem +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_util.py +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_verify_ecc.pem +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/test_verify_rsa.pem +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/withoutxmlheader.svg +0 -0
- {openbadgeslib-3.0.0 → openbadgeslib-3.0.1}/tests/withxmlheader.svg +0 -0
|
@@ -4,6 +4,14 @@ OpenBadgesLib - Changelog
|
|
|
4
4
|
Newest first. Dates are ISO 8601 (YYYY-MM-DD).
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
* v3.0.1 - 2026-07-02
|
|
8
|
+
|
|
9
|
+
- fix(cli): the OpenBadges 1.0 signer (`-V 1`) now writes the signed badge
|
|
10
|
+
before appending to the audit log, and guards the log write, so a missing
|
|
11
|
+
or unwritable `base_log` reports a clean error instead of crashing with a
|
|
12
|
+
raw OSError and losing the already-signed badge (matches the OB2 path).
|
|
13
|
+
|
|
14
|
+
|
|
7
15
|
* v3.0.0 - 2026-07-01
|
|
8
16
|
|
|
9
17
|
- BREAKING: the pre-2.0 wire format previously shipped as `-V 2` is relabelled
|
|
@@ -233,15 +233,21 @@ def _sign_ob1(args: argparse.Namespace, conf: configparser.ConfigParser, badge:
|
|
|
233
233
|
badge_signed = sf.sign_badge(badge_obj)
|
|
234
234
|
|
|
235
235
|
if badge_signed:
|
|
236
|
+
# Persist the signed badge first, then append to the audit log. Writing
|
|
237
|
+
# the log first and unguarded meant a missing/unwritable base_log raised
|
|
238
|
+
# a raw OSError out of the CLI and lost the already-signed badge; mirror
|
|
239
|
+
# the OB2 path — save, then log inside try/except.
|
|
240
|
+
badge_signed.save_to_file(badge_file_out)
|
|
241
|
+
|
|
236
242
|
sign_log = os.path.join(conf['paths']['base_log'], conf['logs']['signer'])
|
|
237
|
-
msg = '%s %s SIGNED for %s UID %s
|
|
243
|
+
msg = '%s %s SIGNED for %s UID %s' \
|
|
238
244
|
% (datetime.today().isoformat(), badge,
|
|
239
245
|
badge_signed.get_identity(), badge_signed.get_serial_num())
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
try:
|
|
247
|
+
with open(sign_log, 'a') as file:
|
|
248
|
+
file.write(msg + '\n')
|
|
249
|
+
except OSError as err:
|
|
250
|
+
print('[!] Could not write sign log: %s' % err)
|
|
245
251
|
|
|
246
252
|
if bool(args.mail_badge):
|
|
247
253
|
server = conf['smtp']['smtp_server']
|
|
@@ -266,7 +272,7 @@ def _sign_ob1(args: argparse.Namespace, conf: configparser.ConfigParser, badge:
|
|
|
266
272
|
# crashing with a traceback.
|
|
267
273
|
print('[!] Could not send mail: %s' % err)
|
|
268
274
|
|
|
269
|
-
print('%s at: %s' % (msg
|
|
275
|
+
print('%s at: %s' % (msg, badge_file_out))
|
|
270
276
|
|
|
271
277
|
|
|
272
278
|
def _sign_ob3(args: argparse.Namespace, conf: configparser.ConfigParser, badge: str,
|
|
@@ -303,6 +303,37 @@ def test_signer_ob3_then_verify_roundtrip(tmp_path, capsys):
|
|
|
303
303
|
assert 'valid' in capsys.readouterr().out.lower()
|
|
304
304
|
|
|
305
305
|
|
|
306
|
+
def test_signer_ob1_missing_log_dir_still_saves_badge(tmp_path, svg_rsa_badge, capsys):
|
|
307
|
+
"""A missing/unwritable base_log must not crash OB1 signing or lose the
|
|
308
|
+
already-signed badge: the badge is saved and a clean [!] message is printed
|
|
309
|
+
instead of a raw OSError traceback (mirrors the OB2 signer's handling)."""
|
|
310
|
+
import argparse
|
|
311
|
+
from pathlib import Path
|
|
312
|
+
from openbadgeslib import openbadges_signer
|
|
313
|
+
|
|
314
|
+
# base_log points at a directory that does not exist (its parent too).
|
|
315
|
+
conf = {
|
|
316
|
+
'paths': {'base_log': str(tmp_path / 'nonexistent' / 'log')},
|
|
317
|
+
'logs': {'signer': 'signer.log'},
|
|
318
|
+
}
|
|
319
|
+
badge_file_out = str(tmp_path / 'badge_out.svg')
|
|
320
|
+
args = argparse.Namespace(receptor='user@example.com', expires=None,
|
|
321
|
+
mail_badge=False)
|
|
322
|
+
|
|
323
|
+
# Bypass the network reachability precheck (the badge's URLs are unreachable
|
|
324
|
+
# in tests); the path under test is the save/log ordering after it.
|
|
325
|
+
with patch.object(openbadges_signer.Badge, 'urls_has_problems',
|
|
326
|
+
return_value=False):
|
|
327
|
+
openbadges_signer._sign_ob1(args, conf, 'badge_test_1', svg_rsa_badge,
|
|
328
|
+
badge_file_out, evidence=None)
|
|
329
|
+
|
|
330
|
+
out = capsys.readouterr().out
|
|
331
|
+
# The signed badge is written despite the log failure ...
|
|
332
|
+
assert Path(badge_file_out).is_file()
|
|
333
|
+
# ... and the failure is reported cleanly rather than as a traceback.
|
|
334
|
+
assert 'Could not write sign log' in out
|
|
335
|
+
|
|
336
|
+
|
|
306
337
|
# ── openbadges-publish ──────────────────────────────────────────────────────────
|
|
307
338
|
|
|
308
339
|
def test_publish_ob3_prints_info(tmp_path, capsys):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|