@@ -14624,6 +14624,7 @@ static const char *const py_reexport_calls[][2] = {
1462414624 {"ctl_from_cls", "direct.impl.Direct"},
1462514625 {"ctl_from_fn", "direct.impl.direct_fn"},
1462614626 {"lazy_tc", "lz.lazy_mod.Lazy"},
14627+ {"doc_reexport", "docp.impl.Doc"},
1462714628};
1462814629enum { PY_REEXPORT_N_CALLS = sizeof(py_reexport_calls) / sizeof(py_reexport_calls[0]) };
1462914630
@@ -14633,7 +14634,7 @@ enum { PY_REEXPORT_N_CALLS = sizeof(py_reexport_calls) / sizeof(py_reexport_call
1463314634static const char *const py_reexport_excluded[][2] = {
1463414635 {"excl_unlisted", "pkg.all_mod.Unlisted"}, {"excl_private", "pkg.star_mod._private_fn"},
1463514636 {"excl_shadowed", "shad.impl.Gone"}, {"excl_barrier", "barr.impl.Before"},
14636- {"excl_compat", "cmp.types_only.Shim"},
14637+ {"excl_compat", "cmp.types_only.Shim"}, {"excl_fstring", "fsp.impl.Kept"},
1463714638};
1463814639enum { PY_REEXPORT_N_EXCLUDED = sizeof(py_reexport_excluded) / sizeof(py_reexport_excluded[0]) };
1463914640
@@ -14693,13 +14694,28 @@ static int py_reexport_run(bool parallel, bool incremental, bool *lsp, bool *exc
1469314694 " except ImportError:\n Shim = None\n");
1469414695 write_temp_file(tmp, "app/cmp/types_only.py", "class Shim:\n pass\n");
1469514696 write_temp_file(tmp, "app/cmp/runtime_impl.py", "class Shim:\n pass\n");
14697+ /* The sql/expression.py shape of sqlalchemy: docstrings and a __future__
14698+ * import around the re-exports; an f-string with a field stays a barrier. */
14699+ write_temp_file(tmp, "app/docp/__init__.py",
14700+ "\"\"\"Package docstring.\"\"\"\n"
14701+ "from __future__ import annotations\n"
14702+ "from .impl import Doc\n"
14703+ "alias = Doc\n"
14704+ "\"\"\"Attribute docstring.\"\"\"\n");
14705+ write_temp_file(tmp, "app/docp/impl.py", "class Doc:\n pass\n");
14706+ write_temp_file(tmp, "app/fsp/__init__.py",
14707+ "from .impl import Kept\n"
14708+ "f\"{Kept}\"\n");
14709+ write_temp_file(tmp, "app/fsp/impl.py", "class Kept:\n pass\n");
1469614710 write_temp_file(tmp, "app/main.py",
1469714711 "from app import pkg\n"
1469814712 "from app import cyc\n"
1469914713 "from app import shad\n"
1470014714 "from app import barr\n"
1470114715 "from app import lz\n"
1470214716 "from app import cmp\n"
14717+ "from app import docp\n"
14718+ "from app import fsp\n"
1470314719 "from app.db import models\n"
1470414720 "from app.pkg import Explicit, Listed, Deep, star_fn, Renamed\n"
1470514721 "from app.direct.impl import Direct, direct_fn\n\n\n"
@@ -14725,6 +14741,8 @@ static int py_reexport_run(bool parallel, bool incremental, bool *lsp, bool *exc
1472514741 "def excl_barrier():\n barr.Before()\n\n\n"
1472614742 "def excl_compat():\n cmp.Shim()\n\n\n"
1472714743 "def lazy_tc():\n lz.Lazy()\n\n\n"
14744+ "def doc_reexport():\n docp.Doc()\n\n\n"
14745+ "def excl_fstring():\n fsp.Kept()\n\n\n"
1472814746 "def ctl_from_cls():\n Direct()\n\n\n"
1472914747 "def ctl_from_fn():\n direct_fn()\n");
1473014748 for (int i = 0; parallel && i < 52; i++) {
@@ -23459,26 +23477,32 @@ TEST(pipeline_python_namespace_codec_owns_ordered_facts) {
2345923477}
2346023478
2346123479TEST(pipeline_python_namespace_codec_rejects_non_authoritative_rows) {
23462- /* Numeric values below are the frozen version-1 namespace wire values.
23463- * Even an empty LSP array must validate its namespace envelope. */
23480+ /* Numeric values below are the frozen namespace wire values (version 2
23481+ * changed which statements extraction proves harmless, not the wire
23482+ * shape). Even an empty LSP array must validate its namespace envelope,
23483+ * and a payload of an older facts version is no authority: its facts
23484+ * were extracted under other rules, so the incremental run that reads
23485+ * it re-extracts in full. */
2346423486 const char *bad[] = {
2346523487 "{\"v\":1,\"lsp\":[]}",
2346623488 "{\"v\":3,\"lang\":1,\"lsp\":[]}",
2346723489 "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":null}",
2346823490 "{\"v\":3,\"lang\":1.0,\"lsp\":[],\"py\":null}",
2346923491 "{\"v\":3,\"v\":3,\"lang\":0,\"lsp\":[],\"py\":null}",
23470- "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":1 ,\"lang\":1,"
23492+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":2 ,\"lang\":1,"
2347123493 "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":3,\"failure\":2,\"events\":[]}}",
23494+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":1,\"lang\":1,"
23495+ "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":2,\"failure\":0,\"events\":[]}}",
2347223496 "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":99,\"lang\":1,"
2347323497 "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":2,\"failure\":0,\"events\":[]}}",
23474- "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":1 ,\"lang\":1,"
23498+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":2 ,\"lang\":1,"
2347523499 "\"module\":\"p.m\",\"path\":\"m.py\\u0000suffix\",\"status\":2,"
2347623500 "\"failure\":0,\"events\":[]}}",
23477- "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":1 ,\"lang\":1,"
23501+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":2 ,\"lang\":1,"
2347823502 "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":2,\"failure\":0,\"events\":["
2347923503 "{\"k\":999,\"d\":0,\"s\":0,\"r\":0,\"f\":0,\"l\":0,"
2348023504 "\"n\":null,\"m\":null,\"i\":null,\"a\":[]}]}}",
23481- "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":1 ,\"lang\":1,"
23505+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"py\":{\"v\":2 ,\"lang\":1,"
2348223506 "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":2,\"failure\":0,\"events\":["
2348323507 "{\"k\":8,\"d\":0,\"s\":1,\"r\":0,\"f\":0,\"l\":4294967296,"
2348423508 "\"n\":null,\"m\":null,\"i\":null,\"a\":[]}]}}",
@@ -23498,7 +23522,7 @@ TEST(pipeline_python_namespace_codec_rejects_non_authoritative_rows) {
2349823522 cbm_arena_destroy(&arena);
2349923523 }
2350023524 const char *unknown =
23501- "{\"v\":3,\"lang\":1,\"lsp\":[],\"reg\":[],\"py\":{\"v\":1 ,\"lang\":1,"
23525+ "{\"v\":3,\"lang\":1,\"lsp\":[],\"reg\":[],\"py\":{\"v\":2 ,\"lang\":1,"
2350223526 "\"module\":\"p.m\",\"path\":\"m.py\",\"status\":2,\"failure\":0,\"events\":["
2350323527 "{\"k\":7,\"d\":0,\"s\":0,\"r\":7,\"f\":0,\"l\":0,"
2350423528 "\"n\":null,\"m\":null,\"i\":null,\"a\":[]}]}}";
@@ -23511,6 +23535,7 @@ TEST(pipeline_python_namespace_codec_rejects_non_authoritative_rows) {
2351123535 facts.facts.items[0].kind == CBM_PY_NS_UNKNOWN &&
2351223536 facts.facts.items[0].reason == CBM_PY_NS_REASON_PARSE;
2351323537 cbm_arena_destroy(&arena);
23538+ ASSERT_EQ(CBM_PY_NAMESPACE_FACTS_VERSION, 2u); /* the rows above spell it */
2351423539 ASSERT_TRUE(rejected);
2351523540 ASSERT_EQ(unknown_rc, 1);
2351623541 ASSERT_EQ(equal_rc, 0);
0 commit comments