Skip to content

port: pycountry==26.2.16#177

Draft
ada-x64 wants to merge 1 commit into
mainfrom
feat/port-pycountry
Draft

port: pycountry==26.2.16#177
ada-x64 wants to merge 1 commit into
mainfrom
feat/port-pycountry

Conversation

@ada-x64
Copy link
Copy Markdown
Contributor

@ada-x64 ada-x64 commented May 7, 2026

Closes #111.

What

Adds the pycountry (26.2.16)
ISO country / language / currency / script database wrapper to the
Nanvix CPython port:

  • Appends pycountry==26.2.16 to requirements/site-packages-extra.txt
    under the existing Runtime and typing helpers section,
    alphabetically between platformdirs and python-dotenv.
  • Adds tests/func/test_110_pycountry.py — a single-file smoke test in
    the canonical test_NNN_<pkg>.py shape (cf.
    tests/func/test_020_click.py). Three lookups, one per independent
    database file (countries.get(alpha_2='US'),
    currencies.get(alpha_3='EUR'), languages.get(alpha_3='eng')), so a
    missing or unreadable JSON surfaces as a specific FAIL rather than a
    generic import error.
  • Adds a new ### Locale and ISO data sub-section to doc/packages.md
    under ## Extra Packages (sentence-case, mirroring the existing
    extra-side heading style); pycountry is the inaugural row.
  • Back-fills the missing pluggy 1.6.0 row in doc/packages.md under
    ## Base Packages### Core utilities. pluggy was added to
    requirements/site-packages-base.txt in pluggy: add pluggy==1.6.0 to site-packages-base + smoke test #176 but the documentation
    row never landed and the table is meant to be exhaustive.

Four-path diff: one requirements/ line, one new test file, one
doc/packages.md edit (new sub-section + pluggy back-fill row). No
edits to .nanvix/, patches/, Modules/Setup.local, or any other
manifest.

Why

pycountry is upstream Tier-2: pure Python (~40 KiB of source, no
runtime dependencies, py3-none-any wheel), but it ships ~20 MiB of
bundled package data (1.4 MiB of ISO JSON databases plus 18.6 MiB of
Debian iso-codes .mo translation catalogs). Its stdlib surface is
json / os.path / importlib.resources / importlib.metadata /
unicodedata / threading / logging — all enabled on Nanvix CPython.

The unusual axis is importlib.resources.files(). pycountry computes
LOCALES_DIR and DATABASE_DIR at import time via
str(_importlib_resources.files("pycountry") / "<subdir>") and then
feeds the resulting path to plain open(). That assumes the
Traversable returned by files() is filesystem-backed; for a
MultiplexedPath or ZipPath the cast would yield a string open()
cannot resolve. Pre-implementation verification across standalone
(ramfs, bytecode-only, dist-info trimmed) and single-process
(Linux-backed VFS) modes confirmed the cast resolves to a real
PosixPath in both — pycountry is a regular package, not a namespace
package — and that all 7 JSON databases plus all 614 .mo files
survive _create_stripped_sysroot and _precompile_pyc. No stdlib
gap, no patch, no shim.

Decisions

  • Install pathway. Use the existing pure-Python manifest
    (requirements/site-packages-{base,extra}.txt) plus the host-side
    pip install --target step in .nanvix/z.py. No new
    .nanvix/pycountry.py, no patches/pycountry/, no vendored copy.
  • -base vs -extra bucket. Unlike the prior pure-Python siblings
    (srt, iniconfig, schedule, pluggy — all <1 MiB and all
    -base.txt), pycountry ships ~20 MiB of bundled package data. That
    clears the "heavyweight or optional" bar for -extra.txt.
  • Acceptance bar. Smoke-only, matching the existing
    tests/func/test_NNN_<pkg>.py convention. pycountry's upstream
    tests/ suite is intentionally not invoked from here — it tests
    Python semantics, not the Nanvix port.
  • No console scripts. pycountry declares none; nothing to drop.
  • Numbering. NNN = 110 chosen as max+1 over tests/func/
    (previous high watermark: test_109_pluggy.py).
  • doc/packages.md. New ### Locale and ISO data sub-section is
    the first locale/ISO-data grouping; pycountry would otherwise have to
    squat under an awkwardly-named existing heading. The pluggy row is
    back-filled in the same edit because the table is meant to be
    exhaustive and the omission was a drift, not a deliberate exclusion.

