Repository navigation
obelize upgrade now writes part of a repository where the library keeps its import name, which it
wrote whole or not at all, and takes --from where a manifest declares the library, which it took
only where none did. With 0.9.0 its dry run wrote a file for none of 80 public repositories; with
this release it writes one for 5 of them, and a trial of those 5 passed for 1 (the benchmark below
says how small that is).
A move can be partial now. A file that holds a place the pack can only flag is left as it was, the
others are written, and the summary, REPORT.md, the commit message of --branch, the pull request
of the action and trial.json name the files left and say that a passing trial does not show the
rest has moved. Without --branch such a move ends 4, as fix --apply does where places are left
for you. A pin that rules out the release --from names (pydantic==2.5.0 with --from 1.10.26)
stops the plan, where the pack's floor let it through in 0.9.0. Everything else is reached as it
was: fix, scan, --pack and an upgrade with an agent set up (--agent, or agent.backend in
your own file) keep the rule of one repository whole or not at all, and scan and fix with the
bundled packs gave the same output as 0.9.0 on the repositories of the test suite and the examples.
Benchmark
I took the dry run of obelize upgrade again with this release, over the same 80 public
repositories at the same commits (twenty each that still use the old API of pydantic 1, SQLAlchemy
1.4, urllib3 1 and pandas 2), so its records read obelize 0.10.0. With no pack it writes a file for
5 and none for the other 75: 32 stop before planning, 32 are held and 11 have no usage of a name the
pack lists. The 0.9.0 dry run wrote no file for any (36 stopped, 33 were held and 11 had no usage).
The 5 are all pydantic. It finds 944 usages: 78 are places a rule would rewrite (all in pydantic,
rename_member), the pack only flags 810 and 56 are held for a cause of its own, and 14 are in a
file the dry run would write; 0.9.0 found the same 944, none of them in a file it would write. Of the
32 that stop, 14 stop on a manifest that declares the library in a way the pack does not take
(legacy_version_unsupported; 18 with 0.9.0, of which 12 do not stop now, and 8 that were held do)
and 18 on a declared Python that the new release does not run on. 4 of the 5 that write had stopped
on legacy_version_unsupported with 0.9.0, and 1 was held by a place left.
The trial, which installs the dependencies of a repository and runs its tests, is measured for the
first time, in a box that reaches only the package index, over the 5 whose plan writes a file (the
results). It passed for 1 (with 20 places left for a person
and 3 tests compared), could not install the dependencies of 3 and got no test result from 1. The 3
have three causes: no recipe uv knows, a package that builds against a system library the image
lacks, and a requirement on a GitHub URL, which the box does not reach. That is one repository and
not a rate: n is 5 of 80, drawn by code search of repositories that import the old API, and a pass
means that the tests that passed before still pass, 3 of them here. It says nothing about the 20
places left for a person or about code no test reaches. The box is arm64 Linux, has no GitHub and
lacks system libraries.
What limits the number now is the pack. A pack made from two releases mostly flags: 810 of the 944
usages (85.8%) are places it only flags and never rewrites, and in pandas, SQLAlchemy and urllib3
none of the 663 is a place a rule would rewrite, so those three frames write nothing.
scan and fix with the bundled packs gave the same output as 0.9.0 on the repositories of the test
suite and the examples, and the fixtures of the packs are unchanged and pass, so Gate 1's scan and
the three fix dry runs are the records 0.9.0 made and read obelize 0.9.0; they were not taken
again.
Unsupported patterns
What the 0.9.0 list says still holds, except what it says of upgrade with no pack: that --from
counts only where no manifest declares the library, and that a repository is written only when
nothing in it is left. This release changes both, and what is unsupported now is:
- A pack made from two releases rewrites a name that the library's own message says to replace with
a name that exists in the newer release, and a name that left a submodule for its package, and
reports the rest. In these frames a rule rewrites something for pydantic only (rename_member). - A file with a place the pack only flags is left as it was, so a written move is partial where one
exists: the files that hold such places run on the new release until someone moves them, and a
passing trial does not say they are done. 30 of the 32 held repositories have such a place, and 2
have a file the scan cannot parse. A dependency line the rule cannot write (a requirement with
extras the new release does not list), a notebook, a stub, a.pywscript and a file obelize
could not open still hold the whole repository, and so dofix,scan,--packand anupgrade
with an agent set up. - A declaration of the library that rules out the release
--fromnames, or that obelize cannot
read, stops the plan: 14 of the 80 stop onlegacy_version_unsupported. - The trial is measured over 5 repositories, of which 1 passed. A repository whose dependencies need
a system library the box lacks, or a requirement on GitHub, ends as an error there.
The formats that changed: none of the JSON Schemas, and not the pack format. trial.json, which has
no schema, gains held, the files the move left as they were. In run.json, packs[].stated is
also set where every declaration of the library admits the release --from names and is never set
together with assumed, and blocked is legacy_version_unsupported also for a declaration that
rules that release out, which the pack's floor passed on its own in 0.9.0. The exit code of
upgrade --apply is 4 where a passing trial left places for you; a move to another distribution
that left places (PyPDF2 to pypdf) ended 0 in 0.9.0 when no verification command of your own
ran.
Added
- The harness that measures the trial (
bench/trial_box.py,bench/trial_collect.py,
bench/trial_score.pyandbench/trial/) is a tool of the repository, in neither the wheel nor
the source distribution: installing obelize adds no Docker code and no way to run another
repository's tests. The trial ofupgrade --applythat you run is unchanged by it.
Changed
obelize upgrade --from <release>takes that release for the one in use where every dependency
file that declares the library admits it, and not only where none declares it:pydantic,
pydantic<2,pydantic>=1.8andpydantic = "^1.9.1"all admit--from 1.10.26. The plan goes
with your word against the file's, says so in its summary and inREPORT.md, and a dry run does
not check it;--applydoes, with your tests. A declaration that rules the release out
(pydantic==2.5.0,pydantic>=2,pydantic<1.5), or that obelize cannot read, stops the plan
and says so, including one that reached the pack's floor on its own, which--fromwas not asked
about before. Where the pack would take a release of its own for such a declaration (its newest,
forpydantic>=1.8), your--fromis the release the plan takes and says, andrun.json
records it asstatedand not asassumed.fix,scan,--packand anupgradewithout
--fromare gated as they were
(the decision).obelize upgradewrites a file at a time where the library keeps its import name (one
distribution for both APIs:pydantic,SQLAlchemy,openai,numpy), in its dry run, in the
trial's migration and in the write after a passing trial. A file that holds a place the pack can
only flag is left as it was, every other file is written, and the dependency line follows the
files written, where a single such place used to hold the whole repository back. The trial runs
your tests on the move as it would be written and writes nothing if one that passed before fails.
The summary,REPORT.md(a Held back section), the commit message of--branch, the pull request
of the action andtrial.json(held) name the files left and say that a pass does not show that
the rest has moved. Without--branchthe command ends4for such a move, asfix --applydoes
where places are left for you, and0where none is, whether a verification command of your own
ran or not; with--branchit ends0after the commit either way, so read the text. A dry run
that plans part of a repository ends with theupgradecommand that writes it, notfix --apply,
which would write none of it. The whole repository is still held where no file can be written,
where the dependency line cannot be written, and forfix,scanand--pack, and for an
upgradewith an agent set up (--agent, oragent.backendin your own file), whose dry run,
trial and write all keep that rule, since the agent is asked about the places only when a first
run of the rules writes nothing, and whose dry run says the agent is why.upgrade numpyand
upgrade openaiwrite the files that hold no place where 0.9.0 wrote none
(the decision).- The upgrade mode of the action names the files a partial move left in the commit message and in
the pull request ("Left as they were, for you to change"), and a name of such a file that the
action would not write itself (tools/run:all.py, a decomposed Unicode name) is only shown as
text, so it does not refuse a branch that was written whole. - A trial of
obelize upgradethat changed no file says what held the repository: a place left in a
file, a dependency line it cannot write, or a notebook, a stub or a file it could not open that
may call the library. 0.9.0 said only that it changed no file.