#498: A Tiny Episode
About the show
Sponsored by us! Support our work through:
- Our courses at Talk Python
- Consulting from Six Feet Up
Connect with the hosts
- Michael: Mastodon / BlueSky / X / LinkedIn
- Calvin: Mastodon / BlueSky / X / LinkedIn
- Show: Mastodon / BlueSky / X
Join us on YouTube at pythonbytes.fm/live to be part of the audience. Usually Tuesday at 7am PT. Older video versions available there too.
Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to our friends of the show list, we'll never share it.
Calvin #1: MemTensor / MemoryOS PyPI package hijacked via a malicious build backend
- On Sept 23 an attacker published backdoored MemoryOS 2.0.34 on PyPI and three bad versions (0.1.21, 0.1.23, 0.1.25) of MemTensor's OpenClaw plugin on npm. PyPI had no clean release that day, so 2.0.34 was the newest.
- They pushed commits to MemTensor's own GitHub Actions release pipelines. On PyPI that was a custom Poetry build backend, and on npm a tweaked validation script. Both used BASH_ENV to hand the publish token to the attacker before the real publish ran. SafeDep couldn't confirm how the attacker got push access.
- Runs on import, not install: A Go implant called sckit starts when the library loads, so --ignore-scripts won't save you.
- It harvests credentials from your home directory (npm and PyPI tokens, GitHub tokens, SSH keys, cloud CLI tokens, .env files) and sends them to skyleen[.]fr servers.
- It's a worm: It uses stolen tokens to copy itself into other repos and packages, so the victim list could grow.
- If you installed it: Downgrade to MemoryOS 2.0.33 (plugin 0.1.20) and rotate every credential reachable from $HOME. Also kill any running sckit stage0 process and check repos you can push to for a stray runtime-update.yml workflow or .sckit/ directory.
Michael #2: TinyMongo
- Want to use a MongoDB data interface, but swap out the storage engine?
- Memory for testing/caching
- JSON/TinyDB simple JSON files
- SQLite for durable, high-perf reads with WAL
- SQLIte shared for high write apps
- DuckDB + Parquet for analytics apps
- Postgres + MariaDB for multi-machine client/server
- Great for teaching, examples, and simple deployments
- Amazing story of paired AI development
- Will completely run talkpython.fm after weeks of shared work together (in SQLite mode).
Calvin #3: Jev: what to know
- What it is: Jev is a model from TypeSafe AI that answers with typed results (yes/no probabilities, scores, picks from your options) instead of prose. Real Python published a hands-on tutorial on 2026-09-24 and the buzz on hacker news is almost deafening.
- It's proprietary: Jev is a hosted, closed-weight model. There are no weights to download and no self-hosting. Everything called "open Jev" is an independent reimplementation, not TypeSafe's model.
- Your data leaves your machine: Every call sends your input text to a third-party API. In the tutorial that path goes through OpenRouter to TypeSafe. Think twice before sending customer messages, tickets or anything sensitive.
- Cost and stability are open questions: The tutorial calls Jev "cheap, but not free" and says it's fast and cheap "at the moment." It also says whether that stays true is "something to keep an eye on."
- Credit to Real Python: It's a good, practical intro. It shows the Noul, Score and Choice primitives, and its point that instruction wording matters more than thresholds is useful advice for any model. The tutorial itself says similar results are possible with a well-prompted LLM.
- Open options to look at instead:
- JevK5 (https://github.com/allebee/jevk5): Apache-2.0 weights and code, 4B or 9B parameters, and it accepts TypeSafe-style requests.
- SemIf, formerly OpenJev (https://github.com/TheoLeeCJ/openjev): MIT-licensed, small models, and it can run CPU-only.
- openjev-sglang (https://github.com/ekzhang/openjev-sglang): a Jev-compatible endpoint running Qwen3.6-35B-A3B, but no license is stated, so check before commercial use.
- The catch: These copy Jev's interface, not its model or training. Results will differ, and I haven't run any of them. Benchmarks are self-reported, and JevK5 is English-only.
Michael #4: One innocent dict read makes attribute access permanently slower
Timofei Ivankov benchmarks a CPython internals surprise: since 3.11, attribute access skips the instance dict entirely. A specialized opcode reads the attri.bute at a fixed byte offset in the object's inline values array. Read obj.__dict__ once, though, and the dict gets materialized, the object loses that specialized path for the rest of its life, and a million-iteration loop goes from 33 ms to 51 ms on CPython 3.14. vars() and copy.copy() trigger the same thing, so a debugging print or a shallow copy in code touching your hot objects quietly makes every later attribute access roughly 1.5x slower.
- The slowdown is permanent and nothing about it looks like a performance decision: ordinary code far from the hot loop can trigger it, and the function that gets slower never changes.
- Materializing dict produces a split table, and the LOAD_ATTR_WITH_HINT fallback declines split tables, so the object ends up with no specialization at all
- vars(), 'x' in o.dict, and copy.copy() all materialize it; copy.copy is the realistic trap since nobody treats a shallow copy as a performance decision
- slots instances read attributes at exactly the same speed and cannot fall into the trap since there is no dict to materialize
- On the free-threaded build both effects grow: atomic incref on reads plus an object lock on writes push the penalty from 17.6 to 25.4 ns
- Credit: this item was surfaced by the PyCoder's Weekly newsletter
Extras
Calvin:
- whatsnewt - a TUI text adventure through what's new in Python 3.15; playful but niche.
Joke: Shipping a button in 2026…
Episode Transcript
Collapse transcript
00:00
00:05
00:10
00:13
00:14
00:15
00:18
00:21
00:23
00:26
00:31
00:34
00:36
00:37
00:43
00:44
00:45
00:46
00:47
00:49
00:52
00:53
00:54
01:01
01:02
01:03
01:04
01:10
01:15
01:18
01:25
01:29
01:34
01:38
01:43
01:53
02:02
02:10
02:16
02:18
02:23
02:27
02:30
02:35
02:40
02:43
02:47
02:51
02:54
02:58
03:00
03:04
03:08
03:14
03:18
03:26
03:30
03:33
03:39
03:45
03:52
03:56
04:02
04:04
04:04
04:08
04:11
04:13
04:16
04:20
04:23
04:26
04:30
04:33
04:36
04:37
04:38
04:43
04:46
04:48
04:50
04:53
04:55
04:55
04:59
05:03
05:06
05:10
05:12
05:15
05:19
05:22
05:25
05:29
05:32
05:33
05:34
05:38
05:39
05:39
05:43
05:45
05:48
05:50
05:52
05:54
05:55
05:56
05:57
05:59
06:00
06:03
06:06
06:08
06:12
06:16
06:19
06:21
06:28
06:29
06:33
06:34
06:39
06:40
06:41
06:44
06:47
06:49
06:53
07:00
07:04
07:07
07:12
07:15
07:19
07:20
07:24
07:27
07:29
07:36
07:41
07:45
07:49
07:53
07:56
07:57
08:01
08:07
08:09
08:15
08:18
08:19
08:21
08:23
08:24
08:26
08:28
08:30
08:32
08:33
08:38
08:38
08:40
08:43
08:48
08:49
08:53
08:55
08:57
08:58
09:03
09:05
09:07
09:08
09:09
09:13
09:14
09:18
09:20
09:22
09:25
09:27
09:28
09:28
09:30
09:30
09:32
09:33
09:36
09:41
09:43
09:46
09:49
09:50
09:51
09:53
09:59
10:03
10:06
10:07
10:08
10:09
10:09
10:11
10:15
10:17
10:17
10:18
10:21
10:23
10:24
10:28
10:30
10:33
10:36
10:41
10:47
10:49
10:55
11:00
11:02
11:03
11:08
11:10
11:10
11:11
11:15
11:16
11:22
11:23
11:28
11:31
11:33
11:35
11:38
11:40
11:43
11:47
11:52
11:56
11:57
11:58
12:04
12:06
12:08
12:10
12:12
12:13
12:14
12:15
12:18
12:20
12:22
12:24
12:26
12:27
12:29
12:31
12:34
12:37
12:40
12:42
12:43
12:48
12:51
12:55
12:59
13:01
13:02
13:07
13:11
13:17
13:19
13:23
13:24
13:26
13:28
13:30
13:35
13:37
13:40
13:41
13:44
13:49
13:54
13:56
13:59
14:01
14:02
14:04
14:07
14:09
14:09
14:10
14:12
14:13
14:16
14:18
14:19
14:28
14:29
14:35
14:38
14:42
14:43
14:47
14:50
14:55
14:59
15:03
15:05
15:09
15:11
15:16
15:19
15:23
15:29
15:33
15:39
15:40
15:43
15:48
15:49
15:52
15:54
15:57
15:58
16:00
16:04
16:07
16:09
16:11
16:18
16:21
16:24
16:28
16:29
16:33
16:38
16:40
16:46
16:48
16:51
16:54
16:59
17:01
17:05
17:07
17:08
17:12
17:12
17:17
17:20
17:23
17:28
17:30
17:30
17:34
17:35
17:37
17:39
17:43
17:44
17:47
17:49
17:52
17:58
18:00
18:04
18:09
18:15
18:18
18:20
18:22
18:26
18:31
18:35
18:38
18:40
18:43
18:48
18:53
18:56
18:59
19:06
19:07
19:11
19:13
19:17
19:22
19:24
19:31
19:33
19:35
19:36
19:38
19:39
19:41
19:44
19:49
19:56
19:59
20:01
20:01
20:14
20:16
20:18
20:18
20:21
20:22
20:24
20:28
20:30
20:31
20:35
20:41
20:43
20:45
20:47
20:50
20:53
20:54
21:02
21:08
21:12
21:17
21:22
21:26
21:30
21:32
21:35
21:36
21:40
21:46
21:47
21:48
21:49
21:51
21:54
21:57
21:59
22:02
22:05
22:06
22:09
22:10
22:12
22:14
22:17
22:20
22:24
22:28
22:32
22:33
22:34
22:37
22:38
22:43
22:46
22:47
22:49
22:49
22:50
22:53
23:00
23:03
23:10
23:15
23:19
23:19
23:23
23:26
23:29
23:31
23:34
23:36
23:43
23:44
23:46
23:49
23:50
23:51
23:54
23:59
24:03
24:04
24:06
24:09
24:13
24:19
24:23
24:26
24:28
24:34
24:37
24:37
24:38
24:42
24:45
24:49
24:55
24:59
25:04
25:08
25:11
25:20
25:22
25:24
25:30
25:35
25:42
25:48
25:50
25:55
26:04
26:07
26:08
26:10
26:14
26:15
26:20
26:25
26:26
26:30
26:34
26:41
26:45
26:48
26:50
26:52
26:53
26:55
26:57
27:00
27:03
27:04
27:08
27:10
27:13
27:14
27:21
27:24
27:27
27:31
27:36
27:41
27:44
27:48
27:48
27:52
27:54
27:57
28:00
28:03
28:04
28:07
28:09
28:11
28:13
28:17
28:20
28:23
28:28
28:33
28:38
28:47
28:51
28:55
28:57
29:03
29:09
29:10
29:12
29:15
29:18
29:21
29:22
29:25
29:26
29:28
29:33
29:35
29:37
29:40
29:41
29:42
29:43
29:45
29:46
29:47
29:48
29:49
29:49
29:50
29:51
29:51
29:52
29:53
29:53
29:54
30:00
30:02
30:04
30:09
30:14
30:16
30:17
30:19
30:23
30:26
30:27
30:28
30:28
30:29
30:30
30:31
30:31
30:33
30:34
30:35
30:36
30:37
30:40
30:42
30:47
30:47
30:51
30:51
30:52
30:54
30:57
30:57
30:58
30:59
31:05
31:07
31:09
31:10
31:11
31:12
31:14
31:17
31:23
31:24
31:30
31:33
31:39
31:42
31:46
31:49
31:53
31:57
32:00
32:02
32:06
32:11
32:18
32:26
32:33
32:38
32:46
32:51
32:57
33:02
33:02
33:08
33:10
33:11
33:14
33:15
33:16