Caveat: ramfs delta and the bundled locales tree

This is the largest single-package delta in the pure-Python porting
series so far: image grows from 81.1 MiB to 111.2 MiB, a +30.07 MiB /
+37.07 % step. The dominant contribution is the ~19 MB
pycountry/locales/ tree
(~22 MB upstream wheel; 18.6 MiB on the
staged sysroot after install-time pruning), which ships intact and
deliberate
as part of this PR rather than being stripped by a
port-specific carve-out in .nanvix/z.py.

Rationale:

  • pycountry's own runtime never imports gettext or touches .mo
    files; the catalogs are shipped for downstream consumers that want
    translated ISO names.
  • There is no precedent in .nanvix/z.py for per-package data
    stripping; introducing one here would set a load-bearing convention
    for every subsequent data-bearing port.
  • Reactive stance: if reviewer feedback or image-budget pressure says
    the locales tree is unacceptable, a follow-up PR can add a targeted
    strip — either as a wholesale pycountry/locales/ removal or as a
    configurable subset. Happy to do that here instead if the reviewer
    prefers; flagging the carve-out option explicitly so the decision is
    visible rather than implicit.

Test plan

Local verification per AGENTS.md, all three deployment modes, on
this branch's tip:

./z distclean; ./z clean; NANVIX_DEPLOYMENT_MODE=$MODE ./z setup; ./z build; ./z test
MODE Result pycountry
standalone passed PASS
single-process 108 passed, 0 failed, 0 skipped PASS
multi-process passed PASS

(Single-process aggregate captured during a clean-state retry after a
runner-side no-output flake on the first sweep; standalone and
multi-process passed first try without the per-mode aggregate
transcribed.) CI exercises the full platform matrix per
doc/contributing.md step 5.

Diff scope

  • requirements/site-packages-extra.txt — +1 line.
  • tests/func/test_110_pycountry.py — new file, ~20 lines.
  • doc/packages.md — new ### Locale and ISO data sub-section under
    ## Extra Packages with the pycountry row; one back-fill row for
    pluggy 1.6.0 under ## Base Packages### Core utilities.

No other paths touched.

Ramfs size increase

Measured on a clean tree (standalone mode) via the commit-then-measure
protocol: build at HEAD~1 (baseline, pre-pycountry) then build at
HEAD (with pycountry landed), ./z distclean; ./z clean; NANVIX_DEPLOYMENT_MODE=standalone ./z setup; ./z build between each.

baseline with pycountry delta
ramfs image (nanvix_rootfs.img) 85,053,440 B 116,584,448 B +31,531,008 B (+30.07 MiB)
files in ramfs 4,804 5,429 +625

Per-tree breakdown of the new payload (du -sb against
.nanvix/sysroot/lib/python3.12/site-packages/pycountry/):

subtree bytes MiB
pycountry/locales/ 19,512,841 18.61
pycountry/databases/ 1,469,785 1.40
pycountry/ total install 21,018,461 20.04

New ramfs paths (non-locales; the 614
pycountry/locales/<lang>/LC_MESSAGES/iso*.mo entries are elided for
brevity):

  • lib/python3.12/site-packages/pycountry-26.2.16.dist-info/METADATA
  • lib/python3.12/site-packages/pycountry/COPYRIGHT.txt
  • lib/python3.12/site-packages/pycountry/__init__.pyc
  • lib/python3.12/site-packages/pycountry/db.pyc
  • lib/python3.12/site-packages/pycountry/databases/iso15924.json
  • lib/python3.12/site-packages/pycountry/databases/iso3166-1.json
  • lib/python3.12/site-packages/pycountry/databases/iso3166-2.json
  • lib/python3.12/site-packages/pycountry/databases/iso3166-3.json
  • lib/python3.12/site-packages/pycountry/databases/iso4217.json
  • lib/python3.12/site-packages/pycountry/databases/iso639-3.json
  • lib/python3.12/site-packages/pycountry/databases/iso639-5.json

