Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [
"python",
"fortran",
"namelist",
"parser"
],
"is_fork": false,
"size_kb": 842,
"has_wiki": true,
"homepage": null,
"languages": {
"TeX": 4872,
"Shell": 702,
"Python": 155214,
"Makefile": 162
},
"pushed_at": "2026-07-17T14:04:09Z",
"created_at": "2014-02-27T01:20:48Z",
"owner_type": "User",
"updated_at": "2026-07-17T14:05:08Z",
"description": "A Python module and command line tool for working with Fortran namelists",
"is_archived": false,
"is_disabled": false,
"license_spdx": "Apache-2.0",
"default_branch": "main",
"license_spdx_raw": "Apache-2.0",
"primary_language": "Python",
"significant_languages": [
"Python"
]
},
"owner": {
"blog": "http://marshallward.org",
"name": "Marshall Ward",
"type": "User",
"login": "marshallward",
"company": "@noaa-gfdl",
"location": "Princeton, NJ, USA",
"followers": 88,
"avatar_url": "https://avatars.githubusercontent.com/u/462315?v=4",
"created_at": "2010-11-01T05:31:51Z",
"is_verified": null,
"public_repos": 115,
"account_age_days": 5751
},
"license": {
"state": "standard",
"spdx_id": "Apache-2.0",
"raw_spdx": "Apache-2.0",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v1.4.1",
"kind": "patch",
"published_at": "2022-05-31T13:18:37Z"
},
{
"tag": "v1.4",
"kind": "other",
"published_at": "2022-05-18T01:17:44Z"
},
{
"tag": "v1.3.1",
"kind": "patch",
"published_at": "2021-05-26T02:12:08Z"
},
{
"tag": "v1.3",
"kind": "other",
"published_at": "2021-05-18T00:15:29Z"
},
{
"tag": "v1.1.2",
"kind": "patch",
"published_at": "2019-06-13T21:15:41Z"
},
{
"tag": "v1.1",
"kind": "other",
"published_at": "2019-05-23T19:38:19Z"
},
{
"tag": "v1.0.2",
"kind": "patch",
"published_at": "2018-01-30T13:06:32Z"
},
{
"tag": "v1.0.1",
"kind": "patch",
"published_at": "2018-01-30T01:20:17Z"
},
{
"tag": "v0.23",
"kind": "other",
"published_at": "2017-12-13T05:41:34Z"
}
],
"recent_commits": [
{
"oid": "1a5def3d60b5b0e1616bfffd937e6fb6c5576255",
"body": "Kind-type specification with _ is not supported in either namelists or\nlist-directed IO. This tokenization was leftover from the Fortran\nscanner. This patch eliminates this content.\n\nTests have been added to ensure that lexemes like `1_8` are not formed.",
"is_bot": false,
"headline": "Scanner: Eliminate kind-parsing of scalars",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2026-07-17T14:04:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "40bb1c5a7e73cc141bb6536853bbdb1f0c1db46a",
"body": "The simpler nature of multiline strings in namelists, along with other\nchanges in the DFA machine, mean that we no longer need to check against\n\\n when running the Unicode KeyError exception test.\n\nThis block has been simplified and the endline is no longer tested.",
"is_bot": false,
"headline": "Scanner: Simplified unicode catch",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2026-07-17T14:04:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f365a8d6de402155924d3efd1bf775a5f085cd44",
"body": "First draft of a few scanner unit tests. Needs work.\n\nSeveral new tests by Codex (but needs polishing)\n\nAlso found some bugs :O",
"is_bot": false,
"headline": "Testing: Scanner unit tests",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2026-07-17T14:04:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d5f68e80785132df777ca1beea98fe3da366fe5e",
"body": "In namelists, endlines have no semantic meaning (outside of strings, and\neven that is tricky), so the line-based iteration was a bit unintuitive\nin some places.\n\nAnd the comment line-complete optimization made less sense, since we\nwant the endline and following whitespace to join the comment token.\n\nIn order to better align with these facts, and line-based logic has been\ndropped and the iterator is now solely per-character.",
"is_bot": false,
"headline": "Scanner: Exclusively character-based scan",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2026-07-17T14:04:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cafedf863412440970ab93338b849b9e72ca81fe",
"body": null,
"is_bot": false,
"headline": "Security: Update idna to 3.15",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2026-07-17T13:42:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "34da4c873d3eb169da7892b54f868b077d4a9c27",
"body": "The parser now checks whether the f77 style &end token case\ninsensitively. It now also allows both opening tokens & and $ to\nfollow another group.",
"is_bot": false,
"headline": " allow caps END token, check for & and $ in next group",
"author_name": "David Hohn",
"author_login": null,
"committed_at": "2026-04-27T18:50:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "656ab0d4335a1bd6ec46d23570ded3600f5709ab",
"body": null,
"is_bot": false,
"headline": "add tests for capitel &END token and unclosed $group",
"author_name": "David Hohn",
"author_login": null,
"committed_at": "2026-04-27T18:50:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "369e7b6c1011287067c51b844296377087974218",
"body": "This adds a check whether a group is closed correctly. old behaviour\nwould just skip group that follows the misformated group\nsilently. Also added a few more test cases for f77 formatting because\nit apparently allows bare '&' to close a group.",
"is_bot": false,
"headline": "check groups are closed correctly",
"author_name": "David Hohn",
"author_login": null,
"committed_at": "2026-04-27T18:50:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e9aa2eaacb69417e0a127a714939e238b2553c66",
"body": "up to now only the last group is required to be closed correctly. If\nany previous group omits the closing '/' it is silently skipped.",
"is_bot": false,
"headline": "Add a test for unclosed groups that are not the last group.",
"author_name": "David Hohn",
"author_login": null,
"committed_at": "2026-04-27T18:50:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "420c780c45a2d26cefe33a740887a2170752a10b",
"body": null,
"is_bot": false,
"headline": "Version 1.5 release",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-10-07T14:57:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8162b11f653a57f1a6e9f8f19a467a9b8a00a135",
"body": "The README badges were still using legacy services like AppVeyor and\nCoveralls, which I no longer use regularly.\n\nThe new badges are replaced with GitHub Actions and Codecov.io.",
"is_bot": false,
"headline": "Update README badges",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-10-07T14:57:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "88e547e945e33338c7efce3311809aaf54212486",
"body": "Certain compilers require null value assignments to end with commas.\nThe `Namelist` writer contains a special rule to append this comma.\n\nIf `end_comma` is enabled, which always finalizes values with commas,\nthen this would append a second comma, which would transform the record\ninto two null values.\n\nThis patch prevents the redundant comma if end_commas are enabled.\n\nThanks to Paul Leopardi (@penguian) for reporting.",
"is_bot": false,
"headline": "Remove redundant commas of tail null values",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-10-07T13:26:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "778fb0c23b5863868ab8369f2030a954d52579a9",
"body": null,
"is_bot": false,
"headline": "Scanner: Remove unused modules",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-10-02T19:54:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "91558fed510a3b8e8496239029d23edd08557568",
"body": "This patch makes several changes to the GH action CI:\n\n* Python and OS version testing actually works now.\n\n - The incorrect `python` was renamed to `python-version`\n (Thanks to Clément Robert, @neutrinoceros)\n\n - `runs-on` now correctly pulls from the matrix, rather than set to\n `ubuntu-lat\n[…]\nof\n\n* `pull_request` trigger added (again, thanks @neutrinoceros)\n\n* `setup-python` upgraded to @v5\n\nAll tests appear to be running correctly now.\n\nCo-authored-by: Clément Robert <cr52@protonmail.com>",
"is_bot": false,
"headline": "GH Actions: Fix OS issue, separate legacy tests",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-07-30T12:39:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e04517069b29bce181565be91bd4182f78589351",
"body": "This patch \"de-versions\" the scanner to work on older versions of\nPython. We did not mean to drop Python 2.7 suddenly, so this removes the\nfollowing constructs from the scanner:\n\n* No `d1 | d2` merges of dicts.\n\n* No use of \"walrus\" operator, `|=`\n\nPerhaps a lot of work for nothing, since we plan to drop Py2.7 very\nsoon, but at least it will be on purpose!",
"is_bot": false,
"headline": "Backwards compatible scanner",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-07-30T12:39:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ce0d8b127b4dd71eef4a6120864e4fee2395ed25",
"body": "I also removed any untested versions from the classifiers.",
"is_bot": false,
"headline": "GitHub: Extend python versions to 3.13 + PyPy",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-06-10T19:47:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "483cd61042728eac7d59adbcf777c536e66ff011",
"body": "This moves most of the content in setup.py to setup.cfg.\n\nOnly the project name and the version parser are left in setup.py.\n\nNot really sure about the whole classifiers thing but we'll come back to\nit.\n\nAdded a make rule to test the package (unsure about the name)",
"is_bot": false,
"headline": "setup.py: Move content to setup.cfg",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-06-10T19:47:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ae39ec93777a09489c6d9bdf6761d4379565b8a4",
"body": "The old bin/f90nml script is finally removed. Now that we have better\nsupport for pip installs, we can switch to entry_points with a little\nmore confidence.",
"is_bot": false,
"headline": "setup.py: Replace scripts with entry_points",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-06-10T19:47:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "395c54ab84c1dfce5f40e8808d68b6a7978900c1",
"body": "Three major changes to setup.py, in order to approach conformace with\nPyPA guidelines.\n\n* the `setup.py test` command has been removed, since it is now\n discouraged. Testing is now done by direct invokation of unittest.\n\n A new Makefile with `make test` has been added to simplify testing.\n\n* Vers\n[…]\nools around the f90nml path and module itself.\n\n Since importing f90nml while installing is discouraged, we now just\n explicitly parse version.py.\n\n* Minor point, but setup.py is now PEP8 compliant.",
"is_bot": false,
"headline": "setup.py: Remove test cmd, parse version",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-06-10T19:47:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0f8f4efae0fc4995d6b9c13e3c5a470d06d0a6c9",
"body": "There have been issues with coveralls reporting, so I have switched to\ncodecov.io. And so we dance to the next free service provider.",
"is_bot": false,
"headline": "Move coverage reporting to codecov.io",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-04-13T15:06:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "18cda8f393244d81a60f391bec81f4fd8c36523b",
"body": "This patch replaces the hand-scanner with a more formal DFA-based\nscanner. Lexemes are constructed per-character and state is tracked\nwith a dictionary, rather than complex if-statements and other awkward\nlookahead-like constructs.\n\nThe major change here is that whitespace is now formally tokenized\n[…]\nAlthough every test has\npassed, there is still enormous room for error, and I do not believe we\ncatch every possible case. This is going to need some time before it\ncan be moved into the main branch.",
"is_bot": false,
"headline": "DFA-based tokenization",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-04-13T15:06:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4fecdc3d28dbfefb538aee37906afe3b8335729f",
"body": null,
"is_bot": false,
"headline": "Minor README update about conda",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-04-10T15:17:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5f3049b1d8ce3892a28ec78102a59489b29c1f77",
"body": null,
"is_bot": false,
"headline": "Version 1.4.5 release",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-04-10T14:58:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f56660429d8015d5fe14ab25655fc854b56a708f",
"body": "New property Namelist.assign_spacing that allows to trigger the use of white spacing around the assignment operator in the output",
"is_bot": false,
"headline": "Formatting option assign_spacing",
"author_name": "Balthasar Reuter",
"author_login": "reuterbal",
"committed_at": "2025-04-03T13:34:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6ff04b0d01cf06216e2aafc2f0cca734cc3b35f9",
"body": "IDNA version update to 3.7, used in Python 2.6 version testing.",
"is_bot": false,
"headline": "Security update (Python 2.6 testing)",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-01-22T13:59:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4211505be04f96a62924197ed99a02a98a08e50e",
"body": null,
"is_bot": false,
"headline": "Merge branch 'main' of https://github.com/marshallward/f90nml",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-01-22T13:59:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "662663b9ca6727a931879f1ec9ad9b05a570ca1d",
"body": "Very minor cleanup of various docs. Mostly just rewritten in a more\nneutral tone.",
"is_bot": false,
"headline": "Minor documentation update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2025-01-22T13:57:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1525a6a8b396776d82bd7140d1fa8d1c08b285ff",
"body": null,
"is_bot": false,
"headline": "Fixed small typo",
"author_name": "Aidan Heerdegen",
"author_login": "aidanheerdegen",
"committed_at": "2024-08-06T12:53:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1fea0c4c767261320cc8ec036865f0fa24577b49",
"body": null,
"is_bot": false,
"headline": "Update README with conda install instructions",
"author_name": "Aidan Heerdegen",
"author_login": "aidanheerdegen",
"committed_at": "2024-08-06T12:53:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "21db6a7afc6b5df6e53cdc1980f1301660732d01",
"body": null,
"is_bot": false,
"headline": "Version 1.4.4 release",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-10-11T03:33:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "aefff0557126540c1536224e255016e4bb80f4d7",
"body": "Added tests for cogroup patch and update methods. As with other cogroup\ntests, the equivalent operations are still not well-developed, so the\noutput tests need some improvement in the future.",
"is_bot": false,
"headline": "Testing: cogroup patch/update tests",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-10-11T02:04:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5b85248f7f60d7c3e7361ec1960d8a6c4713cb2f",
"body": "If a group was a Cogroup, then patch() would apply the patch to all\ncogroups. This change introduces a `_index` argument which specifies\nthe specific cougroup which should be patched.",
"is_bot": false,
"headline": "Provide index support for namelist cogroup patches",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-08-23T15:03:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d65e593ab70e61d90bb0f1ec1ed4f6bb3551b9ad",
"body": "Cogroups, although subclasses of lists, are designed to behave as dicts\nin many situations. One absence is the support of certain intrinsic\nmethods.\n\nThe `patch` method of `Namelist` relied on `update`, but this was not\nsupported by Cogroups and would raise an error if one was returned.\nThis patch \n[…]\noes not address which elements of the Cogroup should receive the\npatch. Currently, all elements in the cogroup are patched. This is\nsufficient to avoid errors, but should be addressed in the future.",
"is_bot": false,
"headline": "Add update method for cogroups",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-07-12T19:33:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5aa7f2bf14c9f6ed9f7f665d34893405ca108d45",
"body": "Using the new required Read the Docs configuration file. Just setting\nthe default for now (after updating the path of conf.py).",
"is_bot": false,
"headline": "Update \"Read the Docs\" configuration",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-06-25T13:40:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "771339a3542f67c629412e6f2b1835e8d96eb43a",
"body": "Addition of tests for higher dimension negative index values.\n\nSpecifically testing 0 and -1 which were the ones causing errors.",
"is_bot": false,
"headline": "Multidimension negative index tests",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-06-06T16:25:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "52d4c295391823e7fc4a9dec7228a1edd159ad91",
"body": "Two checks related to multidimensional indices were incorrectly apply\ngeneric `if index` tests, which return false if `index` is zero.\n\nThis raised errors in two cases:\n\n1. The end-bound of an array a(0), which is bounded by 1, was\n incorrectly set to None rather than 1, and treated as a floating\n\n[…]\nwhen the index bounds are\nunspecified, and are implicitly determined when values are provided.\n\nBoth of these tests have been replaced with `if None` tests, which\nappear to have resolved these errors.",
"is_bot": false,
"headline": "Fix \"if index\"-like test with None test",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-06-06T15:16:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4fd9d664cf936afc693b7b3824fb73bf6d7a9971",
"body": null,
"is_bot": false,
"headline": "Remove Travis info from README",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-05-04T13:31:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a6556fb2c57e1b178be44c8c1731ba0d3f3a259f",
"body": "Semantic versioning appears to be required now for version\nspecifications.\n\nUpdated checkout to v3 (whatever that means)\n\nAlso, PyPy appears to be done and dusted in GitHub, and I don't know\nanyone using it anyway, so this patch removes it from the GitHub Actions\ntesting.",
"is_bot": false,
"headline": "Revise GitHub Actions Python versioning",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-03-23T20:53:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5b9891b2e0adc6d25de1af2067aca30d4fec16af",
"body": null,
"is_bot": false,
"headline": "Merge branch 'main' of https://github.com/marshallward/f90nml",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-03-23T20:19:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "25c09db4a7affbabf7d25c400c9ac701883eef11",
"body": "This patch replaces a `pop` with `get` in a derived type patch\nassignment.\n\nWhile the exact behavior is not yet clear, it seems reasonable that we\nwould not want to prematurely pop each value, since the contents are\nreused across all fields of the derived type.\n\nThere may be unexpected consequences here, but I believe this is \"more\ncorrect\", and fixes some known issues. I can only hope it does not\ncreate any new ones.",
"is_bot": false,
"headline": "Do not pop off derived type patch assignments",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2023-03-23T20:18:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8a9cca77fc02d1c7be15c5eae183131c3f2dfadd",
"body": "NumPy's .tolist() can convert ND arrays to lists (of lists...),\r\nand NumPy dtypes/0D arrays to scalars, and so performs a similar\r\ntask to to_primitive. This change does not require explicit NumPy\r\ndependence.",
"is_bot": false,
"headline": "Change to accept NumPy arrays and similar objects (#151)",
"author_name": "LiamPattinson",
"author_login": "LiamPattinson",
"committed_at": "2022-11-16T15:17:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a8663aa7dfc06a446fbab6aae20d928f694f3fb",
"body": null,
"is_bot": false,
"headline": "AUR update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-07-12T14:05:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bbc519dbf85d2fec3721f143aff858bfa63675ea",
"body": null,
"is_bot": false,
"headline": "Documentation for releasing a new version",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-07-12T13:06:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bb93aec913d77d92b5a6199484ab8943bd1f8596",
"body": null,
"is_bot": false,
"headline": "Version 1.4.3",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-07-12T12:54:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c126a5f47957bc01ea51c5f87e63035169fc5c79",
"body": "A very weak usage test of creating a namelist cogroup from another\ncogroup.\n\nThis needs to be updated once cogroup equivalent has been further\ndeveloped.",
"is_bot": false,
"headline": "Test: set from cogroup",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-07-12T12:30:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3d854879afe23f6f63c03a5424909b6f0a253975",
"body": "This patch resolves an issue where a Cogroup was used to re-initialize a\nNamelist.\n\nThis fix is touching issues around the ambiguity of list interpetation\nas either a list of derived types or a list of repeated keys. Currently\nboth are represented by lists. The latter may be represented by a\nCogroup, if it came from a previous Namelist.\n\nThis patch addresses the latter case, but not the more general case.\nSome major refactoring would be needed to resolve it.",
"is_bot": false,
"headline": "Cogroup initialization support",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-06-21T00:04:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b02f6c832b9aaf705ddd417d24874834a0b252a1",
"body": null,
"is_bot": false,
"headline": "Version 1.4.2 update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-06-02T03:29:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0fdcedd12fe0d1aef22845ee7aa28224dc36258a",
"body": "Changes to __delitem__ broke the usage of the case-insensitive\n(lowercase) key, which caused key errors in some cases.\n\nThis patch now uses the case-insensitive key and includes a test for\ncase-insensitive `del`.\n\nThanks to GitHub user @mandresm for reporting.",
"is_bot": false,
"headline": "Case-insensitive del fix",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-06-01T15:48:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3e24a974fcb2437eb8b50174ab141d604fcffc98",
"body": "Due to changes in Travis, I don't see us going back to using it. So\nthere is no longer any need to maintain this config file.",
"is_bot": false,
"headline": "Removal of Travis test configuration",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-31T13:21:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7fbba7cedd02852be94832bb3de6151a385cebde",
"body": null,
"is_bot": false,
"headline": "Version 1.4.1 update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-31T12:33:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b6630b2999b8823407a1cf04c0ffd8a0426ff83",
"body": "Some difference in the pop() implementation on PyPy requires that we\npope the internal key, rather than use the NmlKey string. Most likely\nnot leaning on __delitem__ as much.\n\nIn any case, it makes more sense to pass the internal key, so it's a\nreasonable change.\n\nThis patch restores PyPy support.",
"is_bot": false,
"headline": "Pypy: Pop internal key for cogroup reorder",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-31T04:18:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d270d91445a0e54000292040487de81850a30053",
"body": "Adds several tests for cogroups:\n\n* Legacy cogroup case (where they appear next to each other)\n* Generalized case, where they may appear betweeen other groups\n* Cogroup creation and conversion\n* Output to dict (via YAML testing)",
"is_bot": false,
"headline": "Cogroup tests",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-31T03:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5cf112edb0877d1202ded1c50c689bfa968c4238",
"body": "Cogroup generation of the Namelist() from dict was using the older\nexplicit (now internal) keys. The new NmlKey broke this by using the\nolder, ambiguous group name. This patch now iterates over the internal\nkeys.",
"is_bot": false,
"headline": "Namelist cogroup key init bugfix",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-31T02:43:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "27140f53586e33bd3a5538894c40a229eb0b4120",
"body": "This patch modifies the todict() method to use the internal keys, rather\nthan the ambiguous namelist keys. This prevents clobbering of repeated\ngroups.",
"is_bot": false,
"headline": "Namelist.todict uses internal keys",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-30T16:39:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8fb0a21a994f698dca4f8ebd0b4552ed9b383c82",
"body": "Minor revision to the contributing doc page.",
"is_bot": false,
"headline": "Documentation update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-30T15:51:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7cd6b9cb61432e82d299c35a608025ae4077385e",
"body": "Changes to cogroups mean that we no longer need to explicitly check for\nlists when attempting to detect cogroups. They now exist as regular\ngroups with special keys (via NmlKey).\n\nA bug was also fixed to allow create_cogroup() to function properly when\ncalled inside add_cogroup().",
"is_bot": false,
"headline": "Refactored group handling",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-30T14:12:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "794068f03c246e3bd3213b096a7bf4731bac035f",
"body": "The introduction of NmlKey means that we no longer need to check if a\nkey contains the _grp_[key]_### metadata, since this is handled\ninternally.",
"is_bot": false,
"headline": "Remove cogroup name test from _write_nmlgrp",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-29T22:22:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bf63882e14215de3f86dd9fe4a3d89249ef4f838",
"body": "Deletion (`del`) of individual elements inside a cogroup was not\nworking, due to some legacy code (back when Namelist._cogroups was a\nlist) and overall faulty logic.\n\nThis new method will correctly allow for deletion of an individual\nelement within a cogroup list.",
"is_bot": false,
"headline": "Improved delete of cogroup key elements",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-29T15:22:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c2246b5d6c7225fdfd3b48a58cc899af9ad4b7bc",
"body": "A Namelist generated from a dict may assign an empty list as a value,\nwhich was unhandled by the _var_string() function, which converts\nvariables to strings, as used by print().\n\nFor example:\n\n nml = Namelist({'sec': {'a': []}})\n\nshould yield\n\n &sec\n a = ,\n /\n\nSuch a namelist would nor\n[…]\ntion of the Namelist(), since Fortran does contain a notion of a\nzero-length list. Instead, we check for both None and [] when deciding\nhow to write the output, which (as before) has the same output.",
"is_bot": false,
"headline": "Check for empty list when printing",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-27T21:12:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9bce38c01aae2ed93c467d7ceb75ae4eef2994d8",
"body": "Checking for the existence of a key would fail if the key was a cogroup,\nsince cogroup keys were renamed to the internal format (`_grp_..._###`).\n\nThis was resolved by searching both the namelist dict keys and the\ninternal cogroup list.\n\nThis also fixed a bug with removal of elements from self._cogroups,\nwhich was apparently untested before this point.",
"is_bot": false,
"headline": "Check cogroups list for key existence",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-25T16:26:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "731204eb9deb991e9a397cd49d0a261d2a14537c",
"body": "Given the legacy of using lists to identify repeated strings, and how\nthis breaks the output of str(), an additional test was added to track\nthis issue.\n\nI remove the trailing '\\n' from the IO file for the comparison, which\nstr() does not apply.",
"is_bot": false,
"headline": "Test str() output for repeated string",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-14T13:03:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f8ec5669e34c82d4765764f2b515bf0e08845bd3",
"body": null,
"is_bot": false,
"headline": "Version 1.4 update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-14T02:37:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "42ad8a66d7a89bbcead72bc9daad273d7ee87acd",
"body": null,
"is_bot": false,
"headline": "Update docstrings of Cogroup and associated classes",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-14T02:13:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "68966d190656454d614bb5112d15956af9c9df2b",
"body": "This patch introduces a NmlKey class, which externally matches the\nnamelist key as it appears in the file, but contains a field (_key)\nwhich holds its internal key, used when duplicate groups exist within\nthe namelist.\n\nThe `keys`, `items` and `__iter__` of Namelist were also modified to\nreturn thes\n[…]\nhey will\nreturn the specific value for which they represent. Externally, they\nuse the generic name.\n\nUsage across namelists is not addressed here, nor any other creative\nattempts to use this feature.",
"is_bot": false,
"headline": "NmlKey class for namelist keys",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2022-05-03T20:42:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6e9483a4c4065175c3e3e1d6dc7336d88618574a",
"body": "This patch redefines the self._cogroups to be a dict which tracks the\ninternal keys, rather than just a set of the public cogroup keys.\n\nThis patch also renames the initial cogroup to use the internal key name\n(usually _grp_{name}_0) rather than just occupying the original key.\nThis ought to simplif\n[…]\nollection of cogroups from the addition of\na new cogroup.\n\nSome other minor stuff was changed too, but will be summed up in the\nproper commit log. (e.g. `default_start_index` is handled differently)",
"is_bot": false,
"headline": "Cogroup set to dict; all cogroups use internal key",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-11-28T06:26:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "80f381facf97e6b5924ef5991ed22fa2ab392383",
"body": "The get() function was using the lower level `dict()` subroutine, which\nis now an issue since we are overriding __getitem__ to accommodate\ncogroups.\n\nThis patch re-implements get() so that it uses the Namelist dunder\nmethods.\n\nThanks to GitHub user @chunderbunny for reporting this issue.",
"is_bot": false,
"headline": "Override Namelist get() to handle cogroups",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0509dc34a265b4f1593fdc0a27a1ece85da2c18c",
"body": "Currently, if we pass a namelist through `Namelist()`, it will normall\nrecreate itself. This is not true for namelists containing cogroups,\nwhich will return Cogroup lists for the prinicipal cogroup key.\n\nFor example::\n\n >>> nml = f90nml.reads('&grp x = 1 / &grp x = 2 /')\n >>> print(nml)\n \n[…]\nfficult duality of treating the namelist simultaneously as a\nlist and a dict.)\n\nWe also fixed a bug where the `_cogroups` helper field was being reset.\nIt's now properly reconstructed from the values.",
"is_bot": false,
"headline": "Prevent Cogroup lists for Namelist(nml)",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5f116ac308c35ecf319040361ec6e41d1149b47d",
"body": "Fixed several issues with del operations, which were not at all working!\n\nAlso replaced `dict` parent calls with `OrderedDict`, which was both an\noutright error and also fixed some of the del issues.",
"is_bot": false,
"headline": "Stronger del support; OrderedDict parent class",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e6592f34fbaf9b7a024d93a7dcb8afe85c19451f",
"body": "del is now supported for cogroups via __delitem__ implementations.\n\nAlso removed some problematic super() usage; super() should only be used\nto reference the parent class within a class. We were using it to\naccess the parent class of a field in the class. This has been fixed by\nexplicitly referencing dict.\n\n(In truth, we should not even need super() and it should be sufficient\nto explicit reference the parent, but oh well.)",
"is_bot": false,
"headline": "del support; fixed super() errors",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9b647d69f51904e3dfd701b65f2ccab01abb0c0a",
"body": "Some cleanup of the Cogroup:\n\n- Cogroup keys is now a property\n\n- Cogroup values are now generated inside its __init__ rather than\n explicitly by the Namelist\n\n- Various comment cleanups",
"is_bot": false,
"headline": "Object-like refactor of Cogroup",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "76726a717e44d6ff7ada46b318492406262e530d",
"body": "A Cogroup class was introduced to create a direct link between the\ngenerated list of cogroups and the original values from the namelist.\n\nWithout this cogroup object, it is not possible to manipulate the list\nof groups, which are served as a new list when created via __getitem__.\n\nIndividual elements can now be replaced via the access.\n\nMuch work to do, but this is at least starting to work as expected.",
"is_bot": false,
"headline": "Cogroup class",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fd3a4cf45a468ccd492a118efc40c8d72b37910e",
"body": "This change tracks the cogroup keys in a list, and checks against them\non every __getitem__ call.\n\nThe cogroup list is now generated on __getitem__ rather than\npre-computing it. This avoids the messiness of updating the cogroup\nlist on every __setitem__.\n\nMaybe I will regret these decisions, but they are the simplest path to\nsomething functional.",
"is_bot": false,
"headline": "Key-based cogroup tracking",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6d3e1e791217067b883fde2224a0e29d69cbbe96",
"body": "Incorrectly used `lstrip` to remove a leading string, when I should have\nexplicitly removed the substring with an indexed slice.",
"is_bot": false,
"headline": "Bugfix: Replace 'lstrip' with slice",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3a20074b6de11b4223193cc17c8bb78522d03f93",
"body": "This is a proposal for tracking repeated groups while retaining their\ncurrent position.\n\n* Repeated groups are renamed as `'_grp_' + name + '_##'` where `name`\n is the group name and `##` is a counter.\n\n The original group would be unchanged.\n\n* Groups of the same name are tracked inside an intern\n[…]\n(excepting any formatting issues).\n\nThis does change the `Namelist`, and the `repr()` will look different\nand will not match the expected behavior, e.g. `nml[name]` will return a\nlist, not an element.",
"is_bot": false,
"headline": "Draft for in-place repeated groups",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-10-11T20:40:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "37bcdb0e599f74f09f10f895500ddf93646ac9bf",
"body": "The `count_values` function would count the number of available values\nin a statement, in order to determine if a value was present and\nassignable to the current variable.\n\nHowever, this function was currently attempting to count the total\nnumber of values, even though we only needed to determine if\n[…]\nue, and\nPhilip Cross for the proposed solution. Marshall Ward made some minor\nadjustments to the patch.\n\nCommit log authored by Marshall Ward.\n\nCo-authored-by: Marshall Ward <marshall.ward@gmail.com>",
"is_bot": false,
"headline": "count_values stops after two valid tokens",
"author_name": "Philip Cross",
"author_login": "pcro6",
"committed_at": "2021-10-11T20:31:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1de1048d8439bc3058339abc5fb5aa094fc6c7cb",
"body": "Added a test for namelists with repeated keys in the same group.",
"is_bot": false,
"headline": "Testing: Repeated keys",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-07-06T13:34:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e5bd5a2b7dfb42a31ce98459948b888f9979907e",
"body": "Squeeze 1d lists due to repeated variables",
"is_bot": false,
"headline": "Merge pull request #133 from malmans2/squeeze_1d_lists",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-07-02T16:02:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b8be5d212024e53ad6503afb48816cf3cd40bd4c",
"body": null,
"is_bot": false,
"headline": "Squeeze 1d lists due to repeated variables",
"author_name": "malmans2",
"author_login": "malmans2",
"committed_at": "2021-06-25T19:40:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c41eddd6b7dac33fa0d8bf177121ddb0fa8521fb",
"body": null,
"is_bot": false,
"headline": "Version 1.3.1 update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-26T01:54:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b15c502dbc2e2c19e12ec7c4ec58fefd3624454",
"body": null,
"is_bot": false,
"headline": "Merge branch 'main' of https://github.com/marshallward/f90nml",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-24T00:11:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "62be72f058ef4c08d0da6753d91f5f4db5a764f3",
"body": "This patch restores the original behavior of strings, where the default\npermits an individual string element to extend beyond the column width.\n\nString splitting is now enabled by the `split_strings` property of the\n`Namelist`.",
"is_bot": false,
"headline": "String split as option; default behavior restored",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-24T00:05:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cf82b992efb7735f2fa6f3ee19c772e587af1891",
"body": "Namelist properties had been declared in alphabetical order, but that\nseems to have diverged a bit. This patch reorders them alphabetically.",
"is_bot": false,
"headline": "Reorder Namelist properties alphabetically",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-23T14:43:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "af64e33efe88478864cb8957742659446725d72d",
"body": "Namelist properties had been declared in alphabetical order, but that\nseems to have diverged a bit. This patch reorders them alphabetically.",
"is_bot": false,
"headline": "Reorder Namelist properties alphabetically",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-23T14:41:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7b27456ce0482ac218b8e2a1d288dd0f35f85d35",
"body": "Several bugs had been introduced by the long string splitting methods\nwhen applied to lists of strings. Aside from arbitrarily splitting\nsmaller strings which would have previously remained on the current\nline, redunant commas were also being inserted into split values.\n\nAlthough the comma bug was \n[…]\napply a string split.\n\nWe also detected an error where trailing whitespace on the end of a\nstring split was dropped. This whitespace is now preserved.\n\nThanks to Jared Lewis for reporting this error.",
"is_bot": false,
"headline": "Bugfix: Do not split string if next line fits",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-22T21:50:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7690f2e4223cde03f34466dc85397639f9927e9a",
"body": "The string-splitting method is currently applied to lists of strings,\nand was incorrectly inserting commas at the split point.\n\nThis patch now only inserts a comma if the string has not been split.",
"is_bot": false,
"headline": "Bugfix: Do not insert commas on array string split",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-20T13:57:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b528b6ae76ef0b81f1ee023a0a8ba54e1e8e434",
"body": null,
"is_bot": false,
"headline": "AUR pkg config update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-18T00:33:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8ddd1230a7e7ee000cbf7ef23a0d44dec5b22925",
"body": null,
"is_bot": false,
"headline": "Version 1.3 update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-17T14:37:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "57ff283d9b4969230ad3a46813e678b344ef5848",
"body": null,
"is_bot": false,
"headline": "Testing: PEP8 cleanup of test_f90nml.py",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-17T14:00:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "782423f4ac77b3d82af5ebcbda9132a12a37492f",
"body": "Added a test case which includes a new group in the repatching. We now\ntest these three cases:\n* New variables in groups\n* New fields in derived types\n* New groups",
"is_bot": false,
"headline": "Testing: New group in patch",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-17T13:45:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1a0c3bcfcf08391be7ff4fa1cf6f32bb5466f75c",
"body": "`f90nml.patch` will append additional variables to an existing namelist\ngroup, but would not append new groups to an existing namelist.\n\nThis patch now gathers any remaining groups after a patch and now\nappends them to the target namelist.\n\nWe also have fixed a bug where indentation was being applied twice to\npatched values. The indent is now part of the variable's string and no\nlonger needs to be prepended.\n\nThanks to Cory Kramer for reporting this bug.",
"is_bot": false,
"headline": "Patch: Append additional namelists; indent bugfix",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-15T22:01:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dc5a70bcceb43e9b6afe1f8f33487b17e9a176e0",
"body": "The Python 3 implementation of splitlines uses a keyword, keepends, but\nthe Python 2 implementation does not. This patch removes the keyword\nand just retains the argument.",
"is_bot": false,
"headline": "Python 2: splitlines has no keyword",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-02T18:10:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a94f45338ccc4e6208a6447b4063fd4b33e43000",
"body": "The string parser function, reads(), used `splitlines` to produce a list\nof per-line output, but also stripped the endline characters.\n\nNormally the parser was robust enough to handle this, but it causes\nisses for any tokens outside of the namelist groups, and tended to drop\nthe final character (presumably assuming it was an endline).\n\nThis patch adds a keepends flag to splitlines, which retains the endline\nand keeps everything working.",
"is_bot": false,
"headline": "Preserve newlines in reads() string parser",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-05-02T17:57:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "86141c04ec566345ca1a0858c3660e2aedd7de13",
"body": null,
"is_bot": false,
"headline": "PEP257 Docstring update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T21:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "245998bb7d3296452bcf8c6437880b0667f42c79",
"body": null,
"is_bot": false,
"headline": "Merge branch 'master' of https://github.com/marshallward/f90nml",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T17:12:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7483ecb366889227a3e40cbe44dc18b04fd4f250",
"body": "I guess some people do use it :D",
"is_bot": false,
"headline": "Adding PyPy2 and 3 to GitHub Actions",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T17:12:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c126d83ae656e28e7160e381d68d7f34d1fdb59b",
"body": "Compress",
"is_bot": false,
"headline": "Merge pull request #123 from HoWol76/compress",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T17:10:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "07b27f2c36e008800ee86f3f8dd20eff10a089d1",
"body": "No one uses PyPy 2 anyway...",
"is_bot": false,
"headline": "Travis: Disable PyPy2",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T16:29:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fb17123a945b03a379556f8d8b36c5f41689839f",
"body": null,
"is_bot": false,
"headline": "Adding coveralls token",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T15:36:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dcf6e26a5934a7df5d9004756ff9eeedbebc4a1a",
"body": null,
"is_bot": false,
"headline": "GitHub Actions: First test",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-04T15:17:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8c739026e7892dec6c5cc4378be709363322970e",
"body": null,
"is_bot": false,
"headline": "README: DOI link update",
"author_name": "Marshall Ward",
"author_login": "marshallward",
"committed_at": "2021-02-01T19:32:54Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 9,
"commits_last_year": 13,
"latest_release_at": "2022-05-31T13:18:37Z",
"latest_release_tag": "v1.4.1",
"releases_from_tags": false,
"days_since_last_push": 13,
"active_weeks_last_year": 5,
"days_since_latest_release": 1521,
"mean_days_between_releases": 203.8
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 42,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": []
},
"popularity": {
"forks": 61,
"stars": 149,
"watchers": 9,
"fork_history": {
"days": [
{
"date": "2014-04-30",
"count": 1
},
{
"date": "2014-08-18",
"count": 1
},
{
"date": "2015-02-23",
"count": 1
},
{
"date": "2015-07-12",
"count": 1
},
{
"date": "2015-09-23",
"count": 1
},
{
"date": "2015-12-18",
"count": 1
},
{
"date": "2016-07-04",
"count": 1
},
{
"date": "2016-07-22",
"count": 1
},
{
"date": "2016-09-13",
"count": 1
},
{
"date": "2016-10-12",
"count": 1
},
{
"date": "2016-12-16",
"count": 1
},
{
"date": "2017-03-10",
"count": 1
},
{
"date": "2017-09-17",
"count": 1
},
{
"date": "2017-10-16",
"count": 1
},
{
"date": "2017-11-06",
"count": 1
},
{
"date": "2017-12-01",
"count": 1
},
{
"date": "2018-02-16",
"count": 1
},
{
"date": "2018-03-03",
"count": 1
},
{
"date": "2018-03-28",
"count": 1
},
{
"date": "2018-05-01",
"count": 1
},
{
"date": "2018-05-21",
"count": 1
},
{
"date": "2018-06-20",
"count": 1
},
{
"date": "2018-09-11",
"count": 1
},
{
"date": "2018-12-07",
"count": 1
},
{
"date": "2019-02-26",
"count": 1
},
{
"date": "2019-03-04",
"count": 1
},
{
"date": "2019-03-24",
"count": 1
},
{
"date": "2019-06-19",
"count": 1
},
{
"date": "2019-06-29",
"count": 1
},
{
"date": "2019-09-06",
"count": 1
},
{
"date": "2020-09-18",
"count": 1
},
{
"date": "2020-09-25",
"count": 1
},
{
"date": "2020-11-07",
"count": 1
},
{
"date": "2021-01-05",
"count": 1
},
{
"date": "2021-03-13",
"count": 1
},
{
"date": "2021-11-12",
"count": 1
},
{
"date": "2022-05-30",
"count": 1
},
{
"date": "2022-06-06",
"count": 1
},
{
"date": "2022-11-10",
"count": 1
},
{
"date": "2022-11-20",
"count": 1
},
{
"date": "2022-12-15",
"count": 1
},
{
"date": "2022-12-26",
"count": 1
},
{
"date": "2023-01-23",
"count": 1
},
{
"date": "2023-04-15",
"count": 1
},
{
"date": "2023-06-15",
"count": 1
},
{
"date": "2024-02-24",
"count": 1
},
{
"date": "2024-03-18",
"count": 2
},
{
"date": "2025-03-27",
"count": 1
},
{
"date": "2025-04-03",
"count": 1
},
{
"date": "2025-07-12",
"count": 1
},
{
"date": "2025-07-21",
"count": 1
},
{
"date": "2025-09-04",
"count": 1
},
{
"date": "2025-09-19",
"count": 1
},
{
"date": "2026-03-17",
"count": 1
},
{
"date": "2026-03-26",
"count": 1
},
{
"date": "2026-04-23",
"count": 1
},
{
"date": "2026-04-29",
"count": 1
},
{
"date": "2026-07-18",
"count": 1
}
],
"complete": true,
"collected": 59,
"total_forks": 61
},
"star_history": null,
"open_issues_and_prs": 28
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile",
"docs/Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [],
"largest_source_bytes": 54754,
"source_files_sampled": 13,
"oversized_source_files": 0,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"pyproject.toml",
"setup.cfg",
"setup.py",
"tests/requirements_test.txt"
],
"advisories": {
"error": "No resolved dependencies carried a version and a supported ecosystem",
"scope": "repository_graph",
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 1,
"direct_affected_count": 0
},
"ecosystems": [
"pypi"
],
"dependencies": [],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "coveralls",
"direct": false,
"version": null,
"ecosystem": "pypi"
}
],
"collected": true,
"truncated": false,
"total_count": 1,
"direct_count": 0,
"indirect_count": 1
}
},
"maintainership": {
"issues": {
"open_prs": 2,
"merged_prs": 33,
"open_issues": 26,
"closed_ratio": 0.81,
"closed_issues": 111,
"closed_unmerged_prs": 9
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "marshallward",
"commits": 671,
"avatar_url": "https://avatars.githubusercontent.com/u/462315?v=4"
},
{
"type": "User",
"login": "angrsp1",
"commits": 6,
"avatar_url": "https://avatars.githubusercontent.com/u/254206098?v=4"
},
{
"type": "User",
"login": "jamesp",
"commits": 5,
"avatar_url": "https://avatars.githubusercontent.com/u/22805?v=4"
},
{
"type": "User",
"login": "danielskatz",
"commits": 4,
"avatar_url": "https://avatars.githubusercontent.com/u/2913845?v=4"
},
{
"type": "User",
"login": "jenssss",
"commits": 3,
"avatar_url": "https://avatars.githubusercontent.com/u/37403847?v=4"
},
{
"type": "User",
"login": "naught101",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/167164?v=4"
},
{
"type": "User",
"login": "dalon-work",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/9160407?v=4"
},
{
"type": "User",
"login": "rgieseke",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/198537?v=4"
},
{
"type": "User",
"login": "MartinDix",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/1627802?v=4"
},
{
"type": "User",
"login": "guziy",
"commits": 2,
"avatar_url": "https://avatars.githubusercontent.com/u/900941?v=4"
}
],
"contributors_sampled": 22,
"top_contributor_share": 0.942
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"testing.yaml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": null,
"reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 5,
"reason": "4 out of 8 merged PRs checked by a CI test -- score normalized to 5",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 1,
"reason": "Found 3/19 approved changesets -- score normalized to 1",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 6 contributing companies or organizations",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 0,
"reason": "no update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 5,
"reason": "5 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": null,
"reason": "no releases found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 10,
"reason": "0 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "1a5def3d60b5b0e1616bfffd937e6fb6c5576255",
"ran_at": "2026-07-31T06:37:03Z",
"aggregate_score": 4.2,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-17T14:05:59Z",
"oldest_open_prs": [
{
"number": 117,
"created_at": "2020-05-17T07:36:07Z",
"last_comment_at": "2020-07-27T04:48:20Z",
"last_comment_author": "aekiss"
},
{
"number": 184,
"created_at": "2026-05-02T00:17:38Z",
"last_comment_at": "2026-07-16T22:38:24Z",
"last_comment_author": "MuellerSeb"
}
],
"last_merged_pr_at": "2026-07-17T14:04:09Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": [
{
"number": 24,
"created_at": "2016-02-29T16:28:13Z",
"last_comment_at": "2016-03-01T03:30:46Z",
"last_comment_author": "marshallward"
},
{
"number": 39,
"created_at": "2016-11-23T03:03:36Z",
"last_comment_at": "2019-06-09T15:51:20Z",
"last_comment_author": "jacobwilliams"
},
{
"number": 59,
"created_at": "2018-01-09T05:04:19Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 66,
"created_at": "2018-01-29T01:33:53Z",
"last_comment_at": "2018-08-09T00:36:56Z",
"last_comment_author": "marshallward"
},
{
"number": 74,
"created_at": "2018-04-26T14:52:47Z",
"last_comment_at": "2018-04-29T15:04:26Z",
"last_comment_author": "gitporst"
},
{
"number": 77,
"created_at": "2018-05-28T09:05:59Z",
"last_comment_at": "2019-06-29T14:48:56Z",
"last_comment_author": "marshallward"
},
{
"number": 79,
"created_at": "2018-05-28T10:12:02Z",
"last_comment_at": "2018-05-30T01:27:10Z",
"last_comment_author": "marshallward"
},
{
"number": 80,
"created_at": "2018-05-29T08:04:32Z",
"last_comment_at": "2019-09-06T12:14:42Z",
"last_comment_author": "marshallward"
},
{
"number": 84,
"created_at": "2018-09-13T16:28:22Z",
"last_comment_at": "2018-09-24T00:17:35Z",
"last_comment_author": "marshallward"
},
{
"number": 103,
"created_at": "2019-06-26T13:34:56Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 105,
"created_at": "2019-07-16T20:55:16Z",
"last_comment_at": "2019-07-17T17:12:19Z",
"last_comment_author": "marshallward"
},
{
"number": 110,
"created_at": "2019-11-23T16:23:36Z",
"last_comment_at": "2019-11-24T16:43:36Z",
"last_comment_author": "marshallward"
},
{
"number": 121,
"created_at": "2020-07-26T15:36:20Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 126,
"created_at": "2021-03-09T02:14:09Z",
"last_comment_at": "2021-03-09T04:05:53Z",
"last_comment_author": "marshallward"
},
{
"number": 127,
"created_at": "2021-03-31T17:15:37Z",
"last_comment_at": "2021-04-06T15:44:40Z",
"last_comment_author": "marshallward"
},
{
"number": 146,
"created_at": "2022-10-10T07:01:43Z",
"last_comment_at": "2022-10-10T14:14:54Z",
"last_comment_author": "marshallward"
},
{
"number": 156,
"created_at": "2023-07-06T17:46:59Z",
"last_comment_at": "2023-07-06T18:54:11Z",
"last_comment_author": "marshallward"
},
{
"number": 159,
"created_at": "2023-12-22T03:27:58Z",
"last_comment_at": "2023-12-22T14:22:11Z",
"last_comment_author": "marshallward"
},
{
"number": 160,
"created_at": "2024-01-29T03:08:34Z",
"last_comment_at": "2024-01-30T02:55:38Z",
"last_comment_author": "aidanheerdegen"
},
{
"number": 167,
"created_at": "2024-11-26T14:45:25Z",
"last_comment_at": "2025-05-14T02:08:54Z",
"last_comment_author": "marshallward"
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/marshallward/f90nml",
"host": "github.com",
"name": "f90nml",
"owner": "marshallward"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": "The weighted overall 52 is calibrated to 53 on the published index scale (record calibration 2026-08-02).",
"notes": [
{
"code": "overall_calibration",
"params": {
"raw": 52,
"calibrated": 53,
"calibration": "2026-08-02"
}
}
],
"value": 53,
"inputs": {
"security": 42,
"vitality": 46,
"community": 53,
"governance": 53,
"calibration": "2026-08-02",
"engineering": 69,
"ai_readiness": 41,
"weighted_overall_raw": 52
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "weak",
"name": "Vitality",
"value": 46,
"weight": 0.21,
"metrics": [
{
"key": "development_activity",
"band": "weak",
"name": "Development activity",
"note": null,
"notes": [],
"value": 48,
"inputs": {
"commits_last_year": 13,
"human_commit_share": 1,
"days_since_last_push": 13,
"active_weeks_last_year": 5
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 13 days ago",
"points": 28.8,
"status": "partial",
"details": [
{
"code": "push_recency",
"params": {
"days": 13
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "5/52 weeks with commits",
"points": 3.5,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 5
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "13 commits in the last year",
"points": 10.3,
"status": "partial",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 13
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "5 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5",
"points": 5,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "weak",
"name": "Release discipline",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 44,
"inputs": {
"releases_count": 9,
"latest_release_tag": "v1.4.1",
"releases_from_tags": false,
"days_since_latest_release": 1521,
"mean_days_between_releases": 203.8
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "9 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 9
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 1521 days ago",
"points": 0,
"status": "missed",
"details": [
{
"code": "release_recency",
"params": {
"days": 1521
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~203.8 days",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 203.8
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "exceptional",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "maintained",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": null,
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": 18,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "last human commit 18 days ago",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_maintained",
"params": {
"days": 18
}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "moderate",
"name": "Community & Adoption",
"value": 53,
"weight": 0.17,
"metrics": [
{
"key": "popularity",
"band": "moderate",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"forks": 61,
"stars": 149,
"watchers": 9,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "149 stars",
"points": 35.2,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 149
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "61 forks",
"points": 14.8,
"status": "partial",
"details": [
{
"code": "forks",
"params": {
"count": 61
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "9 watchers",
"points": 5,
"status": "partial",
"details": [
{
"code": "watchers",
"params": {
"count": 9
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"readme_badges": null,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"readme_badge_services": [],
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (Apache-2.0)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "Apache-2.0"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 53,
"weight": 0.23,
"metrics": [
{
"key": "maintainer_resilience",
"band": "at_risk",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 34,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 22,
"top_contributor_share": 0.942
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 94% of commits",
"points": 1.3,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 94
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "22 contributors",
"points": 13.5,
"status": "met",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 22
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 6 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "good",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"newcomer_pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 68,
"inputs": {
"merged_prs": 33,
"open_issues": 26,
"closed_issues": 111,
"prs_merged_7d": null,
"prs_decided_7d": null,
"prs_merged_30d": null,
"prs_decided_30d": null,
"issue_closed_ratio": 0.81,
"closed_unmerged_prs": 9,
"first_time_authors_30d": null,
"first_time_prs_merged_30d": null,
"first_time_prs_decided_30d": null
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "81% of issues closed",
"points": 34,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 81
}
}
],
"max_points": 42
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "33/42 decided PRs merged",
"points": 23.6,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 33,
"decided": 42
}
}
],
"max_points": 30
},
{
"key": "newcomer_pr_acceptance",
"name": "Newcomer PR acceptance",
"detail": "no first-time contributor's PR decided in 30d",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_newcomer_prs",
"params": {
"days": 30
}
}
],
"max_points": 13
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 3/19 approved changesets -- score normalized to 1",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 61,
"inputs": {
"followers": 88,
"owner_type": "User",
"is_verified": null,
"owner_login": "marshallward",
"public_repos": 115,
"account_age_days": 5751
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "88 followers of marshallward",
"points": 14,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 88,
"login": "marshallward"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "115 public repos, account ~15 yr old",
"points": 25,
"status": "met",
"details": [
{
"code": "public_repos",
"params": {
"count": 115
}
},
{
"code": "account_age_years",
"params": {
"years": 15
}
}
],
"max_points": 25
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "good",
"name": "Engineering Quality",
"value": 69,
"weight": 0.19,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 58,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "1 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 1
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "4 out of 8 merged PRs checked by a CI test -- score normalized to 5",
"points": 10,
"status": "partial",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "excellent",
"name": "Documentation",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"topics": [
"python",
"fortran",
"namelist",
"parser"
],
"has_wiki": true,
"homepage": null,
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": "4 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 4
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "weak",
"name": "Security",
"value": 42,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "weak",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): Branch-Protection, Packaging, Signed-Releases. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"branch_protection",
"packaging",
"signed_releases"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 42,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 15,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 3,
"scorecard_aggregate": 4.2
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "4 out of 8 merged PRs checked by a CI test -- score normalized to 5",
"points": 1.2,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 3/19 approved changesets -- score normalized to 1",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 6 contributing companies or organizations",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "no update tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "5 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5",
"points": 3.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "0 existing vulnerabilities detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "exceptional",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"commit_weight_rule": {
"min_commits": 50,
"min_commit_share": 0.1
},
"review_only_matches": 0,
"below_threshold_exposures": [],
"assessed_self_published_locations": 11
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "weak",
"name": "AI Readiness",
"value": 41,
"weight": 0.04,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 34,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.64,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "64 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 34.1,
"status": "partial",
"details": [
{
"code": "legible_history",
"params": {
"legible": 64,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "weak",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [],
"has_dockerfile": false,
"typed_language": false,
"bootstrap_files": [
"Makefile",
"docs/Makefile"
],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0,
"toolchain_manifests": [],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile, docs/Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile, docs/Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "moderate",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"primary_language": "Python",
"largest_source_bytes": 54754,
"source_files_sampled": 13,
"oversized_source_files": 0
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Python without a type-check config",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_typecheck_config_language",
"params": {
"language": "Python"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "0/13 source files over 60KB",
"points": 55,
"status": "met",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 13,
"oversized": 0
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
}
],
"classification": {
"top": [],
"labels": [],
"scores": {
"cli": 2
},
"primary": null,
"evidence": [
{
"tier": "description",
"label": "cli",
"source": "description:cli",
"weight": 2
}
],
"artifacts": [],
"confidence": "none",
"host_extension": false,
"runs_as_process": false,
"consumed_by_code": false
},
"metrics_version": "2.5.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"No resolved dependencies carried a version and a supported ecosystem"
],
"report_type": "repository",
"generated_at": "2026-07-31T06:37:23.088872Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/m/marshallward/f90nml.svg",
"full_name": "marshallward/f90nml",
"license_state": "standard",
"license_spdx": "Apache-2.0"
}