. "$BST_LIB" # BST-TIMEOUT: 1200 # THREE python3 starts and nothing else. # # # # They are: a bare `import', a second one whose STDERR is # # the assertion (`import-quiet'), and the probe, which # # takes ONE start for 156 measurements. # # # # 400s per start is the budget the neighbouring python3 # # suites use on this arm. Nothing here forks or execs and # # nothing touches a device: every case is a string parsed # # in memory, so the interpreter start IS the whole cost. # # # # A suite-timeout red is a batch-wide cost, so if the # # starts prove slower than that on target the RIGHT fix is # # this number, not fewer cases. # # # # NOT MEASURED ON TARGET YET: this port's first on-target # # run is the batch verify, and the measured elapsed # # replaces this note in the test plan rather than in this # # comment, which would cost an image build to keep the # # shipped suite byte-identical. # # python3-ruamel-yaml 0.18.6 (poky meta/recipes-devtools/python, # python3-ruamel-yaml_0.18.6.bb -- `inherit pypi setuptools3', PyPI sdist) on # the wasm32-hwjs glibc image. # # ============================================================================ # WHAT THE PACKAGE IS, AND THEREFORE WHAT HAS TO BE TESTED. # ============================================================================ # # A YAML 1.2 parser and emitter whose distinguishing feature is ROUND-TRIP # PRESERVATION: comments, key order, anchors, aliases, merge keys, quoting # style and block/flow style are meant to survive a load-and-dump cycle. That # property is the reason the package exists, so it is this suite's backbone -- # `roundtrip-*' loads one document carrying every one of those constructs at # once and asserts the emitted text is BYTE-IDENTICAL to the input, then # changes a single scalar and asserts that exactly one line moved. # # It is PURE PARSING: no socket, no subprocess, no device and no terminal. # Every fixture is a string the probe writes. That is what lets this port close # on its suite with no BRINTOS-780 follow-on. # # ============================================================================ # THE TICKET'S ROUND-TRIP EXPECTATION IS TRUE ONLY WITH `preserve_quotes'. # ============================================================================ # # A DEFAULT `YAML()' drops the double quotes off `"hi there"' and emits it # plain, so the naive round trip is NOT byte-identical -- `roundtrip-identical- # default' is `no' and says so. With `preserve_quotes = True' it is identical. # Both are asserted, because a caller who reads the package summary and sets no # flag gets the first answer, and the pair is what says which knob buys the # second. # # ============================================================================ # THIS IS A YAML 1.2 PARSER BY DEFAULT, WHICH IS THE FIRST THING A CALLER # CARRYING 1.1 HABITS GETS WRONG. # ============================================================================ # # `yes', `no', `on' and `off' are STRINGS here, not booleans, and `017' is # SEVENTEEN, not fifteen. Setting `version = (1, 1)' turns both back -- and # takes the 1.2 spelling `0o17' away, which then parses as the string `0o17'. # The `v11-*' cases assert that trade in both directions, so a document that # needs 1.1 semantics has a place to point at. # # `0b101' and `1_000' are ruamel EXTENSIONS -- the YAML 1.2 core schema defines # neither -- and they are asserted so a later release that drops them is a red # here rather than a surprise in a caller. # # ============================================================================ # ROUND-TRIP MODE RETURNS SUBCLASSES, NOT THE BUILT-IN TYPES. # ============================================================================ # # `rt' hands back OctalInt, HexInt, BinaryInt, ScalarInt, ScalarFloat, # TimeStamp, CommentedMap, CommentedSeq -- each carrying the style it was # written in, which is exactly how the dump puts it back. `safe' hands back # plain int, float, datetime, dict, list. The `rt-*-types' / `safe-*-types' # pairs assert that split directly: they are the round-trip machinery made # visible, and a caller doing `type(x) is int' gets a different answer in the # two modes. # # ============================================================================ # THE ONE THING THAT COULD REACH THE HOST IS ASSERTED BY SIDE EFFECT. # ============================================================================ # # YAML has `!!python/object/apply', which in the UNSAFE constructor CALLS the # named function. The probe hands all three modes a tag naming `os.mknod' on a # path in its own $TMPDIR and then asks whether that file exists. # # safe -- refuses with ConstructorError. What the ticket asks for. # unsafe -- constructs it. Named here so the boundary is stated, not implied. # rt -- NEITHER. It does not construct the object and it does not raise: # it drops the tag and hands back the argument sequence. Nothing is # called, so it is not a hole -- but a caller relying on "rt is safe # because it raises" is relying on something that does not happen, # and `roundtrip-pyapply-*' is the three cases that say so. # # ============================================================================ # THE MODULE-LEVEL FUNCTIONS 0.18 REMOVED ARE STILL ATTRIBUTES. # ============================================================================ # # `ruamel.yaml.safe_load' and its five siblings were removed in 0.18 -- but the # names are still THERE, so `hasattr' says yes and a feature probe written that # way is wrong. They raise AttributeError when CALLED, with a message naming # the replacement. Both halves are asserted, because the gap between them is # what a caller ported from 0.17 falls into. # # ============================================================================ # NO PATCH, NO BBAPPEND AND NO SITE ANSWER. # ============================================================================ # # The recipe is poky's exactly as written. There is no configure step, no # compile step and no C in what ships, so there is nothing on this arm for an # override to reach. The optional `_ruamel_yaml' C loader is NOT built, and the # `cext-*' cases assert both that it is absent and that `pure=False' still # works -- main.py falls back to the Python implementation when CParser is # None. That fallback is why the port works at all on an interpreter with an # empty lib-dynload and no dynamic loader (BRINTOS-1476). # # `ruamel' is an IMPLICIT NAMESPACE PACKAGE: the .deb ships no # ruamel/__init__.py, which is how several unrelated `ruamel.*' distributions # share the name. `namespace-no-init' is the case that says so, and it is worth # its line: a stray ruamel/__init__.py from anything else would make this a # regular package and shadow `ruamel.yaml' out of existence. P=python3-ruamel-yaml # --------------------------------------------------------------------------- bst_ok $P/suite-canary require python3 $P/python3-present SITE=/usr/lib/python3.12/site-packages PKGDIR=$SITE/ruamel/yaml DI=$SITE/ruamel.yaml-0.18.6.dist-info PKGLIST=/var/lib/dpkg/info/python3-ruamel-yaml.list PROBE=$BST_DATA/python3-ruamel-yaml-probe.py tmp=${TMPDIR:-/tmp} W=$tmp/bst-ruamel-yaml-suite.$$ mkdir -p "$W" || { bst_notok $P/workdir "cannot create $W"; exit 0; } # --- the module, as installed --------------------------------------------- check $P/site-packages-dir test -d "$SITE" check $P/namespace-dir test -d "$SITE/ruamel" check $P/package-dir test -d "$PKGDIR" # The namespace parent carries NO __init__.py -- see the header. check $P/namespace-no-init test ! -e "$SITE/ruamel/__init__.py" check $P/not-a-flat-module test ! -e "$SITE/ruamel/yaml.py" check $P/init-file test -s "$PKGDIR/__init__.py" check $P/main-file test -s "$PKGDIR/main.py" check $P/scanner-file test -s "$PKGDIR/scanner.py" check $P/parser-file test -s "$PKGDIR/parser.py" check $P/composer-file test -s "$PKGDIR/composer.py" check $P/constructor-file test -s "$PKGDIR/constructor.py" check $P/representer-file test -s "$PKGDIR/representer.py" check $P/serializer-file test -s "$PKGDIR/serializer.py" check $P/emitter-file test -s "$PKGDIR/emitter.py" check $P/resolver-file test -s "$PKGDIR/resolver.py" check $P/comments-file test -s "$PKGDIR/comments.py" check $P/error-file test -s "$PKGDIR/error.py" check $P/timestamp-file test -s "$PKGDIR/timestamp.py" check $P/scalarstring-file test -s "$PKGDIR/scalarstring.py" check $P/scalarint-file test -s "$PKGDIR/scalarint.py" check $P/scalarfloat-file test -s "$PKGDIR/scalarfloat.py" check $P/scalarbool-file test -s "$PKGDIR/scalarbool.py" check $P/anchor-file test -s "$PKGDIR/anchor.py" check $P/tag-file test -s "$PKGDIR/tag.py" # cyaml.py ships and imports the C loader behind a try/except -- it is the file # that must NOT bring the import down on an image that has no such loader. check $P/cyaml-file test -s "$PKGDIR/cyaml.py" # PEP 561 marker: this package declares itself typed. check $P/py-typed test -f "$PKGDIR/py.typed" check $P/pycache-init test -s "$PKGDIR/__pycache__/__init__.cpython-312.pyc" check $P/pycache-main test -s "$PKGDIR/__pycache__/main.cpython-312.pyc" # --- the package, as dpkg has it ------------------------------------------ cat "$PKGLIST" > "$W/pkgf" 2>/dev/null || : > "$W/pkgf" check $P/pkg-list-present test -s "$W/pkgf" # This image's python3 has no dynamic loader at all (BRINTOS-1476), so a .so in # this list would be a file that could never be imported. check_eq $P/pkg-no-so "" \ "$(grep -E '\.so($|\.)' "$W/pkgf" 2>/dev/null)" # setup.py declares no entry_points and no scripts, so nothing lands in a bindir. check_eq $P/pkg-no-bin "" \ "$(grep -E '^/usr/(s?bin)/' "$W/pkgf" 2>/dev/null)" # Everything shipped is a .py, a .pyc, dist-info metadata, or the py.typed # marker. Nothing else -- which is the machine-readable form of "pure Python". _bad="" while IFS= read -r _f; do [ -f "$_f" ] || continue case "$_f" in *.py|*.pyc) continue ;; */py.typed) continue ;; */__pycache__/*) continue ;; */*.dist-info/*) continue ;; esac _bad="$_bad $_f" done < "$W/pkgf" check_eq $P/pkg-only-python "" "$_bad" sed -n '/^Package: python3-ruamel-yaml$/,/^$/p' /var/lib/dpkg/status > "$W/st" 2>/dev/null check $P/pkg-known test -s "$W/st" check_out $P/pkg-installed "Status: install ok installed" cat "$W/st" check_out $P/pkg-version "Version: 0.18.6-r0" cat "$W/st" # The recipe's RDEPENDS, as the built package states them. Load-bearing rather # than decorative: `datetime' is what makes a timestamp scalar a datetime # rather than a string, and the constructor imports `base64' out of # python3-netclient for `!!binary'. check_out $P/pkg-depends \ "Depends: python3-core, python3-datetime, python3-netclient, python3-shell" \ cat "$W/st" # --- the wheel metadata ---------------------------------------------------- check $P/dist-info-dir test -d "$DI" check $P/dist-info-metadata test -f "$DI/METADATA" check_out $P/dist-info-name "Name: ruamel.yaml" cat "$DI/METADATA" check_out $P/dist-info-version "Version: 0.18.6" cat "$DI/METADATA" check $P/dist-info-record test -s "$DI/RECORD" check $P/dist-info-license test -s "$DI/LICENSE" # Purelib and a py3-none-any tag are the machine-readable form of "there is # nothing arch-specific in here", which is the whole reason this port is cheap. check_out $P/dist-info-purelib "Root-Is-Purelib: true" cat "$DI/WHEEL" check_out $P/dist-info-tag-py3 "Tag: py3-none-any" cat "$DI/WHEEL" check_eq $P/dist-info-no-py2-tag "" \ "$(grep '^Tag: py2' "$DI/WHEEL" 2>/dev/null)" # The top-level name is the NAMESPACE, not the distribution. check_out $P/dist-info-top-level "ruamel" cat "$DI/top_level.txt" # --- import ---------------------------------------------------------------- check $P/import python3 -c 'import ruamel.yaml' # An import that WORKS but complains is a port that is not finished. Asserted # on its own start so that the noise, if any, is the whole of the evidence. check_eq $P/import-quiet "" \ "$(python3 -c 'import ruamel.yaml' 2>&1)" # --- the probe ------------------------------------------------------------- if [ ! -f "$PROBE" ]; then bst_notok $P/probe-present "$PROBE did not ship" rm -rf "$W" exit 0 fi bst_ok $P/probe-present bst_probe $P/probe-run "$W/probe" 900 python3 "$PROBE" OUT="$W/probe" pv() { grep "^$1=" "$OUT" 2>/dev/null | head -n 1 | cut -d= -f2-; } if [ -s "$OUT" ]; then bst_ok $P/probe-output else bst_notok $P/probe-output "the probe emitted nothing -- python3 did not start, or died before its first line; every CASE below is unscorable" fi check_eq $P/probe-complete "yes" "$(pv probe_done)" check_eq $P/probe-count "156" "$(pv emitted_count)" # The library logs nothing to stdout on any path this probe takes, and the # probe parses its own stdout. One stray byte corrupts every case below. check_eq $P/probe-stdout-clean "yes" "$(pv stdout_clean)" # --- the module, as the interpreter sees it -------------------------------- check_eq $P/module-answered "$PKGDIR/__init__.py" "$(pv module_file)" check_eq $P/version-attr "0.18.6" "$(pv version_attr)" check_eq $P/version-info "0.18.6" "$(pv version_info)" check_eq $P/namespace-parent-has-no-file "yes" "$(pv parent_is_namespace)" check_eq $P/namespace-parent-file "None" "$(pv parent_file)" # The optional C loader is not built for this arm and the recipe does not ask # for it. Asserted as a TRIO: absent, both C hooks None, and `pure=False' still # loads -- because it is the fallback, not the absence, that makes the port work. check_eq $P/cext-absent "no" "$(pv cext_importable)" check_eq $P/cext-cparser-none "yes" "$(pv cparser_is_none)" check_eq $P/cext-cemitter-none "yes" "$(pv cemitter_is_none)" # --- the round trip, which is the whole point of the package --------------- check_eq $P/roundtrip-doc-lines "13" "$(pv doc_lines)" check_eq $P/roundtrip-load-type "CommentedMap" "$(pv rt_load_type)" # Byte-identical, with preserve_quotes. The backbone case. check_eq $P/roundtrip-identical-preserve-quotes "yes" "$(pv rt_identical_preserve_quotes)" check_eq $P/roundtrip-out-len "169" "$(pv rt_out_len)" # And NOT byte-identical without it -- the ticket's expectation, corrected. check_eq $P/roundtrip-identical-default "no" "$(pv rt_identical_default)" check_eq $P/roundtrip-default-quoted-line "quoted: hi there" "$(pv rt_default_quoted_line)" # ...and the quotes are the ONLY thing that differs, which is what makes the # pair a statement about `preserve_quotes' rather than about the round trip. check_eq $P/roundtrip-default-only-quotes-differ "yes" "$(pv rt_default_only_quotes_differ)" # Change one scalar; everything else is unchanged. The property the library # exists for, stated as a diff of exactly one line. check_eq $P/roundtrip-change-one-scalar "yes" "$(pv rt_change_identical_except_scalar)" check_eq $P/roundtrip-change-diff-lines "1" "$(pv rt_change_diff_line_count)" check_eq $P/roundtrip-change-diff-at "1" "$(pv rt_change_diff_line_index)" check_eq $P/roundtrip-change-eol-comment "yes" "$(pv rt_change_eol_comment_kept)" check_eq $P/roundtrip-change-top-comment "yes" "$(pv rt_change_top_comment_kept)" # The constructs, one at a time, as the round-trip loader hands them back. check_eq $P/roundtrip-key-order "name,nested,flow,base,alias,literal,quoted" \ "$(pv rt_key_order)" check_eq $P/roundtrip-nested-type "CommentedMap" "$(pv rt_nested_type)" check_eq $P/roundtrip-flow-type "CommentedSeq" "$(pv rt_flow_type)" check_eq $P/roundtrip-flow-values "1,2,3" "$(pv rt_flow_values)" check_eq $P/roundtrip-alias-equals-base "yes" "$(pv rt_alias_equals_base)" # The alias is the SAME OBJECT, not a copy -- so a mutation through one name is # visible through the other, which is a caller-visible consequence of the # anchor and not merely an internal detail. check_eq $P/roundtrip-alias-is-base "yes" "$(pv rt_alias_is_base)" check_eq $P/roundtrip-literal-value "line one\nline two\n" "$(pv rt_literal_value)" check_eq $P/roundtrip-quoted-value "hi there" "$(pv rt_quoted_value)" check_eq $P/roundtrip-quoted-type "DoubleQuotedScalarString" "$(pv rt_quoted_type)" check_eq $P/roundtrip-anchor-name "anchor" "$(pv rt_anchor_name)" # --- the YAML 1.2 core schema ---------------------------------------------- # `yes'/`no'/`on'/`off' are STRINGS in 1.2. This is the single most common way # a document written for a 1.1 parser changes meaning here. check_eq $P/schema-bool-types-rt \ "bool,bool,bool,bool,bool,bool,str,str,str,str" "$(pv rt_bool_types)" check_eq $P/schema-bool-types-safe \ "bool,bool,bool,bool,bool,bool,str,str,str,str" "$(pv safe_bool_types)" check_eq $P/schema-bool-values-rt \ "True,False,True,False,True,False,'yes','no','on','off'" "$(pv rt_bool_values)" check_eq $P/schema-bool-values-safe \ "True,False,True,False,True,False,'yes','no','on','off'" "$(pv safe_bool_values)" check_eq $P/schema-null-types-rt "NoneType,NoneType,NoneType,NoneType" "$(pv rt_null_types)" check_eq $P/schema-null-types-safe "NoneType,NoneType,NoneType,NoneType" "$(pv safe_null_types)" # `017' is SEVENTEEN. `0o17' is the 1.2 octal. `0b101' and `1_000' are ruamel # extensions the core schema does not define. check_eq $P/schema-int-values-rt "0,7,17,15,31,5,-12,34,1000,685230" "$(pv rt_int_values)" check_eq $P/schema-int-values-safe "0,7,17,15,31,5,-12,34,1000,685230" "$(pv safe_int_values)" # rt keeps the base it was written in, as a subclass; safe flattens to int. check_eq $P/schema-int-types-rt \ "int,int,ScalarInt,OctalInt,HexInt,BinaryInt,int,int,ScalarInt,ScalarInt" \ "$(pv rt_int_types)" check_eq $P/schema-int-types-safe \ "int,int,int,int,int,int,int,int,int,int" "$(pv safe_int_types)" check_eq $P/schema-float-repr-rt "0.5,-1000.0,inf,-inf,nan,inf,nan,1000.0,12000.0" \ "$(pv rt_float_repr)" check_eq $P/schema-float-repr-safe "0.5,-1000.0,inf,-inf,nan,inf,nan,1000.0,12000.0" \ "$(pv safe_float_repr)" # The infinities and the NaN come back as PLAIN floats even in rt: there is no # style to preserve on a scalar whose spelling the emitter fixes. check_eq $P/schema-float-types-rt \ "ScalarFloat,ScalarFloat,float,float,float,float,float,ScalarFloat,ScalarFloat" \ "$(pv rt_float_types)" check_eq $P/schema-float-types-safe \ "float,float,float,float,float,float,float,float,float" "$(pv safe_float_types)" # --- timestamps ------------------------------------------------------------ check_eq $P/timestamp-types-safe "date,datetime,datetime,datetime" "$(pv safe_ts_types)" check_eq $P/timestamp-types-rt "date,TimeStamp,TimeStamp,TimeStamp" "$(pv rt_ts_types)" check_eq $P/timestamp-iso-safe \ "2024-02-07,2024-02-07T11:22:33+00:00,2024-02-07T11:22:33.500000-05:00,2001-12-14T21:59:43.100000-05:00" \ "$(pv safe_ts_iso)" check_eq $P/timestamp-iso-rt \ "2024-02-07,2024-02-07T11:22:33+00:00,2024-02-07T11:22:33.500000-05:00,2001-12-14T21:59:43.100000-05:00" \ "$(pv rt_ts_iso)" # The ticket says timestamps decode to `datetime'. A DATE-ONLY scalar does not # -- it is a `datetime.date', and code annotated for datetime breaks on it. check_eq $P/timestamp-date-is-not-datetime-safe "no" "$(pv safe_ts_date_is_datetime)" check_eq $P/timestamp-date-is-not-datetime-rt "no" "$(pv rt_ts_date_is_datetime)" # --- YAML 1.1, by attribute and by directive ------------------------------- check_eq $P/v11-bool-types "bool,bool,bool,bool" "$(pv v11_bool_types)" check_eq $P/v11-bool-values "True,False,True,False" "$(pv v11_bool_values)" # The trade in the other direction: 1.1 gives `017' back as octal and takes the # 1.2 spelling `0o17' away, which then parses as a plain string. check_eq $P/v11-int-values "15,'0o17',5" "$(pv v11_int_values)" check_eq $P/v11-int-types "OctalInt,str,BinaryInt" "$(pv v11_int_types)" check_eq $P/v11-directive "True" "$(pv v11_directive_bool)" # --- merge keys ------------------------------------------------------------ check_eq $P/merge-inherited-rt "1" "$(pv rt_merge_a)" check_eq $P/merge-overridden-rt "3" "$(pv rt_merge_b_overridden)" check_eq $P/merge-keys-rt "a,b" "$(pv rt_merge_keys)" check_eq $P/merge-type-rt "CommentedMap" "$(pv rt_merge_type)" check_eq $P/merge-inherited-safe "1" "$(pv safe_merge_a)" check_eq $P/merge-overridden-safe "3" "$(pv safe_merge_b_overridden)" check_eq $P/merge-keys-safe "a,b" "$(pv safe_merge_keys)" check_eq $P/merge-type-safe "dict" "$(pv safe_merge_type)" # The merge is not flattened on the way out: `<<: *b' comes back as `<<: *b'. check_eq $P/merge-roundtrip-identical "yes" "$(pv rt_merge_roundtrip_identical)" check_eq $P/merge-roundtrip-out \ "base: &b\n a: 1\n b: 2\nderived:\n <<: *b\n b: 3\n" \ "$(pv rt_merge_roundtrip_out)" # --- the `!!' tag forms ---------------------------------------------------- check_eq $P/tags-types-safe \ "s:str,i:int,f:float,b:bool,n:NoneType,seq:list,map:dict,bin:bytes,st:set,om:ordereddict" \ "$(pv safe_tag_types)" check_eq $P/tags-types-rt \ "s:TaggedScalar,i:int,f:ScalarFloat,b:bool,n:NoneType,seq:CommentedSeq,map:CommentedMap,bin:bytes,st:CommentedSet,om:CommentedOrderedMap" \ "$(pv rt_tag_types)" # `!!str 123' is the string "123", not the integer -- an explicit tag overriding # the implicit resolver is the reason the tag exists. check_eq $P/tags-str-overrides-resolver "'123'" "$(pv safe_tag_str)" check_eq $P/tags-binary-decoded "68656c6c6f" "$(pv safe_tag_binary_hex)" check_eq $P/tags-omap-order "a,b" "$(pv safe_tag_omap_keys)" # rt is INCONSISTENT here, and this is the pair that says so: it keeps `!!str' # as a TaggedScalar so the dump can put the tag back, and it APPLIES `!!int'. # A caller doing `isinstance(x, str)' on a `!!str' scalar in rt mode gets False. check_eq $P/tags-rt-str-is-not-str "no" "$(pv rt_tag_str_is_str)" check_eq $P/tags-rt-int-is-int "yes" "$(pv rt_tag_int_is_int)" # ...and the consequence for the round trip: the tags rt APPLIED are lost on # the way out, so a tagged document is NOT byte-identical. check_eq $P/tags-roundtrip-not-identical "no" "$(pv rt_tag_roundtrip_identical)" check_eq $P/tags-roundtrip-out \ "s: !!str 123\ni: 7\nf: 2.5\nb: true\nn:\nseq: [1, 2]\nmap: {a: 1}\nbin: !!binary |\n aGVsbG8=\nst: !!set {a, b}\nom: !!omap [a: 1, b: 2]\n" \ "$(pv rt_tag_roundtrip_out)" check_eq $P/tags-unknown-rt "TaggedScalar" "$(pv rt_unknown_tag_type)" check_eq $P/tags-unknown-safe "!ConstructorError" "$(pv safe_unknown_tag)" check_eq $P/tags-unknown-yaml-org-safe "!ConstructorError" "$(pv safe_unknown_yaml_org_tag)" # --- the python tags, asserted by side effect ------------------------------ # What the ticket asks for: safe REFUSES to construct an arbitrary Python tag. check_eq $P/pyapply-safe-refuses "!ConstructorError" "$(pv safe_pyapply)" check_eq $P/pyapply-safe-no-side-effect "no" "$(pv safe_pyapply_side_effect)" check_eq $P/pyname-safe-refuses "!ConstructorError" "$(pv safe_pyname)" # rt does neither -- see the header. Three cases, because the interesting fact # is the conjunction: no exception, no call, and the argument handed straight # back with the tag silently gone. check_eq $P/pyapply-rt-type "CommentedSeq" "$(pv rt_pyapply_type)" check_eq $P/pyapply-rt-len "1" "$(pv rt_pyapply_len)" check_eq $P/pyapply-rt-returns-the-argument "yes" "$(pv rt_pyapply_is_the_argument)" check_eq $P/pyapply-rt-no-side-effect "no" "$(pv rt_pyapply_side_effect)" check_eq $P/pyname-rt-type "TaggedScalar" "$(pv rt_pyname_type)" # unsafe DOES construct. Named so the boundary is stated rather than implied -- # and so that a change making `unsafe' safe is a red here, not a silent shift. check_eq $P/pyname-unsafe-constructs "'/'" "$(pv unsafe_pyname)" check_eq $P/pyapply-unsafe-constructs "yes" "$(pv unsafe_pyapply_available)" check_eq $P/pyapply-marker-cleaned "yes" "$(pv pytag_marker_cleaned)" # --- error paths ----------------------------------------------------------- # Class, `is a YAMLError', and the line:column the mark carries -- all three, # because a parser that raises the right class at the wrong place is no more # use to a caller than one that does not raise. for _m in rt safe; do check_eq $P/err-tab-indent-$_m "ScannerError" "$(pv ${_m}_err_tab_indent)" check_eq $P/err-tab-indent-mark-$_m "1:0" "$(pv ${_m}_err_tab_indent_mark)" check_eq $P/err-tab-indent-kind-$_m "yes" "$(pv ${_m}_err_tab_indent_is_yamlerror)" check_eq $P/err-dup-key-$_m "DuplicateKeyError" "$(pv ${_m}_err_dup_key)" check_eq $P/err-dup-key-mark-$_m "1:0" "$(pv ${_m}_err_dup_key_mark)" check_eq $P/err-dup-key-kind-$_m "yes" "$(pv ${_m}_err_dup_key_is_yamlerror)" check_eq $P/err-undef-alias-$_m "ComposerError" "$(pv ${_m}_err_undef_alias)" check_eq $P/err-undef-alias-mark-$_m "0:3" "$(pv ${_m}_err_undef_alias_mark)" check_eq $P/err-undef-alias-kind-$_m "yes" "$(pv ${_m}_err_undef_alias_is_yamlerror)" check_eq $P/err-trunc-block-$_m "ScannerError" "$(pv ${_m}_err_trunc_block)" check_eq $P/err-trunc-block-mark-$_m "4:0" "$(pv ${_m}_err_trunc_block_mark)" check_eq $P/err-trunc-block-kind-$_m "yes" "$(pv ${_m}_err_trunc_block_is_yamlerror)" check_eq $P/err-unterm-quote-$_m "ScannerError" "$(pv ${_m}_err_unterm_quote)" check_eq $P/err-unterm-quote-kind-$_m "yes" "$(pv ${_m}_err_unterm_quote_is_yamlerror)" check_eq $P/err-unterm-flow-$_m "ParserError" "$(pv ${_m}_err_unterm_flow)" check_eq $P/err-unterm-flow-kind-$_m "yes" "$(pv ${_m}_err_unterm_flow_is_yamlerror)" done # --- the API 0.18 removed -------------------------------------------------- # Present as a NAME, absent as a FUNCTION. Both halves, for all six. for _f in load safe_load round_trip_load dump safe_dump round_trip_dump; do check_eq $P/removed-$_f-still-an-attribute "yes" "$(pv removed_${_f}_present)" check_eq $P/removed-$_f-raises "!AttributeError" "$(pv removed_${_f}_call)" done check_eq $P/removed-message-says-removed "yes" "$(pv removed_safe_load_msg_has_removed)" check_eq $P/removed-message-names-the-fix "yes" "$(pv removed_safe_load_names_replacement)" # --- the four constructors ------------------------------------------------- check_eq $P/typ-default "rt" "$(pv typ_rt_default)" check_eq $P/typ-rt-constructor "RoundTripConstructor" "$(pv typ_rt_constructor)" check_eq $P/typ-rt-representer "RoundTripRepresenter" "$(pv typ_rt_representer)" check_eq $P/typ-safe-constructor "SafeConstructor" "$(pv typ_safe_constructor)" check_eq $P/typ-safe-representer "SafeRepresenter" "$(pv typ_safe_representer)" check_eq $P/typ-unsafe-constructor "Constructor" "$(pv typ_unsafe_constructor)" check_eq $P/typ-unsafe-representer "Representer" "$(pv typ_unsafe_representer)" check_eq $P/typ-base-constructor "BaseConstructor" "$(pv typ_base_constructor)" check_eq $P/typ-base-representer "BaseRepresenter" "$(pv typ_base_representer)" # `base' resolves no implicit types at all: `1' is the string "1". check_eq $P/typ-base-no-resolution "str" "$(pv base_scalar_type)" # --- the emitter knobs ----------------------------------------------------- check_eq $P/emit-indent "a:\n b: 1\nc:\n - 1\n - 2\n" "$(pv emit_indent)" check_eq $P/emit-flow "{a: {b: 1}}\n" "$(pv emit_flow)" check_eq $P/emit-explicit "---\na: 1\n...\n" "$(pv emit_explicit)" # --- multi-document -------------------------------------------------------- check_eq $P/multidoc-load-count "2" "$(pv load_all_count)" check_eq $P/multidoc-load-values "a=1,b=2" "$(pv load_all_values)" check_eq $P/multidoc-dump-out "a: 1\n---\nb: 2\n" "$(pv dump_all_out)" # `dump_all' separates documents but does NOT lead with `---', so its output is # not a valid concatenation target for a stream that already has one. check_eq $P/multidoc-dump-no-leading-marker "no" "$(pv dump_all_leads_with_marker)" rm -rf "$W"