pycountry's actual payload is ~20 MiB on disk; the gap to +30 MiB on
the image is mkramfs block-alignment overhead, consistent with prior
data-bearing ports. Net: +30.07 MiB on a now-111.2 MiB image
(+37.07 % of the previous image, +27.05 % of the new one).

Checklist

  • Four-path diff matches the design's Files changed table
  • Smoke test follows the test_NNN_<pkg>.py convention
  • pycountry: PASS verified locally in standalone, single-process,
    and multi-process modes
  • No .nanvix/ / patches/ / Modules/Setup.local edits
  • Ramfs size delta measured (see above)
  • doc/packages.md updated (new sub-section + pluggy back-fill)
  • Closes upstream issue Support package: pycountry #111

Add pycountry under '# Runtime and typing helpers' in
requirements/site-packages-extra.txt, list it in doc/packages.md
under a new '### Locale and ISO data' sub-section, and back-fill
the missing pluggy row under the existing Base sub-section. New
tests/func/test_110_pycountry.py exercises three independent ISO
JSON databases (countries, currencies, languages).

Closes #111
Copilot AI review requested due to automatic review settings May 7, 2026 16:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ports pycountry into the Nanvix CPython distribution as an extra pure-Python package, adds a functional smoke test to validate bundled ISO databases are readable at runtime, and updates the package documentation (including back-filling the missing pluggy entry).

Changes:

  • Add pycountry==26.2.16 to requirements/site-packages-extra.txt.
  • Add tests/func/test_110_pycountry.py smoke test covering country/currency/language lookups.
  • Update doc/packages.md to document pycountry under a new “Locale and ISO data” subsection and add the missing pluggy 1.6.0 row.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
requirements/site-packages-extra.txt Adds pycountry==26.2.16 to the extra runtime helper set.
tests/func/test_110_pycountry.py Adds a smoke test validating pycountry lookups (countries/currencies/languages).
doc/packages.md Documents pycountry under a new extra subsection and adds a pluggy row to Base Packages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/packages.md
@ada-x64 ada-x64 marked this pull request as ready for review May 7, 2026 16:42
@ada-x64 ada-x64 requested a review from ppenna May 7, 2026 16:43
@ppenna ppenna self-assigned this May 7, 2026
@ppenna ppenna added the wontfix This Will Not Be Worked On for Now label May 7, 2026
@ppenna ppenna marked this pull request as draft May 7, 2026 16:54
@ppenna
Copy link
Copy Markdown
Contributor

ppenna commented May 7, 2026

Making this a draft and tagging this as "wontfix" because it bloats the ramfs image way more than we can affort.

@ada-x64
Copy link
Copy Markdown
Contributor Author

ada-x64 commented May 7, 2026

Closing as wontfix per maintainer feedback: ramfs bloat (~30 MiB / +37 %) exceeds image budget. The bundled tree (~19 MiB of .mo translation catalogs) is the dominant contributor; pycountry's own runtime never touches them. A future port could revisit with a port-specific carve-out in .nanvix/z.py to drop the locales subtree.

@ada-x64 ada-x64 closed this May 7, 2026
@ada-x64 ada-x64 deleted the feat/port-pycountry branch May 7, 2026 17:00
@ppenna ppenna restored the feat/port-pycountry branch May 7, 2026 17:04
@ppenna
Copy link
Copy Markdown
Contributor

ppenna commented May 7, 2026

@ada-x64 keep it open so the branch stays around.

@ppenna ppenna reopened this May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wontfix This Will Not Be Worked On for Now

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support package: pycountry

3 participants