. "$BST_LIB" # BST-TIMEOUT: 1200 # TWO python3 starts, and they are the bulk of the cost. # # Every other case here reads the filesystem or dpkg with # # shell builtins, or greps the second start's output. # # # # The two are: one `importlib.import_module' call (so the # # import result is legible from the console without reading # # a transcript) and the probe, which takes ONE start for # # sixty-odd measurements. # # # # THE PROBE FORKS NOTHING. It has no fixtures to build and # # no children to spawn -- see the note in the probe about # # why a stub-only distribution has nothing to drive. It # # reads nineteen files, sha256s them, and parses fourteen. # # That is a smaller budget than the 1800 the probes with # # /bin/sh children beside it take, and 1200 is what the # # pure-python probes in this directory use. # # # # NOTHING HERE SLEEPS, opens a socket, starts a thread, or # # reaches a device, a peer or a terminal. Nothing is # # written anywhere: this suite is entirely read-only, which # # is unusual here and is a property of the package. # # python3-types-psutil 5.9.5.20240316 (meta-openembedded meta-python, # recipes-devtools/python/python3-types-psutil_5.9.5.20240316.bb, `inherit pypi # setuptools3', PyPI sdist) on the wasm32-hwjs glibc image. # # ============================================================================ # WHAT THE PACKAGE IS, AND WHAT THAT MAKES THE SUITE ASSERT. # ============================================================================ # # It is the typeshed stub distribution for `psutil': a `psutil-stubs' directory # of fourteen `.pyi' files plus a `METADATA.toml', carrying type declarations # for the process, CPU, memory, disk, network and sensor APIs. There is NOT ONE # EXECUTABLE LINE in the whole distribution -- no `.py', no `.so', no console # script, no entry point. `install_requires' is empty and it does not require # `psutil' itself to be installed. # # So there is no behaviour to drive, and a suite that pretended otherwise would # be asserting things it made up. What CAN be asserted, and what this suite # does, is three things: # # 1. PACKAGING -- that the files the wheel promises are the files on disk, # byte for byte, scored against the wheel's OWN `RECORD' rather than # against a list typed into this suite; # 2. PARSE -- that this arm's interpreter can compile every `.pyi' with its # own `ast.parse' in type-comment mode. This is the one genuine demand a # stubs package makes of a ported interpreter, and it is a real one: stub # syntax is a corner of the grammar -- `@overload' stacks, `TypeAlias', # PEP 604 unions in annotation position, `...' as an entire function body, # `if sys.platform' at class scope -- that appears almost nowhere else in # this image's python payload; # 3. STRUCTURE -- that a sample of the declarations is really there, because # an empty file parses perfectly and "it parsed" would otherwise pass a # truncated install. # # ---------------------------------------------------------------------------- # THE ONE THING THIS SUITE SAYS THAT THE TICKET GOT WRONG. # ---------------------------------------------------------------------------- # # The ticket asks the suite to assert that "importing the stubs as a module is # *not* possible, which is the documented behaviour of a stubs-only package". # Half of that is right and half of it is not, and the difference was MEASURED # rather than reasoned about -- on an x86-64 control, against this build's own # .deb payload. # # - AS AN IMPORT STATEMENT it is right, and for a reason that has nothing to # do with this image or with stubs: `psutil-stubs' is not an identifier, so # `import psutil-stubs' is a SyntaxError in any CPython. # (`import-stmt-syntaxerror') # # - AS `importlib.import_module("psutil-stubs")' IT SUCCEEDS. PEP 420 makes # any directory on sys.path a namespace-package portion whatever it is # called, so the name resolves -- to a module with `__file__' None, a # `NamespaceLoader', and an entirely EMPTY public surface. Nothing in the # payload is reachable through it, because `.pyi' is not in # `SOURCE_SUFFIXES', so every submodule import fails. # # Writing "it does not import" into the suite would therefore have put a false # statement into the record, and one that a later reader could not have told # from a measurement. The accurate assertion is "it imports EMPTY and reaches # nothing", and that is what `import-module-ok', `import-module-is-namespace', # `import-module-surface' and `importable-submodules' carry between them. # # ---------------------------------------------------------------------------- # THE STUBS SIT BESIDE THE REAL LIBRARY, WHICH IS WHY `no-shadow' IS HERE. # ---------------------------------------------------------------------------- # # `python3-psutil' is on this image (IMAGE_INSTALL, and 99-python3-psutil.test # asserts its `import' green and pins its `module_file' to # $SITE/psutil/__init__.py). So this port puts annotations for a library into # the same site-packages as the library, and the thing worth ruling out is that # doing so changed what importing the library does. Measured by the resolved # `__file__', not by the import merely succeeding. # # ---------------------------------------------------------------------------- # WHERE THE EXPECTATIONS COME FROM. # ---------------------------------------------------------------------------- # # Every value asserted below was MEASURED on an x86-64 control under CPython # 3.12.3 -- the same 3.12 this image ships -- running THIS PROBE against THIS # BUILD's own .deb payload, unpacked with `dpkg-deb -x'. The payload was also # compared against the sdist whose sha256 the recipe pins # (`5636f571...'): `diff -r' over `psutil-stubs' is clean, so the recipe # repackages upstream without touching a byte. A red here is therefore this # arm, not a version skew and not a repackaging. # # ---------------------------------------------------------------------------- # WHAT IS PREDICTED RATHER THAN MEASURED, AND SO MIGHT BE RED. # ---------------------------------------------------------------------------- # # EXPECTED, NOT YET MEASURED -- this is a prediction and is written as one. The # recipe phase cannot build the image and so cannot run this suite; its first # on-target run is the batch verify. # # The prediction is that NOTHING here is red, and it is a weaker claim than it # looks rather than a stronger one: this package ships no code, so the suite's # only exposure to the arm is `ast.parse' and the file reads, and both are # interpreter-internal work over bytes already on the rootfs. There is no # syscall surface for the port to fall through -- no fork, no socket, no # device, no clock, no thread -- which is the whole of what the ports beside # this one in this batch go red on. # # The single place a surprise could come from is the PARSE, which is the reason # it is in the suite at all: `parse-node-count' (8014) and # `ellipsis-body-count' (549) pin the parser's output shape, not merely its # exit, so a parser that accepted the files and built a different tree is a red # here rather than a silent pass. If this arm's parser diverges, the predicted # shape is a mismatch in those two counts with `parse-failures' still empty -- # not an exception. That is a prediction about the shape, not a claim about the # result. # # `psutil-file' is the one case whose expected value is not measured on the # control, because the control's `import psutil' resolves to the host's own # psutil rather than the image's. It is cross-checked instead against # 99-python3-psutil.test, which already pins that same path and lands green. P=python3-types-psutil # ============================================================================ # The suite proper. # ============================================================================ # # `suite-canary' is emitted FIRST and unconditionally. A suite that dies before # its first result line is indistinguishable from one that was never scheduled, # so this one line is what separates "ran and found nothing" from "did not run". bst_ok $P/suite-canary require python3 $P/python3-present SITE=/usr/lib/python3.12/site-packages SD=$SITE/psutil-stubs DI=$SITE/types_psutil-5.9.5.20240316.dist-info PKGLIST=/var/lib/dpkg/info/python3-types-psutil.list PROBE=$BST_DATA/python3-types-psutil-probe.py tmp=${TMPDIR:-/tmp} W=$tmp/bst-types-psutil.$$ mkdir -p "$W" || { bst_notok $P/workdir "cannot create $W"; exit 0; } # ---------------------------------------------------------------- payload --- # WHERE THE PACKAGING SAYS THE FILES LAND. These run before any import, so a red # here says the .deb is wrong rather than that something misbehaved. check $P/site-packages-dir test -d "$SITE" check $P/stubs-dir test -d "$SD" check $P/init-pyi-present test -s "$SD/__init__.pyi" check $P/metadata-toml-present test -s "$SD/METADATA.toml" # THE WHOLE INSTALLED SET, in one string, rather than only the files this suite # happens to name. LC_ALL=C so the order is the byte order rather than the # guest's locale. Fourteen `.pyi' and one `METADATA.toml' -- exactly the fifteen # names setup.py's `package_data' lists. check_eq $P/stubs-file-set \ "METADATA.toml,__init__.pyi,_common.pyi,_compat.pyi,_psaix.pyi,_psbsd.pyi,_pslinux.pyi,_psosx.pyi,_psposix.pyi,_pssunos.pyi,_psutil_linux.pyi,_psutil_osx.pyi,_psutil_posix.pyi,_psutil_windows.pyi,_pswindows.pyi," \ "$(LC_ALL=C ls -1 "$SD" 2>/dev/null | LC_ALL=C sort | tr '\n' ',')" # TWO SIZES PINNED IN THE SHELL, so a truncated payload is a red that does not # depend on the probe having started. The full set is scored by sha256 against # RECORD inside the probe (`record-*' below); these two are the console-legible # version of it. check_eq $P/init-pyi-size 9206 \ "$(wc -c < "$SD/__init__.pyi" 2>/dev/null | tr -d ' ')" # BST-REDIRECT-OK: forked -- inside $( ) check_eq $P/metadata-toml-size 136 \ "$(wc -c < "$SD/METADATA.toml" 2>/dev/null | tr -d ' ')" # BST-REDIRECT-OK: forked -- inside $( ) # NO EXECUTABLE CODE SHIPS. Three absences, asserted over the payload rather # than over the recipe, because "stub-only" is the entire claim this package # makes and nothing else in the suite would notice it being broken. # # The `.so' case is not decoration on this image: python3 here is ONE STATIC # BINARY with an empty lib-dynload and no dynamic loader (BRINTOS-1476), so a # compiled extension would not be a speed-up but an ImportError. check_eq $P/no-py-files "" "$(find "$SD" -maxdepth 1 -name '*.py' 2>/dev/null)" check_eq $P/no-so-files "" "$(find "$SD" -maxdepth 1 -name '*.so' 2>/dev/null)" check $P/no-pycache test ! -d "$SD/__pycache__" # NO `py.typed'. A stub-only distribution is discovered by its `-stubs' suffix # under PEP 561 and must NOT carry the marker an inline-typed package uses; # asserted as an absence so a release that added one is visible. check $P/no-py-typed test ! -e "$SD/py.typed" # NOTHING LANDS IN /usr/bin. setup.py declares no `scripts' and no entry points # at all -- the dist-info carries no `entry_points.txt', which `dist-info-file-set' # below pins. check $P/no-bin-script test ! -e /usr/bin/types-psutil # ------------------------------------------------------------- dist-info --- check $P/dist-info-dir test -d "$DI" check $P/dist-info-record test -s "$DI/RECORD" check $P/dist-info-metadata test -s "$DI/METADATA" check $P/dist-info-wheel test -s "$DI/WHEEL" # THE WHOLE METADATA FILE SET. Four files and no `entry_points.txt' -- the # absence is the assertion, and it is the packaging half of `no-bin-script'. check_eq $P/dist-info-file-set \ "METADATA,RECORD,WHEEL,top_level.txt," \ "$(LC_ALL=C ls -1 "$DI" 2>/dev/null | LC_ALL=C sort | tr '\n' ',')" # THE HYPHEN IS LOAD-BEARING and is asserted here as data. `top_level.txt' names # `psutil-stubs', not `psutil_stubs': setup.py declares # `packages=["psutil-stubs"]', a name that is deliberately NOT a valid python # identifier, and that single fact is what `import-stmt-syntaxerror' below is # about. check_eq $P/dist-info-top-level "psutil-stubs" \ "$(cat "$DI/top_level.txt" 2>/dev/null | tr -d ' \r\n')" # --------------------------------------------------------------- dpkg --- # The package is REGISTERED, not merely unpacked. A payload that arrived some # other way would pass every path case above and fail here. check $P/dpkg-list test -s "$PKGLIST" check $P/dpkg-lists-init grep -q "^$SD/__init__\.pyi\$" "$PKGLIST" check $P/dpkg-lists-toml grep -q "^$SD/METADATA\.toml\$" "$PKGLIST" # THE `-dev' SPLIT IS PRODUCED AND EMPTY, so it is not installed and must not be # here. Measured on this build: `python3-types-psutil-dev' contains `./' and # nothing else, and `-dbg' likewise. Only the main package is in IMAGE_INSTALL. check $P/no-dev-installed test ! -e /var/lib/dpkg/info/python3-types-psutil-dev.list check $P/no-dbg-installed test ! -e /var/lib/dpkg/info/python3-types-psutil-dbg.list # ------------------------------------------------------------------ import --- # ONE case for the import, so the result is legible from the console without # reading the probe's transcript. It is `importlib' and not an `import' # statement, which cannot be written for this name at all -- see the header, and # `import-stmt-syntaxerror' below. check $P/import python3 -c 'import importlib; importlib.import_module("psutil-stubs")' # ------------------------------------------------------------------- probe --- if [ ! -s "$PROBE" ]; then bst_notok $P/probe-present "probe missing at $PROBE" exit 0 fi bst_ok $P/probe-present # 1000s, inside the 1200s suite budget so a hung probe is reported as a probe # overrun naming the last line it printed, rather than as a bare suite timeout. # # The probe EXITS 0 even when the payload is absent, so this case passing means # "the probe ran", not "the package is right" -- `stubs-found' below is what # carries that. bst_probe $P/probe-run "$W/probe" 1000 python3 "$PROBE" OUT="$W/probe" # pv : the value the probe emitted for , or empty. `head -n 1' # because a key is emitted once and a duplicate would otherwise concatenate; # `cut -f2-' because a value may legitimately contain `='. pv() { grep "^$1=" "$OUT" 2>/dev/null | head -n 1 | cut -d= -f2-; } # The probe reached its end. Every case below reads a value it printed, so a # probe that stopped early would otherwise turn into a run of empty-string # mismatches that all name the wrong thing. check_eq $P/probe-complete "yes" "$(pv probe_done)" _found=$(pv stubs_found) check_eq $P/stubs-found "yes" "$_found" if [ "$_found" != "yes" ]; then # The probe found no `psutil-stubs' anywhere on sys.path. Skip -- not red -- # every case that reads the payload, each with the reason attached: they are # all one fact, and fifty reds would bury it rather than report it. The path # cases above and `stubs-found' are the reds that carry the verdict. _why="psutil-stubs not on sys.path; site_dir=$(pv site_dir)" for _c in probe-count site-dir stub-file-set stub-file-count pyi-count \ probe-no-py probe-no-so probe-no-pycache probe-no-py-typed \ probe-has-init-pyi probe-no-init-py probe-has-metadata-toml \ metadata-toml-bytes metadata-toml-text record-read record-entries \ record-missing record-size-mismatch record-hash-mismatch \ record-unlisted parse-ok-count parse-failures parse-node-count \ parse-negative-control ellipsis-body-count overload-count \ init-parsed init-classes init-functions init-function-count \ init-platform-functions has-process-class process-methods \ process-method-count process-guarded-methods process-bases \ process-pid-is-property popen-bases import-stmt-syntaxerror \ import-module-ok import-module-file import-module-origin \ import-module-loader import-module-is-namespace \ import-module-surface importable-submodules \ pyi-in-source-suffixes psutil-import-ok psutil-file no-shadow \ probe-dist-info-file-set meta-name meta-version meta-license \ meta-requires-python meta-requires-dist probe-dist-top-level \ wheel-root-is-purelib importlib-metadata-version \ importlib-metadata-file-count; do bst_skip $P/$_c "$_why" done rm -rf "$W" exit 0 fi # The probe emitted every key it intended to. A probe that returned 0 having # skipped a section would otherwise leave those cases reading empty strings. check_eq $P/probe-count "62" "$(pv emitted_count)" # WHERE THE PAYLOAD WAS FOUND. Pinned to site-packages so a directory satisfied # from somewhere else on sys.path -- a leftover in the cwd, a second install -- # is a red here rather than a green suite measuring the wrong tree. check_eq $P/site-dir "$SITE" "$(pv site_dir)" # The probe's own view of the payload, which is the same set the shell asserted # above read a second way. Both are kept: the shell one is legible on the # console, this one is what the parse and structure cases below were taken from, # and a disagreement between them would itself be the finding. check_eq $P/stub-file-set \ "METADATA.toml,__init__.pyi,_common.pyi,_compat.pyi,_psaix.pyi,_psbsd.pyi,_pslinux.pyi,_psosx.pyi,_psposix.pyi,_pssunos.pyi,_psutil_linux.pyi,_psutil_osx.pyi,_psutil_posix.pyi,_psutil_windows.pyi,_pswindows.pyi" \ "$(pv stub_file_set)" check_eq $P/stub-file-count "15" "$(pv stub_file_count)" check_eq $P/pyi-count "14" "$(pv pyi_count)" check_eq $P/probe-no-py "" "$(pv py_files)" check_eq $P/probe-no-so "" "$(pv so_files)" check_eq $P/probe-no-pycache "no" "$(pv has_pycache)" check_eq $P/probe-no-py-typed "no" "$(pv has_py_typed)" check_eq $P/probe-has-init-pyi "yes" "$(pv has_init_pyi)" check_eq $P/probe-no-init-py "no" "$(pv has_init_py)" check_eq $P/probe-has-metadata-toml "yes" "$(pv has_metadata_toml)" # THE STUB DISTRIBUTION'S OWN MARKER FILE, asserted as its whole content. It # declares which psutil release these annotations aim at (`5.9.*'), which is the # one fact about this package not derivable from the file names -- and the fact # that makes it meaningful beside this image's psutil rather than merely # present. Newlines are flattened to `|' by the probe so the value stays one # counted result. check_eq $P/metadata-toml-bytes "136" "$(pv metadata_toml_bytes)" check_eq $P/metadata-toml-text \ 'version = "5.9.*"|upstream_repository = "https://github.com/giampaolo/psutil"||[tool.stubtest]|platforms = ["darwin", "linux", "win32"]' \ "$(pv metadata_toml_text)" # ------------------------------------------------- payload vs the wheel --- # THE INSTALLED SET SCORED AGAINST THE WHEEL'S OWN `RECORD' -- its sha256 and # byte count for every file it installed -- rather than against a list typed # into this suite. This is the case the ticket asks for by name, and it is the # strongest one here: it makes a packaging change VISIBLE instead of leaving it # to be noticed. # # Four empties and a count, deliberately split rather than folded into one # verdict: "a file is missing", "a file is the wrong length", "a file has the # wrong bytes" and "a file is installed that RECORD does not list" are four # different faults with four different causes, and one combined red would name # none of them. check_eq $P/record-read "yes" "$(pv record_read)" check_eq $P/record-entries "19" "$(pv record_entries)" check_eq $P/record-missing "" "$(pv record_missing)" check_eq $P/record-size-mismatch "" "$(pv record_size_mismatch)" check_eq $P/record-hash-mismatch "" "$(pv record_hash_mismatch)" check_eq $P/record-unlisted "" "$(pv record_unlisted)" # ------------------------------------------------------------------ parse --- # EVERY `.pyi' THROUGH THIS ARM'S OWN `ast.parse', in `type_comments=True' mode # -- the mode a type checker uses, and a genuinely different code path in # CPython's parser rather than a flag it ignores. check_eq $P/parse-ok-count "14" "$(pv parse_ok_count)" check_eq $P/parse-failures "" "$(pv parse_failures)" # THE PARSER'S OUTPUT SHAPE, not merely its exit status. An empty file parses # perfectly and a parser that silently dropped constructs would still report # fourteen successes; the node count is what makes those two different results. check_eq $P/parse-node-count "8014" "$(pv parse_node_count)" # THE PARSE HAS TEETH. A harness that caught everything would report # `parse-ok-count' 14 for fourteen good files and for fourteen empty ones alike. # Feeding the same parser, in the same mode, a file that MUST fail is what says # the mode is really on and the exception really propagates. check_eq $P/parse-negative-control "yes" "$(pv parse_negative_control)" # THE TWO CONSTRUCTS THAT MAKE STUB SYNTAX ITS OWN CORNER OF THE GRAMMAR, # counted structurally off the tree. `...' as an entire function body is the # form this whole distribution is written in; `@overload' is the one a parser is # most likely to get wrong. Both are counted rather than assumed, so a tree that # came back reinterpreted is a red here. check_eq $P/ellipsis-body-count "549" "$(pv ellipsis_body_count)" check_eq $P/overload-count "9" "$(pv overload_count)" # -------------------------------------------------------------- structure --- # A SAMPLE OF THE DECLARATIONS, so a truncated install is caught rather than # passing as "it parsed". check_eq $P/init-parsed "yes" "$(pv init_parsed)" check_eq $P/init-classes "Process,Popen" "$(pv init_classes)" # THE MODULE-LEVEL FUNCTIONS UPSTREAM DOCUMENTS, as a set. The count is 26 while # the set is 22 names, and the gap is not an error: `cpu_percent', # `disk_io_counters' and `net_io_counters' each carry `@overload' declarations, # so they are declared more than once. Both numbers are asserted, because the # set alone would not notice an overload being lost and the count alone would # not notice a function being renamed. check_eq $P/init-functions \ "boot_time,cpu_count,cpu_freq,cpu_percent,cpu_stats,cpu_times,cpu_times_percent,disk_io_counters,disk_partitions,disk_usage,getloadavg,net_connections,net_if_addrs,net_if_stats,net_io_counters,pid_exists,pids,process_iter,swap_memory,users,virtual_memory,wait_procs" \ "$(pv init_functions)" check_eq $P/init-function-count "26" "$(pv init_function_count)" # THE SENSOR API IS PLATFORM-GUARDED, and is asserted SEPARATELY from the # unconditional set rather than folded in with it. psutil's sensor surface # genuinely differs by platform and the stub says so with `if sys.platform == # "linux"' at module scope; keeping the two apart is what makes this a statement # about the declaration rather than a headcount that a release could satisfy by # moving a name across the boundary. check_eq $P/init-platform-functions \ "sensors_battery,sensors_fans,sensors_temperatures" \ "$(pv init_platform_functions)" # `Process' -- THE CLASS THE TICKET NAMES -- described by its declaration. check_eq $P/has-process-class "yes" "$(pv has_process_class)" check_eq $P/process-methods \ "__eq__,__hash__,__init__,__ne__,as_dict,children,cmdline,connections,cpu_percent,cpu_times,create_time,cwd,environ,exe,is_running,kill,memory_full_info,memory_info,memory_info_ex,memory_percent,name,nice,num_ctx_switches,num_threads,oneshot,open_files,parent,parents,pid,ppid,resume,send_signal,status,suspend,terminate,threads,username,wait" \ "$(pv process_methods)" check_eq $P/process-method-count "38" "$(pv process_method_count)" # THE PLATFORM-GUARDED METHODS, again kept apart from the unconditional ones. # These are the eleven declared inside `if sys.platform != "win32"' and its # siblings -- the POSIX-only, the non-darwin and the linux-only surface. check_eq $P/process-guarded-methods \ "cpu_affinity,cpu_num,gids,io_counters,ionice,memory_maps,num_fds,num_handles,rlimit,terminal,uids" \ "$(pv process_guarded_methods)" # `Process' INHERITS FROM NOTHING, and `Popen' INHERITS FROM `Process'. The # second is the interesting one -- it is how the stub says a Popen IS a Process # with the subprocess API bolted on -- and asserting the first as an empty # string is what stops a release that gave Process a base from passing silently. check_eq $P/process-bases "" "$(pv process_bases)" check_eq $P/popen-bases "Process" "$(pv popen_bases)" # `pid' IS A PROPERTY, NOT A METHOD. The one part of this class a caller is most # likely to get wrong, so the decorator is read off the tree rather than the # name being counted among the methods. check_eq $P/process-pid-is-property "yes" "$(pv process_pid_is_property)" # ----------------------------------------------------------------- import --- # WHAT `import' ACTUALLY DOES WITH A STUBS-ONLY DIRECTORY. The header explains # at length why these five cases say "imports empty and reaches nothing" rather # than the ticket's "cannot be imported"; the short version is that the second # was measured to be false and the first to be true. # THE IMPORT STATEMENT CANNOT BE WRITTEN. `psutil-stubs' is not an identifier, # so this is a SyntaxError in any CPython -- a fact about the name upstream # chose, asserted here because it is the accurate half of the ticket's premise. check_eq $P/import-stmt-syntaxerror "yes" "$(pv import_stmt_syntaxerror)" # BUT `importlib.import_module' RESOLVES IT, as a PEP 420 namespace package. check_eq $P/import-module-ok "yes" "$(pv import_module_ok)" check_eq $P/import-module-file "None" "$(pv import_module_file)" check_eq $P/import-module-origin "None" "$(pv import_module_origin)" check_eq $P/import-module-loader "NamespaceLoader" "$(pv import_module_loader)" check_eq $P/import-module-is-namespace "yes" "$(pv import_module_is_namespace)" # AND IT DELIVERS NOTHING. The empty surface and the empty submodule list are # the two halves that make the namespace package harmless: the directory answers # to the name and hands back no declaration, no file and no submodule. check_eq $P/import-module-surface "" "$(pv import_module_surface)" check_eq $P/importable-submodules "" "$(pv importable_submodules)" # THE MECHANISM UNDERNEATH THAT. `.pyi' is not a source suffix, so the finder # never offers one of these files however the name is spelled -- which is why # the namespace package above can be empty while fourteen parseable modules sit # inside it. check_eq $P/pyi-in-source-suffixes "no" "$(pv pyi_in_source_suffixes)" # ------------------------------------------------------------- no shadow --- # THE REAL LIBRARY IS UNAFFECTED. `python3-psutil' is on this image, so this port # adds annotations for a library into the same site-packages as the library. # `no-shadow' is the case that says installing them did not change what # `import psutil' resolves to. # # `psutil-file' is the one expected value here NOT taken from the x86-64 control # -- the control's `import psutil' finds the host's own copy. It is cross-checked # instead against 99-python3-psutil.test, which pins this same path and lands # green. check_eq $P/psutil-import-ok "yes" "$(pv psutil_import_ok)" check_eq $P/psutil-file "$SITE/psutil/__init__.py" "$(pv psutil_file)" check_eq $P/no-shadow "no" "$(pv psutil_from_stubs_dir)" # ---------------------------------------------------------- installed meta --- check_eq $P/probe-dist-info-file-set "METADATA,RECORD,WHEEL,top_level.txt" \ "$(pv dist_info_file_set)" check_eq $P/meta-name "types-psutil" "$(pv meta_name)" check_eq $P/meta-version "5.9.5.20240316" "$(pv meta_version)" # `Apache-2.0 license' -- the trailing word is upstream's, from setup.py's # `license=' string, and the recipe's LICENSE is the clean `Apache-2.0'. Pinned # as it is rather than as it ought to be. check_eq $P/meta-license "Apache-2.0 license" "$(pv meta_license)" check_eq $P/meta-requires-python ">=3.8" "$(pv meta_requires_python)" # NO RUNTIME DEPENDENCY IS DECLARED, AND SPECIFICALLY NOT ON `psutil'. This is # the fact that lets a stubs package be installed on an image that does not # carry the library it describes -- `install_requires=[]' upstream -- and it is # what makes the recipe's `Depends: python3-core' correct rather than thin. A # `Requires-Dist:' line appearing here is a release changing its mind. check_eq $P/meta-requires-dist "none" "$(pv meta_requires_dist)" check_eq $P/probe-dist-top-level "psutil-stubs" "$(pv dist_top_level)" # A PURE-PYTHON WHEEL, from the wheel's own metadata. It is the packaging-side # statement of `no-so-files' above: `Root-Is-Purelib: true' means nothing in it # is platform-specific, which for a wasm32 image is the difference between a # package that ports and one that cannot. check_eq $P/wheel-root-is-purelib "true" "$(pv wheel_root_is_purelib)" # `importlib.metadata' MUST ANSWER FOR IT. The dist-info being on disk and the # interpreter being able to FIND it are two different facts, and only the second # is what a caller asking "is types-psutil installed" actually uses. The file # count is RECORD's 19 read back through the metadata API. check_eq $P/importlib-metadata-version "5.9.5.20240316" "$(pv importlib_metadata_version)" check_eq $P/importlib-metadata-file-count "19" "$(pv importlib_metadata_file_count)" rm -rf "$W" exit 0