)]}'
{
  "log": [
    {
      "commit": "4925937223eb285618ac2e91494f75e7425fba60",
      "tree": "75b42afbfbefac0a5ccfd916a9a0eae2d0bfe3a7",
      "parents": [
        "a7c1158c184162386bf96ac076888b9ee72e51a7"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 18:55:19 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 18:55:19 2026"
      },
      "message": "changelog_bot.py: run rstwrap directly to avoid security holes\n"
    },
    {
      "commit": "a7c1158c184162386bf96ac076888b9ee72e51a7",
      "tree": "e11de7ecccaf4fa68df2a75879c527565202564e",
      "parents": [
        "b408cfc0a05266a0509ccbb13e253f2d2000ed9f"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 18:43:22 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 18:43:22 2026"
      },
      "message": "Bump the github-actions group with 4 updates (#2870)"
    },
    {
      "commit": "b408cfc0a05266a0509ccbb13e253f2d2000ed9f",
      "tree": "1e6eda9853f5d6928fa4162b24ba51fa567867b9",
      "parents": [
        "f6a92029a437f5d579d5a4a081c08c7bda691049"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 17:46:19 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 17:46:19 2026"
      },
      "message": "Handle RLIM_INFINITY on Python 3.15 on linux (#2871)\n\n`Process.rlimit` returns `RLIM_INFINITY` as unsigned `2**64-1` instead\nof `-1` on Python 3.15+, which changed `resource.prlimit()` accordingly.\npsutil now maps it back to `psutil.RLIM_INFINITY` so the value stays\nconsistent across Python versions."
    },
    {
      "commit": "f6a92029a437f5d579d5a4a081c08c7bda691049",
      "tree": "804bfa3d2cf3ac7e1ebc5ef7ae70482cbb2693be",
      "parents": [
        "c8569cac9ba31e529d5d942f90b1a239843cfe67"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 17:21:42 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 17:21:42 2026"
      },
      "message": "print_dist.py: check expected wheel files\n"
    },
    {
      "commit": "c8569cac9ba31e529d5d942f90b1a239843cfe67",
      "tree": "27aaefa76c31e4f490cd9e2fd7e5f36d6c208c71",
      "parents": [
        "0e80da2a7e92280000391e49101eff9727309eaf"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 16:36:30 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 16:36:30 2026"
      },
      "message": "Add dependabot.yml\n"
    },
    {
      "commit": "0e80da2a7e92280000391e49101eff9727309eaf",
      "tree": "1094bd20e9afdae3811624351a40ee8a35254702",
      "parents": [
        "e26876b05f7531f58493e97cc2e7799a926c89ce",
        "423d3b93a464e2d7b36759c3d290e376133491ef"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:25 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:25 2026"
      },
      "message": "Merge branch \u0027triage-bot\u0027\n"
    },
    {
      "commit": "e26876b05f7531f58493e97cc2e7799a926c89ce",
      "tree": "910f7fdcd806b96299a0675a32c1868f36d769a8",
      "parents": [
        "7811a4727f88e7cc9ee705a515958dc9af3a1c96",
        "4763689caf49d475380ac3135be8d8ecc1a6b1ff"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:20 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:20 2026"
      },
      "message": "Merge branch \u0027master\u0027 of github.com:giampaolo/psutil\n"
    },
    {
      "commit": "423d3b93a464e2d7b36759c3d290e376133491ef",
      "tree": "696083eee9f504b1e75d31220a4b2c0738443bec",
      "parents": [
        "7811a4727f88e7cc9ee705a515958dc9af3a1c96"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:09 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 15:50:09 2026"
      },
      "message": "triage_bot.py: comment on PR on changelog changes + add labels from files\n"
    },
    {
      "commit": "4763689caf49d475380ac3135be8d8ecc1a6b1ff",
      "tree": "c15d724a9fae75650dbc8f60d068fce2763457e2",
      "parents": [
        "614e5f03867186692622f1ded7b51492cb52442f"
      ],
      "author": {
        "name": "Marcel Telka",
        "email": "marcel@telka.sk",
        "time": "Fri Jul 17 12:39:16 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 12:39:16 2026"
      },
      "message": "[illumos] skip test_cpu_times_comparison() test on SunOS (#2688)"
    },
    {
      "commit": "7811a4727f88e7cc9ee705a515958dc9af3a1c96",
      "tree": "21c0747285597574a7c39266c4360618cd18d1ab",
      "parents": [
        "614e5f03867186692622f1ded7b51492cb52442f"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 12:38:36 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 12:38:36 2026"
      },
      "message": "Update credits / changelog\n"
    },
    {
      "commit": "614e5f03867186692622f1ded7b51492cb52442f",
      "tree": "b58bdf00499261b6468941148187a543783573fa",
      "parents": [
        "6962fc0a7a9eef055554fb48e224d4105386a784"
      ],
      "author": {
        "name": "Marcel Telka",
        "email": "marcel@telka.sk",
        "time": "Fri Jul 17 12:36:43 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 12:36:43 2026"
      },
      "message": "[illumos] Update users() implementation for SunOS (#2687)"
    },
    {
      "commit": "6962fc0a7a9eef055554fb48e224d4105386a784",
      "tree": "ee30d440f76353c573aa600226cd9e394d575fb7",
      "parents": [
        "8d8ffe516627c024ccd216485b5920e8ffa8a88e"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 12:34:58 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 12:34:58 2026"
      },
      "message": "Update changelog\n"
    },
    {
      "commit": "8d8ffe516627c024ccd216485b5920e8ffa8a88e",
      "tree": "82ca591fbd0abcfcfe87392674c9fa1b8aafe5a2",
      "parents": [
        "afaaf9f340ff6561541f9f4781c58268b59abdac"
      ],
      "author": {
        "name": "Hanson Wang",
        "email": "hansonw@users.noreply.github.com",
        "time": "Fri Jul 17 11:19:50 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 11:19:50 2026"
      },
      "message": "[Linux] virtual_memory() fails when /proc/meminfo contains ShadowCallStack \u003e\u003d 10GB (#2810)\n\nCo-authored-by: Hanson Wang \u003chanson@openai.com\u003e\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e"
    },
    {
      "commit": "afaaf9f340ff6561541f9f4781c58268b59abdac",
      "tree": "109ffe0ed6c42451626f1713dd07c624e7457182",
      "parents": [
        "8ced0689903f007fd694214834c01236b39a2d28"
      ],
      "author": {
        "name": "Data-hYg",
        "email": "Heyenga.t@gmail.com",
        "time": "Fri Jul 17 11:09:07 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 11:09:07 2026"
      },
      "message": "Address AIX build error (#2789)\n\nAddress error: \u0027perfstat_netinterface_t\u0027 has no member named \u0027if_iqdrop\u0027\n\n## Summary\n\n- OS: AIX\n- Bug fix: yes\n- Type:  core\n\n\n## Description\nSeems like during C-Code reformatting #2667 an accidental space was\nadded to one of the Py_BuildValue\n\n---------\n\nCo-authored-by: Data-hYg"
    },
    {
      "commit": "8ced0689903f007fd694214834c01236b39a2d28",
      "tree": "8513b60aeabd38aea33f1d2593b00912cce77d3a",
      "parents": [
        "6e616180f9ccbcf9462a4e7fb276a5a2c633143d"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 10:58:31 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 10:58:31 2026"
      },
      "message": "Revert last commit: github doesn\u0027t allow us to push on user branch/PR\n"
    },
    {
      "commit": "6e616180f9ccbcf9462a4e7fb276a5a2c633143d",
      "tree": "530ca7ccd80bd4c296b2a2e52c0b88f202fa8e1c",
      "parents": [
        "15baa349334a65c1bda6b74afb903a783e9d5ab8"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 10:44:12 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 10:44:12 2026"
      },
      "message": "Changelog bot: update PR branch to master before adding the entry\n\nGitHub\u0027s web merge ignores .gitattributes merge\u003dunion, so relying on\nit to auto-resolve changelog/credits conflicts doesn\u0027t work. Instead,\non /changelog the bot now drops the PR\u0027s changes to changelog.rst and\ncredits.rst, merges current master into the branch, then adds the\nentry on top. The entry applies cleanly against master, so the PR\nstays mergeable via the button. A code conflict during the merge\naborts with a message asking to resolve it manually.\n\nAlso drop the now-unused .gitattributes.\n"
    },
    {
      "commit": "15baa349334a65c1bda6b74afb903a783e9d5ab8",
      "tree": "43febb661363c2c4d4125d91793291745b05b9bb",
      "parents": [
        "73a2bfb9152b20a85b4ea51d71b5d139c174aa02"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 09:40:51 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 09:40:51 2026"
      },
      "message": "docs/changelog.rst and docs/credits.rst are bot-owned.\n\nReset them to The PR\u0027s fork point (merge-base with\nmaster) before inserting the entry, so it renders\nas a clean one-line diff instead of master\u0027s\naccumulated churn, and any stale/bloated state\nfrom earlier runs gets wiped. Needs full history\n(fetch-depth: 0) to compute the merge-base.\n"
    },
    {
      "commit": "73a2bfb9152b20a85b4ea51d71b5d139c174aa02",
      "tree": "d19ad5ff2746196ba7d26e910b9c95a82ab4f591",
      "parents": [
        "1ae01d1210f73b411d38c0b7dc365727ae07608d"
      ],
      "author": {
        "name": "Ehtesham Siddiqui",
        "email": "91150060+EhteshamSid@users.noreply.github.com",
        "time": "Fri Jul 17 08:56:16 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 08:56:16 2026"
      },
      "message": "Fix #2793: process_iter() skips zombie processes (#2818)\n\nFixes #2793.\n\n`ZombieProcess` is a subclass of `NoSuchProcess`, so the `except\nNoSuchProcess` clause in the inner loop of `process_iter()` was catching\nit and calling `remove(pid)` - same as if the process had disappeared.\nThat meant zombies were silently dropped from the iteration instead of\nbeing yielded.\n\nThe fix adds an explicit `except ZombieProcess` handler before `except\nNoSuchProcess` and yields the process. The `if proc is not None` guard\ncovers the case where `ZombieProcess` is raised during `add(pid)` before\n`proc` is assigned (shouldn\u0027t happen in practice since\n`Process.__init__` catches it internally, but worth being safe about).\n\nAdded `test_emulate_zombie` alongside the existing `test_emulate_nsp` /\n`test_emulate_access_denied` tests which do the same kind of mock-based\ncheck.\n\n---------\n\nCo-authored-by: EhteshamSid \u003cgh-patchbot@example.com\u003e\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e\nCo-authored-by: github-actions[bot] \u003cgithub-actions[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "1ae01d1210f73b411d38c0b7dc365727ae07608d",
      "tree": "22b77393c7fb4a77eae9a019ec6bfbda9becd8fd",
      "parents": [
        "ef5bc21474d42dca602c9810881539b11a0390a8"
      ],
      "author": {
        "name": "Sebastian Cao",
        "email": "cycsmail@gmail.com",
        "time": "Fri Jul 17 08:52:41 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 08:52:41 2026"
      },
      "message": "Fix cpu_freq() taking offline CPU cores into account on Linux (#2850)\n\n## Summary\n\n- OS: Linux\n- Bug fix: yes\n- Type: core\n- Fixes: #2628\n\n## Description\n\nWhen a CPU core is offline its `online` sysfs file reads `0` and it has\nno frequency file. We were appending `scpufreq(0.0, 0.0, 0.0)` for it,\nwhich left a bogus all-zero entry in `cpu_freq(percpu\u003dTrue)` and dragged\ndown the averaged `current`/`min`/`max` returned by `cpu_freq()`. Now\noffline cores are skipped entirely, so they no longer appear in the\npercpu list nor skew the aggregate.\n\nAdded a regression test (`TestCpuFreq.test_emulate_offline_cpus`) that\nmocks 4 policies with cores 2-3 offline and checks both the percpu\nresult and the aggregate; it fails before this change (returns 4\nentries, average halved, min 0) and passes after. The cpu_freq tests\npass (`tests/test_linux.py::TestCpuFreq` and\n`tests/test_system.py::TestCpuAPIs::test_cpu_freq`) and `ruff check` on\nthe touched files is clean."
    },
    {
      "commit": "ef5bc21474d42dca602c9810881539b11a0390a8",
      "tree": "58080062fa0a1c525aa4996cf49d77e0e3ed1034",
      "parents": [
        "68ed0142fff38f25b9f3ac5c5133d5a7a1e40cda"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:17:20 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:17:20 2026"
      },
      "message": "Changelog bot: rely on .gitattributes\n"
    },
    {
      "commit": "68ed0142fff38f25b9f3ac5c5133d5a7a1e40cda",
      "tree": "f465b0aba4e0aa83a966094e81d9fd41f5b751e8",
      "parents": [
        "82e76065d2af1630414d5088eca2718032458f89",
        "3215d7e5f00dfd0bde186be2b7ac658c2dc1afa4"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:08:17 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:08:17 2026"
      },
      "message": "Merge branch \u0027master\u0027 of github.com:giampaolo/psutil\n"
    },
    {
      "commit": "82e76065d2af1630414d5088eca2718032458f89",
      "tree": "2ddf80722c0a052666f1dc91f61973c8a424d345",
      "parents": [
        "71c43475e99537237db461102f2101ab09a80f50"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:08:10 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 08:08:10 2026"
      },
      "message": "Changelog bot: rebase files to avoid conflicts\n"
    },
    {
      "commit": "3215d7e5f00dfd0bde186be2b7ac658c2dc1afa4",
      "tree": "493995f95aaf7680f3baa994f0a1fe0d3ead4130",
      "parents": [
        "a8c3d764c20675ab9e2741860763df9ffbae9c17"
      ],
      "author": {
        "name": "Bert Pluymers",
        "email": "44161457+bertpl@users.noreply.github.com",
        "time": "Fri Jul 17 07:35:44 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 07:35:44 2026"
      },
      "message": "[macOS] fix cpu_freq on Apple M4 and M5-family chips (#2824)\n\n## Summary\n\n- OS: macOS\n- Bug fix: yes\n- Type: core\n- Fixes: #2642\n\n## Description\n\n### Context\n\nOn Apple Silicon, macOS exposes no public API for CPU frequency.\n`psutil` therefore reads the DVFS (dynamic voltage and frequency\nscaling) tables that the power manager (`pmgr` entry of\n`AppleARMIODevice`) publishes in the IORegistry: properties named\n`voltage-states\u003cN\u003e-sram`, containing `(frequency, voltage)` pairs as raw\nlittle-endian integers.\n\nThese tables are undocumented by Apple, and they don\u0027t only describe CPU\ncores — the same key family also covers GPU, NPU and fabric clusters.\nUntil now, `psutil` relied on two conventions that happened to hold from\nM1 through M3:\n\n* the CPU tables live at **fixed indexes**: `voltage-states5-sram` (P\ncores) and `voltage-states1-sram` (E cores);\n* frequencies are encoded in **Hz**, so a hardcoded division by 10⁶\nyields MHz.\n\n### Bug\n\nOn M4 and later chips, both conventions were broken by (undocumented)\nhardware/firmware changes:\n\n* **M4 and above** — frequencies are now encoded in **kHz** instead of\nHz, so the hardcoded ÷10⁶ produces values ~1000× too small (`cpu_freq()`\nreporting e.g. `4.5 MHz` instead of `4512 MHz`). This is #2642.\n* **M5 and above** — the `voltage-states\u003cN\u003e-sram` index space was\n**renumbered**, so the hardcoded indexes 5 and 1 no longer point at CPU\nclusters at all.\n\nThe hard part of fixing this is *not* finding the updated indexes and\ndivision factors for M4/M5 — it is finding a mechanism that doesn\u0027t need\nre-fixing on every future M-series release. A lookup table keyed on chip\ngeneration would break again, silently or loudly, each time Apple\nreshuffles the registry.\n\n### Adjacent ecosystem fixes\n\nOther open-source tools read the exact same IORegistry properties and\nwere hit by the same two changes. How they fixed it:\n\n| Tool | M4 unit fix (Hz → kHz) | M5 index renumbering | Approach |\n|---|---|---|---|\n| [fastfetch](https://github.com/fastfetch-cli/fastfetch)\n([#1394](https://github.com/fastfetch-cli/fastfetch/discussions/1394),\nNov 2024) | Per-value magnitude heuristic: `\u003e 10⁸ ⇒ Hz, else kHz` | ❌\nnot handled — still hardcodes `voltage-states5-sram` | Partial: dynamic\nunit, fixed index |\n| [macmon](https://github.com/vladkens/macmon)\n([#11](https://github.com/vladkens/macmon/issues/11) → v0.4.0, Dec 2024;\nv0.7.0, Jun 2025) | Keyed on chip-name substring (`M1/M2/M3 ⇒ Hz, else\nkHz`) | Fallback to Apple\u0027s `acc-clusters` property when the hardcoded\nkeys are missing | Hardcoded primary path + structural fallback |\n| [stats](https://github.com/exelban/stats)\n([#2285](https://github.com/exelban/stats/issues/2285) → v2.11.24, Jan\n2025; v2.11.67 for M5) | Per-generation handling | Handled in a separate\nM5-specific fix | Per-generation conditionals |\n| [macpow](https://github.com/k06a/macpow) | Per-table magnitude\nheuristic | Full dynamic enumeration — no hardcoded indexes at all |\nEnumerate \u0026 classify (fmax threshold) |\n| **this PR** | Per-value magnitude heuristic | Full dynamic enumeration\n— no hardcoded indexes | Enumerate \u0026 classify, simplified: no E/P/S\nlabeling needed since `psutil` exposes only overall min/max |\n\nTwo observations from this survey:\n\n1. The tools that kept hardcoded indexes (fastfetch) or per-generation\nconditionals (stats, macmon\u0027s primary path) each needed a *second* fix\nwhen M5 arrived — confirming that generation-keyed logic is a recurring\nmaintenance burden.\n2. macmon\u0027s `acc-clusters` fallback is not trustworthy as a general\nmechanism: on a physical M3 Max we found `acc-clusters` mislabels\n`voltage-states5-sram` as E-core and omits the real E-core table\nentirely (macmon never hits this in practice only because its hardcoded\nprimary path succeeds on M3).\n\nThe most future-proof design in the ecosystem is macpow\u0027s: **enumerate\nall tables, classify by content, hardcode nothing**. That is the\napproach this PR adopts.\n\n### Solution proposed in this PR\n\n`psutil_cpu_freq()` now discovers the CPU tables dynamically instead of\nassuming indexes or units:\n\n1. **Enumerate** all properties on the `pmgr` entry matching\n`voltage-states\u003cN\u003e-sram` (digit-only `\u003cN\u003e`). No hardcoded indexes —\nrenumbering (M5) is handled automatically.\n2. **Decode** each table as little-endian `uint32` `(frequency,\nvoltage)` pairs.\n3. **Detect the unit per value, by magnitude**: raw value \u003e 10⁸ ⇒ Hz\n(÷10⁶); else ⇒ kHz (÷10³). A real CPU frequency can\u0027t be below 100\nMHz-as-Hz or above 100 GHz-as-kHz, so the two encodings are unambiguous.\nThis handles M1–M3 (Hz) and M4+ (kHz) with no generation table.\n4. **Filter implausible values**: keep only 500–20000 MHz, dropping\nterminator zeros and junk entries.\n5. **Classify CPU vs. non-CPU tables**: a table qualifies as a CPU\ncluster only if its maximum frequency is **≥ 2000 MHz**. This is what\nfilters out the GPU/NPU/fabric DVFS tables, which share the `-sram`\nsuffix.\n6. Report `min` \u003d lowest qualifying frequency, `max` \u003d highest;\n`current` \u003d `max` (Apple Silicon exposes no live-frequency API, matching\nprevious behavior).\n\nSince `psutil` only exposes an overall min/max (not per-cluster values),\nno E/P/S/GPU *labeling* is needed — only the CPU/non-CPU split, which\nmakes the 2000 MHz threshold the single load-bearing heuristic.\n\nNote the classification exists primarily to keep `min` correct: `max`\nalone would need no filter, since the fastest table is always a CPU\ncluster — but without it, the low rungs of GPU/NPU ladders (e.g. 648 MHz\non M3 Max, above the 500 MHz plausibility floor yet below the real CPU\nminimum of 1020) would leak into the reported minimum.\n\n**Why not the obvious alternatives?**\n\n- *Keep the hardcoded indexes and just update them for M4/M5?* Breaks\nagain at the next renumbering — M5 already proved this happens, and\nfastfetch (which kept hardcoded index 5) remains exposed to exactly this\non M5-family chips.\n- *Dispatch on chip generation (via `machdep.cpu.brand_string`)?* An\nearlier draft of this PR did exactly that. It works, but (a) it couples\ncorrectness to a lookup table that needs updating on every Apple\nrelease, and (b) it forces users on unknown future chips onto a fallback\npath. The magnitude of the raw values already tells us the unit — no\ngeneration awareness needed.\n- *Use Apple\u0027s `acc-clusters` property (macmon\u0027s M5+ fallback)?*\nEmpirically untrustworthy — see observation 2 above (mislabels and omits\nCPU clusters on M3 Max).\n\n**Why 2000 MHz is a safe threshold.** Every non-CPU DVFS ladder we could\nfind data for peaks well below 2 GHz — GPUs are usually the closest\n(ANE/fabric are comparable or lower; on M1 Max the ANE ladder peaks at\n1500 MHz, slightly above its GPU\u0027s 1296). So the threshold only needs to\nseparate the slowest CPU cluster ever shipped from the fastest GPU:\n\n*CPU cluster frequency ranges per generation (MHz):*\n\n| Chip family | E-core max | P-core max | S-core max |\n|---|---|---|---|\n| M1 (all variants) | 2064 | 3228 | — |\n| M2 (all variants) | 2424 | 3696 | — |\n| M3 (all variants) | 2748 | 4056 | — |\n| M4 (all variants) | 2892 | 4512 | — |\n| M5 (all variants) | 3048 | 4380 | 4608 |\n\n*(M5 introduced a third CPU cluster type: \"Super\" (S) cores, clocked\nabove the P-cores. For the threshold discussion only the slowest and\nfastest CPU clusters matter, so S-cores fold in transparently.)*\n\n*Non-CPU DVFS tables observed on a physical M3 Max (all `-sram`\nsuffixed, i.e. all would be misclassified by a suffix-only filter):*\n\n| Table | fmax (MHz) | Component |\n|---|---|---|\n| `voltage-states1-sram` | 2568 | CPU (E cluster) |\n| `voltage-states5-sram` | 4056 | CPU (P cluster) |\n| `voltage-states13-sram` | 4056 | CPU (P cluster, duplicate on Max) |\n| `voltage-states9-sram` | 1380 | GPU |\n| `voltage-states14/15/16-sram` | 1380 | GPU/NPU/fabric |\n\nThe slowest CPU cluster ever shipped (M1 E-cores) peaks at **2064 MHz**;\nmeasured GPU fmax is 1278/1398/1380/1578 MHz on M1/M2/M3/M4 (Refs 7–8),\nwith base-M5 measurements around 1578–1620 MHz (GPU clocks have\nhistorically been shared across base/Pro/Max variants within a\ngeneration) — so the 2000 MHz threshold sits between CPU and non-CPU on\nevery generation to date. (The long-term evolution of this gap, and a\npossible relative-threshold variant, are discussed in a comment below.)\n\n### Implementation notes\n\nAll changes live in `psutil_cpu_freq()` in `psutil/arch/osx/cpu.c`\n(single code path, no generation detection, no `sysctl` lookups, no\n`acc-clusters` dependency):\n\n- Properties are enumerated via `IORegistryEntryCreateCFProperties()` on\nthe `pmgr` entry; a key qualifies only if it matches\n`voltage-states\u003cN\u003e-sram` with digit-only `\u003cN\u003e` (defensive against future\nnon-numeric key variants).\n- Each qualifying `CFData` blob is walked in 8-byte strides: 4-byte\nlittle-endian frequency + 4-byte voltage; only the frequency is read.\n- The named constants encoding the heuristics described above:\n- `UNIT_THRESHOLD \u003d 1e8` — raw value above ⇒ Hz (÷10⁶), below ⇒ kHz\n(÷10³); see step 3 above for why the encodings can\u0027t collide.\n- `MIN_PLAUSIBLE_MHZ \u003d 500` / `MAX_PLAUSIBLE_MHZ \u003d 20000` — per-value\nfilter dropping terminator zeros and junk entries.\n- `CPU_CLUSTER_MIN_FMAX_MHZ \u003d 2000` — per-table CPU-vs-GPU/NPU\nclassification.\n- Min/max are first accumulated **per table**, and a table\u0027s values are\nfolded into the overall result only if the table qualifies as a CPU\ncluster — so a GPU table\u0027s low frequencies can never leak into the\nreported minimum.\n- Duplicate CPU tables (Max/Ultra chips replicate P-cluster tables, e.g.\n`voltage-states5-sram` and `voltage-states13-sram` on M3 Max) are\nharmless: they contribute the same min/max already represented, so no\ndeduplication is needed.\n- If the `pmgr` entry is missing (e.g. on virtualized ARM64 such as CI\nrunners) or no table qualifies, the function returns `None` (with a\n`psutil_debug` message), which `cpu_freq()` surfaces as an empty list —\nfollowing the contract introduced in #2382 / #2868.\n- `current` is reported as `max`, unchanged from the previous\nimplementation (Apple Silicon exposes no live-frequency API). The\nforward-risk trade-off of the 2 GHz threshold is documented in a comment\nblock above the function, so a future maintainer hits the reasoning\nbefore the code.\n\n### Tests\n\nNo new test is included. An earlier revision added a plausibility-bounds\ntest, but it was removed during review: the C code already clamps every\nvalue to the same [500 MHz, 20 GHz] range, making the assertions\ntautological, and CI runs on virtualized ARM64 where `cpu_freq()`\nreturns no data and the test would skip anyway. Verification is by\ndirect measurement on physical hardware (below).\n\n### Validated on physical hardware\n\n| Machine | Result | Cross-check |\n|---|---|---|\n| Apple M3 Max (macOS 15) — Hz path | `scpufreq(current\u003d4056, min\u003d1020,\nmax\u003d4056)` | matches published M3 P-core peak of 4056 MHz ✓ |\n| Apple M4 Pro — kHz path | `scpufreq(current\u003d4512, min\u003d1020, max\u003d4512)`\n| matches published M4 P-core peak of 4512 MHz ✓ — the hardware class\nwhere #2642 was filed |\n\nAlso validated on a base M3 (Hz path). Values on all three machines\nmatch Apple\u0027s published specs and Eclectic Light\u0027s crowdsourced DVFS\ntables (Ref 5).\n\n### References\n\n1. fastfetch Discussion #1394 — primary external confirmation of the Hz\n→ kHz unit change on M4 (maintainer diagnosis: *\"Apple changed the unit\nreported by IO service. Your M4 Pro reports kHz while my M1 Pro reports\nHz\"*), including a raw ioreg dump that only decodes plausibly as kHz:\nhttps://github.com/fastfetch-cli/fastfetch/discussions/1394\n2. macmon Issue #11 (M4 unit bug) and v0.7.0 release notes (M5 Max\nrenumbered-keys crash fix):\nhttps://github.com/vladkens/macmon/issues/11,\nhttps://github.com/vladkens/macmon/releases\n3. stats Issue #2285 — the same M4 bug independently hit and fixed in a\nthird tool (v2.11.24): https://github.com/exelban/stats/issues/2285\n4. k06a/macpow — reference implementation of the dynamic-enumeration\npattern adopted here:\nhttps://github.com/k06a/macpow/blob/main/src/ioreport.rs\n5. Eclectic Light — crowdsourced per-chip DVFS min/max tables for all\nApple Silicon Macs (ground truth used for validation):\nhttps://eclecticlight.co/2026/04/13/cpu-core-frequencies-updated-for-all-current-apple-silicon-macs/\n6. Wikipedia — Apple M1/M4/M5 (chip release dates, peak frequencies,\nvariant line-up): https://en.wikipedia.org/wiki/Apple_M1,\nhttps://en.wikipedia.org/wiki/Apple_M4,\nhttps://en.wikipedia.org/wiki/Apple_M5\n7. Eclectic Light — \"Power modes and Apple silicon GPUs\" (measured GPU\nfmax: M3 Pro 1380 MHz, M4 Pro 1578 MHz):\nhttps://eclecticlight.co/2025/01/06/power-modes-and-apple-silicon-gpus/\n— and ASi-Mac-DVFS (per-chip DVFS ladder dumps incl. GPU/ANE, e.g. M1\nMax GPU 1296 / ANE 1500 MHz):\nhttps://github.com/GaoKaipeng2023/ASi-Mac-DVFS\n8. \"Apple vs. Oranges: Evaluating the Apple Silicon M-Series SoCs for\nHPC Performance and Efficiency\" (Table I: GPU clocks M1 1.27 / M2 1.39 /\nM3 1.38 / M4 1.47 GHz): https://arxiv.org/html/2502.05317v1\n\n---\n\n*AI assistance was used for reference research, prose drafting, and to\ncross-check the fix; all code and technical decisions reviewed by me.*"
    },
    {
      "commit": "a8c3d764c20675ab9e2741860763df9ffbae9c17",
      "tree": "bcb0cbc8692b3221e6728e7c01f112b0a7b9bf94",
      "parents": [
        "71c43475e99537237db461102f2101ab09a80f50"
      ],
      "author": {
        "name": "Ding Qiuran",
        "email": "133388209+dynapx@users.noreply.github.com",
        "time": "Fri Jul 17 07:21:50 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 07:21:50 2026"
      },
      "message": "Fix unchecked PyLong_FromLong in CPU affinity and missing exception i… (#2860)\n\n## Description\nHi there! 👋\n\nDuring a robustness audit of Python C-API contracts using a static\nanalysis tool, we identified two edge-case issues in the psutil C\nextension that could lead to interpreter crashes or SystemError under\nspecific conditions. This PR addresses both to ensure graceful exception\npropagation and strict adherence to CPython’s error‑handling contract.\n___\n## 1. Potential NULL pointer dereference in psutil_proc_cpu_affinity_get\n(proc.c)\n### Issue:\nIn psutil_proc_cpu_affinity_get, the loop that builds the CPU affinity\nlist directly embeds PyLong_FromLong(cpu) as an argument to\npylist_append_obj:\n\n```c\nif (!pylist_append_obj(py_list, PyLong_FromLong(cpu)))\n    goto error;\n```\nPyLong_FromLong can return NULL on allocation failure (e.g.,\nout-of-memory condition). Because the return value is never checked, a\nNULL is passed straight into pylist_append_obj → PyList_Append →\nPy_INCREF(obj), which dereferences the null pointer and **immediately\nterminates the Python interpreter with SIGSEGV.**\nThe crash happens before any Python-level except MemoryError can be\ntriggered, making the failure unrecoverable.\n\n### Why this matters (System Monitoring Robustness):\npsutil is a foundational library for system health monitoring and\nresource management. The Process.cpu_affinity() API is frequently called\nby automation, container orchestration, and CI/CD pipelines. If a system\nis already under extreme memory pressure, a crash in psutil would hide\nthe original MemoryError, destroy the process state, and potentially\ncascade into service outages or data loss. A graceful MemoryError\npropagation instead allows upper layers to react appropriately (e.g.,\nshedding load, restarting gracefully).\n\n### Fix:\nBreak the chained call to explicitly check the result of PyLong_FromLong\nand handle the reference safely:\n\n```c\nPyObject *py_cpu \u003d PyLong_FromLong(cpu);\nif (py_cpu \u003d\u003d NULL)\n    goto error;\nif (!pylist_append_obj(py_list, py_cpu)) {\n    Py_DECREF(py_cpu);\n    goto error;\n}\nPy_DECREF(py_cpu);\n```\nThis ensures the interpreter stays alive and a proper MemoryError is\nraised.\n\n___\n## 2. Missing exception set in defensive NULL check (posix/init.c)\n### Issue:\nIn psutil_posix_add_constants, a defensive guard checks whether the\nmodule object is NULL:\n```c\nif (!mod)\n    return -1;\n```\nWhile this branch is currently unreachable (all callers validate mod\nbeforehand), it returns an error indicator (-1) **without setting a\nPython exception.** According to the Python C API specification, any\nfunction that returns a negative value must have previously called an\nexception-setting function. If this path were ever reached (due to\nfuture refactoring or a logic bug), the interpreter would encounter an\n“error return without exception set” and raise a cryptic SystemError,\nmasking the actual problem and breaking proper exception handling.\n\n### Why this matters (API contract compliance):\nDefensive code is meant to make the system safer, but when it violates\nthe error‑handling contract it creates a latent trap. Static analysis\ntools and new developers rely on these contracts to reason about\ncorrectness. Fixing this pattern now prevents a confusing runtime error\nif the code ever evolves.\nAdd PyErr_BadInternalCall() before the return:\n\n```c\nif (!mod) {\n    PyErr_BadInternalCall();\n    return -1;\n}\n```\nNow the function correctly signals a fatal internal error if the\nunthinkable happens, preserving the expected error‑handling flow.\n___\nBoth changes are minimal, do not alter normal behavior, and bring the\ncodebase closer to full compliance with Python C-API best practices.\nThank you for considering this robustness improvement!\n\n---------\n\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e\nCo-authored-by: github-actions[bot] \u003cgithub-actions[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "71c43475e99537237db461102f2101ab09a80f50",
      "tree": "93ba419e30f4d789ef531a49bf0fed62b62dda8a",
      "parents": [
        "e1ed3fadd67833ebc67e83d58bc4b0fdb869103b"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 07:20:04 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Jul 17 07:20:04 2026"
      },
      "message": "Fix changelog bot error on commit\n"
    },
    {
      "commit": "e1ed3fadd67833ebc67e83d58bc4b0fdb869103b",
      "tree": "7620c733222e1ee7a3acadaea37c1cfcb8e98d6a",
      "parents": [
        "8a759af9d536571adbd095e1b94ac2c044624bd0"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 23:40:03 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 23:40:03 2026"
      },
      "message": "[macOS] `cpu_freq()`: return None instead of raising (#2868)\n\n## Summary\n\n- OS: macOS\n- Bug fix: yes\n- Type: core\n- Fixes: #2382\n\n## Description\n\n`cpu_freq()` on a virtualized or AARCH64 macOS can fail with\nRuntimeError. Since on Linux we already return `None` in case\n`cpu_freq()` is not available for any reason, we do the same on macOS,\nas opposed to NOT exposing the function."
    },
    {
      "commit": "8a759af9d536571adbd095e1b94ac2c044624bd0",
      "tree": "a3efca3b46c3898bbc8023c7e444e3979c99aae4",
      "parents": [
        "827e4143ed7388420cf1edbc1e9fa0b99a9058db",
        "29e570458b5afc160ed66fdc878b494e1c53327d"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 22:49:20 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 22:49:20 2026"
      },
      "message": "Merge from master\n"
    },
    {
      "commit": "827e4143ed7388420cf1edbc1e9fa0b99a9058db",
      "tree": "b8c36aef68a62b959661def71600ae03341c386f",
      "parents": [
        "4f6658b00aa65e76b9b3756730477c8d24971734"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 22:48:45 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 22:48:45 2026"
      },
      "message": "Changelog bot: run rst-fix + sort entries\n"
    },
    {
      "commit": "29e570458b5afc160ed66fdc878b494e1c53327d",
      "tree": "00f662ef37410942b25c2195ffc4eb172ac8f913",
      "parents": [
        "4a27e3b45946b74702b54c9d3ac86f8188db68b0"
      ],
      "author": {
        "name": "Kataoka Katsuki",
        "email": "49934462+kataokatsuki@users.noreply.github.com",
        "time": "Thu Jul 16 22:32:48 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 22:32:48 2026"
      },
      "message": "macOS: fix SystemError in cpu_freq() (#2862)\n\n## Summary\n\n- OS: macOS\n- Bug fix: yes\n- Type: core\n- Fixes: N/A (related to #2841)\n\n## Description\n\nRelated issue: #2841. This only fixes the `SystemError` error path;\nactually\nreturning frequencies on the affected chips is covered by the pending\nrewrite in #2824, so this PR does not close the issue.\n\nIn `psutil_cpu_freq()` (`psutil/arch/osx/cpu.c`), when either\n`voltage-states*-sram` property is missing, has the wrong Core\nFoundation\ntype, or is too short (which is what happens on M5-family chips, see\n#2824), the function sets `RuntimeError: invalid CPU frequency data` but\nthen falls through to the `Py_BuildValue()` at the end of `cleanup`,\nreturning a result with an exception set:\n\n```text\nSystemError: \u003cbuilt-in function cpu_freq\u003e returned a result with an exception set\n```\n\nSame bug class as #2854. I checked the other `error:` / `cleanup:`\nlabels\nunder `psutil/arch/osx/` and this is the only remaining spot.\n\nFix: initialize `py_ret` to `NULL`, assign it only on success, and\nreturn\nit after the releases in `cleanup`.\n\nNo M5 hardware here, so I forced the error branch by temporarily\nchanging\none property name in `cpu.c` to a non-existent key on an M1-family Mac:\nunpatched, this reproduces the exact `SystemError` from the report;\npatched, the same forced failure raises the intended `RuntimeError`. The\nnormal path returns the same values as unmodified master.\n\nVerified with:\n\n- `make build PYTHON\u003d.venv/bin/python`\n- `make test PYTHON\u003d.venv/bin/python ARGS\u003d\u0027tests/test_system.py -k\ncpu_freq\u0027`\n\nCo-authored-by: kataokatsuki \u003ckataokatsuki@users.noreply.github.com\u003e\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e"
    },
    {
      "commit": "4a27e3b45946b74702b54c9d3ac86f8188db68b0",
      "tree": "1f3e58c5d98711592b91cfb946d978295130eafa",
      "parents": [
        "4f6658b00aa65e76b9b3756730477c8d24971734"
      ],
      "author": {
        "name": "E Shattow",
        "email": "eshattow@users.noreply.github.com",
        "time": "Thu Jul 16 22:22:46 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 22:22:46 2026"
      },
      "message": "Bump version cibuildwheel v3.4.1 (#2832)"
    },
    {
      "commit": "4f6658b00aa65e76b9b3756730477c8d24971734",
      "tree": "d4ab6a3e5ec800fd97f2d5e931c1e712b855c733",
      "parents": [
        "781d8321944c22bbe15aae84fc7df4b9893d9d17"
      ],
      "author": {
        "name": "Karl Hill",
        "email": "karlhillx@gmail.com",
        "time": "Thu Jul 16 22:11:54 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 22:11:54 2026"
      },
      "message": "Fix refcount leaks on parse failure (Linux disk_partitions, SunOS proc_environ) (#2857)\n\nI went through the 28 alloc-before-parse call sites in the C source. Two\nleak, the\nother 26 already goto-error correctly.\n\n- psutil/arch/linux/disk.c::psutil_disk_partitions\n`py_retlist` allocated before `PyArg_ParseTuple` — leak on parse-fail\nbranch.\n  Move parse above allocation.\n\n- psutil/arch/sunos/proc.c::psutil_proc_environ\n`py_retdict` allocated before `PyArg_ParseTuple` — same leak. Same fix.\n\nWhile in the sunos function: line 215 checks `!py_envname` after\nassigning\n`py_envval`. The check is wrong (and is always false at that point), so\na NULL\n`py_envval` from `PyUnicode_DecodeFSDefault` slips through to\n`PyDict_SetItem`\nwith a NULL value. Fix to `if (!py_envval)`.\n\nTests:\n- tests/test_linux.py: tracemalloc snapshot around\n`cext.disk_partitions`\ncalled with a non-string arg, looking for allocation drift over 100\ncalls.\n- tests/test_sunos.py: same shape, sunos-only gated.\n\n---------\n\nAuthored by: Karl Hill\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e"
    },
    {
      "commit": "781d8321944c22bbe15aae84fc7df4b9893d9d17",
      "tree": "2d1599394e51c60be14e15ceac35cc8574ff90ba",
      "parents": [
        "b7022dfb29c34db74d7973b1e5cbcf5d55d83601"
      ],
      "author": {
        "name": "Alex Chen",
        "email": "l46983284@gmail.com",
        "time": "Thu Jul 16 20:33:21 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 20:33:21 2026"
      },
      "message": "Windows: avoid invalid Py_DECREF(NULL) in net_connections error path (#2867)\n\n## Summary\n\n- OS: Windows\n- Bug fix: yes\n- Type: core\n- Fixes: #2859\n\n## Description\n\n`psutil_net_connections()` initializes `py_retlist` to `NULL` and only\nallocates it after argument parsing. On `PyArg_ParseTuple` failure the\nshared `error:` label used `Py_DECREF(py_retlist)`, which is not\nNULL-safe and can crash on ordinary bad input.\n\nThis PR switches that cleanup to `Py_XDECREF(py_retlist)` and makes\n`psutil_conn_decref_objs()` use `Py_XDECREF` for the temporary\nAF_*/SOCK_* objects as well, matching the existing NULL-safe pattern in\n`proc_handles.c`.\n\n## Test plan\n\n- Static review on Linux: confirmed `py_retlist` starts NULL, error path\nnow uses `Py_XDECREF`, macro uses `Py_XDECREF`, no remaining\n`Py_DECREF(py_retlist)`.\n- Windows C extension not buildable on this Linux host; no runtime\nWindows canary here.\n\nSigned-off-by: Alex Chen \u003cl46983284@gmail.com\u003e\nCo-authored-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e"
    },
    {
      "commit": "b7022dfb29c34db74d7973b1e5cbcf5d55d83601",
      "tree": "ec6ec603ddfdf27b6c764c6de87030232fc54eef",
      "parents": [
        "ade78e5df4cbf1c88130a6b440bd545020b0c943"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 20:29:37 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 20:29:37 2026"
      },
      "message": "credits.rst: remove legacy users refs\n"
    },
    {
      "commit": "ade78e5df4cbf1c88130a6b440bd545020b0c943",
      "tree": "65478108144a3b8367369de0d876ea4d5d64c8ba",
      "parents": [
        "d46726028ac01e27e052ec60371951e789d2b101"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Jul 16 15:33:11 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 15:33:11 2026"
      },
      "message": "Full rewrite of the /changelog script + tests (#2866)"
    },
    {
      "commit": "d46726028ac01e27e052ec60371951e789d2b101",
      "tree": "7afc5ba0e7c7e7d8029130a93bea9f14dd6736d9",
      "parents": [
        "5ec16ad4d887c069f6b758fd0659fb6bc9b47f7d"
      ],
      "author": {
        "name": "Gabriel Changamire",
        "email": "254220776+gabrielchangamire-arch@users.noreply.github.com",
        "time": "Thu Jul 16 12:09:14 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 12:09:14 2026"
      },
      "message": "Linux: fix swap_memory() ValueError when a /proc/meminfo field has no space after the colon (#2865)\n\n## Summary\n\n- OS: Linux\n- Bug fix: yes\n- Type: core\n- Fixes: (part of #2809, complements #2810 — see below)\n\n## Description\n\n`swap_memory()` parses `/proc/meminfo` with the same two lines as\n`virtual_memory()`:\n\n```py\nfields \u003d line.split()\nmems[fields[0]] \u003d int(fields[1]) * 1024\n```\n\n...so it crashes with the same `ValueError` described in #2809 when the\nkernel emits a field with no space after the colon\n(`ShadowCallStack:10373888 kB`, due to the fixed-width `%8lu` format in\n`fs/proc/meminfo.c`, once the value reaches 8 digits / ~10 GB on arm64).\n\n#2810 fixes `virtual_memory()` but not `swap_memory()`; this PR applies\nthe\nsame colon-splitting fix to `swap_memory()`, so together they fully\nresolve\n#2809. Reproduced on arm64 (python:3.12 container):\n\n```\ntests/test_linux.py::TestSwapMemory::test_no_space_after_colon FAILED\npsutil/_pslinux.py:379: in swap_memory\n    mems[fields[0]] \u003d int(fields[1]) * 1024\nE   ValueError: invalid literal for int() with base 10: b\u0027kB\u0027\n```\n\nIncludes a regression test (`TestSwapMemory::test_no_space_after_colon`)\nmirroring the one in #2810, plus changelog/credits entries."
    },
    {
      "commit": "5ec16ad4d887c069f6b758fd0659fb6bc9b47f7d",
      "tree": "aa12bd2f8cdb1df89a493bc176d2f49cf509e49b",
      "parents": [
        "f38de3225c1b04676b32bb3cfed9acd171adc4ec"
      ],
      "author": {
        "name": "max",
        "email": "87073104+maxtaran2010@users.noreply.github.com",
        "time": "Fri Jul 10 06:29:38 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 10 06:29:38 2026"
      },
      "message": "Fix typos in comments (#2861)"
    },
    {
      "commit": "f38de3225c1b04676b32bb3cfed9acd171adc4ec",
      "tree": "1f45380590d8dda2c4d14c99baf784575c9ddc47",
      "parents": [
        "da599756a5fe06fec3693ad66df2cc4d1eeaa83d"
      ],
      "author": {
        "name": "Dominick",
        "email": "123526624+HoraDomu@users.noreply.github.com",
        "time": "Mon Jul 06 10:09:23 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 10:09:23 2026"
      },
      "message": "SunOS: proper error check for PyUnicode_DecodeFSDefault"
    },
    {
      "commit": "da599756a5fe06fec3693ad66df2cc4d1eeaa83d",
      "tree": "b16d91a417d533fd1d038e7ed64c895ea22f63da",
      "parents": [
        "7b6a9a63d829682342c0bffdefbd7455ba343989"
      ],
      "author": {
        "name": "Kataoka Katsuki",
        "email": "49934462+kataokatsuki@users.noreply.github.com",
        "time": "Mon Jul 06 10:08:03 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 10:08:03 2026"
      },
      "message": "macOS: fix SystemError in Process.cmdline() and environ() (#2854)\n\n## Summary\n\n- OS: macOS\n- Bug fix: yes\n- Type: core\n- Fixes: N/A (related to #2708)\n\n## Description\n\nRelated issue: #2708. There is no separate public ticket for the\nresulting\n`SystemError` — it was observed locally while running Glances 4.5.5 with\npsutil\n7.2.2 on macOS (Nix / Python 3.13).\n\nThe 7.2.2 fix for #2708 made `psutil_sysctl_procargs()` set\n`AccessDenied`\nwhen `sysctl(KERN_PROCARGS2)` fails with `errno \u003d\u003d 0`, but that branch\nreturns\n`0`. `0` means success for this helper, so `Process.cmdline()` and\n`Process.environ()` continue and return a Python object while an\nexception is\nalready set, which CPython reports as:\n\n```text\nSystemError: \u003cbuilt-in function proc_cmdline\u003e returned a result with an exception set\n```\n\nReturn `-1` from that branch, matching the existing `EINVAL` and `EIO`\n`AccessDenied` branches.\n\nThis also avoids parsing the malloc\u0027d procargs buffer after the failed\n`sysctl()` call.\n\nVerified with:\n\n- `make build PYTHON\u003d.venv/bin/python`\n- `make test PYTHON\u003d.venv/bin/python\nARGS\u003d\u0027tests/test_process.py::TestProcess::test_cmdline\ntests/test_process.py::TestProcess::test_long_cmdline\ntests/test_process.py::TestProcess::test_environ\ntests/test_process.py::TestProcess::test_weird_environ\ntests/test_process.py::TestProcess::test_as_dict\ntests/test_unicode.py::TestFSAPIs::test_proc_cmdline\ntests/test_unicode.py::TestNonFSAPIS::test_proc_environ\u0027`\n\nCo-authored-by: kataokatsuki \u003ckataokatsuki@users.noreply.github.com\u003e"
    },
    {
      "commit": "7b6a9a63d829682342c0bffdefbd7455ba343989",
      "tree": "8c72084d1fa6fb41bef1c8aff013b86ace43495b",
      "parents": [
        "ac2cc069480fa9f78491dfe6194c33ed4a91966e"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Jun 15 18:46:49 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 15 18:46:49 2026"
      },
      "message": "Doc: lots of various improvements (no CDN for fonts + improve About This Site) (#2845)\n\nPerformance\n\n- Self-host all web fonts (Inter, JetBrains Mono, Merriweather) instead\nof using external CDN (Google). This is good to render the same doc from\nmainland China.\n- Ship a smaller portion of Font Awesome icons, so page is less heave\n(around 300K in total).\n\nUX\n\n- \"Flash\" every time we click on a link that teleports us to a\nheading/anchor, so that it\u0027s immediately clear where we\u0027re at.\n\nAbout page\n\n- Extend it and also include images showing how to use different site\u0027s\nfeatures. Also explain how to use `intersphinx` to link to psutil doc.\n\nFooter\n\n- Add GitHub + PyPI + RSS icons\n\nFixes\n\n- Eliminate \"flashing\" when scrolling very fast\n- Accessibility fixes (axe/ally), OpenGraph/SEO tweaks, print.css."
    },
    {
      "commit": "ac2cc069480fa9f78491dfe6194c33ed4a91966e",
      "tree": "cf3d7483a7fc194a0fa2f6d802de4e46bf0cabef",
      "parents": [
        "3cd668d13e0ad9b2c63f205641ef68dbb64ebcef"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Jun 14 22:56:35 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 22:56:35 2026"
      },
      "message": "Remove docs/ from tarball (#2844)\n\nThe docs/ dir became quite big, and it includes lots of .js, .css and\nnow also binary files (fonts, icons).\nIn general, a tarball is supposed to be pip-installable. Docs is not\nsupposed to stay in the tarball, so let\u0027s just remove it.\n\nTarball before: 586K\nTarball now: 396K"
    },
    {
      "commit": "3cd668d13e0ad9b2c63f205641ef68dbb64ebcef",
      "tree": "7ddc66541107c850fb6546ab5a6b7325c8bbd927",
      "parents": [
        "127840daad0b474065ed42583f8db4f80ecfa033"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Jun 14 13:42:35 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 14 13:42:35 2026"
      },
      "message": "psutil-sphinx-theme: get rid of RTD theme (#2843)\n\nGet rid of RTD theme and build on top of Sphinx \"basic\" theme. This is\nmuch cleaner and allows us to get rid of tons of `!important` directives\nin CSS."
    },
    {
      "commit": "127840daad0b474065ed42583f8db4f80ecfa033",
      "tree": "eb55bad9c8bdffa64756401291b354780c44dc42",
      "parents": [
        "1a2569db0b2ad7489539ad6b6b6b85cb13b755f7"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun May 31 15:17:27 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun May 31 15:17:27 2026"
      },
      "message": "Fix RCE in changelog_bot workflow\n\nThe changelog-bot workflow checked out the PR head and executed\n.github/workflows/changelog_bot.py straight from that untrusted\ncheckout. Although only a trusted commenter can trigger the job, the\nexecuted code came from the PR branch, so an attacker could open a\nbenign PR, wait for the /changelog comment, and swap in a malicious\nchangelog_bot.py via a TOCTOU race on the mutable PR head. The result\nwas arbitrary code execution on the runner with access to GITHUB_TOKEN\nand ANTHROPIC_API_KEY.\n\nRun the trusted changelog_bot.py from master (extracted via git show)\ninstead of the PR\u0027s copy, so untrusted code is never executed. Also\npin the checkout to the PR head SHA resolved in the Get PR info step,\nsince github.event.pull_request is null on issue_comment events.\n\nReported via Depi, validated by Garance de la Brosse (Lupin \u0026 Holmes).\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n"
    },
    {
      "commit": "1a2569db0b2ad7489539ad6b6b6b85cb13b755f7",
      "tree": "f3dbeb0e42f449deaa82438c89622be182d843c5",
      "parents": [
        "ed9afa132a124283b78a1d5bf8f221022b5e21b8"
      ],
      "author": {
        "name": "Tobias Klauser",
        "email": "tklauser@distanz.ch",
        "time": "Thu May 21 13:01:49 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu May 21 13:01:49 2026"
      },
      "message": "Fix broadcast address being discarded in `net_if_addrs` on Windows (#2836)\n\nPatch by Tobias Klauser. "
    },
    {
      "commit": "ed9afa132a124283b78a1d5bf8f221022b5e21b8",
      "tree": "6d38bf19c8a048a19973e1197b12ebc22ddf37a5",
      "parents": [
        "5d2762a9005c3a231d95028e6a4298a4ab90f1d1"
      ],
      "author": {
        "name": "Tobias Klauser",
        "email": "tobias.klauser@gmail.com",
        "time": "Wed May 20 22:32:55 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed May 20 22:32:55 2026"
      },
      "message": "Credit correct user (#2835)"
    },
    {
      "commit": "5d2762a9005c3a231d95028e6a4298a4ab90f1d1",
      "tree": "569d6749ea342596836c1e85f48d9f2422b98b97",
      "parents": [
        "cba7802e9935e6252f6c8264f96217ec80fd973a"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 12:07:09 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 12:07:09 2026"
      },
      "message": "CSS style + remove hyphen from HTML title\n"
    },
    {
      "commit": "cba7802e9935e6252f6c8264f96217ec80fd973a",
      "tree": "452565eab787e19a740631e00150f9208566f9f4",
      "parents": [
        "95ae5378ad1c60d040bf2f0fcb32f1d9e298c2f6",
        "79b5e67787fdbe58a5eecef7551309a61d48de01"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:38:37 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:38:37 2026"
      },
      "message": "Merge branch \u0027master\u0027 of github.com:giampaolo/psutil\n"
    },
    {
      "commit": "95ae5378ad1c60d040bf2f0fcb32f1d9e298c2f6",
      "tree": "452565eab787e19a740631e00150f9208566f9f4",
      "parents": [
        "81b45fd0fe37f2c3f084aa25e367b9079a342143"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:38:26 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:38:26 2026"
      },
      "message": "Add sphinx_design dep\n\nSigned-off-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e\n"
    },
    {
      "commit": "79b5e67787fdbe58a5eecef7551309a61d48de01",
      "tree": "d2c62b32531661240041210e8283bf83f2ede5f7",
      "parents": [
        "81b45fd0fe37f2c3f084aa25e367b9079a342143"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:30:05 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 08 00:30:05 2026"
      },
      "message": "Doc: improve home (install tip, dynamic examples)\n"
    },
    {
      "commit": "81b45fd0fe37f2c3f084aa25e367b9079a342143",
      "tree": "ead444f533ce279e6f11fddfb214ae8a81d4c905",
      "parents": [
        "cff769002524b2fa3aba8bcfb19737f2d5531135"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu May 07 21:50:40 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu May 07 21:50:40 2026"
      },
      "message": "Doc: improve home (install tip, dynamic examples)\n"
    },
    {
      "commit": "cff769002524b2fa3aba8bcfb19737f2d5531135",
      "tree": "9db41679ea9994e971c137459264fcff4494f8a3",
      "parents": [
        "e165f87c6f56a82110a3d4cde6320fce6367a6c7"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed May 06 22:21:06 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed May 06 22:21:06 2026"
      },
      "message": "Doc: dynamical refresh of adoption stats + fix site for mobile\n"
    },
    {
      "commit": "e165f87c6f56a82110a3d4cde6320fce6367a6c7",
      "tree": "d24420880cdc38cc93ce4b2203a5863a229e652f",
      "parents": [
        "2bfa3b4cafd592fff8b04f70ea19fc9572f17cd6"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue May 05 22:41:48 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue May 05 22:41:48 2026"
      },
      "message": "Doc: cross-reference roles + assorted polish\n\nThe bulk: replace one-off named-link targets and explicit hyperlinks\nwith reusable extlinks. New roles: :user:, :commit:, :pypi:, :bpo:,\n:cpy:, :cpy-pr:, :src:. Plus a custom :proc: role for /proc/\u003cfile\u003e\npaths. :manpage: wired to manpages.debian.org.\nChangelog backfilled with clickable contributor attributions.\n\nOther:\n- .readthedocs.yaml: fail_on_warning matches local Makefile flag.\n- Footer \"Updated:\" date links to the file\u0027s GitHub commit history.\n- _ext/proc_role.py: new local extension.\n- changelog_bot.py: emits :user:`Name \u003chandle\u003e` for new entries.\n- _globals.rst removed; rst_prolog inlined in conf.py.\n- code blocks: disable JetBrains Mono programming ligatures.\n- wide-table: opt out of global fixed-column layout (no more\n  monospace cells overflowing into the next column).\n- rst_unused_targets.py: scan repo-wide for \"used\" refs even when\n  called with a subset (fixes pre-commit false positives).\n- install.rst: add uv add psutil alongside pip install psutil.\n- layout.html: GoatCounter analytics alongside GA4.\n"
    },
    {
      "commit": "2bfa3b4cafd592fff8b04f70ea19fc9572f17cd6",
      "tree": "3173a3f77b4d4e9e450555af68fda7770d7110fc",
      "parents": [
        "cff1b1c5d21fa200222242d66d5d473cb3494dba"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat May 02 00:12:16 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat May 02 00:12:16 2026"
      },
      "message": "Doc: custom 404 page + easter egg (#2829)\n\nDoc now provides a custom 404 page. In the footer, hovering over the ©\ncopyright reveals an easter egg. Clicking it takes you to the 404 page\ncontaining a joke."
    },
    {
      "commit": "cff1b1c5d21fa200222242d66d5d473cb3494dba",
      "tree": "797f004841a6c923fc21808011cb05f60c162f55",
      "parents": [
        "d53c708117d561311e97ad294474bbf971d07c3d"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 23:59:17 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 23:59:17 2026"
      },
      "message": "Blog \u0026 site cleanups\n\n* Blog OpenGraph: classify posts as og:type\u003d\"article\", use post\n  summary (not first paragraph) for og:description, drop the\n  shared site-wide image (custom Sphinx ext under\n  docs/_ext/opengraph_override.py).\n* Blog feed: force UTC in atom feed; use canonical URLs.\n* Blog tag pages: show the tag in different color.\n* Blog index: render an h1.\n* Layout: hide RTD version and language selectors.\n* Tests: extend docs tests (regression coverage for blog index\n  metadata, OG, tags).\n"
    },
    {
      "commit": "d53c708117d561311e97ad294474bbf971d07c3d",
      "tree": "d108fbd60fc9d24e1e5427ed4a112e1d41e3c74c",
      "parents": [
        "36c677a95890ca4ecbd614c83f6ab851b58a85e5",
        "571ee2854df9b97fdae79313e04c7708780526d1"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 17:42:21 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 17:42:21 2026"
      },
      "message": "Merge branch \u0027github-stars\u0027\n"
    },
    {
      "commit": "571ee2854df9b97fdae79313e04c7708780526d1",
      "tree": "d108fbd60fc9d24e1e5427ed4a112e1d41e3c74c",
      "parents": [
        "368cc61eec39e3ce3ed59f6357a4e4ce7a0b3acd"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 17:42:09 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 17:42:09 2026"
      },
      "message": "Add github stars + versions in the topbar\n"
    },
    {
      "commit": "36c677a95890ca4ecbd614c83f6ab851b58a85e5",
      "tree": "3c4e8dba2cfa713079729c321da4bebcae2852e7",
      "parents": [
        "368cc61eec39e3ce3ed59f6357a4e4ce7a0b3acd"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 16:53:03 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri May 01 16:53:03 2026"
      },
      "message": "CSS / style refact + change font + align JS TOC aligned with pydata-theme\n"
    },
    {
      "commit": "368cc61eec39e3ce3ed59f6357a4e4ce7a0b3acd",
      "tree": "d341dd02de8cb997cef4e68b9ee41a71a9b65101",
      "parents": [
        "3d9dbbc42ea41ad434a597ddd560be9659252414"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 28 15:17:31 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Apr 28 15:17:31 2026"
      },
      "message": "Doc: TOC navigation bar (#2828)\n\nShow a TOC navigation right sidebar, which automatically follows the\nscrolling via JS. This is especially useful for /api.html view, which is\nsuper long. Heavily inspired by pydata-sphinx-data theme."
    },
    {
      "commit": "3d9dbbc42ea41ad434a597ddd560be9659252414",
      "tree": "f9b7daae9fd66891a2648e3e32dbc1bd6c2f2aae",
      "parents": [
        "c987b0c9f5584ddf9d8c3e5bfa34a3276c405bd8"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 24 17:59:32 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 24 17:59:32 2026"
      },
      "message": "Fix some broken URLs\n"
    },
    {
      "commit": "c987b0c9f5584ddf9d8c3e5bfa34a3276c405bd8",
      "tree": "120233079286fae50c4aeb23aa3c2a71a46a635e",
      "parents": [
        "66f43c6c9d44ef6aa0cbcd51e9a7e3e26a396ee9"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 24 17:44:22 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 24 17:44:22 2026"
      },
      "message": "CSS: split sections into code.css and home.css\n"
    },
    {
      "commit": "66f43c6c9d44ef6aa0cbcd51e9a7e3e26a396ee9",
      "tree": "f094174664dbe00f49828eaacb8d89fe0d342477",
      "parents": [
        "0482ac774460a1bde61f32449b98b65a2b59cb4a"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 23 23:09:35 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 23 23:09:35 2026"
      },
      "message": "Sphinx code autolink (#2826)\n\nDoc: make code sample clickable (brings to API ref)\n\nAdds check-codeautolink sphinx extension:\nhttps://sphinx-codeautolink.readthedocs.io/en/latest/\n\nIdentifiers in code blocks (e.g. ``p \u003d psutil.Process()``,\n``p.cpu_percent()``) are now clickable. Hover over one of those to see\nthe highlight, then click to jump to the corresponding API reference\ndoc."
    },
    {
      "commit": "0482ac774460a1bde61f32449b98b65a2b59cb4a",
      "tree": "aac77c0eb7620ab87a0fc3c8c32d5b8c49fd0554",
      "parents": [
        "38fc10b1d414b06b599adbf21243de283c79a2f1"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 23 19:30:03 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 23 19:30:03 2026"
      },
      "message": "Bump RTD python version to 3.12 so we can use sphinx 9.1\n"
    },
    {
      "commit": "38fc10b1d414b06b599adbf21243de283c79a2f1",
      "tree": "a36e20a7394eaddb8d40ec7b821c1dd33ed9d843",
      "parents": [
        "a9bc87ab8501c50b96f7e32add69fad20323992f"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 23 19:27:31 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 23 19:27:31 2026"
      },
      "message": "Add blog (#2825)\n\nAdd a new blog to the doc/site, built on top of `ablog`, with 20 posts imported \nfrom https://gmpy.dev, covering psutil topics from 2014 to 2026.\n\nWith this, blog posts become part of the official doc, fully integrated\nin the site, meaning they are **searchable**, which is the real value\nhere. Hopefully this will encourage me to post more frequently and write\nhigher-quality posts.\n\nBlog is accessible via a `Blog` link in the top bar.\n\nAlso:\n\n- Add `sphinxext-opengraph` extension: every post emits `og:*` HTML\n  tags, meaning URLs shared on social medias (X, Reddit, etc) will show rich\n  previews (logo + title) instead of a raw URL. This applies to all site pages, not\n  only blog posts.\n\n- Use `sphinx-sitemap` extensions: reachable at `/sitemap.xml`, it\n  should help search engine discovery.\n\n- Atom feed is at `/blog/atom.xml`, auto-discovered from every page (not\n  only blog pages).\n\n- Add new `make test-docs` target and `docs/test_docs.py`, which runs\n  sanity checks against the built HTML docs. \n\n## List page\n\nCustomize `ablog` template to show tags, years, title, summary and a\n\"featured\" icon, to mark the best posts (the \"must read\"). Also show a\nRSS icon on top and in the footer.\n\n## Post page\n\nCustomize `ablog` template, to show pretty much the same things + a \"X\nminutes read\" info:\n\n## Selected tag page\n\nCustomize `ablog` template, to highlight the clicked tag + show all\ntags:\n\n## Search results page\n\nMake the search results page show an icon for blog posts, so they are\nidentifiable:"
    },
    {
      "commit": "a9bc87ab8501c50b96f7e32add69fad20323992f",
      "tree": "9cf883bb3da70d1e12b4ac0e258e8819800fc19d",
      "parents": [
        "06950267a42107d3859fe3703f20ad313bd87e01"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 19 15:27:15 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 19 15:27:15 2026"
      },
      "message": "Theming of pygments, glossary, adoptions, search res, footer\n"
    },
    {
      "commit": "06950267a42107d3859fe3703f20ad313bd87e01",
      "tree": "6b15038fddd3a90415e10577d6836195e2b1667f",
      "parents": [
        "bc6fdac8f208f1faa2920875cad931450c939e5c"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 19:38:58 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 19:38:58 2026"
      },
      "message": "Simplify and rename rst_unused_targets.py script\n"
    },
    {
      "commit": "bc6fdac8f208f1faa2920875cad931450c939e5c",
      "tree": "fe11372723ed55147aac3d93a849526f239ba99d",
      "parents": [
        "d58067a182d2ffbe609c3f4f27683ffd4b45da77"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:49:27 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:49:27 2026"
      },
      "message": "Doc: use rst_prolog to avoid including links + module in every .rst file\n"
    },
    {
      "commit": "d58067a182d2ffbe609c3f4f27683ffd4b45da77",
      "tree": "e1691c102d571fcc40b1e088484466fc11516538",
      "parents": [
        "02eb82f0a374b1915a95efd74be59dd1187cce90"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:29:10 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:29:10 2026"
      },
      "message": "Revert \"Get rid of _links.rst; use sphinx prolog + remove rst_check_dead_refs.py\"\n\nThis reverts commit 02eb82f0a374b1915a95efd74be59dd1187cce90.\n"
    },
    {
      "commit": "02eb82f0a374b1915a95efd74be59dd1187cce90",
      "tree": "bd4a717f40d88f46a328f66c23485371fed7df8c",
      "parents": [
        "05cd23530488f549a1a3abc447ab2e07889b7b03"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:25:44 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 18:27:24 2026"
      },
      "message": "Get rid of _links.rst; use sphinx prolog + remove rst_check_dead_refs.py\n"
    },
    {
      "commit": "05cd23530488f549a1a3abc447ab2e07889b7b03",
      "tree": "e1691c102d571fcc40b1e088484466fc11516538",
      "parents": [
        "6811bd4c29b34f4d2bd67507f36859c35c29f3ad"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Fri Apr 17 12:07:49 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 17 12:07:49 2026"
      },
      "message": "Doc: wrap .rst lines to 79 chars + introduce `rstwrap` formatter (#2823)"
    },
    {
      "commit": "6811bd4c29b34f4d2bd67507f36859c35c29f3ad",
      "tree": "0370b3845d92515981fd7b87019d6e6ddc4b2259",
      "parents": [
        "92bed3e35cd12abb17282bca4ccdf3b939525ffa"
      ],
      "author": {
        "name": "Santhosh Raju",
        "email": "santhosh.raju@gmail.com",
        "time": "Fri Apr 17 07:35:14 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Apr 17 07:35:14 2026"
      },
      "message": "Handle `EFAULT` for NetBSD processes correctly. (#2822)"
    },
    {
      "commit": "92bed3e35cd12abb17282bca4ccdf3b939525ffa",
      "tree": "7221462ce6fd35fc4a1f7778d70c2fabba05ec43",
      "parents": [
        "f5f8ad7b3f9667a66e4f71beb883d038dda0782e"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 16 20:49:54 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 16 20:49:54 2026"
      },
      "message": "Add more PYPI metadata (issues, changelog, etc.)\n"
    },
    {
      "commit": "f5f8ad7b3f9667a66e4f71beb883d038dda0782e",
      "tree": "340e5f34bbd9b5ce15bc2d8f5eaa2e71f5ce05f1",
      "parents": [
        "ba88eddfd16006a38c5b2d7a805a684d06177792"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 14 10:24:04 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 14 10:24:04 2026"
      },
      "message": "Doc: wrap line len to max 79 chars for all .rst files\n"
    },
    {
      "commit": "ba88eddfd16006a38c5b2d7a805a684d06177792",
      "tree": "81c2a85e40b31e6ce33657205f794beccbcbb107",
      "parents": [
        "55a6c788d82f9ebbd4777a4cc09dfc873a612531"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 23:58:18 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 23:58:18 2026"
      },
      "message": "RsT: fix warnings\n\nSigned-off-by: Giampaolo Rodola \u003cg.rodola@gmail.com\u003e\n"
    },
    {
      "commit": "55a6c788d82f9ebbd4777a4cc09dfc873a612531",
      "tree": "c8b1860b0d06e37110945ac76b818a870ba2a726",
      "parents": [
        "d4c820b63f82836f4898468744eade476b39de50"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 19:21:41 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 19:21:41 2026"
      },
      "message": "Make rst linter more strict\n"
    },
    {
      "commit": "d4c820b63f82836f4898468744eade476b39de50",
      "tree": "0f77d4823f9e814b5d672242367253808da6b088",
      "parents": [
        "3f3c26a5f3f1c5cf7578abf0087543d119c83a82"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 15:54:11 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 13 15:54:11 2026"
      },
      "message": "Doc: light theme for code blocks (no longer monokai)\n"
    },
    {
      "commit": "3f3c26a5f3f1c5cf7578abf0087543d119c83a82",
      "tree": "c6360d6d99a9b738078d9526f9ceec6b3354c4fd",
      "parents": [
        "2ed90c66c75ccfd5212f1e621199c30f4c656df6"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 12 18:39:38 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 12 18:39:38 2026"
      },
      "message": "Doc: keyboard shortcuts for search, search results, toggle dark mode (#2820)\n\n## Keyboard shortcuts (search)\n\n- Search: ``Ctrl+K`` now focuses the search box (replaces ``/``).\n- We no longer rely on Read The Docs search pop-up (I don\u0027t like it).\n- Instead we rely on Sphinx search results, which are now styled similar\nto GitHub search results, using cards with subtle borders and shadows.\n- We can use ``Up``/``Down`` arrow keys to navigate Sphinx search\nresults, and ``Enter`` to open them.\n\n## Keyboard shortcuts (dark mode)\n\n- ``Shift+D`` can be used to toggle dark mode (mouse hover will provide\na hint)\n\n## New /about page\n\nIt is shown only in the footer, and points to instructions on how to use\nthey keyboard shortcuts.\n\n## UI\n\nThe search box shows a hint that it\u0027s possible to use the new shortcut\nvia ``ctrl + k``."
    },
    {
      "commit": "2ed90c66c75ccfd5212f1e621199c30f4c656df6",
      "tree": "b2d9a93fc11e24e0ba1addbcf9696769cfab80de",
      "parents": [
        "6d8e37ab5ff830b385d3e3961a2949772a287b8f"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 12 02:27:25 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 12 02:27:25 2026"
      },
      "message": "Modify rendering of genindex.html\n"
    },
    {
      "commit": "6d8e37ab5ff830b385d3e3961a2949772a287b8f",
      "tree": "7e4c29cb48c50bc6487fff58fcbdffdcb79c14d1",
      "parents": [
        "67dbfebeb9b2de966625d3eda5a67b878903421c"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 12 01:26:42 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 12 01:26:42 2026"
      },
      "message": "Doc: add top bar (#2819)\n\nThe main reason to add a top bar is because of the need to show a GitHub button somewhere. It\u0027s too important not to.  Right now I showed that in the home and in the footer, but it\u0027s not enough. So let\u0027s use a top bar, which is what (e.g.) pydata theme or rtdocs does.\n\nMove the light/dark theme button in the top bar, and also show the current psutil version (points to PyPI).\n\nOn the left, we always have a clickable \"[LOGO] psutil\" thingie, which is the way to \"go home\". For this reason I removed the \"Home\" link from the sidebar: it\u0027s redundant now, and the sidebar is already pretty long, so let\u0027s save space\n\n\u003cimg width\u003d\"1833\" height\u003d\"1069\" alt\u003d\"image\" src\u003d\"https://github.com/user-attachments/assets/03098a81-b1a5-49d9-b103-b150e2f7ff13\" /\u003e"
    },
    {
      "commit": "67dbfebeb9b2de966625d3eda5a67b878903421c",
      "tree": "41d5f0a5cb41d55779196fb8672841ffb42816a9",
      "parents": [
        "f0142488536e2102b543122a0ccd9991bd704687"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 20:19:49 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 20:19:49 2026"
      },
      "message": "Some home CSS style\n"
    },
    {
      "commit": "f0142488536e2102b543122a0ccd9991bd704687",
      "tree": "81cc823ca83527ebb78cf1b13ddb8609f9eb7114",
      "parents": [
        "9ee58fcba2a99220833e510aaef031f17a500db9"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 16:40:03 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 16:40:03 2026"
      },
      "message": "Doc / home: add description cards\n"
    },
    {
      "commit": "9ee58fcba2a99220833e510aaef031f17a500db9",
      "tree": "9f240783ba4d5ca9cf682ea6f36decc3c34c9de4",
      "parents": [
        "ae09c82d85aab7b0e97ef90ad15abd3b5c4a6647"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 14:32:42 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 14:32:42 2026"
      },
      "message": "Add System tools source code section in DEVNOTES.md\n"
    },
    {
      "commit": "ae09c82d85aab7b0e97ef90ad15abd3b5c4a6647",
      "tree": "0fd9183ff8d75df80ba59c2dd4c51a225d7b316f",
      "parents": [
        "970287d2239050921d0ad69d7099718193cb506a"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 11 11:46:41 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Apr 11 11:46:41 2026"
      },
      "message": "[OpenBSD] expose swap_memory() sin and sout counters #2816 (#2817)"
    },
    {
      "commit": "970287d2239050921d0ad69d7099718193cb506a",
      "tree": "951727d78e1d151cd678c045ba3f30276fec83c8",
      "parents": [
        "dbe15d9c73674b2b140e7309f148b6ddbbabda38"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 16:19:56 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 16:19:56 2026"
      },
      "message": "#2815 / NetBSD: don\u0027t include virtual pages in shared mem calculation\n"
    },
    {
      "commit": "dbe15d9c73674b2b140e7309f148b6ddbbabda38",
      "tree": "68ea1bd36d0c09dcbfd2c6f9d80ac9662ebc6c23",
      "parents": [
        "3c6056265302395208a131b342721ad936ddb169"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 16:07:17 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 16:07:17 2026"
      },
      "message": "#2814 / NetBSD: don\u0027t include anon pages in cached mem calculation\n"
    },
    {
      "commit": "3c6056265302395208a131b342721ad936ddb169",
      "tree": "f9a040e52eacbbc24db635be34058b6dc41081a0",
      "parents": [
        "74e6793c75bcac13e587dcd61080b75e5fdbc467"
      ],
      "author": {
        "name": "Santhosh Raju",
        "email": "santhosh.raju@gmail.com",
        "time": "Thu Apr 09 15:19:42 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 09 15:19:42 2026"
      },
      "message": "Remove procfs dependency for NetBSD (#2805)"
    },
    {
      "commit": "74e6793c75bcac13e587dcd61080b75e5fdbc467",
      "tree": "5ccf49bc54668dad387f1c40d43b7713ffd452d2",
      "parents": [
        "6829d2dcc71ca499c2cdc7934eaa6b96fd91ec87"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 15:12:42 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 15:12:42 2026"
      },
      "message": "Write OpenBSD tests for virtual memory + add clarifying comments about it\n"
    },
    {
      "commit": "6829d2dcc71ca499c2cdc7934eaa6b96fd91ec87",
      "tree": "8d0d4cdc1d90c09f829162cb4c06261d1bd1bcd1",
      "parents": [
        "1228be61b355148fe004a9eaea6ad74c15a73161"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 13:44:19 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 13:44:19 2026"
      },
      "message": "Add OpenBSD comment about total memory\n"
    },
    {
      "commit": "1228be61b355148fe004a9eaea6ad74c15a73161",
      "tree": "8ca965743b4c964b29a55b1e8a42df987c3599ca",
      "parents": [
        "1209a765b996f10ba39a4673a258b4d3824585ec"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 13:27:58 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 13:27:58 2026"
      },
      "message": "OpenBSD: treat \u0027cached\u0027 and \u0027buffers\u0027 as aliases\n\n\"top\" derives cached memory from `bcstats.numbufpages`, which\ntechnically corresponds to \u0027buffers\u0027 memory:\nhttps://github.com/openbsd/src/blob/master/usr.bin/top/machine.c\n\nIntuitively, \u0027cached\u0027 memory should instead be\n`uvmexp.vnodepages`, described as \u0027vnode page cache\u0027, but it\u0027s\nalways 0, and the struct contains an \"XXX\" comment, suggesting\nthat `vnodepages` should probably not be used. This article\nsuggests that \u0027buffers\u0027 became the primary caching mechanism in\nthe system:\nhttps://undeadly.org/cgi?action\u003darticle;sid\u003d20140908113732\n\nSo, treat \u0027cached\u0027 and \u0027buffers\u0027 as aliases. See:\nhttps://github.com/giampaolo/psutil/issues/2813\n"
    },
    {
      "commit": "1209a765b996f10ba39a4673a258b4d3824585ec",
      "tree": "5138da1c8b35859dfce15cd05f856d973a4c0f61",
      "parents": [
        "d9eb9855a63d76089c0ebc4b685f2efd441eda0d"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 11:33:54 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Apr 09 11:33:54 2026"
      },
      "message": "[OpenBSD] return correct virtual_memory().shared (#2812)\n\nRelated: https://github.com/giampaolo/psutil/issues/2792.\n\nOn OpenBSD,  `shared` memory is missing the `* pagesize` multiplier. In addition, the way we calculate it\u0027s wrong. We calculate it as:\n\n\n```c\nshared \u003d (unsigned long long)vmdata.t_vmshr + vmdata.t_rmshr;\n```\n\nWhich means \"shared virtual memory\" + \"shared real memory\". \nFrom:\n\n```c\n/* systemwide totals computed every five seconds */\nstruct vmtotal {\n    u_int16_t t_rq;     /* length of the run queue */\n    u_int16_t t_dw;     /* jobs in ``disk wait\u0027\u0027 (neg priority) */\n    u_int16_t t_pw;     /* jobs in page wait */\n    u_int16_t t_sl;     /* jobs sleeping in core */\n    u_int16_t t_sw;     /* swapped out runnable/short block jobs */\n    u_int32_t t_vm;     /* total virtual memory */\n    u_int32_t t_avm;    /* active virtual memory */\n    u_int32_t t_rm;     /* total real memory in use */\n    u_int32_t t_arm;    /* active real memory */\n    u_int32_t t_vmshr;  /* shared virtual memory */\n    u_int32_t t_avmshr; /* active shared virtual memory */\n    u_int32_t t_rmshr;  /* shared real memory */\n    u_int32_t t_armshr; /* active shared real memory */\n    u_int32_t t_free;   /* free memory pages */\n};\n```\n\nNotice how there\u0027s 3 values related to shared memory:\n\n```\n    u_int32_t t_vmshr;  /* shared virtual memory */\n    u_int32_t t_avmshr; /* active shared virtual memory */\n    u_int32_t t_rmshr;  /* shared real memory */\n```\n\nOur calculation is probably incorrect, or a \"double count\".\nWhat we\u0027re probably interested in is `t_rmshr;  /* shared real memory */`."
    },
    {
      "commit": "d9eb9855a63d76089c0ebc4b685f2efd441eda0d",
      "tree": "598a384243434983e469adbf314e633d7edcea65",
      "parents": [
        "eb0eb30c184352d6ffd23450e87f179795b0fee8"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 08:38:34 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Thu Apr 09 08:38:34 2026"
      },
      "message": "Turn DEVNOTES into DEVNOTES.md\n"
    },
    {
      "commit": "eb0eb30c184352d6ffd23450e87f179795b0fee8",
      "tree": "c18830647d8227195d10bd1d1255fcd06e8a3a17",
      "parents": [
        "9c2a9a4f078d632fd250ba9325b666cb2f0d9073"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed Apr 08 17:02:08 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed Apr 08 17:02:08 2026"
      },
      "message": "Doc: on mobile, close the sidebar when tapping content or swiping left\n"
    },
    {
      "commit": "9c2a9a4f078d632fd250ba9325b666cb2f0d9073",
      "tree": "0a3dd5a29877097837204fc90fc3d27eb6bae108",
      "parents": [
        "99284b4a223d343faf84fa02f71551e1d0d580cd"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed Apr 08 01:09:12 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed Apr 08 01:09:12 2026"
      },
      "message": "Fix RTD build failure\n"
    },
    {
      "commit": "99284b4a223d343faf84fa02f71551e1d0d580cd",
      "tree": "d0dce6f588a3d5d431c4cee3f8fe44d865d963f7",
      "parents": [
        "45ee4ac8ea10b48571120d74974773d100f7fd60"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Wed Apr 08 01:02:17 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Apr 08 01:02:17 2026"
      },
      "message": "Doc: add general index (#2808)\n\nThis is provided for free by Sphinx, and one of its most underrated features. For a big lib like psutil, having a general index is extremely useful."
    },
    {
      "commit": "45ee4ac8ea10b48571120d74974773d100f7fd60",
      "tree": "0f0996d9c66458a5c2a621002f434e5e4864b335",
      "parents": [
        "5c183d48bd9599ffb8a522516a760992a95af176"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 07 14:25:54 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 07 14:25:54 2026"
      },
      "message": "Doc: add more cross-refs to glossary, fix typos\n"
    },
    {
      "commit": "5c183d48bd9599ffb8a522516a760992a95af176",
      "tree": "bc744186ffacde899d5f782b2c19a7fee06bd5da",
      "parents": [
        "cc9c0f000eb1733854f80b782b04677be9e84682"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 07 00:01:46 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Tue Apr 07 00:01:46 2026"
      },
      "message": "Doc: yet another cleanup / rewording\n"
    },
    {
      "commit": "cc9c0f000eb1733854f80b782b04677be9e84682",
      "tree": "ae4185b548e0fc4c4a996ceb0f8ea2e82c2d9237",
      "parents": [
        "e40529227462d4aae30f26c5c9f14d0c9b76d079"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 06 21:44:23 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 06 21:44:23 2026"
      },
      "message": "[Windows] make `boot_time()` return the same result across processes  (#2807)\n\nFixes #1007 for the second time.\n\n`boot_time()` on Windows no longer fluctuates by ~1 second across calls or across processes. \nIt is now read atomically from the kernel via ``NtQuerySystemInformation(SystemTimeOfDayInformation)``, replacing the old ``time.time() - uptime()`` computation that sampled two counters from Python and produced sub-second differences.\n\nDoc had this note:\n\n```\n  .. note::\n    on Windows this function may return a time which is off by 1 second if it\u0027s\n    used across different processes (see issue :gh:`1007`).\n```\n    \nThis is now fixed."
    },
    {
      "commit": "e40529227462d4aae30f26c5c9f14d0c9b76d079",
      "tree": "c558444727d6ef207cf310cd8d6d15aee9055d1f",
      "parents": [
        "55dfba1b86900ef90c1a89b096f3b6783d65f1c0"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Mon Apr 06 00:18:08 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Apr 06 00:18:08 2026"
      },
      "message": "Doc big rewording (#2804)"
    },
    {
      "commit": "55dfba1b86900ef90c1a89b096f3b6783d65f1c0",
      "tree": "36c7c73c4e2ddb361a6ef509b1f83df482acd7f3",
      "parents": [
        "e46927379970bf98dd72bda9b12b9a8643001307"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sun Apr 05 00:33:54 2026"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Apr 05 00:33:54 2026"
      },
      "message": "Doc dark theme (#2803)"
    },
    {
      "commit": "e46927379970bf98dd72bda9b12b9a8643001307",
      "tree": "a1760c9c8b5c8ba6ad5b58fe1db889c875900de2",
      "parents": [
        "2e74d02745109355b5ae975395b73396d71dafa4",
        "b8269e1dc01c304f86eda8d242687479905cd05d"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:22:01 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:22:01 2026"
      },
      "message": "Merge branch \u0027doc-reorg-2\u0027\n"
    },
    {
      "commit": "b8269e1dc01c304f86eda8d242687479905cd05d",
      "tree": "a1760c9c8b5c8ba6ad5b58fe1db889c875900de2",
      "parents": [
        "5ae217d18c03eca5fa57d0ccdcd14f357089c3b4"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:21:21 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:21:21 2026"
      },
      "message": "Shorten changelog.rst entries\n"
    },
    {
      "commit": "2e74d02745109355b5ae975395b73396d71dafa4",
      "tree": "338a52e460949619cf462fba97d2283fa2e2ca40",
      "parents": [
        "027774dae15103a9a531e2678c302310b2ad449c",
        "5ae217d18c03eca5fa57d0ccdcd14f357089c3b4"
      ],
      "author": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:01:21 2026"
      },
      "committer": {
        "name": "Giampaolo Rodola",
        "email": "g.rodola@gmail.com",
        "time": "Sat Apr 04 19:01:21 2026"
      },
      "message": "Merge branch \u0027doc-reorg-2\u0027\n"
    }
  ],
  "next": "5ae217d18c03eca5fa57d0ccdcd14f357089c3b4"
}
