frida 16.2.1 → 16.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BSDmakefile +6 -0
- package/Makefile +16 -0
- package/README.md +14 -11
- package/configure +18 -0
- package/configure.bat +22 -0
- package/dist/native.js +0 -8
- package/lib/application.ts +98 -0
- package/lib/authentication.ts +3 -0
- package/lib/build.py +50 -0
- package/lib/bus.ts +30 -0
- package/lib/cancellable.ts +33 -0
- package/lib/child.ts +15 -0
- package/lib/crash.ts +11 -0
- package/lib/device.ts +329 -0
- package/lib/device_manager.ts +69 -0
- package/lib/endpoint_parameters.ts +56 -0
- package/lib/icon.ts +15 -0
- package/lib/index.ts +311 -0
- package/lib/iostream.ts +78 -0
- package/lib/meson.build +53 -0
- package/lib/native.ts +9 -0
- package/lib/portal_membership.ts +10 -0
- package/lib/portal_service.ts +105 -0
- package/lib/process.ts +57 -0
- package/lib/relay.ts +44 -0
- package/lib/script.ts +352 -0
- package/lib/session.ts +113 -0
- package/lib/signals.ts +45 -0
- package/lib/socket_address.ts +35 -0
- package/lib/spawn.ts +4 -0
- package/lib/system_parameters.ts +78 -0
- package/make.bat +23 -0
- package/meson.build +160 -0
- package/meson.options +11 -0
- package/package.json +27 -6
- package/releng/deps.py +1133 -0
- package/releng/deps.toml +391 -0
- package/releng/devkit-assets/frida-core-example-unix.c +188 -0
- package/releng/devkit-assets/frida-core-example-windows.c +197 -0
- package/releng/devkit-assets/frida-core-example.sln +28 -0
- package/releng/devkit-assets/frida-core-example.vcxproj +157 -0
- package/releng/devkit-assets/frida-core-example.vcxproj.filters +27 -0
- package/releng/devkit-assets/frida-gum-example-unix.c +122 -0
- package/releng/devkit-assets/frida-gum-example-windows.c +132 -0
- package/releng/devkit-assets/frida-gum-example.sln +28 -0
- package/releng/devkit-assets/frida-gum-example.vcxproj +157 -0
- package/releng/devkit-assets/frida-gum-example.vcxproj.filters +27 -0
- package/releng/devkit-assets/frida-gumjs-example-unix.c +84 -0
- package/releng/devkit-assets/frida-gumjs-example-windows.c +91 -0
- package/releng/devkit-assets/frida-gumjs-example.sln +28 -0
- package/releng/devkit-assets/frida-gumjs-example.vcxproj +157 -0
- package/releng/devkit-assets/frida-gumjs-example.vcxproj.filters +27 -0
- package/releng/devkit.py +535 -0
- package/releng/env.py +420 -0
- package/releng/env_android.py +150 -0
- package/releng/env_apple.py +176 -0
- package/releng/env_generic.py +373 -0
- package/releng/frida_version.py +69 -0
- package/releng/machine_file.py +44 -0
- package/releng/machine_spec.py +290 -0
- package/releng/meson/meson.py +27 -0
- package/releng/meson/mesonbuild/__init__.py +0 -0
- package/releng/meson/mesonbuild/_pathlib.py +63 -0
- package/releng/meson/mesonbuild/_typing.py +69 -0
- package/releng/meson/mesonbuild/arglist.py +321 -0
- package/releng/meson/mesonbuild/ast/__init__.py +23 -0
- package/releng/meson/mesonbuild/ast/interpreter.py +441 -0
- package/releng/meson/mesonbuild/ast/introspection.py +374 -0
- package/releng/meson/mesonbuild/ast/postprocess.py +109 -0
- package/releng/meson/mesonbuild/ast/printer.py +620 -0
- package/releng/meson/mesonbuild/ast/visitor.py +161 -0
- package/releng/meson/mesonbuild/backend/__init__.py +0 -0
- package/releng/meson/mesonbuild/backend/backends.py +2047 -0
- package/releng/meson/mesonbuild/backend/ninjabackend.py +3808 -0
- package/releng/meson/mesonbuild/backend/nonebackend.py +26 -0
- package/releng/meson/mesonbuild/backend/vs2010backend.py +2078 -0
- package/releng/meson/mesonbuild/backend/vs2012backend.py +35 -0
- package/releng/meson/mesonbuild/backend/vs2013backend.py +34 -0
- package/releng/meson/mesonbuild/backend/vs2015backend.py +35 -0
- package/releng/meson/mesonbuild/backend/vs2017backend.py +59 -0
- package/releng/meson/mesonbuild/backend/vs2019backend.py +54 -0
- package/releng/meson/mesonbuild/backend/vs2022backend.py +54 -0
- package/releng/meson/mesonbuild/backend/xcodebackend.py +1781 -0
- package/releng/meson/mesonbuild/build.py +3249 -0
- package/releng/meson/mesonbuild/cargo/__init__.py +5 -0
- package/releng/meson/mesonbuild/cargo/builder.py +238 -0
- package/releng/meson/mesonbuild/cargo/cfg.py +274 -0
- package/releng/meson/mesonbuild/cargo/interpreter.py +733 -0
- package/releng/meson/mesonbuild/cargo/manifest.py +227 -0
- package/releng/meson/mesonbuild/cargo/version.py +95 -0
- package/releng/meson/mesonbuild/cmake/__init__.py +28 -0
- package/releng/meson/mesonbuild/cmake/common.py +331 -0
- package/releng/meson/mesonbuild/cmake/data/__init__.py +0 -0
- package/releng/meson/mesonbuild/cmake/data/preload.cmake +82 -0
- package/releng/meson/mesonbuild/cmake/executor.py +241 -0
- package/releng/meson/mesonbuild/cmake/fileapi.py +324 -0
- package/releng/meson/mesonbuild/cmake/generator.py +186 -0
- package/releng/meson/mesonbuild/cmake/interpreter.py +1267 -0
- package/releng/meson/mesonbuild/cmake/toolchain.py +248 -0
- package/releng/meson/mesonbuild/cmake/traceparser.py +814 -0
- package/releng/meson/mesonbuild/cmake/tracetargets.py +161 -0
- package/releng/meson/mesonbuild/compilers/__init__.py +86 -0
- package/releng/meson/mesonbuild/compilers/asm.py +307 -0
- package/releng/meson/mesonbuild/compilers/c.py +788 -0
- package/releng/meson/mesonbuild/compilers/c_function_attributes.py +143 -0
- package/releng/meson/mesonbuild/compilers/compilers.py +1388 -0
- package/releng/meson/mesonbuild/compilers/cpp.py +1035 -0
- package/releng/meson/mesonbuild/compilers/cs.py +136 -0
- package/releng/meson/mesonbuild/compilers/cuda.py +806 -0
- package/releng/meson/mesonbuild/compilers/cython.py +91 -0
- package/releng/meson/mesonbuild/compilers/d.py +861 -0
- package/releng/meson/mesonbuild/compilers/detect.py +1396 -0
- package/releng/meson/mesonbuild/compilers/fortran.py +523 -0
- package/releng/meson/mesonbuild/compilers/java.py +113 -0
- package/releng/meson/mesonbuild/compilers/mixins/__init__.py +0 -0
- package/releng/meson/mesonbuild/compilers/mixins/arm.py +167 -0
- package/releng/meson/mesonbuild/compilers/mixins/ccrx.py +113 -0
- package/releng/meson/mesonbuild/compilers/mixins/clang.py +170 -0
- package/releng/meson/mesonbuild/compilers/mixins/clike.py +1330 -0
- package/releng/meson/mesonbuild/compilers/mixins/compcert.py +117 -0
- package/releng/meson/mesonbuild/compilers/mixins/elbrus.py +93 -0
- package/releng/meson/mesonbuild/compilers/mixins/emscripten.py +89 -0
- package/releng/meson/mesonbuild/compilers/mixins/gnu.py +629 -0
- package/releng/meson/mesonbuild/compilers/mixins/intel.py +167 -0
- package/releng/meson/mesonbuild/compilers/mixins/islinker.py +120 -0
- package/releng/meson/mesonbuild/compilers/mixins/metrowerks.py +279 -0
- package/releng/meson/mesonbuild/compilers/mixins/pgi.py +88 -0
- package/releng/meson/mesonbuild/compilers/mixins/ti.py +130 -0
- package/releng/meson/mesonbuild/compilers/mixins/visualstudio.py +458 -0
- package/releng/meson/mesonbuild/compilers/mixins/xc16.py +111 -0
- package/releng/meson/mesonbuild/compilers/objc.py +120 -0
- package/releng/meson/mesonbuild/compilers/objcpp.py +102 -0
- package/releng/meson/mesonbuild/compilers/rust.py +230 -0
- package/releng/meson/mesonbuild/compilers/swift.py +131 -0
- package/releng/meson/mesonbuild/compilers/vala.py +121 -0
- package/releng/meson/mesonbuild/coredata.py +1532 -0
- package/releng/meson/mesonbuild/dependencies/__init__.py +252 -0
- package/releng/meson/mesonbuild/dependencies/base.py +663 -0
- package/releng/meson/mesonbuild/dependencies/boost.py +1083 -0
- package/releng/meson/mesonbuild/dependencies/cmake.py +656 -0
- package/releng/meson/mesonbuild/dependencies/coarrays.py +80 -0
- package/releng/meson/mesonbuild/dependencies/configtool.py +163 -0
- package/releng/meson/mesonbuild/dependencies/cuda.py +295 -0
- package/releng/meson/mesonbuild/dependencies/data/CMakeLists.txt +102 -0
- package/releng/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt +204 -0
- package/releng/meson/mesonbuild/dependencies/data/CMakePathInfo.txt +31 -0
- package/releng/meson/mesonbuild/dependencies/data/__init__.py +0 -0
- package/releng/meson/mesonbuild/dependencies/detect.py +225 -0
- package/releng/meson/mesonbuild/dependencies/dev.py +707 -0
- package/releng/meson/mesonbuild/dependencies/dub.py +424 -0
- package/releng/meson/mesonbuild/dependencies/factory.py +146 -0
- package/releng/meson/mesonbuild/dependencies/framework.py +111 -0
- package/releng/meson/mesonbuild/dependencies/hdf5.py +168 -0
- package/releng/meson/mesonbuild/dependencies/misc.py +618 -0
- package/releng/meson/mesonbuild/dependencies/mpi.py +231 -0
- package/releng/meson/mesonbuild/dependencies/pkgconfig.py +570 -0
- package/releng/meson/mesonbuild/dependencies/platform.py +52 -0
- package/releng/meson/mesonbuild/dependencies/python.py +431 -0
- package/releng/meson/mesonbuild/dependencies/qt.py +484 -0
- package/releng/meson/mesonbuild/dependencies/scalapack.py +142 -0
- package/releng/meson/mesonbuild/dependencies/ui.py +281 -0
- package/releng/meson/mesonbuild/depfile.py +82 -0
- package/releng/meson/mesonbuild/envconfig.py +480 -0
- package/releng/meson/mesonbuild/environment.py +987 -0
- package/releng/meson/mesonbuild/interpreter/__init__.py +47 -0
- package/releng/meson/mesonbuild/interpreter/compiler.py +900 -0
- package/releng/meson/mesonbuild/interpreter/dependencyfallbacks.py +386 -0
- package/releng/meson/mesonbuild/interpreter/interpreter.py +3595 -0
- package/releng/meson/mesonbuild/interpreter/interpreterobjects.py +1096 -0
- package/releng/meson/mesonbuild/interpreter/kwargs.py +479 -0
- package/releng/meson/mesonbuild/interpreter/mesonmain.py +487 -0
- package/releng/meson/mesonbuild/interpreter/primitives/__init__.py +29 -0
- package/releng/meson/mesonbuild/interpreter/primitives/array.py +108 -0
- package/releng/meson/mesonbuild/interpreter/primitives/boolean.py +52 -0
- package/releng/meson/mesonbuild/interpreter/primitives/dict.py +88 -0
- package/releng/meson/mesonbuild/interpreter/primitives/integer.py +86 -0
- package/releng/meson/mesonbuild/interpreter/primitives/range.py +38 -0
- package/releng/meson/mesonbuild/interpreter/primitives/string.py +247 -0
- package/releng/meson/mesonbuild/interpreter/type_checking.py +853 -0
- package/releng/meson/mesonbuild/interpreterbase/__init__.py +126 -0
- package/releng/meson/mesonbuild/interpreterbase/_unholder.py +25 -0
- package/releng/meson/mesonbuild/interpreterbase/baseobjects.py +174 -0
- package/releng/meson/mesonbuild/interpreterbase/decorators.py +806 -0
- package/releng/meson/mesonbuild/interpreterbase/disabler.py +35 -0
- package/releng/meson/mesonbuild/interpreterbase/exceptions.py +22 -0
- package/releng/meson/mesonbuild/interpreterbase/helpers.py +67 -0
- package/releng/meson/mesonbuild/interpreterbase/interpreterbase.py +665 -0
- package/releng/meson/mesonbuild/interpreterbase/operator.py +32 -0
- package/releng/meson/mesonbuild/linkers/__init__.py +20 -0
- package/releng/meson/mesonbuild/linkers/base.py +39 -0
- package/releng/meson/mesonbuild/linkers/detect.py +229 -0
- package/releng/meson/mesonbuild/linkers/linkers.py +1614 -0
- package/releng/meson/mesonbuild/mcompile.py +380 -0
- package/releng/meson/mesonbuild/mconf.py +368 -0
- package/releng/meson/mesonbuild/mdevenv.py +234 -0
- package/releng/meson/mesonbuild/mdist.py +376 -0
- package/releng/meson/mesonbuild/mesondata.py +38 -0
- package/releng/meson/mesonbuild/mesonlib.py +23 -0
- package/releng/meson/mesonbuild/mesonmain.py +289 -0
- package/releng/meson/mesonbuild/minit.py +204 -0
- package/releng/meson/mesonbuild/minstall.py +864 -0
- package/releng/meson/mesonbuild/mintro.py +667 -0
- package/releng/meson/mesonbuild/mlog.py +542 -0
- package/releng/meson/mesonbuild/modules/__init__.py +270 -0
- package/releng/meson/mesonbuild/modules/cmake.py +442 -0
- package/releng/meson/mesonbuild/modules/cuda.py +377 -0
- package/releng/meson/mesonbuild/modules/dlang.py +117 -0
- package/releng/meson/mesonbuild/modules/external_project.py +306 -0
- package/releng/meson/mesonbuild/modules/fs.py +323 -0
- package/releng/meson/mesonbuild/modules/gnome.py +2215 -0
- package/releng/meson/mesonbuild/modules/hotdoc.py +487 -0
- package/releng/meson/mesonbuild/modules/i18n.py +405 -0
- package/releng/meson/mesonbuild/modules/icestorm.py +123 -0
- package/releng/meson/mesonbuild/modules/java.py +112 -0
- package/releng/meson/mesonbuild/modules/keyval.py +65 -0
- package/releng/meson/mesonbuild/modules/modtest.py +33 -0
- package/releng/meson/mesonbuild/modules/pkgconfig.py +744 -0
- package/releng/meson/mesonbuild/modules/python.py +556 -0
- package/releng/meson/mesonbuild/modules/python3.py +85 -0
- package/releng/meson/mesonbuild/modules/qt.py +621 -0
- package/releng/meson/mesonbuild/modules/qt4.py +23 -0
- package/releng/meson/mesonbuild/modules/qt5.py +23 -0
- package/releng/meson/mesonbuild/modules/qt6.py +22 -0
- package/releng/meson/mesonbuild/modules/rust.py +355 -0
- package/releng/meson/mesonbuild/modules/simd.py +114 -0
- package/releng/meson/mesonbuild/modules/sourceset.py +291 -0
- package/releng/meson/mesonbuild/modules/wayland.py +151 -0
- package/releng/meson/mesonbuild/modules/windows.py +207 -0
- package/releng/meson/mesonbuild/mparser.py +1114 -0
- package/releng/meson/mesonbuild/msetup.py +365 -0
- package/releng/meson/mesonbuild/msubprojects.py +764 -0
- package/releng/meson/mesonbuild/mtest.py +2201 -0
- package/releng/meson/mesonbuild/munstable_coredata.py +107 -0
- package/releng/meson/mesonbuild/optinterpreter.py +276 -0
- package/releng/meson/mesonbuild/programs.py +367 -0
- package/releng/meson/mesonbuild/rewriter.py +1075 -0
- package/releng/meson/mesonbuild/scripts/__init__.py +10 -0
- package/releng/meson/mesonbuild/scripts/clangformat.py +55 -0
- package/releng/meson/mesonbuild/scripts/clangtidy.py +30 -0
- package/releng/meson/mesonbuild/scripts/cleantrees.py +35 -0
- package/releng/meson/mesonbuild/scripts/cmake_run_ctgt.py +103 -0
- package/releng/meson/mesonbuild/scripts/cmd_or_ps.ps1 +17 -0
- package/releng/meson/mesonbuild/scripts/copy.py +19 -0
- package/releng/meson/mesonbuild/scripts/coverage.py +214 -0
- package/releng/meson/mesonbuild/scripts/delwithsuffix.py +27 -0
- package/releng/meson/mesonbuild/scripts/depfixer.py +495 -0
- package/releng/meson/mesonbuild/scripts/depscan.py +198 -0
- package/releng/meson/mesonbuild/scripts/dirchanger.py +20 -0
- package/releng/meson/mesonbuild/scripts/env2mfile.py +402 -0
- package/releng/meson/mesonbuild/scripts/externalproject.py +106 -0
- package/releng/meson/mesonbuild/scripts/gettext.py +86 -0
- package/releng/meson/mesonbuild/scripts/gtkdochelper.py +286 -0
- package/releng/meson/mesonbuild/scripts/hotdochelper.py +40 -0
- package/releng/meson/mesonbuild/scripts/itstool.py +77 -0
- package/releng/meson/mesonbuild/scripts/meson_exe.py +115 -0
- package/releng/meson/mesonbuild/scripts/msgfmthelper.py +29 -0
- package/releng/meson/mesonbuild/scripts/pycompile.py +54 -0
- package/releng/meson/mesonbuild/scripts/python_info.py +121 -0
- package/releng/meson/mesonbuild/scripts/regen_checker.py +55 -0
- package/releng/meson/mesonbuild/scripts/run_tool.py +58 -0
- package/releng/meson/mesonbuild/scripts/scanbuild.py +57 -0
- package/releng/meson/mesonbuild/scripts/symbolextractor.py +322 -0
- package/releng/meson/mesonbuild/scripts/tags.py +44 -0
- package/releng/meson/mesonbuild/scripts/test_loaded_modules.py +14 -0
- package/releng/meson/mesonbuild/scripts/uninstall.py +41 -0
- package/releng/meson/mesonbuild/scripts/vcstagger.py +35 -0
- package/releng/meson/mesonbuild/scripts/yasm.py +24 -0
- package/releng/meson/mesonbuild/templates/__init__.py +0 -0
- package/releng/meson/mesonbuild/templates/cpptemplates.py +143 -0
- package/releng/meson/mesonbuild/templates/cstemplates.py +90 -0
- package/releng/meson/mesonbuild/templates/ctemplates.py +126 -0
- package/releng/meson/mesonbuild/templates/cudatemplates.py +143 -0
- package/releng/meson/mesonbuild/templates/dlangtemplates.py +109 -0
- package/releng/meson/mesonbuild/templates/fortrantemplates.py +101 -0
- package/releng/meson/mesonbuild/templates/javatemplates.py +94 -0
- package/releng/meson/mesonbuild/templates/mesontemplates.py +70 -0
- package/releng/meson/mesonbuild/templates/objcpptemplates.py +126 -0
- package/releng/meson/mesonbuild/templates/objctemplates.py +126 -0
- package/releng/meson/mesonbuild/templates/rusttemplates.py +79 -0
- package/releng/meson/mesonbuild/templates/samplefactory.py +41 -0
- package/releng/meson/mesonbuild/templates/sampleimpl.py +160 -0
- package/releng/meson/mesonbuild/templates/valatemplates.py +82 -0
- package/releng/meson/mesonbuild/utils/__init__.py +0 -0
- package/releng/meson/mesonbuild/utils/core.py +166 -0
- package/releng/meson/mesonbuild/utils/platform.py +27 -0
- package/releng/meson/mesonbuild/utils/posix.py +32 -0
- package/releng/meson/mesonbuild/utils/universal.py +2445 -0
- package/releng/meson/mesonbuild/utils/vsenv.py +126 -0
- package/releng/meson/mesonbuild/utils/win32.py +29 -0
- package/releng/meson/mesonbuild/wrap/__init__.py +59 -0
- package/releng/meson/mesonbuild/wrap/wrap.py +846 -0
- package/releng/meson/mesonbuild/wrap/wraptool.py +198 -0
- package/releng/meson-scripts/BSDmakefile +6 -0
- package/releng/meson-scripts/Makefile +16 -0
- package/releng/meson-scripts/configure +18 -0
- package/releng/meson-scripts/configure.bat +22 -0
- package/releng/meson-scripts/make.bat +23 -0
- package/releng/meson_configure.py +506 -0
- package/releng/meson_make.py +131 -0
- package/releng/mkdevkit.py +107 -0
- package/releng/mkfatmacho.py +54 -0
- package/releng/post-process-oabi.py +97 -0
- package/releng/progress.py +14 -0
- package/releng/sync-from-upstream.py +185 -0
- package/releng/tomlkit/tomlkit/__init__.py +59 -0
- package/releng/tomlkit/tomlkit/_compat.py +22 -0
- package/releng/tomlkit/tomlkit/_types.py +83 -0
- package/releng/tomlkit/tomlkit/_utils.py +158 -0
- package/releng/tomlkit/tomlkit/api.py +308 -0
- package/releng/tomlkit/tomlkit/container.py +875 -0
- package/releng/tomlkit/tomlkit/exceptions.py +227 -0
- package/releng/tomlkit/tomlkit/items.py +1967 -0
- package/releng/tomlkit/tomlkit/parser.py +1141 -0
- package/releng/tomlkit/tomlkit/py.typed +0 -0
- package/releng/tomlkit/tomlkit/source.py +180 -0
- package/releng/tomlkit/tomlkit/toml_char.py +52 -0
- package/releng/tomlkit/tomlkit/toml_document.py +7 -0
- package/releng/tomlkit/tomlkit/toml_file.py +58 -0
- package/releng/winenv.py +140 -0
- package/scripts/adjust-version.py +19 -0
- package/scripts/detect-version.py +40 -0
- package/scripts/fetch-abi-bits.py +343 -0
- package/scripts/install.js +23 -0
- package/scripts/package.py +15 -0
- package/src/addon.cc +76 -0
- package/src/application.cc +148 -0
- package/src/application.h +31 -0
- package/src/authentication.cc +174 -0
- package/src/authentication.h +24 -0
- package/src/bus.cc +167 -0
- package/src/bus.h +33 -0
- package/src/cancellable.cc +117 -0
- package/src/cancellable.h +31 -0
- package/src/child.cc +150 -0
- package/src/child.h +32 -0
- package/src/crash.cc +122 -0
- package/src/crash.h +30 -0
- package/src/device.cc +1302 -0
- package/src/device.h +55 -0
- package/src/device_manager.cc +362 -0
- package/src/device_manager.h +35 -0
- package/src/endpoint_parameters.cc +171 -0
- package/src/endpoint_parameters.h +28 -0
- package/src/glib_context.cc +62 -0
- package/src/glib_context.h +29 -0
- package/src/glib_object.cc +25 -0
- package/src/glib_object.h +37 -0
- package/src/iostream.cc +247 -0
- package/src/iostream.h +30 -0
- package/src/meson.build +26 -0
- package/src/operation.h +94 -0
- package/src/portal_membership.cc +100 -0
- package/src/portal_membership.h +26 -0
- package/src/portal_service.cc +401 -0
- package/src/portal_service.h +40 -0
- package/src/process.cc +135 -0
- package/src/process.h +30 -0
- package/src/relay.cc +139 -0
- package/src/relay.h +31 -0
- package/src/runtime.cc +443 -0
- package/src/runtime.h +64 -0
- package/src/script.cc +301 -0
- package/src/script.h +36 -0
- package/src/session.cc +860 -0
- package/src/session.h +42 -0
- package/src/signals.cc +334 -0
- package/src/signals.h +47 -0
- package/src/spawn.cc +95 -0
- package/src/spawn.h +27 -0
- package/src/usage_monitor.h +117 -0
- package/src/uv_context.cc +118 -0
- package/src/uv_context.h +40 -0
- package/src/win_delay_load_hook.cc +63 -0
- package/subprojects/frida-core.wrap +8 -0
- package/subprojects/nan.wrap +9 -0
- package/subprojects/packagefiles/nan.patch +13 -0
- package/test/data/index.ts +13 -0
- package/test/data/unixvictim-linux-x86 +0 -0
- package/test/data/unixvictim-linux-x86_64 +0 -0
- package/test/data/unixvictim-macos +0 -0
- package/test/device.ts +27 -0
- package/test/device_manager.ts +16 -0
- package/test/labrat.ts +32 -0
- package/test/script.ts +176 -0
- package/test/session.ts +73 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,1967 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import copy
|
|
5
|
+
import dataclasses
|
|
6
|
+
import math
|
|
7
|
+
import re
|
|
8
|
+
import string
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from datetime import date
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from datetime import time
|
|
14
|
+
from datetime import tzinfo
|
|
15
|
+
from enum import Enum
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
from typing import Any
|
|
18
|
+
from typing import Callable
|
|
19
|
+
from typing import Collection
|
|
20
|
+
from typing import Iterable
|
|
21
|
+
from typing import Iterator
|
|
22
|
+
from typing import Sequence
|
|
23
|
+
from typing import TypeVar
|
|
24
|
+
from typing import cast
|
|
25
|
+
from typing import overload
|
|
26
|
+
|
|
27
|
+
from tomlkit._compat import PY38
|
|
28
|
+
from tomlkit._compat import decode
|
|
29
|
+
from tomlkit._types import _CustomDict
|
|
30
|
+
from tomlkit._types import _CustomFloat
|
|
31
|
+
from tomlkit._types import _CustomInt
|
|
32
|
+
from tomlkit._types import _CustomList
|
|
33
|
+
from tomlkit._types import wrap_method
|
|
34
|
+
from tomlkit._utils import CONTROL_CHARS
|
|
35
|
+
from tomlkit._utils import escape_string
|
|
36
|
+
from tomlkit.exceptions import InvalidStringError
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from tomlkit import container
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
ItemT = TypeVar("ItemT", bound="Item")
|
|
44
|
+
Encoder = Callable[[Any], "Item"]
|
|
45
|
+
CUSTOM_ENCODERS: list[Encoder] = []
|
|
46
|
+
AT = TypeVar("AT", bound="AbstractTable")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class _ConvertError(TypeError, ValueError):
|
|
50
|
+
"""An internal error raised when item() fails to convert a value.
|
|
51
|
+
It should be a TypeError, but due to historical reasons
|
|
52
|
+
it needs to subclass ValueError as well.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@overload
|
|
57
|
+
def item(value: bool, _parent: Item | None = ..., _sort_keys: bool = ...) -> Bool:
|
|
58
|
+
...
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@overload
|
|
62
|
+
def item(value: int, _parent: Item | None = ..., _sort_keys: bool = ...) -> Integer:
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def item(value: float, _parent: Item | None = ..., _sort_keys: bool = ...) -> Float:
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@overload
|
|
72
|
+
def item(value: str, _parent: Item | None = ..., _sort_keys: bool = ...) -> String:
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@overload
|
|
77
|
+
def item(
|
|
78
|
+
value: datetime, _parent: Item | None = ..., _sort_keys: bool = ...
|
|
79
|
+
) -> DateTime:
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@overload
|
|
84
|
+
def item(value: date, _parent: Item | None = ..., _sort_keys: bool = ...) -> Date:
|
|
85
|
+
...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@overload
|
|
89
|
+
def item(value: time, _parent: Item | None = ..., _sort_keys: bool = ...) -> Time:
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@overload
|
|
94
|
+
def item(
|
|
95
|
+
value: Sequence[dict], _parent: Item | None = ..., _sort_keys: bool = ...
|
|
96
|
+
) -> AoT:
|
|
97
|
+
...
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@overload
|
|
101
|
+
def item(value: Sequence, _parent: Item | None = ..., _sort_keys: bool = ...) -> Array:
|
|
102
|
+
...
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@overload
|
|
106
|
+
def item(value: dict, _parent: Array = ..., _sort_keys: bool = ...) -> InlineTable:
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@overload
|
|
111
|
+
def item(value: dict, _parent: Item | None = ..., _sort_keys: bool = ...) -> Table:
|
|
112
|
+
...
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@overload
|
|
116
|
+
def item(value: ItemT, _parent: Item | None = ..., _sort_keys: bool = ...) -> ItemT:
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def item(value: Any, _parent: Item | None = None, _sort_keys: bool = False) -> Item:
|
|
121
|
+
"""Create a TOML item from a Python object.
|
|
122
|
+
|
|
123
|
+
:Example:
|
|
124
|
+
|
|
125
|
+
>>> item(42)
|
|
126
|
+
42
|
|
127
|
+
>>> item([1, 2, 3])
|
|
128
|
+
[1, 2, 3]
|
|
129
|
+
>>> item({'a': 1, 'b': 2})
|
|
130
|
+
a = 1
|
|
131
|
+
b = 2
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
from tomlkit.container import Container
|
|
135
|
+
|
|
136
|
+
if isinstance(value, Item):
|
|
137
|
+
return value
|
|
138
|
+
|
|
139
|
+
if isinstance(value, bool):
|
|
140
|
+
return Bool(value, Trivia())
|
|
141
|
+
elif isinstance(value, int):
|
|
142
|
+
return Integer(value, Trivia(), str(value))
|
|
143
|
+
elif isinstance(value, float):
|
|
144
|
+
return Float(value, Trivia(), str(value))
|
|
145
|
+
elif isinstance(value, dict):
|
|
146
|
+
table_constructor = (
|
|
147
|
+
InlineTable if isinstance(_parent, (Array, InlineTable)) else Table
|
|
148
|
+
)
|
|
149
|
+
val = table_constructor(Container(), Trivia(), False)
|
|
150
|
+
for k, v in sorted(
|
|
151
|
+
value.items(),
|
|
152
|
+
key=lambda i: (isinstance(i[1], dict), i[0]) if _sort_keys else 1,
|
|
153
|
+
):
|
|
154
|
+
val[k] = item(v, _parent=val, _sort_keys=_sort_keys)
|
|
155
|
+
|
|
156
|
+
return val
|
|
157
|
+
elif isinstance(value, (list, tuple)):
|
|
158
|
+
if (
|
|
159
|
+
value
|
|
160
|
+
and all(isinstance(v, dict) for v in value)
|
|
161
|
+
and (_parent is None or isinstance(_parent, Table))
|
|
162
|
+
):
|
|
163
|
+
a = AoT([])
|
|
164
|
+
table_constructor = Table
|
|
165
|
+
else:
|
|
166
|
+
a = Array([], Trivia())
|
|
167
|
+
table_constructor = InlineTable
|
|
168
|
+
|
|
169
|
+
for v in value:
|
|
170
|
+
if isinstance(v, dict):
|
|
171
|
+
table = table_constructor(Container(), Trivia(), True)
|
|
172
|
+
|
|
173
|
+
for k, _v in sorted(
|
|
174
|
+
v.items(),
|
|
175
|
+
key=lambda i: (isinstance(i[1], dict), i[0] if _sort_keys else 1),
|
|
176
|
+
):
|
|
177
|
+
i = item(_v, _parent=table, _sort_keys=_sort_keys)
|
|
178
|
+
if isinstance(table, InlineTable):
|
|
179
|
+
i.trivia.trail = ""
|
|
180
|
+
|
|
181
|
+
table[k] = i
|
|
182
|
+
|
|
183
|
+
v = table
|
|
184
|
+
|
|
185
|
+
a.append(v)
|
|
186
|
+
|
|
187
|
+
return a
|
|
188
|
+
elif isinstance(value, str):
|
|
189
|
+
return String.from_raw(value)
|
|
190
|
+
elif isinstance(value, datetime):
|
|
191
|
+
return DateTime(
|
|
192
|
+
value.year,
|
|
193
|
+
value.month,
|
|
194
|
+
value.day,
|
|
195
|
+
value.hour,
|
|
196
|
+
value.minute,
|
|
197
|
+
value.second,
|
|
198
|
+
value.microsecond,
|
|
199
|
+
value.tzinfo,
|
|
200
|
+
Trivia(),
|
|
201
|
+
value.isoformat().replace("+00:00", "Z"),
|
|
202
|
+
)
|
|
203
|
+
elif isinstance(value, date):
|
|
204
|
+
return Date(value.year, value.month, value.day, Trivia(), value.isoformat())
|
|
205
|
+
elif isinstance(value, time):
|
|
206
|
+
return Time(
|
|
207
|
+
value.hour,
|
|
208
|
+
value.minute,
|
|
209
|
+
value.second,
|
|
210
|
+
value.microsecond,
|
|
211
|
+
value.tzinfo,
|
|
212
|
+
Trivia(),
|
|
213
|
+
value.isoformat(),
|
|
214
|
+
)
|
|
215
|
+
else:
|
|
216
|
+
for encoder in CUSTOM_ENCODERS:
|
|
217
|
+
try:
|
|
218
|
+
rv = encoder(value)
|
|
219
|
+
except TypeError:
|
|
220
|
+
pass
|
|
221
|
+
else:
|
|
222
|
+
if not isinstance(rv, Item):
|
|
223
|
+
raise _ConvertError(
|
|
224
|
+
f"Custom encoder returned {type(rv)}, not a subclass of Item"
|
|
225
|
+
)
|
|
226
|
+
return rv
|
|
227
|
+
|
|
228
|
+
raise _ConvertError(f"Invalid type {type(value)}")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
class StringType(Enum):
|
|
232
|
+
# Single Line Basic
|
|
233
|
+
SLB = '"'
|
|
234
|
+
# Multi Line Basic
|
|
235
|
+
MLB = '"""'
|
|
236
|
+
# Single Line Literal
|
|
237
|
+
SLL = "'"
|
|
238
|
+
# Multi Line Literal
|
|
239
|
+
MLL = "'''"
|
|
240
|
+
|
|
241
|
+
@classmethod
|
|
242
|
+
def select(cls, literal=False, multiline=False) -> StringType:
|
|
243
|
+
return {
|
|
244
|
+
(False, False): cls.SLB,
|
|
245
|
+
(False, True): cls.MLB,
|
|
246
|
+
(True, False): cls.SLL,
|
|
247
|
+
(True, True): cls.MLL,
|
|
248
|
+
}[(literal, multiline)]
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def escaped_sequences(self) -> Collection[str]:
|
|
252
|
+
# https://toml.io/en/v1.0.0#string
|
|
253
|
+
escaped_in_basic = CONTROL_CHARS | {"\\"}
|
|
254
|
+
allowed_in_multiline = {"\n", "\r"}
|
|
255
|
+
return {
|
|
256
|
+
StringType.SLB: escaped_in_basic | {'"'},
|
|
257
|
+
StringType.MLB: (escaped_in_basic | {'"""'}) - allowed_in_multiline,
|
|
258
|
+
StringType.SLL: (),
|
|
259
|
+
StringType.MLL: (),
|
|
260
|
+
}[self]
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def invalid_sequences(self) -> Collection[str]:
|
|
264
|
+
# https://toml.io/en/v1.0.0#string
|
|
265
|
+
forbidden_in_literal = CONTROL_CHARS - {"\t"}
|
|
266
|
+
allowed_in_multiline = {"\n", "\r"}
|
|
267
|
+
return {
|
|
268
|
+
StringType.SLB: (),
|
|
269
|
+
StringType.MLB: (),
|
|
270
|
+
StringType.SLL: forbidden_in_literal | {"'"},
|
|
271
|
+
StringType.MLL: (forbidden_in_literal | {"'''"}) - allowed_in_multiline,
|
|
272
|
+
}[self]
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def unit(self) -> str:
|
|
276
|
+
return self.value[0]
|
|
277
|
+
|
|
278
|
+
def is_basic(self) -> bool:
|
|
279
|
+
return self in {StringType.SLB, StringType.MLB}
|
|
280
|
+
|
|
281
|
+
def is_literal(self) -> bool:
|
|
282
|
+
return self in {StringType.SLL, StringType.MLL}
|
|
283
|
+
|
|
284
|
+
def is_singleline(self) -> bool:
|
|
285
|
+
return self in {StringType.SLB, StringType.SLL}
|
|
286
|
+
|
|
287
|
+
def is_multiline(self) -> bool:
|
|
288
|
+
return self in {StringType.MLB, StringType.MLL}
|
|
289
|
+
|
|
290
|
+
def toggle(self) -> StringType:
|
|
291
|
+
return {
|
|
292
|
+
StringType.SLB: StringType.MLB,
|
|
293
|
+
StringType.MLB: StringType.SLB,
|
|
294
|
+
StringType.SLL: StringType.MLL,
|
|
295
|
+
StringType.MLL: StringType.SLL,
|
|
296
|
+
}[self]
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class BoolType(Enum):
|
|
300
|
+
TRUE = "true"
|
|
301
|
+
FALSE = "false"
|
|
302
|
+
|
|
303
|
+
def __bool__(self):
|
|
304
|
+
return {BoolType.TRUE: True, BoolType.FALSE: False}[self]
|
|
305
|
+
|
|
306
|
+
def __iter__(self):
|
|
307
|
+
return iter(self.value)
|
|
308
|
+
|
|
309
|
+
def __len__(self):
|
|
310
|
+
return len(self.value)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@dataclasses.dataclass
|
|
314
|
+
class Trivia:
|
|
315
|
+
"""
|
|
316
|
+
Trivia information (aka metadata).
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
# Whitespace before a value.
|
|
320
|
+
indent: str = ""
|
|
321
|
+
# Whitespace after a value, but before a comment.
|
|
322
|
+
comment_ws: str = ""
|
|
323
|
+
# Comment, starting with # character, or empty string if no comment.
|
|
324
|
+
comment: str = ""
|
|
325
|
+
# Trailing newline.
|
|
326
|
+
trail: str = "\n"
|
|
327
|
+
|
|
328
|
+
def copy(self) -> Trivia:
|
|
329
|
+
return dataclasses.replace(self)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class KeyType(Enum):
|
|
333
|
+
"""
|
|
334
|
+
The type of a Key.
|
|
335
|
+
|
|
336
|
+
Keys can be bare (unquoted), or quoted using basic ("), or literal (')
|
|
337
|
+
quotes following the same escaping rules as single-line StringType.
|
|
338
|
+
"""
|
|
339
|
+
|
|
340
|
+
Bare = ""
|
|
341
|
+
Basic = '"'
|
|
342
|
+
Literal = "'"
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class Key(abc.ABC):
|
|
346
|
+
"""Base class for a key"""
|
|
347
|
+
|
|
348
|
+
sep: str
|
|
349
|
+
_original: str
|
|
350
|
+
_keys: list[SingleKey]
|
|
351
|
+
_dotted: bool
|
|
352
|
+
key: str
|
|
353
|
+
|
|
354
|
+
@abc.abstractmethod
|
|
355
|
+
def __hash__(self) -> int:
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
@abc.abstractmethod
|
|
359
|
+
def __eq__(self, __o: object) -> bool:
|
|
360
|
+
pass
|
|
361
|
+
|
|
362
|
+
def is_dotted(self) -> bool:
|
|
363
|
+
"""If the key is followed by other keys"""
|
|
364
|
+
return self._dotted
|
|
365
|
+
|
|
366
|
+
def __iter__(self) -> Iterator[SingleKey]:
|
|
367
|
+
return iter(self._keys)
|
|
368
|
+
|
|
369
|
+
def concat(self, other: Key) -> DottedKey:
|
|
370
|
+
"""Concatenate keys into a dotted key"""
|
|
371
|
+
keys = self._keys + other._keys
|
|
372
|
+
return DottedKey(keys, sep=self.sep)
|
|
373
|
+
|
|
374
|
+
def is_multi(self) -> bool:
|
|
375
|
+
"""Check if the key contains multiple keys"""
|
|
376
|
+
return len(self._keys) > 1
|
|
377
|
+
|
|
378
|
+
def as_string(self) -> str:
|
|
379
|
+
"""The TOML representation"""
|
|
380
|
+
return self._original
|
|
381
|
+
|
|
382
|
+
def __str__(self) -> str:
|
|
383
|
+
return self.as_string()
|
|
384
|
+
|
|
385
|
+
def __repr__(self) -> str:
|
|
386
|
+
return f"<Key {self.as_string()}>"
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class SingleKey(Key):
|
|
390
|
+
"""A single key"""
|
|
391
|
+
|
|
392
|
+
def __init__(
|
|
393
|
+
self,
|
|
394
|
+
k: str,
|
|
395
|
+
t: KeyType | None = None,
|
|
396
|
+
sep: str | None = None,
|
|
397
|
+
original: str | None = None,
|
|
398
|
+
) -> None:
|
|
399
|
+
if t is None:
|
|
400
|
+
if not k or any(
|
|
401
|
+
c not in string.ascii_letters + string.digits + "-" + "_" for c in k
|
|
402
|
+
):
|
|
403
|
+
t = KeyType.Basic
|
|
404
|
+
else:
|
|
405
|
+
t = KeyType.Bare
|
|
406
|
+
|
|
407
|
+
self.t = t
|
|
408
|
+
if sep is None:
|
|
409
|
+
sep = " = "
|
|
410
|
+
|
|
411
|
+
self.sep = sep
|
|
412
|
+
self.key = k
|
|
413
|
+
if original is None:
|
|
414
|
+
key_str = escape_string(k) if t == KeyType.Basic else k
|
|
415
|
+
original = f"{t.value}{key_str}{t.value}"
|
|
416
|
+
|
|
417
|
+
self._original = original
|
|
418
|
+
self._keys = [self]
|
|
419
|
+
self._dotted = False
|
|
420
|
+
|
|
421
|
+
@property
|
|
422
|
+
def delimiter(self) -> str:
|
|
423
|
+
"""The delimiter: double quote/single quote/none"""
|
|
424
|
+
return self.t.value
|
|
425
|
+
|
|
426
|
+
def is_bare(self) -> bool:
|
|
427
|
+
"""Check if the key is bare"""
|
|
428
|
+
return self.t == KeyType.Bare
|
|
429
|
+
|
|
430
|
+
def __hash__(self) -> int:
|
|
431
|
+
return hash(self.key)
|
|
432
|
+
|
|
433
|
+
def __eq__(self, other: Any) -> bool:
|
|
434
|
+
if isinstance(other, Key):
|
|
435
|
+
return isinstance(other, SingleKey) and self.key == other.key
|
|
436
|
+
|
|
437
|
+
return self.key == other
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class DottedKey(Key):
|
|
441
|
+
def __init__(
|
|
442
|
+
self,
|
|
443
|
+
keys: Iterable[SingleKey],
|
|
444
|
+
sep: str | None = None,
|
|
445
|
+
original: str | None = None,
|
|
446
|
+
) -> None:
|
|
447
|
+
self._keys = list(keys)
|
|
448
|
+
if original is None:
|
|
449
|
+
original = ".".join(k.as_string() for k in self._keys)
|
|
450
|
+
|
|
451
|
+
self.sep = " = " if sep is None else sep
|
|
452
|
+
self._original = original
|
|
453
|
+
self._dotted = False
|
|
454
|
+
self.key = ".".join(k.key for k in self._keys)
|
|
455
|
+
|
|
456
|
+
def __hash__(self) -> int:
|
|
457
|
+
return hash(tuple(self._keys))
|
|
458
|
+
|
|
459
|
+
def __eq__(self, __o: object) -> bool:
|
|
460
|
+
return isinstance(__o, DottedKey) and self._keys == __o._keys
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class Item:
|
|
464
|
+
"""
|
|
465
|
+
An item within a TOML document.
|
|
466
|
+
"""
|
|
467
|
+
|
|
468
|
+
def __init__(self, trivia: Trivia) -> None:
|
|
469
|
+
self._trivia = trivia
|
|
470
|
+
|
|
471
|
+
@property
|
|
472
|
+
def trivia(self) -> Trivia:
|
|
473
|
+
"""The trivia element associated with this item"""
|
|
474
|
+
return self._trivia
|
|
475
|
+
|
|
476
|
+
@property
|
|
477
|
+
def discriminant(self) -> int:
|
|
478
|
+
raise NotImplementedError()
|
|
479
|
+
|
|
480
|
+
def as_string(self) -> str:
|
|
481
|
+
"""The TOML representation"""
|
|
482
|
+
raise NotImplementedError()
|
|
483
|
+
|
|
484
|
+
@property
|
|
485
|
+
def value(self) -> Any:
|
|
486
|
+
return self
|
|
487
|
+
|
|
488
|
+
def unwrap(self) -> Any:
|
|
489
|
+
"""Returns as pure python object (ppo)"""
|
|
490
|
+
raise NotImplementedError()
|
|
491
|
+
|
|
492
|
+
# Helpers
|
|
493
|
+
|
|
494
|
+
def comment(self, comment: str) -> Item:
|
|
495
|
+
"""Attach a comment to this item"""
|
|
496
|
+
if not comment.strip().startswith("#"):
|
|
497
|
+
comment = "# " + comment
|
|
498
|
+
|
|
499
|
+
self._trivia.comment_ws = " "
|
|
500
|
+
self._trivia.comment = comment
|
|
501
|
+
|
|
502
|
+
return self
|
|
503
|
+
|
|
504
|
+
def indent(self, indent: int) -> Item:
|
|
505
|
+
"""Indent this item with given number of spaces"""
|
|
506
|
+
if self._trivia.indent.startswith("\n"):
|
|
507
|
+
self._trivia.indent = "\n" + " " * indent
|
|
508
|
+
else:
|
|
509
|
+
self._trivia.indent = " " * indent
|
|
510
|
+
|
|
511
|
+
return self
|
|
512
|
+
|
|
513
|
+
def is_boolean(self) -> bool:
|
|
514
|
+
return isinstance(self, Bool)
|
|
515
|
+
|
|
516
|
+
def is_table(self) -> bool:
|
|
517
|
+
return isinstance(self, Table)
|
|
518
|
+
|
|
519
|
+
def is_inline_table(self) -> bool:
|
|
520
|
+
return isinstance(self, InlineTable)
|
|
521
|
+
|
|
522
|
+
def is_aot(self) -> bool:
|
|
523
|
+
return isinstance(self, AoT)
|
|
524
|
+
|
|
525
|
+
def _getstate(self, protocol=3):
|
|
526
|
+
return (self._trivia,)
|
|
527
|
+
|
|
528
|
+
def __reduce__(self):
|
|
529
|
+
return self.__reduce_ex__(2)
|
|
530
|
+
|
|
531
|
+
def __reduce_ex__(self, protocol):
|
|
532
|
+
return self.__class__, self._getstate(protocol)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
class Whitespace(Item):
|
|
536
|
+
"""
|
|
537
|
+
A whitespace literal.
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
def __init__(self, s: str, fixed: bool = False) -> None:
|
|
541
|
+
self._s = s
|
|
542
|
+
self._fixed = fixed
|
|
543
|
+
|
|
544
|
+
@property
|
|
545
|
+
def s(self) -> str:
|
|
546
|
+
return self._s
|
|
547
|
+
|
|
548
|
+
@property
|
|
549
|
+
def value(self) -> str:
|
|
550
|
+
"""The wrapped string of the whitespace"""
|
|
551
|
+
return self._s
|
|
552
|
+
|
|
553
|
+
@property
|
|
554
|
+
def trivia(self) -> Trivia:
|
|
555
|
+
raise RuntimeError("Called trivia on a Whitespace variant.")
|
|
556
|
+
|
|
557
|
+
@property
|
|
558
|
+
def discriminant(self) -> int:
|
|
559
|
+
return 0
|
|
560
|
+
|
|
561
|
+
def is_fixed(self) -> bool:
|
|
562
|
+
"""If the whitespace is fixed, it can't be merged or discarded from the output."""
|
|
563
|
+
return self._fixed
|
|
564
|
+
|
|
565
|
+
def as_string(self) -> str:
|
|
566
|
+
return self._s
|
|
567
|
+
|
|
568
|
+
def __repr__(self) -> str:
|
|
569
|
+
return f"<{self.__class__.__name__} {repr(self._s)}>"
|
|
570
|
+
|
|
571
|
+
def _getstate(self, protocol=3):
|
|
572
|
+
return self._s, self._fixed
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
class Comment(Item):
|
|
576
|
+
"""
|
|
577
|
+
A comment literal.
|
|
578
|
+
"""
|
|
579
|
+
|
|
580
|
+
@property
|
|
581
|
+
def discriminant(self) -> int:
|
|
582
|
+
return 1
|
|
583
|
+
|
|
584
|
+
def as_string(self) -> str:
|
|
585
|
+
return (
|
|
586
|
+
f"{self._trivia.indent}{decode(self._trivia.comment)}{self._trivia.trail}"
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
def __str__(self) -> str:
|
|
590
|
+
return f"{self._trivia.indent}{decode(self._trivia.comment)}"
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
class Integer(Item, _CustomInt):
|
|
594
|
+
"""
|
|
595
|
+
An integer literal.
|
|
596
|
+
"""
|
|
597
|
+
|
|
598
|
+
def __new__(cls, value: int, trivia: Trivia, raw: str) -> Integer:
|
|
599
|
+
return int.__new__(cls, value)
|
|
600
|
+
|
|
601
|
+
def __init__(self, value: int, trivia: Trivia, raw: str) -> None:
|
|
602
|
+
super().__init__(trivia)
|
|
603
|
+
self._original = value
|
|
604
|
+
self._raw = raw
|
|
605
|
+
self._sign = False
|
|
606
|
+
|
|
607
|
+
if re.match(r"^[+\-]\d+$", raw):
|
|
608
|
+
self._sign = True
|
|
609
|
+
|
|
610
|
+
def unwrap(self) -> int:
|
|
611
|
+
return self._original
|
|
612
|
+
|
|
613
|
+
__int__ = unwrap
|
|
614
|
+
|
|
615
|
+
def __hash__(self) -> int:
|
|
616
|
+
return hash(self.unwrap())
|
|
617
|
+
|
|
618
|
+
@property
|
|
619
|
+
def discriminant(self) -> int:
|
|
620
|
+
return 2
|
|
621
|
+
|
|
622
|
+
@property
|
|
623
|
+
def value(self) -> int:
|
|
624
|
+
"""The wrapped integer value"""
|
|
625
|
+
return self
|
|
626
|
+
|
|
627
|
+
def as_string(self) -> str:
|
|
628
|
+
return self._raw
|
|
629
|
+
|
|
630
|
+
def _new(self, result):
|
|
631
|
+
raw = str(result)
|
|
632
|
+
if self._sign:
|
|
633
|
+
sign = "+" if result >= 0 else "-"
|
|
634
|
+
raw = sign + raw
|
|
635
|
+
|
|
636
|
+
return Integer(result, self._trivia, raw)
|
|
637
|
+
|
|
638
|
+
def _getstate(self, protocol=3):
|
|
639
|
+
return int(self), self._trivia, self._raw
|
|
640
|
+
|
|
641
|
+
# int methods
|
|
642
|
+
__abs__ = wrap_method(int.__abs__)
|
|
643
|
+
__add__ = wrap_method(int.__add__)
|
|
644
|
+
__and__ = wrap_method(int.__and__)
|
|
645
|
+
__ceil__ = wrap_method(int.__ceil__)
|
|
646
|
+
__eq__ = int.__eq__
|
|
647
|
+
__floor__ = wrap_method(int.__floor__)
|
|
648
|
+
__floordiv__ = wrap_method(int.__floordiv__)
|
|
649
|
+
__invert__ = wrap_method(int.__invert__)
|
|
650
|
+
__le__ = int.__le__
|
|
651
|
+
__lshift__ = wrap_method(int.__lshift__)
|
|
652
|
+
__lt__ = int.__lt__
|
|
653
|
+
__mod__ = wrap_method(int.__mod__)
|
|
654
|
+
__mul__ = wrap_method(int.__mul__)
|
|
655
|
+
__neg__ = wrap_method(int.__neg__)
|
|
656
|
+
__or__ = wrap_method(int.__or__)
|
|
657
|
+
__pos__ = wrap_method(int.__pos__)
|
|
658
|
+
__pow__ = wrap_method(int.__pow__)
|
|
659
|
+
__radd__ = wrap_method(int.__radd__)
|
|
660
|
+
__rand__ = wrap_method(int.__rand__)
|
|
661
|
+
__rfloordiv__ = wrap_method(int.__rfloordiv__)
|
|
662
|
+
__rlshift__ = wrap_method(int.__rlshift__)
|
|
663
|
+
__rmod__ = wrap_method(int.__rmod__)
|
|
664
|
+
__rmul__ = wrap_method(int.__rmul__)
|
|
665
|
+
__ror__ = wrap_method(int.__ror__)
|
|
666
|
+
__round__ = wrap_method(int.__round__)
|
|
667
|
+
__rpow__ = wrap_method(int.__rpow__)
|
|
668
|
+
__rrshift__ = wrap_method(int.__rrshift__)
|
|
669
|
+
__rshift__ = wrap_method(int.__rshift__)
|
|
670
|
+
__rxor__ = wrap_method(int.__rxor__)
|
|
671
|
+
__trunc__ = wrap_method(int.__trunc__)
|
|
672
|
+
__xor__ = wrap_method(int.__xor__)
|
|
673
|
+
|
|
674
|
+
def __rtruediv__(self, other):
|
|
675
|
+
result = int.__rtruediv__(self, other)
|
|
676
|
+
if result is NotImplemented:
|
|
677
|
+
return result
|
|
678
|
+
return Float._new(self, result)
|
|
679
|
+
|
|
680
|
+
def __truediv__(self, other):
|
|
681
|
+
result = int.__truediv__(self, other)
|
|
682
|
+
if result is NotImplemented:
|
|
683
|
+
return result
|
|
684
|
+
return Float._new(self, result)
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
class Float(Item, _CustomFloat):
|
|
688
|
+
"""
|
|
689
|
+
A float literal.
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
def __new__(cls, value: float, trivia: Trivia, raw: str) -> Float:
|
|
693
|
+
return float.__new__(cls, value)
|
|
694
|
+
|
|
695
|
+
def __init__(self, value: float, trivia: Trivia, raw: str) -> None:
|
|
696
|
+
super().__init__(trivia)
|
|
697
|
+
self._original = value
|
|
698
|
+
self._raw = raw
|
|
699
|
+
self._sign = False
|
|
700
|
+
|
|
701
|
+
if re.match(r"^[+\-].+$", raw):
|
|
702
|
+
self._sign = True
|
|
703
|
+
|
|
704
|
+
def unwrap(self) -> float:
|
|
705
|
+
return self._original
|
|
706
|
+
|
|
707
|
+
__float__ = unwrap
|
|
708
|
+
|
|
709
|
+
def __hash__(self) -> int:
|
|
710
|
+
return hash(self.unwrap())
|
|
711
|
+
|
|
712
|
+
@property
|
|
713
|
+
def discriminant(self) -> int:
|
|
714
|
+
return 3
|
|
715
|
+
|
|
716
|
+
@property
|
|
717
|
+
def value(self) -> float:
|
|
718
|
+
"""The wrapped float value"""
|
|
719
|
+
return self
|
|
720
|
+
|
|
721
|
+
def as_string(self) -> str:
|
|
722
|
+
return self._raw
|
|
723
|
+
|
|
724
|
+
def _new(self, result):
|
|
725
|
+
raw = str(result)
|
|
726
|
+
|
|
727
|
+
if self._sign:
|
|
728
|
+
sign = "+" if result >= 0 else "-"
|
|
729
|
+
raw = sign + raw
|
|
730
|
+
|
|
731
|
+
return Float(result, self._trivia, raw)
|
|
732
|
+
|
|
733
|
+
def _getstate(self, protocol=3):
|
|
734
|
+
return float(self), self._trivia, self._raw
|
|
735
|
+
|
|
736
|
+
# float methods
|
|
737
|
+
__abs__ = wrap_method(float.__abs__)
|
|
738
|
+
__add__ = wrap_method(float.__add__)
|
|
739
|
+
__eq__ = float.__eq__
|
|
740
|
+
__floordiv__ = wrap_method(float.__floordiv__)
|
|
741
|
+
__le__ = float.__le__
|
|
742
|
+
__lt__ = float.__lt__
|
|
743
|
+
__mod__ = wrap_method(float.__mod__)
|
|
744
|
+
__mul__ = wrap_method(float.__mul__)
|
|
745
|
+
__neg__ = wrap_method(float.__neg__)
|
|
746
|
+
__pos__ = wrap_method(float.__pos__)
|
|
747
|
+
__pow__ = wrap_method(float.__pow__)
|
|
748
|
+
__radd__ = wrap_method(float.__radd__)
|
|
749
|
+
__rfloordiv__ = wrap_method(float.__rfloordiv__)
|
|
750
|
+
__rmod__ = wrap_method(float.__rmod__)
|
|
751
|
+
__rmul__ = wrap_method(float.__rmul__)
|
|
752
|
+
__round__ = wrap_method(float.__round__)
|
|
753
|
+
__rpow__ = wrap_method(float.__rpow__)
|
|
754
|
+
__rtruediv__ = wrap_method(float.__rtruediv__)
|
|
755
|
+
__truediv__ = wrap_method(float.__truediv__)
|
|
756
|
+
__trunc__ = float.__trunc__
|
|
757
|
+
|
|
758
|
+
if sys.version_info >= (3, 9):
|
|
759
|
+
__ceil__ = float.__ceil__
|
|
760
|
+
__floor__ = float.__floor__
|
|
761
|
+
else:
|
|
762
|
+
__ceil__ = math.ceil
|
|
763
|
+
__floor__ = math.floor
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
class Bool(Item):
|
|
767
|
+
"""
|
|
768
|
+
A boolean literal.
|
|
769
|
+
"""
|
|
770
|
+
|
|
771
|
+
def __init__(self, t: int, trivia: Trivia) -> None:
|
|
772
|
+
super().__init__(trivia)
|
|
773
|
+
|
|
774
|
+
self._value = bool(t)
|
|
775
|
+
|
|
776
|
+
def unwrap(self) -> bool:
|
|
777
|
+
return bool(self)
|
|
778
|
+
|
|
779
|
+
@property
|
|
780
|
+
def discriminant(self) -> int:
|
|
781
|
+
return 4
|
|
782
|
+
|
|
783
|
+
@property
|
|
784
|
+
def value(self) -> bool:
|
|
785
|
+
"""The wrapped boolean value"""
|
|
786
|
+
return self._value
|
|
787
|
+
|
|
788
|
+
def as_string(self) -> str:
|
|
789
|
+
return str(self._value).lower()
|
|
790
|
+
|
|
791
|
+
def _getstate(self, protocol=3):
|
|
792
|
+
return self._value, self._trivia
|
|
793
|
+
|
|
794
|
+
def __bool__(self):
|
|
795
|
+
return self._value
|
|
796
|
+
|
|
797
|
+
__nonzero__ = __bool__
|
|
798
|
+
|
|
799
|
+
def __eq__(self, other):
|
|
800
|
+
if not isinstance(other, bool):
|
|
801
|
+
return NotImplemented
|
|
802
|
+
|
|
803
|
+
return other == self._value
|
|
804
|
+
|
|
805
|
+
def __hash__(self):
|
|
806
|
+
return hash(self._value)
|
|
807
|
+
|
|
808
|
+
def __repr__(self):
|
|
809
|
+
return repr(self._value)
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
class DateTime(Item, datetime):
|
|
813
|
+
"""
|
|
814
|
+
A datetime literal.
|
|
815
|
+
"""
|
|
816
|
+
|
|
817
|
+
def __new__(
|
|
818
|
+
cls,
|
|
819
|
+
year: int,
|
|
820
|
+
month: int,
|
|
821
|
+
day: int,
|
|
822
|
+
hour: int,
|
|
823
|
+
minute: int,
|
|
824
|
+
second: int,
|
|
825
|
+
microsecond: int,
|
|
826
|
+
tzinfo: tzinfo | None,
|
|
827
|
+
*_: Any,
|
|
828
|
+
**kwargs: Any,
|
|
829
|
+
) -> datetime:
|
|
830
|
+
return datetime.__new__(
|
|
831
|
+
cls,
|
|
832
|
+
year,
|
|
833
|
+
month,
|
|
834
|
+
day,
|
|
835
|
+
hour,
|
|
836
|
+
minute,
|
|
837
|
+
second,
|
|
838
|
+
microsecond,
|
|
839
|
+
tzinfo=tzinfo,
|
|
840
|
+
**kwargs,
|
|
841
|
+
)
|
|
842
|
+
|
|
843
|
+
def __init__(
|
|
844
|
+
self,
|
|
845
|
+
year: int,
|
|
846
|
+
month: int,
|
|
847
|
+
day: int,
|
|
848
|
+
hour: int,
|
|
849
|
+
minute: int,
|
|
850
|
+
second: int,
|
|
851
|
+
microsecond: int,
|
|
852
|
+
tzinfo: tzinfo | None,
|
|
853
|
+
trivia: Trivia | None = None,
|
|
854
|
+
raw: str | None = None,
|
|
855
|
+
**kwargs: Any,
|
|
856
|
+
) -> None:
|
|
857
|
+
super().__init__(trivia or Trivia())
|
|
858
|
+
|
|
859
|
+
self._raw = raw or self.isoformat()
|
|
860
|
+
|
|
861
|
+
def unwrap(self) -> datetime:
|
|
862
|
+
(
|
|
863
|
+
year,
|
|
864
|
+
month,
|
|
865
|
+
day,
|
|
866
|
+
hour,
|
|
867
|
+
minute,
|
|
868
|
+
second,
|
|
869
|
+
microsecond,
|
|
870
|
+
tzinfo,
|
|
871
|
+
_,
|
|
872
|
+
_,
|
|
873
|
+
) = self._getstate()
|
|
874
|
+
return datetime(year, month, day, hour, minute, second, microsecond, tzinfo)
|
|
875
|
+
|
|
876
|
+
@property
|
|
877
|
+
def discriminant(self) -> int:
|
|
878
|
+
return 5
|
|
879
|
+
|
|
880
|
+
@property
|
|
881
|
+
def value(self) -> datetime:
|
|
882
|
+
return self
|
|
883
|
+
|
|
884
|
+
def as_string(self) -> str:
|
|
885
|
+
return self._raw
|
|
886
|
+
|
|
887
|
+
def __add__(self, other):
|
|
888
|
+
if PY38:
|
|
889
|
+
result = datetime(
|
|
890
|
+
self.year,
|
|
891
|
+
self.month,
|
|
892
|
+
self.day,
|
|
893
|
+
self.hour,
|
|
894
|
+
self.minute,
|
|
895
|
+
self.second,
|
|
896
|
+
self.microsecond,
|
|
897
|
+
self.tzinfo,
|
|
898
|
+
).__add__(other)
|
|
899
|
+
else:
|
|
900
|
+
result = super().__add__(other)
|
|
901
|
+
|
|
902
|
+
return self._new(result)
|
|
903
|
+
|
|
904
|
+
def __sub__(self, other):
|
|
905
|
+
if PY38:
|
|
906
|
+
result = datetime(
|
|
907
|
+
self.year,
|
|
908
|
+
self.month,
|
|
909
|
+
self.day,
|
|
910
|
+
self.hour,
|
|
911
|
+
self.minute,
|
|
912
|
+
self.second,
|
|
913
|
+
self.microsecond,
|
|
914
|
+
self.tzinfo,
|
|
915
|
+
).__sub__(other)
|
|
916
|
+
else:
|
|
917
|
+
result = super().__sub__(other)
|
|
918
|
+
|
|
919
|
+
if isinstance(result, datetime):
|
|
920
|
+
result = self._new(result)
|
|
921
|
+
|
|
922
|
+
return result
|
|
923
|
+
|
|
924
|
+
def replace(self, *args: Any, **kwargs: Any) -> datetime:
|
|
925
|
+
return self._new(super().replace(*args, **kwargs))
|
|
926
|
+
|
|
927
|
+
def astimezone(self, tz: tzinfo) -> datetime:
|
|
928
|
+
result = super().astimezone(tz)
|
|
929
|
+
if PY38:
|
|
930
|
+
return result
|
|
931
|
+
return self._new(result)
|
|
932
|
+
|
|
933
|
+
def _new(self, result) -> DateTime:
|
|
934
|
+
raw = result.isoformat()
|
|
935
|
+
|
|
936
|
+
return DateTime(
|
|
937
|
+
result.year,
|
|
938
|
+
result.month,
|
|
939
|
+
result.day,
|
|
940
|
+
result.hour,
|
|
941
|
+
result.minute,
|
|
942
|
+
result.second,
|
|
943
|
+
result.microsecond,
|
|
944
|
+
result.tzinfo,
|
|
945
|
+
self._trivia,
|
|
946
|
+
raw,
|
|
947
|
+
)
|
|
948
|
+
|
|
949
|
+
def _getstate(self, protocol=3):
|
|
950
|
+
return (
|
|
951
|
+
self.year,
|
|
952
|
+
self.month,
|
|
953
|
+
self.day,
|
|
954
|
+
self.hour,
|
|
955
|
+
self.minute,
|
|
956
|
+
self.second,
|
|
957
|
+
self.microsecond,
|
|
958
|
+
self.tzinfo,
|
|
959
|
+
self._trivia,
|
|
960
|
+
self._raw,
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
class Date(Item, date):
|
|
965
|
+
"""
|
|
966
|
+
A date literal.
|
|
967
|
+
"""
|
|
968
|
+
|
|
969
|
+
def __new__(cls, year: int, month: int, day: int, *_: Any) -> date:
|
|
970
|
+
return date.__new__(cls, year, month, day)
|
|
971
|
+
|
|
972
|
+
def __init__(
|
|
973
|
+
self, year: int, month: int, day: int, trivia: Trivia, raw: str
|
|
974
|
+
) -> None:
|
|
975
|
+
super().__init__(trivia)
|
|
976
|
+
|
|
977
|
+
self._raw = raw
|
|
978
|
+
|
|
979
|
+
def unwrap(self) -> date:
|
|
980
|
+
(year, month, day, _, _) = self._getstate()
|
|
981
|
+
return date(year, month, day)
|
|
982
|
+
|
|
983
|
+
@property
|
|
984
|
+
def discriminant(self) -> int:
|
|
985
|
+
return 6
|
|
986
|
+
|
|
987
|
+
@property
|
|
988
|
+
def value(self) -> date:
|
|
989
|
+
return self
|
|
990
|
+
|
|
991
|
+
def as_string(self) -> str:
|
|
992
|
+
return self._raw
|
|
993
|
+
|
|
994
|
+
def __add__(self, other):
|
|
995
|
+
if PY38:
|
|
996
|
+
result = date(self.year, self.month, self.day).__add__(other)
|
|
997
|
+
else:
|
|
998
|
+
result = super().__add__(other)
|
|
999
|
+
|
|
1000
|
+
return self._new(result)
|
|
1001
|
+
|
|
1002
|
+
def __sub__(self, other):
|
|
1003
|
+
if PY38:
|
|
1004
|
+
result = date(self.year, self.month, self.day).__sub__(other)
|
|
1005
|
+
else:
|
|
1006
|
+
result = super().__sub__(other)
|
|
1007
|
+
|
|
1008
|
+
if isinstance(result, date):
|
|
1009
|
+
result = self._new(result)
|
|
1010
|
+
|
|
1011
|
+
return result
|
|
1012
|
+
|
|
1013
|
+
def replace(self, *args: Any, **kwargs: Any) -> date:
|
|
1014
|
+
return self._new(super().replace(*args, **kwargs))
|
|
1015
|
+
|
|
1016
|
+
def _new(self, result):
|
|
1017
|
+
raw = result.isoformat()
|
|
1018
|
+
|
|
1019
|
+
return Date(result.year, result.month, result.day, self._trivia, raw)
|
|
1020
|
+
|
|
1021
|
+
def _getstate(self, protocol=3):
|
|
1022
|
+
return (self.year, self.month, self.day, self._trivia, self._raw)
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
class Time(Item, time):
|
|
1026
|
+
"""
|
|
1027
|
+
A time literal.
|
|
1028
|
+
"""
|
|
1029
|
+
|
|
1030
|
+
def __new__(
|
|
1031
|
+
cls,
|
|
1032
|
+
hour: int,
|
|
1033
|
+
minute: int,
|
|
1034
|
+
second: int,
|
|
1035
|
+
microsecond: int,
|
|
1036
|
+
tzinfo: tzinfo | None,
|
|
1037
|
+
*_: Any,
|
|
1038
|
+
) -> time:
|
|
1039
|
+
return time.__new__(cls, hour, minute, second, microsecond, tzinfo)
|
|
1040
|
+
|
|
1041
|
+
def __init__(
|
|
1042
|
+
self,
|
|
1043
|
+
hour: int,
|
|
1044
|
+
minute: int,
|
|
1045
|
+
second: int,
|
|
1046
|
+
microsecond: int,
|
|
1047
|
+
tzinfo: tzinfo | None,
|
|
1048
|
+
trivia: Trivia,
|
|
1049
|
+
raw: str,
|
|
1050
|
+
) -> None:
|
|
1051
|
+
super().__init__(trivia)
|
|
1052
|
+
|
|
1053
|
+
self._raw = raw
|
|
1054
|
+
|
|
1055
|
+
def unwrap(self) -> time:
|
|
1056
|
+
(hour, minute, second, microsecond, tzinfo, _, _) = self._getstate()
|
|
1057
|
+
return time(hour, minute, second, microsecond, tzinfo)
|
|
1058
|
+
|
|
1059
|
+
@property
|
|
1060
|
+
def discriminant(self) -> int:
|
|
1061
|
+
return 7
|
|
1062
|
+
|
|
1063
|
+
@property
|
|
1064
|
+
def value(self) -> time:
|
|
1065
|
+
return self
|
|
1066
|
+
|
|
1067
|
+
def as_string(self) -> str:
|
|
1068
|
+
return self._raw
|
|
1069
|
+
|
|
1070
|
+
def replace(self, *args: Any, **kwargs: Any) -> time:
|
|
1071
|
+
return self._new(super().replace(*args, **kwargs))
|
|
1072
|
+
|
|
1073
|
+
def _new(self, result):
|
|
1074
|
+
raw = result.isoformat()
|
|
1075
|
+
|
|
1076
|
+
return Time(
|
|
1077
|
+
result.hour,
|
|
1078
|
+
result.minute,
|
|
1079
|
+
result.second,
|
|
1080
|
+
result.microsecond,
|
|
1081
|
+
result.tzinfo,
|
|
1082
|
+
self._trivia,
|
|
1083
|
+
raw,
|
|
1084
|
+
)
|
|
1085
|
+
|
|
1086
|
+
def _getstate(self, protocol: int = 3) -> tuple:
|
|
1087
|
+
return (
|
|
1088
|
+
self.hour,
|
|
1089
|
+
self.minute,
|
|
1090
|
+
self.second,
|
|
1091
|
+
self.microsecond,
|
|
1092
|
+
self.tzinfo,
|
|
1093
|
+
self._trivia,
|
|
1094
|
+
self._raw,
|
|
1095
|
+
)
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
class _ArrayItemGroup:
|
|
1099
|
+
__slots__ = ("value", "indent", "comma", "comment")
|
|
1100
|
+
|
|
1101
|
+
def __init__(
|
|
1102
|
+
self,
|
|
1103
|
+
value: Item | None = None,
|
|
1104
|
+
indent: Whitespace | None = None,
|
|
1105
|
+
comma: Whitespace | None = None,
|
|
1106
|
+
comment: Comment | None = None,
|
|
1107
|
+
) -> None:
|
|
1108
|
+
self.value = value
|
|
1109
|
+
self.indent = indent
|
|
1110
|
+
self.comma = comma
|
|
1111
|
+
self.comment = comment
|
|
1112
|
+
|
|
1113
|
+
def __iter__(self) -> Iterator[Item]:
|
|
1114
|
+
return filter(
|
|
1115
|
+
lambda x: x is not None, (self.indent, self.value, self.comma, self.comment)
|
|
1116
|
+
)
|
|
1117
|
+
|
|
1118
|
+
def __repr__(self) -> str:
|
|
1119
|
+
return repr(tuple(self))
|
|
1120
|
+
|
|
1121
|
+
def is_whitespace(self) -> bool:
|
|
1122
|
+
return self.value is None and self.comment is None
|
|
1123
|
+
|
|
1124
|
+
def __bool__(self) -> bool:
|
|
1125
|
+
try:
|
|
1126
|
+
next(iter(self))
|
|
1127
|
+
except StopIteration:
|
|
1128
|
+
return False
|
|
1129
|
+
return True
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
class Array(Item, _CustomList):
|
|
1133
|
+
"""
|
|
1134
|
+
An array literal
|
|
1135
|
+
"""
|
|
1136
|
+
|
|
1137
|
+
def __init__(
|
|
1138
|
+
self, value: list[Item], trivia: Trivia, multiline: bool = False
|
|
1139
|
+
) -> None:
|
|
1140
|
+
super().__init__(trivia)
|
|
1141
|
+
list.__init__(
|
|
1142
|
+
self,
|
|
1143
|
+
[v for v in value if not isinstance(v, (Whitespace, Comment, Null))],
|
|
1144
|
+
)
|
|
1145
|
+
self._index_map: dict[int, int] = {}
|
|
1146
|
+
self._value = self._group_values(value)
|
|
1147
|
+
self._multiline = multiline
|
|
1148
|
+
self._reindex()
|
|
1149
|
+
|
|
1150
|
+
def _group_values(self, value: list[Item]) -> list[_ArrayItemGroup]:
|
|
1151
|
+
"""Group the values into (indent, value, comma, comment) tuples"""
|
|
1152
|
+
groups = []
|
|
1153
|
+
this_group = _ArrayItemGroup()
|
|
1154
|
+
for item in value:
|
|
1155
|
+
if isinstance(item, Whitespace):
|
|
1156
|
+
if "," not in item.s:
|
|
1157
|
+
groups.append(this_group)
|
|
1158
|
+
this_group = _ArrayItemGroup(indent=item)
|
|
1159
|
+
else:
|
|
1160
|
+
if this_group.value is None:
|
|
1161
|
+
# when comma is met and no value is provided, add a dummy Null
|
|
1162
|
+
this_group.value = Null()
|
|
1163
|
+
this_group.comma = item
|
|
1164
|
+
elif isinstance(item, Comment):
|
|
1165
|
+
if this_group.value is None:
|
|
1166
|
+
this_group.value = Null()
|
|
1167
|
+
this_group.comment = item
|
|
1168
|
+
elif this_group.value is None:
|
|
1169
|
+
this_group.value = item
|
|
1170
|
+
else:
|
|
1171
|
+
groups.append(this_group)
|
|
1172
|
+
this_group = _ArrayItemGroup(value=item)
|
|
1173
|
+
groups.append(this_group)
|
|
1174
|
+
return [group for group in groups if group]
|
|
1175
|
+
|
|
1176
|
+
def unwrap(self) -> list[Any]:
|
|
1177
|
+
unwrapped = []
|
|
1178
|
+
for v in self:
|
|
1179
|
+
if hasattr(v, "unwrap"):
|
|
1180
|
+
unwrapped.append(v.unwrap())
|
|
1181
|
+
else:
|
|
1182
|
+
unwrapped.append(v)
|
|
1183
|
+
return unwrapped
|
|
1184
|
+
|
|
1185
|
+
@property
|
|
1186
|
+
def discriminant(self) -> int:
|
|
1187
|
+
return 8
|
|
1188
|
+
|
|
1189
|
+
@property
|
|
1190
|
+
def value(self) -> list:
|
|
1191
|
+
return self
|
|
1192
|
+
|
|
1193
|
+
def _iter_items(self) -> Iterator[Item]:
|
|
1194
|
+
for v in self._value:
|
|
1195
|
+
yield from v
|
|
1196
|
+
|
|
1197
|
+
def multiline(self, multiline: bool) -> Array:
|
|
1198
|
+
"""Change the array to display in multiline or not.
|
|
1199
|
+
|
|
1200
|
+
:Example:
|
|
1201
|
+
|
|
1202
|
+
>>> a = item([1, 2, 3])
|
|
1203
|
+
>>> print(a.as_string())
|
|
1204
|
+
[1, 2, 3]
|
|
1205
|
+
>>> print(a.multiline(True).as_string())
|
|
1206
|
+
[
|
|
1207
|
+
1,
|
|
1208
|
+
2,
|
|
1209
|
+
3,
|
|
1210
|
+
]
|
|
1211
|
+
"""
|
|
1212
|
+
self._multiline = multiline
|
|
1213
|
+
|
|
1214
|
+
return self
|
|
1215
|
+
|
|
1216
|
+
def as_string(self) -> str:
|
|
1217
|
+
if not self._multiline or not self._value:
|
|
1218
|
+
return f'[{"".join(v.as_string() for v in self._iter_items())}]'
|
|
1219
|
+
|
|
1220
|
+
s = "[\n"
|
|
1221
|
+
s += "".join(
|
|
1222
|
+
self.trivia.indent
|
|
1223
|
+
+ " " * 4
|
|
1224
|
+
+ v.value.as_string()
|
|
1225
|
+
+ ("," if not isinstance(v.value, Null) else "")
|
|
1226
|
+
+ (v.comment.as_string() if v.comment is not None else "")
|
|
1227
|
+
+ "\n"
|
|
1228
|
+
for v in self._value
|
|
1229
|
+
if v.value is not None
|
|
1230
|
+
)
|
|
1231
|
+
s += self.trivia.indent + "]"
|
|
1232
|
+
|
|
1233
|
+
return s
|
|
1234
|
+
|
|
1235
|
+
def _reindex(self) -> None:
|
|
1236
|
+
self._index_map.clear()
|
|
1237
|
+
index = 0
|
|
1238
|
+
for i, v in enumerate(self._value):
|
|
1239
|
+
if v.value is None or isinstance(v.value, Null):
|
|
1240
|
+
continue
|
|
1241
|
+
self._index_map[index] = i
|
|
1242
|
+
index += 1
|
|
1243
|
+
|
|
1244
|
+
def add_line(
|
|
1245
|
+
self,
|
|
1246
|
+
*items: Any,
|
|
1247
|
+
indent: str = " ",
|
|
1248
|
+
comment: str | None = None,
|
|
1249
|
+
add_comma: bool = True,
|
|
1250
|
+
newline: bool = True,
|
|
1251
|
+
) -> None:
|
|
1252
|
+
"""Add multiple items in a line to control the format precisely.
|
|
1253
|
+
When add_comma is True, only accept actual values and
|
|
1254
|
+
", " will be added between values automatically.
|
|
1255
|
+
|
|
1256
|
+
:Example:
|
|
1257
|
+
|
|
1258
|
+
>>> a = array()
|
|
1259
|
+
>>> a.add_line(1, 2, 3)
|
|
1260
|
+
>>> a.add_line(4, 5, 6)
|
|
1261
|
+
>>> a.add_line(indent="")
|
|
1262
|
+
>>> print(a.as_string())
|
|
1263
|
+
[
|
|
1264
|
+
1, 2, 3,
|
|
1265
|
+
4, 5, 6,
|
|
1266
|
+
]
|
|
1267
|
+
"""
|
|
1268
|
+
new_values: list[Item] = []
|
|
1269
|
+
first_indent = f"\n{indent}" if newline else indent
|
|
1270
|
+
if first_indent:
|
|
1271
|
+
new_values.append(Whitespace(first_indent))
|
|
1272
|
+
whitespace = ""
|
|
1273
|
+
data_values = []
|
|
1274
|
+
for i, el in enumerate(items):
|
|
1275
|
+
it = item(el, _parent=self)
|
|
1276
|
+
if isinstance(it, Comment) or add_comma and isinstance(el, Whitespace):
|
|
1277
|
+
raise ValueError(f"item type {type(it)} is not allowed in add_line")
|
|
1278
|
+
if not isinstance(it, Whitespace):
|
|
1279
|
+
if whitespace:
|
|
1280
|
+
new_values.append(Whitespace(whitespace))
|
|
1281
|
+
whitespace = ""
|
|
1282
|
+
new_values.append(it)
|
|
1283
|
+
data_values.append(it.value)
|
|
1284
|
+
if add_comma:
|
|
1285
|
+
new_values.append(Whitespace(","))
|
|
1286
|
+
if i != len(items) - 1:
|
|
1287
|
+
new_values.append(Whitespace(" "))
|
|
1288
|
+
elif "," not in it.s:
|
|
1289
|
+
whitespace += it.s
|
|
1290
|
+
else:
|
|
1291
|
+
new_values.append(it)
|
|
1292
|
+
if whitespace:
|
|
1293
|
+
new_values.append(Whitespace(whitespace))
|
|
1294
|
+
if comment:
|
|
1295
|
+
indent = " " if items else ""
|
|
1296
|
+
new_values.append(
|
|
1297
|
+
Comment(Trivia(indent=indent, comment=f"# {comment}", trail=""))
|
|
1298
|
+
)
|
|
1299
|
+
list.extend(self, data_values)
|
|
1300
|
+
if len(self._value) > 0:
|
|
1301
|
+
last_item = self._value[-1]
|
|
1302
|
+
last_value_item = next(
|
|
1303
|
+
(
|
|
1304
|
+
v
|
|
1305
|
+
for v in self._value[::-1]
|
|
1306
|
+
if v.value is not None and not isinstance(v.value, Null)
|
|
1307
|
+
),
|
|
1308
|
+
None,
|
|
1309
|
+
)
|
|
1310
|
+
if last_value_item is not None:
|
|
1311
|
+
last_value_item.comma = Whitespace(",")
|
|
1312
|
+
if last_item.is_whitespace():
|
|
1313
|
+
self._value[-1:-1] = self._group_values(new_values)
|
|
1314
|
+
else:
|
|
1315
|
+
self._value.extend(self._group_values(new_values))
|
|
1316
|
+
else:
|
|
1317
|
+
self._value.extend(self._group_values(new_values))
|
|
1318
|
+
self._reindex()
|
|
1319
|
+
|
|
1320
|
+
def clear(self) -> None:
|
|
1321
|
+
"""Clear the array."""
|
|
1322
|
+
list.clear(self)
|
|
1323
|
+
self._index_map.clear()
|
|
1324
|
+
self._value.clear()
|
|
1325
|
+
|
|
1326
|
+
def __len__(self) -> int:
|
|
1327
|
+
return list.__len__(self)
|
|
1328
|
+
|
|
1329
|
+
def __getitem__(self, key: int | slice) -> Any:
|
|
1330
|
+
rv = cast(Item, list.__getitem__(self, key))
|
|
1331
|
+
if rv.is_boolean():
|
|
1332
|
+
return bool(rv)
|
|
1333
|
+
return rv
|
|
1334
|
+
|
|
1335
|
+
def __setitem__(self, key: int | slice, value: Any) -> Any:
|
|
1336
|
+
it = item(value, _parent=self)
|
|
1337
|
+
list.__setitem__(self, key, it)
|
|
1338
|
+
if isinstance(key, slice):
|
|
1339
|
+
raise ValueError("slice assignment is not supported")
|
|
1340
|
+
if key < 0:
|
|
1341
|
+
key += len(self)
|
|
1342
|
+
self._value[self._index_map[key]].value = it
|
|
1343
|
+
|
|
1344
|
+
def insert(self, pos: int, value: Any) -> None:
|
|
1345
|
+
it = item(value, _parent=self)
|
|
1346
|
+
length = len(self)
|
|
1347
|
+
if not isinstance(it, (Comment, Whitespace)):
|
|
1348
|
+
list.insert(self, pos, it)
|
|
1349
|
+
if pos < 0:
|
|
1350
|
+
pos += length
|
|
1351
|
+
if pos < 0:
|
|
1352
|
+
pos = 0
|
|
1353
|
+
|
|
1354
|
+
idx = 0 # insert position of the self._value list
|
|
1355
|
+
default_indent = " "
|
|
1356
|
+
if pos < length:
|
|
1357
|
+
try:
|
|
1358
|
+
idx = self._index_map[pos]
|
|
1359
|
+
except KeyError as e:
|
|
1360
|
+
raise IndexError("list index out of range") from e
|
|
1361
|
+
else:
|
|
1362
|
+
idx = len(self._value)
|
|
1363
|
+
if idx >= 1 and self._value[idx - 1].is_whitespace():
|
|
1364
|
+
# The last item is a pure whitespace(\n ), insert before it
|
|
1365
|
+
idx -= 1
|
|
1366
|
+
if (
|
|
1367
|
+
self._value[idx].indent is not None
|
|
1368
|
+
and "\n" in self._value[idx].indent.s
|
|
1369
|
+
):
|
|
1370
|
+
default_indent = "\n "
|
|
1371
|
+
indent: Item | None = None
|
|
1372
|
+
comma: Item | None = Whitespace(",") if pos < length else None
|
|
1373
|
+
if idx < len(self._value) and not self._value[idx].is_whitespace():
|
|
1374
|
+
# Prefer to copy the indentation from the item after
|
|
1375
|
+
indent = self._value[idx].indent
|
|
1376
|
+
if idx > 0:
|
|
1377
|
+
last_item = self._value[idx - 1]
|
|
1378
|
+
if indent is None:
|
|
1379
|
+
indent = last_item.indent
|
|
1380
|
+
if not isinstance(last_item.value, Null) and "\n" in default_indent:
|
|
1381
|
+
# Copy the comma from the last item if 1) it contains a value and
|
|
1382
|
+
# 2) the array is multiline
|
|
1383
|
+
comma = last_item.comma
|
|
1384
|
+
if last_item.comma is None and not isinstance(last_item.value, Null):
|
|
1385
|
+
# Add comma to the last item to separate it from the following items.
|
|
1386
|
+
last_item.comma = Whitespace(",")
|
|
1387
|
+
if indent is None and (idx > 0 or "\n" in default_indent):
|
|
1388
|
+
# apply default indent if it isn't the first item or the array is multiline.
|
|
1389
|
+
indent = Whitespace(default_indent)
|
|
1390
|
+
new_item = _ArrayItemGroup(value=it, indent=indent, comma=comma)
|
|
1391
|
+
self._value.insert(idx, new_item)
|
|
1392
|
+
self._reindex()
|
|
1393
|
+
|
|
1394
|
+
def __delitem__(self, key: int | slice):
|
|
1395
|
+
length = len(self)
|
|
1396
|
+
list.__delitem__(self, key)
|
|
1397
|
+
|
|
1398
|
+
if isinstance(key, slice):
|
|
1399
|
+
indices_to_remove = list(
|
|
1400
|
+
range(key.start or 0, key.stop or length, key.step or 1)
|
|
1401
|
+
)
|
|
1402
|
+
else:
|
|
1403
|
+
indices_to_remove = [length + key if key < 0 else key]
|
|
1404
|
+
for i in sorted(indices_to_remove, reverse=True):
|
|
1405
|
+
try:
|
|
1406
|
+
idx = self._index_map[i]
|
|
1407
|
+
except KeyError as e:
|
|
1408
|
+
if not isinstance(key, slice):
|
|
1409
|
+
raise IndexError("list index out of range") from e
|
|
1410
|
+
else:
|
|
1411
|
+
del self._value[idx]
|
|
1412
|
+
if (
|
|
1413
|
+
idx == 0
|
|
1414
|
+
and len(self._value) > 0
|
|
1415
|
+
and self._value[idx].indent
|
|
1416
|
+
and "\n" not in self._value[idx].indent.s
|
|
1417
|
+
):
|
|
1418
|
+
# Remove the indentation of the first item if not newline
|
|
1419
|
+
self._value[idx].indent = None
|
|
1420
|
+
if len(self._value) > 0:
|
|
1421
|
+
v = self._value[-1]
|
|
1422
|
+
if not v.is_whitespace():
|
|
1423
|
+
# remove the comma of the last item
|
|
1424
|
+
v.comma = None
|
|
1425
|
+
|
|
1426
|
+
self._reindex()
|
|
1427
|
+
|
|
1428
|
+
def _getstate(self, protocol=3):
|
|
1429
|
+
return list(self._iter_items()), self._trivia, self._multiline
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
class AbstractTable(Item, _CustomDict):
|
|
1433
|
+
"""Common behaviour of both :class:`Table` and :class:`InlineTable`"""
|
|
1434
|
+
|
|
1435
|
+
def __init__(self, value: container.Container, trivia: Trivia):
|
|
1436
|
+
Item.__init__(self, trivia)
|
|
1437
|
+
|
|
1438
|
+
self._value = value
|
|
1439
|
+
|
|
1440
|
+
for k, v in self._value.body:
|
|
1441
|
+
if k is not None:
|
|
1442
|
+
dict.__setitem__(self, k.key, v)
|
|
1443
|
+
|
|
1444
|
+
def unwrap(self) -> dict[str, Any]:
|
|
1445
|
+
unwrapped = {}
|
|
1446
|
+
for k, v in self.items():
|
|
1447
|
+
if isinstance(k, Key):
|
|
1448
|
+
k = k.key
|
|
1449
|
+
if hasattr(v, "unwrap"):
|
|
1450
|
+
v = v.unwrap()
|
|
1451
|
+
unwrapped[k] = v
|
|
1452
|
+
|
|
1453
|
+
return unwrapped
|
|
1454
|
+
|
|
1455
|
+
@property
|
|
1456
|
+
def value(self) -> container.Container:
|
|
1457
|
+
return self._value
|
|
1458
|
+
|
|
1459
|
+
@overload
|
|
1460
|
+
def append(self: AT, key: None, value: Comment | Whitespace) -> AT:
|
|
1461
|
+
...
|
|
1462
|
+
|
|
1463
|
+
@overload
|
|
1464
|
+
def append(self: AT, key: Key | str, value: Any) -> AT:
|
|
1465
|
+
...
|
|
1466
|
+
|
|
1467
|
+
def append(self, key, value):
|
|
1468
|
+
raise NotImplementedError
|
|
1469
|
+
|
|
1470
|
+
@overload
|
|
1471
|
+
def add(self: AT, key: Comment | Whitespace) -> AT:
|
|
1472
|
+
...
|
|
1473
|
+
|
|
1474
|
+
@overload
|
|
1475
|
+
def add(self: AT, key: Key | str, value: Any = ...) -> AT:
|
|
1476
|
+
...
|
|
1477
|
+
|
|
1478
|
+
def add(self, key, value=None):
|
|
1479
|
+
if value is None:
|
|
1480
|
+
if not isinstance(key, (Comment, Whitespace)):
|
|
1481
|
+
msg = "Non comment/whitespace items must have an associated key"
|
|
1482
|
+
raise ValueError(msg)
|
|
1483
|
+
|
|
1484
|
+
key, value = None, key
|
|
1485
|
+
|
|
1486
|
+
return self.append(key, value)
|
|
1487
|
+
|
|
1488
|
+
def remove(self: AT, key: Key | str) -> AT:
|
|
1489
|
+
self._value.remove(key)
|
|
1490
|
+
|
|
1491
|
+
if isinstance(key, Key):
|
|
1492
|
+
key = key.key
|
|
1493
|
+
|
|
1494
|
+
if key is not None:
|
|
1495
|
+
dict.__delitem__(self, key)
|
|
1496
|
+
|
|
1497
|
+
return self
|
|
1498
|
+
|
|
1499
|
+
def setdefault(self, key: Key | str, default: Any) -> Any:
|
|
1500
|
+
super().setdefault(key, default)
|
|
1501
|
+
return self[key]
|
|
1502
|
+
|
|
1503
|
+
def __str__(self):
|
|
1504
|
+
return str(self.value)
|
|
1505
|
+
|
|
1506
|
+
def copy(self: AT) -> AT:
|
|
1507
|
+
return copy.copy(self)
|
|
1508
|
+
|
|
1509
|
+
def __repr__(self) -> str:
|
|
1510
|
+
return repr(self.value)
|
|
1511
|
+
|
|
1512
|
+
def __iter__(self) -> Iterator[str]:
|
|
1513
|
+
return iter(self._value)
|
|
1514
|
+
|
|
1515
|
+
def __len__(self) -> int:
|
|
1516
|
+
return len(self._value)
|
|
1517
|
+
|
|
1518
|
+
def __delitem__(self, key: Key | str) -> None:
|
|
1519
|
+
self.remove(key)
|
|
1520
|
+
|
|
1521
|
+
def __getitem__(self, key: Key | str) -> Item:
|
|
1522
|
+
return cast(Item, self._value[key])
|
|
1523
|
+
|
|
1524
|
+
def __setitem__(self, key: Key | str, value: Any) -> None:
|
|
1525
|
+
if not isinstance(value, Item):
|
|
1526
|
+
value = item(value, _parent=self)
|
|
1527
|
+
|
|
1528
|
+
is_replace = key in self
|
|
1529
|
+
self._value[key] = value
|
|
1530
|
+
|
|
1531
|
+
if key is not None:
|
|
1532
|
+
dict.__setitem__(self, key, value)
|
|
1533
|
+
|
|
1534
|
+
if is_replace:
|
|
1535
|
+
return
|
|
1536
|
+
m = re.match("(?s)^[^ ]*([ ]+).*$", self._trivia.indent)
|
|
1537
|
+
if not m:
|
|
1538
|
+
return
|
|
1539
|
+
|
|
1540
|
+
indent = m.group(1)
|
|
1541
|
+
|
|
1542
|
+
if not isinstance(value, Whitespace):
|
|
1543
|
+
m = re.match("(?s)^([^ ]*)(.*)$", value.trivia.indent)
|
|
1544
|
+
if not m:
|
|
1545
|
+
value.trivia.indent = indent
|
|
1546
|
+
else:
|
|
1547
|
+
value.trivia.indent = m.group(1) + indent + m.group(2)
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
class Table(AbstractTable):
|
|
1551
|
+
"""
|
|
1552
|
+
A table literal.
|
|
1553
|
+
"""
|
|
1554
|
+
|
|
1555
|
+
def __init__(
|
|
1556
|
+
self,
|
|
1557
|
+
value: container.Container,
|
|
1558
|
+
trivia: Trivia,
|
|
1559
|
+
is_aot_element: bool,
|
|
1560
|
+
is_super_table: bool | None = None,
|
|
1561
|
+
name: str | None = None,
|
|
1562
|
+
display_name: str | None = None,
|
|
1563
|
+
) -> None:
|
|
1564
|
+
super().__init__(value, trivia)
|
|
1565
|
+
|
|
1566
|
+
self.name = name
|
|
1567
|
+
self.display_name = display_name
|
|
1568
|
+
self._is_aot_element = is_aot_element
|
|
1569
|
+
self._is_super_table = is_super_table
|
|
1570
|
+
|
|
1571
|
+
@property
|
|
1572
|
+
def discriminant(self) -> int:
|
|
1573
|
+
return 9
|
|
1574
|
+
|
|
1575
|
+
def __copy__(self) -> Table:
|
|
1576
|
+
return type(self)(
|
|
1577
|
+
self._value.copy(),
|
|
1578
|
+
self._trivia.copy(),
|
|
1579
|
+
self._is_aot_element,
|
|
1580
|
+
self._is_super_table,
|
|
1581
|
+
self.name,
|
|
1582
|
+
self.display_name,
|
|
1583
|
+
)
|
|
1584
|
+
|
|
1585
|
+
def append(self, key: Key | str | None, _item: Any) -> Table:
|
|
1586
|
+
"""
|
|
1587
|
+
Appends a (key, item) to the table.
|
|
1588
|
+
"""
|
|
1589
|
+
if not isinstance(_item, Item):
|
|
1590
|
+
_item = item(_item, _parent=self)
|
|
1591
|
+
|
|
1592
|
+
self._value.append(key, _item)
|
|
1593
|
+
|
|
1594
|
+
if isinstance(key, Key):
|
|
1595
|
+
key = next(iter(key)).key
|
|
1596
|
+
_item = self._value[key]
|
|
1597
|
+
|
|
1598
|
+
if key is not None:
|
|
1599
|
+
dict.__setitem__(self, key, _item)
|
|
1600
|
+
|
|
1601
|
+
m = re.match(r"(?s)^[^ ]*([ ]+).*$", self._trivia.indent)
|
|
1602
|
+
if not m:
|
|
1603
|
+
return self
|
|
1604
|
+
|
|
1605
|
+
indent = m.group(1)
|
|
1606
|
+
|
|
1607
|
+
if not isinstance(_item, Whitespace):
|
|
1608
|
+
m = re.match("(?s)^([^ ]*)(.*)$", _item.trivia.indent)
|
|
1609
|
+
if not m:
|
|
1610
|
+
_item.trivia.indent = indent
|
|
1611
|
+
else:
|
|
1612
|
+
_item.trivia.indent = m.group(1) + indent + m.group(2)
|
|
1613
|
+
|
|
1614
|
+
return self
|
|
1615
|
+
|
|
1616
|
+
def raw_append(self, key: Key | str | None, _item: Any) -> Table:
|
|
1617
|
+
"""Similar to :meth:`append` but does not copy indentation."""
|
|
1618
|
+
if not isinstance(_item, Item):
|
|
1619
|
+
_item = item(_item)
|
|
1620
|
+
|
|
1621
|
+
self._value.append(key, _item, validate=False)
|
|
1622
|
+
|
|
1623
|
+
if isinstance(key, Key):
|
|
1624
|
+
key = next(iter(key)).key
|
|
1625
|
+
_item = self._value[key]
|
|
1626
|
+
|
|
1627
|
+
if key is not None:
|
|
1628
|
+
dict.__setitem__(self, key, _item)
|
|
1629
|
+
|
|
1630
|
+
return self
|
|
1631
|
+
|
|
1632
|
+
def is_aot_element(self) -> bool:
|
|
1633
|
+
"""True if the table is the direct child of an AOT element."""
|
|
1634
|
+
return self._is_aot_element
|
|
1635
|
+
|
|
1636
|
+
def is_super_table(self) -> bool:
|
|
1637
|
+
"""A super table is the intermediate parent of a nested table as in [a.b.c].
|
|
1638
|
+
If true, it won't appear in the TOML representation."""
|
|
1639
|
+
if self._is_super_table is not None:
|
|
1640
|
+
return self._is_super_table
|
|
1641
|
+
# If the table has only one child and that child is a table, then it is a super table.
|
|
1642
|
+
if len(self) != 1:
|
|
1643
|
+
return False
|
|
1644
|
+
only_child = next(iter(self.values()))
|
|
1645
|
+
return isinstance(only_child, (Table, AoT))
|
|
1646
|
+
|
|
1647
|
+
def as_string(self) -> str:
|
|
1648
|
+
return self._value.as_string()
|
|
1649
|
+
|
|
1650
|
+
# Helpers
|
|
1651
|
+
|
|
1652
|
+
def indent(self, indent: int) -> Table:
|
|
1653
|
+
"""Indent the table with given number of spaces."""
|
|
1654
|
+
super().indent(indent)
|
|
1655
|
+
|
|
1656
|
+
m = re.match("(?s)^[^ ]*([ ]+).*$", self._trivia.indent)
|
|
1657
|
+
if not m:
|
|
1658
|
+
indent_str = ""
|
|
1659
|
+
else:
|
|
1660
|
+
indent_str = m.group(1)
|
|
1661
|
+
|
|
1662
|
+
for _, item in self._value.body:
|
|
1663
|
+
if not isinstance(item, Whitespace):
|
|
1664
|
+
item.trivia.indent = indent_str + item.trivia.indent
|
|
1665
|
+
|
|
1666
|
+
return self
|
|
1667
|
+
|
|
1668
|
+
def invalidate_display_name(self):
|
|
1669
|
+
"""Call ``invalidate_display_name`` on the contained tables"""
|
|
1670
|
+
self.display_name = None
|
|
1671
|
+
|
|
1672
|
+
for child in self.values():
|
|
1673
|
+
if hasattr(child, "invalidate_display_name"):
|
|
1674
|
+
child.invalidate_display_name()
|
|
1675
|
+
|
|
1676
|
+
def _getstate(self, protocol: int = 3) -> tuple:
|
|
1677
|
+
return (
|
|
1678
|
+
self._value,
|
|
1679
|
+
self._trivia,
|
|
1680
|
+
self._is_aot_element,
|
|
1681
|
+
self._is_super_table,
|
|
1682
|
+
self.name,
|
|
1683
|
+
self.display_name,
|
|
1684
|
+
)
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
class InlineTable(AbstractTable):
|
|
1688
|
+
"""
|
|
1689
|
+
An inline table literal.
|
|
1690
|
+
"""
|
|
1691
|
+
|
|
1692
|
+
def __init__(
|
|
1693
|
+
self, value: container.Container, trivia: Trivia, new: bool = False
|
|
1694
|
+
) -> None:
|
|
1695
|
+
super().__init__(value, trivia)
|
|
1696
|
+
|
|
1697
|
+
self._new = new
|
|
1698
|
+
|
|
1699
|
+
@property
|
|
1700
|
+
def discriminant(self) -> int:
|
|
1701
|
+
return 10
|
|
1702
|
+
|
|
1703
|
+
def append(self, key: Key | str | None, _item: Any) -> InlineTable:
|
|
1704
|
+
"""
|
|
1705
|
+
Appends a (key, item) to the table.
|
|
1706
|
+
"""
|
|
1707
|
+
if not isinstance(_item, Item):
|
|
1708
|
+
_item = item(_item, _parent=self)
|
|
1709
|
+
|
|
1710
|
+
if not isinstance(_item, (Whitespace, Comment)):
|
|
1711
|
+
if not _item.trivia.indent and len(self._value) > 0 and not self._new:
|
|
1712
|
+
_item.trivia.indent = " "
|
|
1713
|
+
if _item.trivia.comment:
|
|
1714
|
+
_item.trivia.comment = ""
|
|
1715
|
+
|
|
1716
|
+
self._value.append(key, _item)
|
|
1717
|
+
|
|
1718
|
+
if isinstance(key, Key):
|
|
1719
|
+
key = key.key
|
|
1720
|
+
|
|
1721
|
+
if key is not None:
|
|
1722
|
+
dict.__setitem__(self, key, _item)
|
|
1723
|
+
|
|
1724
|
+
return self
|
|
1725
|
+
|
|
1726
|
+
def as_string(self) -> str:
|
|
1727
|
+
buf = "{"
|
|
1728
|
+
last_item_idx = next(
|
|
1729
|
+
(
|
|
1730
|
+
i
|
|
1731
|
+
for i in range(len(self._value.body) - 1, -1, -1)
|
|
1732
|
+
if self._value.body[i][0] is not None
|
|
1733
|
+
),
|
|
1734
|
+
None,
|
|
1735
|
+
)
|
|
1736
|
+
for i, (k, v) in enumerate(self._value.body):
|
|
1737
|
+
if k is None:
|
|
1738
|
+
if i == len(self._value.body) - 1:
|
|
1739
|
+
if self._new:
|
|
1740
|
+
buf = buf.rstrip(", ")
|
|
1741
|
+
else:
|
|
1742
|
+
buf = buf.rstrip(",")
|
|
1743
|
+
|
|
1744
|
+
buf += v.as_string()
|
|
1745
|
+
|
|
1746
|
+
continue
|
|
1747
|
+
|
|
1748
|
+
v_trivia_trail = v.trivia.trail.replace("\n", "")
|
|
1749
|
+
buf += (
|
|
1750
|
+
f"{v.trivia.indent}"
|
|
1751
|
+
f'{k.as_string() + ("." if k.is_dotted() else "")}'
|
|
1752
|
+
f"{k.sep}"
|
|
1753
|
+
f"{v.as_string()}"
|
|
1754
|
+
f"{v.trivia.comment}"
|
|
1755
|
+
f"{v_trivia_trail}"
|
|
1756
|
+
)
|
|
1757
|
+
|
|
1758
|
+
if last_item_idx is not None and i < last_item_idx:
|
|
1759
|
+
buf += ","
|
|
1760
|
+
if self._new:
|
|
1761
|
+
buf += " "
|
|
1762
|
+
|
|
1763
|
+
buf += "}"
|
|
1764
|
+
|
|
1765
|
+
return buf
|
|
1766
|
+
|
|
1767
|
+
def __setitem__(self, key: Key | str, value: Any) -> None:
|
|
1768
|
+
if hasattr(value, "trivia") and value.trivia.comment:
|
|
1769
|
+
value.trivia.comment = ""
|
|
1770
|
+
super().__setitem__(key, value)
|
|
1771
|
+
|
|
1772
|
+
def __copy__(self) -> InlineTable:
|
|
1773
|
+
return type(self)(self._value.copy(), self._trivia.copy(), self._new)
|
|
1774
|
+
|
|
1775
|
+
def _getstate(self, protocol: int = 3) -> tuple:
|
|
1776
|
+
return (self._value, self._trivia)
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
class String(str, Item):
|
|
1780
|
+
"""
|
|
1781
|
+
A string literal.
|
|
1782
|
+
"""
|
|
1783
|
+
|
|
1784
|
+
def __new__(cls, t, value, original, trivia):
|
|
1785
|
+
return super().__new__(cls, value)
|
|
1786
|
+
|
|
1787
|
+
def __init__(self, t: StringType, _: str, original: str, trivia: Trivia) -> None:
|
|
1788
|
+
super().__init__(trivia)
|
|
1789
|
+
|
|
1790
|
+
self._t = t
|
|
1791
|
+
self._original = original
|
|
1792
|
+
|
|
1793
|
+
def unwrap(self) -> str:
|
|
1794
|
+
return str(self)
|
|
1795
|
+
|
|
1796
|
+
@property
|
|
1797
|
+
def discriminant(self) -> int:
|
|
1798
|
+
return 11
|
|
1799
|
+
|
|
1800
|
+
@property
|
|
1801
|
+
def value(self) -> str:
|
|
1802
|
+
return self
|
|
1803
|
+
|
|
1804
|
+
def as_string(self) -> str:
|
|
1805
|
+
return f"{self._t.value}{decode(self._original)}{self._t.value}"
|
|
1806
|
+
|
|
1807
|
+
def __add__(self: ItemT, other: str) -> ItemT:
|
|
1808
|
+
if not isinstance(other, str):
|
|
1809
|
+
return NotImplemented
|
|
1810
|
+
result = super().__add__(other)
|
|
1811
|
+
original = self._original + getattr(other, "_original", other)
|
|
1812
|
+
|
|
1813
|
+
return self._new(result, original)
|
|
1814
|
+
|
|
1815
|
+
def _new(self, result: str, original: str) -> String:
|
|
1816
|
+
return String(self._t, result, original, self._trivia)
|
|
1817
|
+
|
|
1818
|
+
def _getstate(self, protocol=3):
|
|
1819
|
+
return self._t, str(self), self._original, self._trivia
|
|
1820
|
+
|
|
1821
|
+
@classmethod
|
|
1822
|
+
def from_raw(cls, value: str, type_=StringType.SLB, escape=True) -> String:
|
|
1823
|
+
value = decode(value)
|
|
1824
|
+
|
|
1825
|
+
invalid = type_.invalid_sequences
|
|
1826
|
+
if any(c in value for c in invalid):
|
|
1827
|
+
raise InvalidStringError(value, invalid, type_.value)
|
|
1828
|
+
|
|
1829
|
+
escaped = type_.escaped_sequences
|
|
1830
|
+
string_value = escape_string(value, escaped) if escape and escaped else value
|
|
1831
|
+
|
|
1832
|
+
return cls(type_, decode(value), string_value, Trivia())
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
class AoT(Item, _CustomList):
|
|
1836
|
+
"""
|
|
1837
|
+
An array of table literal
|
|
1838
|
+
"""
|
|
1839
|
+
|
|
1840
|
+
def __init__(
|
|
1841
|
+
self, body: list[Table], name: str | None = None, parsed: bool = False
|
|
1842
|
+
) -> None:
|
|
1843
|
+
self.name = name
|
|
1844
|
+
self._body: list[Table] = []
|
|
1845
|
+
self._parsed = parsed
|
|
1846
|
+
|
|
1847
|
+
super().__init__(Trivia(trail=""))
|
|
1848
|
+
|
|
1849
|
+
for table in body:
|
|
1850
|
+
self.append(table)
|
|
1851
|
+
|
|
1852
|
+
def unwrap(self) -> list[dict[str, Any]]:
|
|
1853
|
+
unwrapped = []
|
|
1854
|
+
for t in self._body:
|
|
1855
|
+
if hasattr(t, "unwrap"):
|
|
1856
|
+
unwrapped.append(t.unwrap())
|
|
1857
|
+
else:
|
|
1858
|
+
unwrapped.append(t)
|
|
1859
|
+
return unwrapped
|
|
1860
|
+
|
|
1861
|
+
@property
|
|
1862
|
+
def body(self) -> list[Table]:
|
|
1863
|
+
return self._body
|
|
1864
|
+
|
|
1865
|
+
@property
|
|
1866
|
+
def discriminant(self) -> int:
|
|
1867
|
+
return 12
|
|
1868
|
+
|
|
1869
|
+
@property
|
|
1870
|
+
def value(self) -> list[dict[Any, Any]]:
|
|
1871
|
+
return [v.value for v in self._body]
|
|
1872
|
+
|
|
1873
|
+
def __len__(self) -> int:
|
|
1874
|
+
return len(self._body)
|
|
1875
|
+
|
|
1876
|
+
@overload
|
|
1877
|
+
def __getitem__(self, key: slice) -> list[Table]:
|
|
1878
|
+
...
|
|
1879
|
+
|
|
1880
|
+
@overload
|
|
1881
|
+
def __getitem__(self, key: int) -> Table:
|
|
1882
|
+
...
|
|
1883
|
+
|
|
1884
|
+
def __getitem__(self, key):
|
|
1885
|
+
return self._body[key]
|
|
1886
|
+
|
|
1887
|
+
def __setitem__(self, key: slice | int, value: Any) -> None:
|
|
1888
|
+
raise NotImplementedError
|
|
1889
|
+
|
|
1890
|
+
def __delitem__(self, key: slice | int) -> None:
|
|
1891
|
+
del self._body[key]
|
|
1892
|
+
list.__delitem__(self, key)
|
|
1893
|
+
|
|
1894
|
+
def insert(self, index: int, value: dict) -> None:
|
|
1895
|
+
value = item(value, _parent=self)
|
|
1896
|
+
if not isinstance(value, Table):
|
|
1897
|
+
raise ValueError(f"Unsupported insert value type: {type(value)}")
|
|
1898
|
+
length = len(self)
|
|
1899
|
+
if index < 0:
|
|
1900
|
+
index += length
|
|
1901
|
+
if index < 0:
|
|
1902
|
+
index = 0
|
|
1903
|
+
elif index >= length:
|
|
1904
|
+
index = length
|
|
1905
|
+
m = re.match("(?s)^[^ ]*([ ]+).*$", self._trivia.indent)
|
|
1906
|
+
if m:
|
|
1907
|
+
indent = m.group(1)
|
|
1908
|
+
|
|
1909
|
+
m = re.match("(?s)^([^ ]*)(.*)$", value.trivia.indent)
|
|
1910
|
+
if not m:
|
|
1911
|
+
value.trivia.indent = indent
|
|
1912
|
+
else:
|
|
1913
|
+
value.trivia.indent = m.group(1) + indent + m.group(2)
|
|
1914
|
+
prev_table = self._body[index - 1] if 0 < index and length else None
|
|
1915
|
+
next_table = self._body[index + 1] if index < length - 1 else None
|
|
1916
|
+
if not self._parsed:
|
|
1917
|
+
if prev_table and "\n" not in value.trivia.indent:
|
|
1918
|
+
value.trivia.indent = "\n" + value.trivia.indent
|
|
1919
|
+
if next_table and "\n" not in next_table.trivia.indent:
|
|
1920
|
+
next_table.trivia.indent = "\n" + next_table.trivia.indent
|
|
1921
|
+
self._body.insert(index, value)
|
|
1922
|
+
list.insert(self, index, value)
|
|
1923
|
+
|
|
1924
|
+
def invalidate_display_name(self):
|
|
1925
|
+
"""Call ``invalidate_display_name`` on the contained tables"""
|
|
1926
|
+
for child in self:
|
|
1927
|
+
if hasattr(child, "invalidate_display_name"):
|
|
1928
|
+
child.invalidate_display_name()
|
|
1929
|
+
|
|
1930
|
+
def as_string(self) -> str:
|
|
1931
|
+
b = ""
|
|
1932
|
+
for table in self._body:
|
|
1933
|
+
b += table.as_string()
|
|
1934
|
+
|
|
1935
|
+
return b
|
|
1936
|
+
|
|
1937
|
+
def __repr__(self) -> str:
|
|
1938
|
+
return f"<AoT {self.value}>"
|
|
1939
|
+
|
|
1940
|
+
def _getstate(self, protocol=3):
|
|
1941
|
+
return self._body, self.name, self._parsed
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
class Null(Item):
|
|
1945
|
+
"""
|
|
1946
|
+
A null item.
|
|
1947
|
+
"""
|
|
1948
|
+
|
|
1949
|
+
def __init__(self) -> None:
|
|
1950
|
+
super().__init__(Trivia(trail=""))
|
|
1951
|
+
|
|
1952
|
+
def unwrap(self) -> None:
|
|
1953
|
+
return None
|
|
1954
|
+
|
|
1955
|
+
@property
|
|
1956
|
+
def discriminant(self) -> int:
|
|
1957
|
+
return -1
|
|
1958
|
+
|
|
1959
|
+
@property
|
|
1960
|
+
def value(self) -> None:
|
|
1961
|
+
return None
|
|
1962
|
+
|
|
1963
|
+
def as_string(self) -> str:
|
|
1964
|
+
return ""
|
|
1965
|
+
|
|
1966
|
+
def _getstate(self, protocol=3) -> tuple:
|
|
1967
|
+
return ()
|