From 169d7bccc02da43f8574d030502cfcf9308f505f Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Fri, 5 Jan 2024 11:33:25 -0600 Subject: subtree updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit meta-raspberrypi: fde68b24f0..4c033eb074: Harunobu Kurokawa (1): rpi-cmdline, rpi-u-boot-src: Support USB boot meta-arm: 0b61cc659a..4d22f982bc: Debbie Martin (2): arm-systemready: Add parted dependency and inherit testimage ci: Add Arm SystemReady firmware and IR ACS builds Harsimran Singh Tungal (3): arm-bsp/documentation: corstone1000: fix the steps in the user guide and instructions corstone1000:arm-bsp/optee: Update optee to v4.0 corstone1000:arm-bsp/tftf: Fix tftf tests on mps3 Jon Mason (5): arm/trusted-firmware-a: move patch file to bbappend arm/trusted-firmware-a: update to 2.10 arm/hafnium: update to v2.10 CI: rename meta-secure-core directory arm/edk2: update to 202311 Ross Burton (1): CI: switch back to master poky: 028b6f6226..4675bbb757: Adrian Freihofer (4): cmake-qemu.bbclass: make it more usable oe-selftest: add a cpp-example recipe oeqa/core/decorator: add skip if not qemu-usermode oe-selftest: add tests for C and C++ build tools Alassane Yattara (22): bitbake: toaster/test: bug-fix on tests/browser/test_all_builds_page bitbake: toaster/test: from test_no_builds_message.py wait for the empty state div to appear bitbake: toaster/test: delay driver action until elements to appear bitbake: toaster/tests: Ensure to kill toaster process create for tests functional bitbake: toaster/tests: Added functional/utils, contains useful methods using by functional tests bitbake: toaster/tests: Refactorize tests/functional bitbake: toaster/tests: Bug fixes, functional tests dependent on each other bitbake: toaster/tests: Fixes warnings in autobuilder bitbake: toaster/tests: bug-fix tests writing files into /tmp on the autobuilders bitbake: toaster/test: fix Copyright bitbake: toaster/tests: logging warning in console, trying to kill unavailable Runbuilds process bitbake: toaster/tests: Removed all time.sleep occurrence bitbake: toaster/tests: Bug-Fix testcase functional/test_project_page_tab_config.py bitbake: toaster/tests: bug-fix element click intercepted in browser/test_layerdetails_page.py bitbake: toaster/tests: Update tests/functional/functional_helpers test_functional_basic bitbake: toaster/tests: Fixes functional tests warning on autobuilder bitbake: toaster/tests: Bug-fix test_functional_basic, delay driver actions bitbake: toaster/tests: bug-fix An element matching "#projectstable" should be visible bitbake: toaster/tests: bug-fix An element matching "#lastest_builds" should be on the page bitbake: toaster/tests: Skip to show more then 100 item in ToasterTable bitbake: toaster/tests: Bug-fix "#project-created-notification" should be visible bitbake: toaster/toastergui: Bug-fix verify given layer path only if import/add local layer Alex Bennée (1): qemurunner: more cleanups for output blocking Alex Kiernan (17): cargo: Rename MANIFEST_PATH -> CARGO_MANIFEST_PATH cargo: Move CARGO_MANIFEST_PATH/CARGO_SRC_DIR to cargo_common rust: cargo: Convert single-valued variables to weak defaults cargo: Add CARGO_LOCK_PATH for path to Cargo.lock rust: Upgrade 1.70.0 -> 1.71.0 rust: Upgrade 1.71.0 -> 1.71.1 sstate-cache-management: Rewrite in python devtool: selftest: Fix test_devtool_modify_git_crates_subpath inequality devtool: selftest: Fix test_devtool_modify_git_crates_subpath bbappend check meta-selftest: hello-rs: Simple rust test recipe devtool: selftest: Swap to hello-rs for crates testing zvariant: Drop recipe rust: Upgrade 1.71.1 -> 1.72.0 rust: Upgrade 1.72.0 -> 1.72.1 rust: Upgrade 1.72.1 -> 1.73.0 rust: Upgrade 1.73.0 -> 1.74.0 rust: Upgrade 1.74.0 -> 1.74.1 Alexander Kanavin (21): selftest/sstatetest: print output from bitbake with actual newlines, not \n selftest/sstatetests: do not delete custom $TMPDIRs under build-st when testing printdiff sstatesig/find_siginfo: special-case gcc-source when looking in sstate caches oeqa/selftest/sstatetests: re-work CDN tests, add local cache tests gobject-introspection: depend on setuptools to obtain distutils module libcap-ng-python: depend on setuptools to obtain distutils copy dnf: remove obsolete python3-gpg dependency (provided by gpgme) gpgme: disable python support (until upstream fixes 3.12 compatibility) python3-setuptools-rust: remove distutils dependency python3-babel: replace distutils with setuptools, as supported by upstream python3-pip: remove distutils depedency glib-2.0: replace distutils dependency with setuptools python3-pytest-runner: remove distutils dependency python3-numpy: distutils is no longer required bitbake: bitbake/codeparser.py: address ast module deprecations in py 3.12 glibc-y2038-tests: do not run tests using 32 bit time APIs bitbake: bitbake/runqueue: add debugging for find_siginfo() calls bitbake: bitbake-diffsigs/runqueue: adapt to reworked find_siginfo() bitbake: bitbake/runqueue: prioritize local stamps over sstate signatures in printdiff sstatesig/find_siginfo: unify a disjointed API lib/sstatesig/find_siginfo: raise an error instead of returning None when obtaining mtime Alexander Lussier-Cullen (6): bitbake: toaster: fix pytest build test execution and test discovery bitbake: toaster: Add verbose printout for missing chrome(driver) dependencies bitbake: bitbake: toaster: add functional testing toaster error details bitbake: toaster/tests: Exit tests on chromedriver creation failure bitbake: toaster/tests: fix functional tests setup and teardown bitbake: toaster/tests: fix chrome argument syntax and wait for driver exit Alexandre Belloni (1): oeqa/selftest/recipetool: stop looking for md5sum Anuj Mittal (9): sqlite3: upgrade 3.44.0 -> 3.44.2 base-passwd: upgrade 3.6.2 -> 3.6.3 bluez5: upgrade 5.70 -> 5.71 glib-2.0: upgrade 2.78.1 -> 2.78.3 glib-networking: upgrade 2.76.1 -> 2.78.0 puzzles: upgrade to latest revision stress-ng: upgrade 0.17.01 -> 0.17.03 libusb1: fix upstream version check enchant2: upgrade 2.6.2 -> 2.6.4 Archana Polampalli (1): bluez5: fix CVE-2023-45866 Bruce Ashfield (31): linux-yocto/6.5: cfg: split runtime and symbol debug linux-yocto/6.5: update to v6.5.11 linux-yocto/6.1: update to v6.1.62 linux-yocto-dev: bump to v6.7 linux-yocto/6.5: update to v6.5.12 linux-yocto/6.5: update to v6.5.13 linux-yocto/6.1: update to v6.1.65 linux-yocto/6.1: drop removed IMA option linux-yocto/6.5: drop removed IMA option linux-yocto-rt/6.1: update to -rt18 linux-yocto/6.1: update to v6.1.66 linux-yocto/6.1: update to v6.1.67 linux-yocto/6.5: fix AB-INT: QEMU kernel panic: No irq handler for vector linux-yocto/6.1: update to v6.1.68 oeqa/runtime/parselogs: add qemux86 ACPI ignore for kernel v6.6+ linux-libc-headers: update to v6.6-lts linux-yocto: introduce 6.6 reference kernel linux-yocto/6.6: fix AB-INT: QEMU kernel panic: No irq handler for vector linux-yocto-rt/6.6: fix CVE exclusion include linux-yocto/6.6: update CVE exclusions linux-yocto/6.6: update to v6.6.8 linux-yocto/6.1: update to v6.1.69 linux-yocto/6.5: drop 6.5 recipes linux-yocto-rt/6.6: correct meta data branch linux-yocto/6.6: update to v6.6.9 linux-yocto/6.6: update CVE exclusions linux-yocto/6.1: update to v6.1.70 linux-yocto/6.1: update CVE exclusions linux-yocto/6.6: ARM fix configuration audit warning linux-yocto/6.6: arm: jitter entropy backport poky/poky-tiny: make 6.6 the default kernel Changqing Li (1): man-pages: remove conflict pages Chen Qi (1): devtool: use straight print in check-upgrade-status output Clay Chang (1): devtool: deploy: provide max_process to strip_execs Daniel Ammann (1): base: Unpack .7z files with p7zip Deepthi Hemraj (1): autoconf: Add missing perl modules to RDEPENDS Dhairya Nagodra (2): cve-update-nvd2-native: faster requests with API keys cve-update-nvd2-native: increase the delay between subsequent request failures Eilís 'pidge' Ní Fhlannagáin (3): useradd: Fix issues with useradd dependencies useradd: Add testcase for bugzilla issue (currently disabled) usergrouptests.py: Add test for switching between static-ids Enrico Scholz (1): tcp-wrappers: drop libnsl2 build dependency Etienne Cordonnier (2): gdb/systemd: enable minidebuginfo support conditionally manuals: document minidebuginfo Fabio Estevam (3): libdrm: Upgrade to 2.4.119 kmscube: Upgrade to latest revision bmap-tools: Upgrade to 3.7 Hongxu Jia (2): socat: 1.7.4.4 -> 1.8.0.0 man-db: 2.11.2 -> 2.12.0 Jason Andryuk (3): linux-firmware: Package iwlwifi .pnvm files linux-firmware: Change bnx2 packaging linux-firmware: Create bnx2x subpackage Jeremy A. Puhlman (1): create-spdx-2.2: combine spdx can try to write before dir creation Jermain Horsman (2): lib/bblayers/makesetup.py: Remove unused imports lib/bblayers/buildconf.py: Remove unused imports/variables Jose Quaresma (2): go: update 1.20.10 -> 1.20.11 go: update 1.20.11 -> 1.20.12 Joshua Watt (11): bitbake: bitbake-hashserv: Add description of permissions bitbake.conf: Add runtimedir rpcbind: Specify state directory under /run libinput: Add packageconfig for tests ipk: Switch to using zstd compression lib/oe/path.py: Add relsymlink() lib/packagedata.py: Fix broken symlinks for providers with a '/' bitbake: contrib/vim: Syntax improvements classes-global/sstate: Fix variable typo lib/packagedata.py: Add API to iterate over rprovides classes-global/insane: Look up all runtime providers for file-rdeps Julien Stephan (19): recipetool: create_buildsys_python.py: initialize metadata recipetool: create: add trailing newlines recipetool: create: add new optional process_url callback for plugins recipetool: create_buildsys_python: add pypi support oeqa/selftest/recipetool: remove spaces on empty lines oeqa/selftest/recipetool/devtool: add test for pypi class recipetool: appendsrcfile(s): add dry-run mode recipeutils: bbappend_recipe: fix undefined variable recipeutils: bbappend_recipe: fix docstring recipeutils: bbappend_recipe: add a way to specify the name of the file to add recipeutils: bbappend_recipe: remove old srcuri entry if parameters are different recipetool: appendsrcfile(s): use params instead of extraline recipeutils: bbappend_recipe: allow to patch the recipe itself recipetool: appendsrcfile(s): add a mode to update the recipe itself oeqa/selftest/recipetool: appendsrfile: add test for machine oeqa/selftest/recipetool: appendsrc: add test for update mode oeqa/selftest/recipetool: add back checksum checks on pypi tests oeqa/selftest/recipetool: remove left over from development oeqa/selftest/recipetool: fix metadata corruption on meta layer Kevin Hao (2): beaglebone-yocto: Remove the redundant kernel-devicetree beaglebone-yocto: Remove the obsolete variables for uImage Khem Raj (13): tiff: Backport fixes for CVE-2023-6277 kmod: Fix build with latest musl elfutils: Use own basename API implementation util-linux: Fix build with latest musl sysvinit: Include libgen.h for basename API attr: Fix build with latest musl opkg: Use own version of portable basename function util-linux: Delete md-raid tests gdb: Update to gdb 14.1 release systemd: Fix build with latest musl qemu: Fix build with latest musl qemu: Add packageconfig knob to enable pipewire support weston: Include libgen.h for basename Lee Chee Yang (5): migration-guides: reword fix in release-notes-4.3.1 migration-guides: add release notes for 4.0.15 perlcross: update to 1.5.2 perl: 5.38.0 -> 5.38.2 curl: update to 8.5.0 Lucas Stach (1): mesa: upgrade 23.2.1 -> 23.3.1 Ludovic Jozeau (1): image-live.bbclass: LIVE_ROOTFS_TYPE support compression Lukas Funke (1): selftest: wic: add test for zerorize option of empty plugin Malte Schmidt (1): wic: extend empty plugin with options to write zeros to partiton Markus Volk (3): gtk4: upgrade 4.12.3 -> 4.12.4 libadwaita: update 1.4.0 -> 1.4.2 appstream: Upgrade 0.16.3 -> 1.0.0 Marlon Rodriguez Garcia (5): bitbake: toaster/tests: Update build test bitbake: toaster: Added new feature to import eventlogs from command line into toaster using replay functionality bitbake: toaster: remove test and update setup to avoid rebuilding image bitbake: toaster: Commandline build import table improvements bitbake: toaster: Added validation to stop import if there is a build in progress Marta Rybczynska (1): bitbake: toastergui: verify that an existing layer path is given Massimiliano Minella (1): zstd: fix LICENSE statement Michael Opdenacker (8): test-manual: text and formatting fixes test-manual: resource updates test-manual: use working example test-manual: add links to python unittest test-manual: explicit or fix file paths test-manual: add or improve hyperlinks dev-manual: runtime-testing: fix test module name poky.conf: update SANITY_TESTED_DISTROS to match autobuilder Mikko Rapeli (1): runqemu: match .rootfs. in addition to -image- for rootfs Ming Liu (1): grub: fs/fat: Don't error when mtime is 0 Mingli Yu (2): python3-license-expression: Fix the ptest failure ptest-packagelists.inc: Add python3-license-expression Pavel Zhukov (2): bitbake: utils: Do not create directories with ${ in the name oeqa/selftest/bbtests: Add test for unexpanded variables in the dirname Peter Kjellerstedt (11): oeqa/selftest/devtool: Correct git clone of local repository oeqa/selftest/devtool: Avoid global Git hooks when amending a patch oeqa/selftest/devtool: Make test_devtool_load_plugin more resilient oeqa/selftest/recipetool: Make test_recipetool_load_plugin more resilient lib/oe/recipeutils: Avoid wrapping any SRC_URI[sha*sum] variables recipetool: create: Improve identification of licenses recipetool: create: Only include the expected SRC_URI checksums devtool: upgrade: Update all existing checksums for the SRC_URI devtool: modify: Make --no-extract work again devtool: modify: Handle recipes with a menuconfig task correctly dev-manual: Discourage the use of SRC_URI[md5sum] Peter Marko (1): dtc: preserve version also from shallow git clones Philip Balister (1): sanity.bbclass: Check for additional native perl modules. Renat Khalikov (1): python3-maturin: Add missing space appending to CFLAGS Richard Purdie (41): bitbake: runqueue: Improve inter setscene task dependency handling bitbake: bb/toaster: Fix assertEquals deprecation warnings bitbake: toaster: Fix assertRegexpMatches deprecation warnings bitbake: toastermain/settings: Avoid python filehandle closure warnings bitbake: toastergui: Fix regex markup issues bitbake: bitbake: Move to version 2.6.1 to mark runqueue changes bitbake: toaster-eventreplay: Remove ordering assumptions sanity.conf: Require bitbake 2.6.1 for recent runqueue change sstate: Remove unneeded code from setscene_depvalid() related to useradd oeqa/runtime/systemd: Ensure test runs only on systemd images bitbake: toaster: Update to use qemux86-64 machine by default bitbake: toaster/tests/builds: Add BB_HASHSERVE passthrough pseudo: Update to pull in syncfs probe fix useradd: Fix useradd do_populate_sysroot dependency bug sstate: Fix dir ownership issues in SSTATE_DIR oeqa/sstatetests: Disable gcc source printdiff test for now build-appliance-image: Update to master head revision bitbake: utils: Fix mkdir with PosixPath bitbake: runqueue: Remove tie between rqexe and starts_worker build-appliance-image: Update to master head revision testimage: Exclude wtmp from target-dumper commands qemurunner: Improve stdout logging handling qemurunner: Improve handling of serial port output blocking oeqa/selftest/overlayfs: Don't overwrite DISTRO_FEATURES testimage: Drop target_dumper and most of monitor_dumper oeqa/selftest/overlayfs: Fix whitespace qemu: Clean up DEPENDS qemu: Ensure pip and the python venv aren't used for meson curl: Disable two intermittently failing tests linux/cve-exclusion6.1: Update to latest kernel point release lib/prservice: Improve lock handling robustness oeqa/selftest/prservice: Improve test robustness scripts: Drop shell sstate-cache-management oeqa/selftest/sstatetests: Update sstate management script tests to python script curl: Disable test 1091 due to intermittent failures bitbake: lib/bb: Add workaround for libgcc issues with python 3.8 and 3.9 bitbake: bitbake: Post release version bump to 2.7.0 bitbake: siggen: Ensure version of siggen is verified bitbake: bitbake: Version bump for find_siginfo chanages sstatesig: Add version information for find_sigingfo sanity: Require bitbake 2.7.1 Robert Berger (1): uninative-tarball.xz - reproducibility fix Robert Yang (5): gettext: Upgrade 0.22.3 -> 0.22.4 nfs-utils: Upgrade 2.6.3 -> 2.6.4 archiver.bbclass: Improve work-shared checking nfs-utils: Update Upstream-Status archiver.bbclass: Drop tarfile module to improve performance Ross Burton (23): avahi: update URL for new project location oeqa/runtime/parselogs: load ignores from disk oeqa/runtime/parselogs: migrate ignores meta-yocto-bsp/oeqa/parselogs: add BSP-specific ignores linux-yocto: update CVE exclusions genericx86: remove redundant assignments images: remove redundant IMAGE_BASENAME assignments insane: ensure more paths have the workdir removed tcl: skip timing-dependent tests in run-ptest qemurunner: remove unused import go: set vendor in CVE_PRODUCT runqemu: add qmp socket support linux-yocto: update CVE exclusions tcl: skip async and event tests in run-ptest images: add core-image-initramfs-boot machine/arch-armv9: remove crc and sve tunes, they are mandatory python3: re-enable profile guided optimisation openssl: mark assembler sections as call targets for PAC/BTI support on aarch64 nativesdk: ensure features don't get backfilled nativesdk: don't unset MACHINE_FEATURES, let machine-sdk/ set it conf/machine-sdk: declare qemu-usermode SDK_MACHINE_FEATURE libseccomp: remove redundant PV assignment oeqa/parselogs-ignores-qemuarmv5: add comments and organise Saul Wold (1): package.py: OEHasPackage: Add MLPREFIX to packagename Shubham Kulkarni (1): tzdata: Upgrade to 2023d Simone Weiß (2): manuals: brief-yoctoprojectqs: align variable order with default local.conf patchtest: Add test for deprecated CVE_CHECK_IGNORE Soumya Sambu (1): ncurses: Fix - tty is hung after reset Sundeep KOKKONDA (1): rust: rustdoc reproducibility issue fix - disable PGO Tim Orling (12): python3-bcrypt: upgrade 4.0.1 -> 4.1.1 python3-pygments: upgrade 2.16.1 -> 2.17.2 recipetool: pypi: do not clobber SRC_URI checksums python3-setuptools-rust: BBCLASSEXTEND + nativesdk python3-maturin: add v1.4.0 python3-maturin: bzip2-sys reproduciblility classes-recipe: add python_maturin.bbclass recipetool: add python_maturin support oe-selfest: add maturn runtime (testimage) test oeqa: add simple 'maturin' SDK (testsdk) test case oeqa: add "maturin develop" SDK test case oeqa: add runtime 'maturin develop' test case Tom Rini (1): inetutils: Update to the 2.5 release Trevor Gamblin (1): scripts/runqemu: fix regex escape sequences Victor Kamensky (5): systemtap: upgrade 4.9 -> 5.0 systemtap: do not install uprobes and uprobes sources systemtap-uprobes: removed as obsolete systemtap: explicit handling debuginfod library dependency systemtap: fix libdebuginfod auto detection logic Vijay Anusuri (1): avahi: backport CVE-2023-1981 & CVE's follow-up patches Viswanath Kraleti (2): image-uefi.conf: Add EFI_UKI_PATH variable systemd-boot: Add recipe to compile native Wang Mingyu (38): kbd: upgrade 2.6.3 -> 2.6.4 libatomic-ops: upgrade 7.8.0 -> 7.8.2 libnl: upgrade 3.8.0 -> 3.9.0 libseccomp: upgrade 2.5.4 -> 2.5.5 libva-utils: upgrade 2.20.0 -> 2.20.1 dnf: upgrade 4.18.1 -> 4.18.2 gpgme: upgrade 1.23.1 -> 1.23.2 kea: upgrade 2.4.0 -> 2.4.1 opkg-utils: upgrade 0.6.2 -> 0.6.3 repo: upgrade 2.39 -> 2.40 sysstat: upgrade 12.7.4 -> 12.7.5 p11-kit: upgrade 0.25.2 -> 0.25.3 python3-babel: upgrade 2.13.1 -> 2.14.0 python3-dbusmock: upgrade 0.29.1 -> 0.30.0 python3-hatchling: upgrade 1.18.0 -> 1.20.0 python3-hypothesis: upgrade 6.90.0 -> 6.92.1 python3-importlib-metadata: upgrade 6.8.0 -> 7.0.0 python3-license-expression: upgrade 30.1.1 -> 30.2.0 python3-pathspec: upgrade 0.11.2 -> 0.12.1 python3-pip: upgrade 23.3.1 -> 23.3.2 python3-psutil: upgrade 5.9.6 -> 5.9.7 python3-pytest-runner: upgrade 6.0.0 -> 6.0.1 python3-trove-classifiers: upgrade 2023.11.22 -> 2023.11.29 python3-typing-extensions: upgrade 4.8.0 -> 4.9.0 python3-wcwidth: upgrade 0.2.11 -> 0.2.12 ttyrun: upgrade 2.29.0 -> 2.30.0 xwayland: upgrade 23.2.2 -> 23.2.3 diffoscope: upgrade 252 -> 253 iputils: upgrade 20221126 -> 20231222 gstreamer1.0: upgrade 1.22.7 -> 1.22.8 dhcpcd: upgrade 10.0.5 -> 10.0.6 fontconfig: upgrade 2.14.2 -> 2.15.0 python3-setuptools: upgrade 69.0.2 -> 69.0.3 python3-dbusmock: upgrade 0.30.0 -> 0.30.1 python3-hatchling: upgrade 1.20.0 -> 1.21.0 python3-importlib-metadata: upgrade 7.0.0 -> 7.0.1 python3-lxml: upgrade 4.9.3 -> 4.9.4 aspell: upgrade 0.60.8 -> 0.60.8.1 Yash Shinde (1): rust: Disable rust oe-selftest Yi Zhao (3): json-glib: upgrade 1.6.6 -> 1.8.0 psplash: upgrade to latest revision debianutils: upgrade 5.14 -> 5.15 Yoann Congal (2): lib/oe/patch: handle creating patches for CRLF sources strace: Disable bluetooth support by default Zang Ruochen (2): ell: upgrade 0.60 -> 0.61 musl: add typedefs for Elf64_Relr and Elf32_Relr Zoltan Boszormenyi (1): update_gtk_icon_cache: Fix for GTK4-only builds venkata pyla (1): wic: use E2FSPROGS_FAKE_TIME and hash_seed to generate reproducible ext4 images meta-openembedded: 5ad7203f68..7d8115d550: Alex Kiernan (7): mdns: Fix HOMEPAGE URL mbedtls: Upgrade 3.5.0 -> 3.5.1 c-ares: Upgrade 1.22.1 -> 1.24.0 mdns: Upgrade 2200.40.37.0.1 -> 2200.60.25.0.4 c-ares: Move to tarballs, add ptest and static support thin-provisioning-tools: Upgrade 1.0.4 -> 1.0.9 bearssl: Upgrade to latest Alexander Kanavin (29): python3-pyinotify: remove as unmaintained python3-supervisor: do not rely on smtpd module python3-meld3: do not rely on smtpd module python3-m2crypto: do not rely on smtpd module python3-uinput: remove as unmaintained python3-mcrypto: rely on setuptools for distutils copy python3-joblib: do not rely in distutils python3-web3: remove distutils dependency python3-cppy: remove unused distutils dependency python3-pyroute2: remove unused distutils dependency python3-eventlet: backport a patch to remove distutils dependency python3-unoconv: rely on setuptools to obtain distutils copy python3-astroid: remove unneeded distutils dependency python3-django: remove unneeded distutils dependency python3-pillow: remove unneeded distutils dependency python3-grpcio: update 1.56.2 -> 1.59.3 gstd: correctly delete files in do_install libplist: fix python 3.12 compatibility libcamera: skip until upstream resolves python 3.12 compatibility nodejs: backport (partially) python 3.12 support nodejs: backport (partially) python 3.12 support polkit: remove long obsolete 0.119 version mozjs-115: split the way-too-long PYTHONPATH line polkit: update mozjs dependency 102 -> 115 mozjs-115: backport py 3.12 compatibility mozjs-102: remove the recipe gthumb: update 3.12.2 -> 3.12.4 flatpak: do not rely on executables from the host bolt: package systemd units Archana Polampalli (1): cjson: upgrade 1.7.16 -> 1.7.17 Bruce Ashfield (1): zfs: update to 2.2.2 Changqing Li (2): postgresql: upgrade 15.4 -> 15.5 redis: upgrade 6.2.13 -> 6.2.14 Derek Straka (70): python3-greenlet: update to version 3.0.2 python3-ujson: update to version 5.9.0 python3-termcolor: update to version 2.4.0 python3-cmake: update to version 3.28.0 python3-pint: upgrade to 0.23 python3-gnupg: update to 0.5.2 python3-pyzmq: update to 25.1.2 python3-tox: update to version 4.11.4 python3-olefile: update to version 0.47 python3-distlib: update to version 0.3.8 python3-colorlog: update to version 6.8.0 python3-pymongo: update version to 4.6.1 python3-bandit: update to version 1.7.6 python3-gmqtt: update to version 0.6.13 python3-portion: update to version 2.4.2 python3-prompt-toolkit: update to version 3.0.43 python3-asyncinotify: update to version 4.0.4 python3-bitstring: update to version 4.1.4 python3-ipython: update to version 8.18.1 nginx: update versions for both the stable branch and mainline python3-portalocker: update to version 2.8.2 python3-astroid: update to version 3.0.2 python3-alembic: update to version 1.13.1 python3-pymisp: update to verion 2.4.182 python3-ninja: update to version 1.11.1.1 python3-coverage: update to version 7.3.4 python3-pdm: update to version 2.11.1 python3-paramiko: update to version 3.4.0 python3-zeroconf: update to version 0.131.0 python3-wtforms: update to version 3.1.1 python3-isort: update to version 5.13.2 python3-protobuf: update to version 4.25.1 python3-lazy-object-proxy: update to version 1.10.0 python3-cantools: update to version 39.4.0 python3-sentry-sdk: update to version 1.39.1 python3-xmlschema: update to version 2.5.1 python3-apiflask: update to version 2.1.0 python3-rapidjson: update to version 1.14 python3-bitarray: update to version 2.9.0 python3-pyfanotify: update to version 0.2.2 python3-eventlet: update to version 0.34.1 python3-flask-wtf: update to version 1.2.1 python3-grpcio: update to version 1.60.0 python3-grpcio-tools: update to version 1.60.0 python3-cmake: update to version 3.28.1 python3-flask-sqlalchemy: fix upstream uri check python3-wtforms: fix upstream uri and version check gyp: update to the latest commit python3-ipython-genutils: fix upstream uri and version check python3-flask: fix upstream uri and version check python3-wpa-supplicant: fix upstream uri and version check python3-uswid: update to version 0.4.7 python3-flask-wtf: fix upstream uri and version check python3-gspread: update to version 5.12.3 python3-pytest-html: update to version 4.1.1 python3-setuptools-scm-git-archive: remove obsolete package python3-pyroute2: update to version 0.7.10 python3-constantly: update to version 23.10.4 python3-mypy: update to version 1.8.0 python3-flask-jwt-extended: update to version 4.6.0 python3-greenlet: update to version 3.0.3 python3-web3: update to version 6.13.0 python3-parse: update to version 1.20.0 python3-kmod: add comment about update to version 0.9.2 python3-engineio: update to version 4.8.1 python3-sqlalchemy: update to version 2.0.24 python3-pdm-backend: update to version 2.1.8 python3-cantools: update to version 39.4.1 python3-argh: update to version 0.30.5 python3-dominate: update to version 2.9.1 Dmitry Baryshkov (2): android-tools: remove two Debianisms networkmanager: drop libnewt dependency Frederic Martinsons (3): crash: factorize recipe with inc file to prepare cross-canadian version crash: add cross canadian version crash: update to 8.0.4 Jan Vermaete (1): netdata: added Python as rdepends Jean-Marc BOUCHE (1): terminus-font: build compressed archives with -n Jose Quaresma (1): ostree: Upgrade 2023.7 -> 2023.8 Joshua Watt (1): redis: Create state directory in systemd service Jörg Sommer (1): i2cdev: New recipe with i2c tools Kai Kang (1): lvm2: 2.03.16 -> 2.03.22 Khem Raj (3): Revert "nodejs: backport (partially) python 3.12 support" Revert "libcamera: skip until upstream resolves python 3.12 compatibility" libcamera: Fix build with python 3.12 Leon Anavi (11): sip: Upgrade 6.7.12 -> 6.8.0 python3-expandvars: add recipe python3-frozenlist: upgrade 1.4.0 -> 1.4.1 python3-yarl: upgrade 1.9.2 -> 1.9.4 python3-coverage: upgrade 7.3.2 -> 7.3.3 python3-cycler: upgrade 0.11.0 -> 0.12.1 python3-aiohue: upgrade 4.6.2 -> 4.7.0 python3-sdbus: upgrade 0.11.0 -> 0.11.1 python3-zeroconf: upgrade 0.128.4 -> 0.130.0 python3-dominate: upgrade 2.8.0 -> 2.9.0 python3-rlp: upgrade 3.0.0 -> 4.0.0 Marek Vasut (1): faad2: Upgrade 2.10.0 -> 2.11.1 Markus Volk (3): wireplumber: update 0.4.15 -> 0.4.17 tracker: dont inherit gsettings gnome-software: update 45.1 -> 45.2 Martin Jansa (4): monocypher: pass LIBDIR to fix installed-vs-shipped QA issue with multilib rygel: fix build with gtk+3 PACKAGECONFIG disabled rygel: add x11 to DISTRO_FEATURES driverctl: fix installed-vs-shipped Meenali Gupta (1): nginx: upgrade 1.25.2 -> 1.25.3 Mingli Yu (2): mariadb: Upgrade to 10.11.6 tk: Remove buildpath issue Nathan BRIENT (1): cyaml: new recipe Niko Mauno (1): pkcs11-provider: Add recipe Ny Antra Ranaivoarison (1): python3-click-spinner: backport patch that fixes deprecated methods Patrick Wicki (1): poco: upgrade 1.12.4 -> 1.12.5p2 Petr Chernikov (1): abseil-cpp: remove -Dcmake_cxx_standard=14 flag from extra_oecmake Robert Yang (1): minifi-cpp: Fix do_configure error builder aarch64 Ross Burton (13): Remove unused SRC_DISTRIBUTE_LICENSES gspell: inherit gtk-doc gspell: update DEPENDS, switch iso-codes for icu librest: remove spurious build dependencies librest: inherit gtk-doc keybinder: use autotools-brokensep instead of setting B keybinder: disable gtk-doc documentation gtksourceview3: remove obsolete DEPENDS libgsf: remove obsolete DEPENDS evolution-data-server: remove obsolete intltool DEPENDS php: remove lemon-native build dependency lemon: upgrade to 3.44.2 renderdoc: no need to depend on vim-native Samuli Piippo (1): jasper: enable opengl only wih x11 Theodore A. Roth (1): python3-flask-sqlalchemy: upgrade 2.5.1 -> 3.1.1 Thomas Perrot (2): networkmanager: add missing modemmanager rdepends networkmanager: fix some missing pkgconfig Tim Orling (8): python3-pydantic-core: add v2.14.5 python3-annotated-types: add v0.6.0 python3-pydantic: fix RDEPENDS python3-dirty-equals: add v0.7.1 python3-pydantic-core: enable ptest python3-cloudpickle: add v3.0.0 python3-pydantic: enable ptest python3-yappi: upgrade 1.4.0 -> 1.6.0; fix ptests Wang Mingyu (61): python3-alembic: upgrade 1.12.1 -> 1.13.0 python3-ansi2html: upgrade 1.8.0 -> 1.9.1 python3-argcomplete: upgrade 3.1.6 -> 3.2.1 python3-dbus-fast: upgrade 2.15.0 -> 2.21.0 python3-django: upgrade 4.2.7 -> 5.0 python3-flask-restx: upgrade 1.2.0 -> 1.3.0 python3-google-api-core: upgrade 2.14.0 -> 2.15.0 python3-google-api-python-client: upgrade 2.108.0 -> 2.111.0 python3-googleapis-common-protos: upgrade 1.61.0 -> 1.62.0 python3-google-auth: upgrade 2.23.4 -> 2.25.2 python3-imageio: upgrade 2.33.0 -> 2.33.1 python3-isort: upgrade 5.12.0 -> 5.13.1 python3-path: upgrade 16.7.1 -> 16.9.0 python3-platformdirs: upgrade 4.0.0 -> 4.1.0 python3-pytest-asyncio: upgrade 0.22.0 -> 0.23.2 python3-sentry-sdk: upgrade 1.37.1 -> 1.39.0 python3-bitarray: upgrade 2.8.3 -> 2.8.5 python3-eth-keyfile: upgrade 0.6.1 -> 0.7.0 python3-eth-rlp: upgrade 0.3.0 -> 1.0.0 python3-fastnumbers: upgrade 5.0.1 -> 5.1.0 python3-pylint: upgrade 3.0.2 -> 3.0.3 python3-tornado: upgrade 6.3.3 -> 6.4 python3-traitlets: upgrade 5.13.0 -> 5.14.0 python3-types-setuptools: upgrade 68.2.0.2 -> 69.0.0.0 python3-virtualenv: upgrade 20.24.7 -> 20.25.0 python3-web3: upgrade 6.11.3 -> 6.12.0 python3-websocket-client: upgrade 1.6.4 -> 1.7.0 python3-zeroconf: upgrade 0.127.0 -> 0.128.4 ctags: upgrade 6.0.20231126.0 -> 6.0.20231210.0 gensio: upgrade 2.8.0 -> 2.8.2 hwdata: upgrade 0.376 -> 0.377 lvgl: upgrade 8.3.10 -> 8.3.11 gjs: upgrade 1.78.0 -> 1.78.1 ifenslave: upgrade 2.13 -> 2.14 libei: upgrade 1.1.0 -> 1.2.0 pkcs11-helper: upgrade 1.29.0 -> 1.30.0 strongswan: upgrade 5.9.12 -> 5.9.13 webkitgtk3: upgrade 2.42.2 -> 2.42.3 sip: upgrade 6.8.0 -> 6.8.1 paho-mqtt-cpp: upgrade 1.3.1 -> 1.3.2 dbus-cxx: upgrade 2.4.0 -> 2.5.0 exiftool: upgrade 12.70 -> 12.71 uftp: upgrade 5.0.2 -> 5.0.3 ctags: upgrade 6.0.20231210.0 -> 6.0.20231224.0 jasper: Fix install conflict when enable multilib. jq: upgrade 1.7 -> 1.7.1 libmbim: upgrade 1.31.1 -> 1.31.2 libqmi: upgrade 1.34.0 -> 1.35.1 opencl-headers: upgrade 2023.04.17 -> 2023.12.14 valijson: upgrade 1.0.1 -> 1.0.2 python3-apispec: upgrade 6.3.0 -> 6.3.1 python3-asyncinotify: upgrade 4.0.4 -> 4.0.5 python3-bitarray: upgrade 2.9.0 -> 2.9.1 python3-cassandra-driver: upgrade 3.28.0 -> 3.29.0 python3-ipython: upgrade 8.18.1 -> 8.19.0 python3-pydantic: upgrade 2.5.2 -> 2.5.3 python3-regex: upgrade 2023.10.3 -> 2023.12.25 opencl-icd-loader: upgrade 2023.04.17 -> 2023.12.14 python3-distro: upgrade 1.8.0 -> 1.9.0 zchunk: upgrade 1.3.2 -> 1.4.0 python3-eventlet: upgrade 0.34.1 -> 0.34.2 William Lyu (1): networkmanager: Improved SUMMARY and added DESCRIPTION Xiangyu Chen (1): layer.conf: add libbpf to NON_MULTILIB_RECIPES Yi Zhao (2): open-vm-tools: upgrade 12.1.5 -> 12.3.5 samba: upgrade 4.18.8 -> 4.18.9 Zoltán Böszörményi (2): mutter: Make gnome-desktop and libcanberra dependencies optional zenity: Upgrade to 4.0.0 alperak (29): jasper: upgrade 2.0.33 -> 4.1.1 xcursorgen: upgrade 1.0.7 -> 1.0.8 xstdcmap: upgrade 1.0.4 -> 1.0.5 xlsclients: upgrade 1.1.4 -> 1.1.5 xlsatoms: upgrade 1.1.3 -> 1.1.4 xkbevd: upgrade 1.1.4 -> 1.1.5 xgamma: upgrade 1.0.6 -> 1.0.7 sessreg: upgrade 1.1.2 -> 1.1.3 xbitmaps: upgrade 1.1.2 -> 1.1.3 xcursor-themes: add recipe xorg-docs: add recipe xorg-sgml-doctools: update summary depends and inc file xf86-video-ati: upgrade 19.1.0 -> 22.0.0 xf86-input-void: upgrade 1.4.1 -> 1.4.2 libxaw: upgrade 1.0.14 -> 1.0.15 xf86-video-mga: upgrade 2.0.0 -> 2.0.1 snappy: upgrade 1.1.9 -> 1.1.10 xsetroot: upgrade 1.1.2 -> 1.1.3 libbytesize: Removed unnecessary setting of B libmxml: use autotools-brokensep instead of setting B libsombok3: use autotools-brokensep instead of setting B pgpool2: use autotools-brokensep instead of setting B qpdf: upgrade 11.6.3 -> 11.6.4 cpprest: upgrade 2.10.18 -> 2.10.19 avro-c: upgrade 1.11.2 -> 1.11.3 dool: upgrade 1.1.0 -> 1.3.1 driverctl: upgrade 0.111 -> 0.115 hstr: upgrade 2.5.0 -> 3.1.0 libharu: upgrade 2.3.0 -> 2.4.4 meta-security: 070a1e82cc..b2e1511338: Armin Kuster (6): libgssglue: update to 0.8 python3-privacyidea: Update to 3.9.1 lynis: Update SRC_URI to improve updater layers: Move READMEs to markdown format arpwatch: adjust CONFIGURE params to allow to build again. python3-pyinotify: fail2ban needs this module Dawid Dabrowski (1): libhoth recipe update Erik Schilling (2): dm-verity-img.bbclass: use bc-native dm-verity-img.bbclass: remove IMAGE_NAME_SUFFIX Mikko Rapeli (2): tpm2-tss: support native builds dm-verity-img.bbclass: add DM_VERITY_DEPLOY_DIR Change-Id: I94d7f1ee5ff2da4555c05fbf63a1293ec8f249c2 Signed-off-by: Patrick Williams --- .../0001-Fix-imports-for-ptests.patch | 3895 -------------------- ...unctionality-convert-line-endings-to-Unix.patch | 3845 +++++++++++++++++++ ...ix-import-of-tests.utils-to-enable-pytest.patch | 101 + .../python3-yappi/0002-add-3.11-to-the-setup.patch | 26 - .../python/python3-yappi/run-ptest | 2 +- 5 files changed, 3947 insertions(+), 3922 deletions(-) delete mode 100644 meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch create mode 100644 meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-test_functionality-convert-line-endings-to-Unix.patch create mode 100644 meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-Fix-import-of-tests.utils-to-enable-pytest.patch delete mode 100644 meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch (limited to 'meta-openembedded/meta-python/recipes-devtools/python/python3-yappi') diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch deleted file mode 100644 index 476db4b7d0..0000000000 --- a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch +++ /dev/null @@ -1,3895 +0,0 @@ -From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001 -From: Trevor Gamblin -Date: Mon, 7 Jun 2021 09:40:20 -0400 -Subject: [PATCH] Fix imports for tests - -Signed-off-by: Trevor Gamblin ---- -Upstream-Status: Pending - - tests/test_asyncio.py | 2 +- - tests/test_asyncio_context_vars.py | 2 +- - tests/test_functionality.py | 2 +- - tests/test_hooks.py | 2 +- - tests/test_tags.py | 2 +- - 5 files changed, 6 insertions(+), 6 deletions(-) - ---- a/tests/test_asyncio.py -+++ b/tests/test_asyncio.py -@@ -2,7 +2,7 @@ import unittest - import yappi - import asyncio - import threading --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io - - - async def async_sleep(sec): ---- a/tests/test_asyncio_context_vars.py -+++ b/tests/test_asyncio_context_vars.py -@@ -5,7 +5,7 @@ import contextvars - import functools - import time - import os --import utils -+import tests.utils as utils - import yappi - - async_context_id = contextvars.ContextVar('async_context_id') ---- a/tests/test_functionality.py -+++ b/tests/test_functionality.py -@@ -1,1916 +1,1916 @@ --import os --import sys --import time --import threading --import unittest --import yappi --import _yappi --import utils --import multiprocessing # added to fix http://bugs.python.org/issue15881 for > Py2.6 --import subprocess -- --_counter = 0 -- -- --class BasicUsage(utils.YappiUnitTestCase): -- -- def test_callback_function_int_return_overflow(self): -- # this test is just here to check if any errors are generated, as the err -- # is printed in C side, I did not include it here. THere are ways to test -- # this deterministically, I did not bother -- import ctypes -- -- def _unsigned_overflow_margin(): -- return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1 -- -- def foo(): -- pass -- -- #with utils.captured_output() as (out, err): -- yappi.set_context_id_callback(_unsigned_overflow_margin) -- yappi.set_tag_callback(_unsigned_overflow_margin) -- yappi.start() -- foo() -- -- def test_issue60(self): -- -- def foo(): -- buf = bytearray() -- buf += b't' * 200 -- view = memoryview(buf)[10:] -- view = view.tobytes() -- del buf[:10] # this throws exception -- return view -- -- yappi.start(builtins=True) -- foo() -- self.assertTrue( -- len( -- yappi.get_func_stats( -- filter_callback=lambda x: yappi. -- func_matches(x, [memoryview.tobytes]) -- ) -- ) > 0 -- ) -- yappi.stop() -- -- def test_issue54(self): -- -- def _tag_cbk(): -- global _counter -- _counter += 1 -- return _counter -- -- def a(): -- pass -- -- def b(): -- pass -- -- yappi.set_tag_callback(_tag_cbk) -- yappi.start() -- a() -- a() -- a() -- yappi.stop() -- stats = yappi.get_func_stats() -- self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given -- stats = yappi.get_func_stats(tag=1) -- -- for i in range(1, 3): -- stats = yappi.get_func_stats(tag=i) -- stats = yappi.get_func_stats( -- tag=i, filter_callback=lambda x: yappi.func_matches(x, [a]) -- ) -- -- stat = stats.pop() -- self.assertEqual(stat.ncall, 1) -- -- yappi.set_tag_callback(None) -- yappi.clear_stats() -- yappi.start() -- b() -- b() -- stats = yappi.get_func_stats() -- self.assertEqual(len(stats), 1) -- stat = stats.pop() -- self.assertEqual(stat.ncall, 2) -- -- def test_filter(self): -- -- def a(): -- pass -- -- def b(): -- a() -- -- def c(): -- b() -- -- _TCOUNT = 5 -- -- ts = [] -- yappi.start() -- for i in range(_TCOUNT): -- t = threading.Thread(target=c) -- t.start() -- ts.append(t) -- -- for t in ts: -- t.join() -- -- yappi.stop() -- -- ctx_ids = [] -- for tstat in yappi.get_thread_stats(): -- if tstat.name == '_MainThread': -- main_ctx_id = tstat.id -- else: -- ctx_ids.append(tstat.id) -- -- fstats = yappi.get_func_stats(filter={"ctx_id": 9}) -- self.assertTrue(fstats.empty()) -- fstats = yappi.get_func_stats( -- filter={ -- "ctx_id": main_ctx_id, -- "name": "c" -- } -- ) # main thread -- self.assertTrue(fstats.empty()) -- -- for i in ctx_ids: -- fstats = yappi.get_func_stats( -- filter={ -- "ctx_id": i, -- "name": "a", -- "ncall": 1 -- } -- ) -- self.assertEqual(fstats.pop().ncall, 1) -- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"}) -- self.assertEqual(fstats.pop().ncall, 1) -- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"}) -- self.assertEqual(fstats.pop().ncall, 1) -- -- yappi.clear_stats() -- yappi.start(builtins=True) -- time.sleep(0.1) -- yappi.stop() -- fstats = yappi.get_func_stats(filter={"module": "time"}) -- self.assertEqual(len(fstats), 1) -- -- # invalid filters` -- self.assertRaises( -- Exception, yappi.get_func_stats, filter={'tag': "sss"} -- ) -- self.assertRaises( -- Exception, yappi.get_func_stats, filter={'ctx_id': "None"} -- ) -- -- def test_filter_callback(self): -- -- def a(): -- time.sleep(0.1) -- -- def b(): -- a() -- -- def c(): -- pass -- -- def d(): -- pass -- -- yappi.set_clock_type("wall") -- yappi.start(builtins=True) -- a() -- b() -- c() -- d() -- stats = yappi.get_func_stats( -- filter_callback=lambda x: yappi.func_matches(x, [a, b]) -- ) -- #stats.print_all() -- r1 = ''' -- tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175 -- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197 -- ''' -- self.assert_traces_almost_equal(r1, stats) -- self.assertEqual(len(stats), 2) -- stats = yappi.get_func_stats( -- filter_callback=lambda x: yappi. -- module_matches(x, [sys.modules[__name__]]) -- ) -- r1 = ''' -- tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065 -- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011 -- tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002 -- tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001 -- ''' -- self.assert_traces_almost_equal(r1, stats) -- self.assertEqual(len(stats), 4) -- -- stats = yappi.get_func_stats( -- filter_callback=lambda x: yappi.func_matches(x, [time.sleep]) -- ) -- self.assertEqual(len(stats), 1) -- r1 = ''' -- time.sleep 2 0.206804 0.220000 0.103402 -- ''' -- self.assert_traces_almost_equal(r1, stats) -- -- def test_print_formatting(self): -- -- def a(): -- pass -- -- def b(): -- a() -- -- func_cols = { -- 1: ("name", 48), -- 0: ("ncall", 5), -- 2: ("tsub", 8), -- } -- thread_cols = { -- 1: ("name", 48), -- 0: ("ttot", 8), -- } -- -- yappi.start() -- a() -- b() -- yappi.stop() -- fs = yappi.get_func_stats() -- cs = fs[1].children -- ts = yappi.get_thread_stats() -- #fs.print_all(out=sys.stderr, columns={1:("name", 70), }) -- #cs.print_all(out=sys.stderr, columns=func_cols) -- #ts.print_all(out=sys.stderr, columns=thread_cols) -- #cs.print_all(out=sys.stderr, columns={}) -- -- self.assertRaises( -- yappi.YappiError, fs.print_all, columns={1: ("namee", 9)} -- ) -- self.assertRaises( -- yappi.YappiError, cs.print_all, columns={1: ("dd", 0)} -- ) -- self.assertRaises( -- yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)} -- ) -- -- def test_get_clock(self): -- yappi.set_clock_type('cpu') -- self.assertEqual('cpu', yappi.get_clock_type()) -- clock_info = yappi.get_clock_info() -- self.assertTrue('api' in clock_info) -- self.assertTrue('resolution' in clock_info) -- -- yappi.set_clock_type('wall') -- self.assertEqual('wall', yappi.get_clock_type()) -- -- t0 = yappi.get_clock_time() -- time.sleep(0.1) -- duration = yappi.get_clock_time() - t0 -- self.assertTrue(0.05 < duration < 0.3) -- -- def test_profile_decorator(self): -- -- def aggregate(func, stats): -- fname = "tests/%s.profile" % (func.__name__) -- try: -- stats.add(fname) -- except IOError: -- pass -- stats.save(fname) -- raise Exception("messing around") -- -- @yappi.profile(return_callback=aggregate) -- def a(x, y): -- if x + y == 25: -- raise Exception("") -- return x + y -- -- def b(): -- pass -- -- try: -- os.remove( -- "tests/a.profile" -- ) # remove the one from prev test, if available -- except: -- pass -- -- # global profile is on to mess things up -- yappi.start() -- b() -- -- # assert functionality and call function at same time -- try: -- self.assertEqual(a(1, 2), 3) -- except: -- pass -- try: -- self.assertEqual(a(2, 5), 7) -- except: -- pass -- try: -- a(4, 21) -- except: -- pass -- stats = yappi.get_func_stats().add("tests/a.profile") -- fsa = utils.find_stat_by_name(stats, 'a') -- self.assertEqual(fsa.ncall, 3) -- self.assertEqual(len(stats), 1) # b() should be cleared out. -- -- @yappi.profile(return_callback=aggregate) -- def count_down_rec(n): -- if n == 0: -- return -- count_down_rec(n - 1) -- -- try: -- os.remove( -- "tests/count_down_rec.profile" -- ) # remove the one from prev test, if available -- except: -- pass -- -- try: -- count_down_rec(4) -- except: -- pass -- try: -- count_down_rec(3) -- except: -- pass -- -- stats = yappi.YFuncStats("tests/count_down_rec.profile") -- fsrec = utils.find_stat_by_name(stats, 'count_down_rec') -- self.assertEqual(fsrec.ncall, 9) -- self.assertEqual(fsrec.nactualcall, 2) -- -- def test_strip_dirs(self): -- -- def a(): -- pass -- -- stats = utils.run_and_get_func_stats(a, ) -- stats.strip_dirs() -- fsa = utils.find_stat_by_name(stats, "a") -- self.assertEqual(fsa.module, os.path.basename(fsa.module)) -- -- @unittest.skipIf(os.name == "nt", "do not run on Windows") -- def test_run_as_script(self): -- import re -- p = subprocess.Popen( -- ['yappi', os.path.join('./tests', 'run_as_script.py')], -- stdout=subprocess.PIPE -- ) -- out, err = p.communicate() -- self.assertEqual(p.returncode, 0) -- func_stats, thread_stats = re.split( -- b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out -- ) -- self.assertTrue(b'FancyThread' in thread_stats) -- -- def test_yappi_overhead(self): -- LOOP_COUNT = 100000 -- -- def a(): -- pass -- -- def b(): -- for i in range(LOOP_COUNT): -- a() -- -- t0 = time.time() -- yappi.start() -- b() -- yappi.stop() -- time_with_yappi = time.time() - t0 -- t0 = time.time() -- b() -- time_without_yappi = time.time() - t0 -- if time_without_yappi == 0: -- time_without_yappi = 0.000001 -- -- # in latest v0.82, I calculated this as close to "7.0" in my machine. -- # however, %83 of this overhead is coming from tickcount(). The other %17 -- # seems to have been evenly distributed to the internal bookkeeping -- # structures/algorithms which seems acceptable. Note that our test only -- # tests one function being profiled at-a-time in a short interval. -- # profiling high number of functions in a small time -- # is a different beast, (which is pretty unlikely in most applications) -- # So as a conclusion: I cannot see any optimization window for Yappi that -- # is worth implementing as we will only optimize %17 of the time. -- sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \ -- (time_with_yappi / time_without_yappi)) -- -- def test_clear_stats_while_running(self): -- -- def a(): -- pass -- -- yappi.start() -- a() -- yappi.clear_stats() -- a() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- self.assertEqual(fsa.ncall, 1) -- -- def test_generator(self): -- -- def _gen(n): -- while (n > 0): -- yield n -- n -= 1 -- -- yappi.start() -- for x in _gen(5): -- pass -- self.assertTrue( -- yappi.convert2pstats(yappi.get_func_stats()) is not None -- ) -- -- def test_slice_child_stats_and_strip_dirs(self): -- -- def b(): -- for i in range(10000000): -- pass -- -- def a(): -- b() -- -- yappi.start(builtins=True) -- a() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- self.assertTrue(fsa.children[0:1] is not None) -- prev_afullname = fsa.full_name -- prev_bchildfullname = fsa.children[fsb].full_name -- stats.strip_dirs() -- self.assertTrue(len(prev_afullname) > len(fsa.full_name)) -- self.assertTrue( -- len(prev_bchildfullname) > len(fsa.children[fsb].full_name) -- ) -- -- def test_children_stat_functions(self): -- _timings = {"a_1": 5, "b_1": 3, "c_1": 1} -- _yappi._set_test_timings(_timings) -- -- def b(): -- pass -- -- def c(): -- pass -- -- def a(): -- b() -- c() -- -- yappi.start() -- a() -- b() # non-child call -- c() # non-child call -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- childs_of_a = fsa.children.get().sort("tavg", "desc") -- prev_item = None -- for item in childs_of_a: -- if prev_item: -- self.assertTrue(prev_item.tavg > item.tavg) -- prev_item = item -- childs_of_a.sort("name", "desc") -- prev_item = None -- for item in childs_of_a: -- if prev_item: -- self.assertTrue(prev_item.name > item.name) -- prev_item = item -- childs_of_a.clear() -- self.assertTrue(childs_of_a.empty()) -- -- def test_no_stats_different_clock_type_load(self): -- -- def a(): -- pass -- -- yappi.start() -- a() -- yappi.stop() -- yappi.get_func_stats().save("tests/ystats1.ys") -- yappi.clear_stats() -- yappi.set_clock_type("WALL") -- yappi.start() -- yappi.stop() -- stats = yappi.get_func_stats().add("tests/ystats1.ys") -- fsa = utils.find_stat_by_name(stats, 'a') -- self.assertTrue(fsa is not None) -- -- def test_subsequent_profile(self): -- _timings = {"a_1": 1, "b_1": 1} -- _yappi._set_test_timings(_timings) -- -- def a(): -- pass -- -- def b(): -- pass -- -- yappi.start() -- a() -- yappi.stop() -- yappi.start() -- b() -- yappi.stop() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- self.assertTrue(fsa is not None) -- self.assertTrue(fsb is not None) -- self.assertEqual(fsa.ttot, 1) -- self.assertEqual(fsb.ttot, 1) -- -- def test_lambda(self): -- f = lambda: time.sleep(0.3) -- yappi.set_clock_type("wall") -- yappi.start() -- f() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, '') -- self.assertTrue(fsa.ttot > 0.1) -- -- def test_module_stress(self): -- self.assertEqual(yappi.is_running(), False) -- -- yappi.start() -- yappi.clear_stats() -- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") -- -- yappi.stop() -- yappi.clear_stats() -- yappi.set_clock_type("cpu") -- self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy") -- self.assertEqual(yappi.is_running(), False) -- yappi.clear_stats() -- yappi.clear_stats() -- -- def test_stat_sorting(self): -- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- b() -- -- def b(): -- if self._ncall == 2: -- return -- self._ncall += 1 -- a() -- -- stats = utils.run_and_get_func_stats(a) -- stats = stats.sort("totaltime", "desc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.ttot >= stat.ttot) -- prev_stat = stat -- stats = stats.sort("totaltime", "asc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.ttot <= stat.ttot) -- prev_stat = stat -- stats = stats.sort("avgtime", "asc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.tavg <= stat.tavg) -- prev_stat = stat -- stats = stats.sort("name", "asc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.name <= stat.name) -- prev_stat = stat -- stats = stats.sort("subtime", "asc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.tsub <= stat.tsub) -- prev_stat = stat -- -- self.assertRaises( -- yappi.YappiError, stats.sort, "invalid_func_sorttype_arg" -- ) -- self.assertRaises( -- yappi.YappiError, stats.sort, "totaltime", -- "invalid_func_sortorder_arg" -- ) -- -- def test_start_flags(self): -- self.assertEqual(_yappi._get_start_flags(), None) -- yappi.start() -- -- def a(): -- pass -- -- a() -- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) -- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) -- self.assertEqual(len(yappi.get_thread_stats()), 1) -- -- def test_builtin_profiling(self): -- -- def a(): -- time.sleep(0.4) # is a builtin function -- -- yappi.set_clock_type('wall') -- -- yappi.start(builtins=True) -- a() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'sleep') -- self.assertTrue(fsa is not None) -- self.assertTrue(fsa.ttot > 0.3) -- yappi.stop() -- yappi.clear_stats() -- -- def a(): -- pass -- -- yappi.start() -- t = threading.Thread(target=a) -- t.start() -- t.join() -- stats = yappi.get_func_stats() -- -- def test_singlethread_profiling(self): -- yappi.set_clock_type('wall') -- -- def a(): -- time.sleep(0.2) -- -- class Worker1(threading.Thread): -- -- def a(self): -- time.sleep(0.3) -- -- def run(self): -- self.a() -- -- yappi.start(profile_threads=False) -- -- c = Worker1() -- c.start() -- c.join() -- a() -- stats = yappi.get_func_stats() -- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') -- fsa2 = utils.find_stat_by_name(stats, 'a') -- self.assertTrue(fsa1 is None) -- self.assertTrue(fsa2 is not None) -- self.assertTrue(fsa2.ttot > 0.1) -- -- def test_run(self): -- -- def profiled(): -- pass -- -- yappi.clear_stats() -- try: -- with yappi.run(): -- profiled() -- stats = yappi.get_func_stats() -- finally: -- yappi.clear_stats() -- -- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) -- -- def test_run_recursive(self): -- -- def profiled(): -- pass -- -- def not_profiled(): -- pass -- -- yappi.clear_stats() -- try: -- with yappi.run(): -- with yappi.run(): -- profiled() -- # Profiling stopped here -- not_profiled() -- stats = yappi.get_func_stats() -- finally: -- yappi.clear_stats() -- -- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) -- self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled')) -- -- --class StatSaveScenarios(utils.YappiUnitTestCase): -- -- def test_pstats_conversion(self): -- -- def pstat_id(fs): -- return (fs.module, fs.lineno, fs.name) -- -- def a(): -- d() -- -- def b(): -- d() -- -- def c(): -- pass -- -- def d(): -- pass -- -- _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2} -- _yappi._set_test_timings(_timings) -- stats = utils.run_and_get_func_stats(a, ) -- stats.strip_dirs() -- stats.save("tests/a1.pstats", type="pstat") -- fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a")) -- fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d")) -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- stats = utils.run_and_get_func_stats(a, ) -- stats.strip_dirs() -- stats.save("tests/a2.pstats", type="pstat") -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- stats = utils.run_and_get_func_stats(b, ) -- stats.strip_dirs() -- stats.save("tests/b1.pstats", type="pstat") -- fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b")) -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- stats = utils.run_and_get_func_stats(c, ) -- stats.strip_dirs() -- stats.save("tests/c1.pstats", type="pstat") -- fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c")) -- -- # merge saved stats and check pstats values are correct -- import pstats -- p = pstats.Stats( -- 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats', -- 'tests/c1.pstats' -- ) -- p.strip_dirs() -- # ct = ttot, tt = tsub -- (cc, nc, tt, ct, callers) = p.stats[fsa_pid] -- self.assertEqual(cc, nc, 2) -- self.assertEqual(tt, 20) -- self.assertEqual(ct, 24) -- (cc, nc, tt, ct, callers) = p.stats[fsd_pid] -- self.assertEqual(cc, nc, 3) -- self.assertEqual(tt, 6) -- self.assertEqual(ct, 6) -- self.assertEqual(len(callers), 2) -- (cc, nc, tt, ct) = callers[fsa_pid] -- self.assertEqual(cc, nc, 2) -- self.assertEqual(tt, 4) -- self.assertEqual(ct, 4) -- (cc, nc, tt, ct) = callers[fsb_pid] -- self.assertEqual(cc, nc, 1) -- self.assertEqual(tt, 2) -- self.assertEqual(ct, 2) -- -- def test_merge_stats(self): -- _timings = { -- "a_1": 15, -- "b_1": 14, -- "c_1": 12, -- "d_1": 10, -- "e_1": 9, -- "f_1": 7, -- "g_1": 6, -- "h_1": 5, -- "i_1": 1 -- } -- _yappi._set_test_timings(_timings) -- -- def a(): -- b() -- -- def b(): -- c() -- -- def c(): -- d() -- -- def d(): -- e() -- -- def e(): -- f() -- -- def f(): -- g() -- -- def g(): -- h() -- -- def h(): -- i() -- -- def i(): -- pass -- -- yappi.start() -- a() -- a() -- yappi.stop() -- stats = yappi.get_func_stats() -- self.assertRaises( -- NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE" -- ) -- stats.save("tests/ystats2.ys") -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- yappi.start() -- a() -- stats = yappi.get_func_stats().add("tests/ystats2.ys") -- fsa = utils.find_stat_by_name(stats, "a") -- fsb = utils.find_stat_by_name(stats, "b") -- fsc = utils.find_stat_by_name(stats, "c") -- fsd = utils.find_stat_by_name(stats, "d") -- fse = utils.find_stat_by_name(stats, "e") -- fsf = utils.find_stat_by_name(stats, "f") -- fsg = utils.find_stat_by_name(stats, "g") -- fsh = utils.find_stat_by_name(stats, "h") -- fsi = utils.find_stat_by_name(stats, "i") -- self.assertEqual(fsa.ttot, 45) -- self.assertEqual(fsa.ncall, 3) -- self.assertEqual(fsa.nactualcall, 3) -- self.assertEqual(fsa.tsub, 3) -- self.assertEqual(fsa.children[fsb].ttot, fsb.ttot) -- self.assertEqual(fsa.children[fsb].tsub, fsb.tsub) -- self.assertEqual(fsb.children[fsc].ttot, fsc.ttot) -- self.assertEqual(fsb.children[fsc].tsub, fsc.tsub) -- self.assertEqual(fsc.tsub, 6) -- self.assertEqual(fsc.children[fsd].ttot, fsd.ttot) -- self.assertEqual(fsc.children[fsd].tsub, fsd.tsub) -- self.assertEqual(fsd.children[fse].ttot, fse.ttot) -- self.assertEqual(fsd.children[fse].tsub, fse.tsub) -- self.assertEqual(fse.children[fsf].ttot, fsf.ttot) -- self.assertEqual(fse.children[fsf].tsub, fsf.tsub) -- self.assertEqual(fsf.children[fsg].ttot, fsg.ttot) -- self.assertEqual(fsf.children[fsg].tsub, fsg.tsub) -- self.assertEqual(fsg.ttot, 18) -- self.assertEqual(fsg.tsub, 3) -- self.assertEqual(fsg.children[fsh].ttot, fsh.ttot) -- self.assertEqual(fsg.children[fsh].tsub, fsh.tsub) -- self.assertEqual(fsh.ttot, 15) -- self.assertEqual(fsh.tsub, 12) -- self.assertEqual(fsh.tavg, 5) -- self.assertEqual(fsh.children[fsi].ttot, fsi.ttot) -- self.assertEqual(fsh.children[fsi].tsub, fsi.tsub) -- #stats.debug_print() -- -- def test_merge_multithreaded_stats(self): -- import _yappi -- timings = {"a_1": 2, "b_1": 1} -- _yappi._set_test_timings(timings) -- -- def a(): -- pass -- -- def b(): -- pass -- -- yappi.start() -- t = threading.Thread(target=a) -- t.start() -- t.join() -- t = threading.Thread(target=b) -- t.start() -- t.join() -- yappi.get_func_stats().save("tests/ystats1.ys") -- yappi.clear_stats() -- _yappi._set_test_timings(timings) -- self.assertEqual(len(yappi.get_func_stats()), 0) -- self.assertEqual(len(yappi.get_thread_stats()), 1) -- t = threading.Thread(target=a) -- t.start() -- t.join() -- -- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) -- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) -- yappi.get_func_stats().save("tests/ystats2.ys") -- -- stats = yappi.YFuncStats([ -- "tests/ystats1.ys", -- "tests/ystats2.ys", -- ]) -- fsa = utils.find_stat_by_name(stats, "a") -- fsb = utils.find_stat_by_name(stats, "b") -- self.assertEqual(fsa.ncall, 2) -- self.assertEqual(fsb.ncall, 1) -- self.assertEqual(fsa.tsub, fsa.ttot, 4) -- self.assertEqual(fsb.tsub, fsb.ttot, 1) -- -- def test_merge_load_different_clock_types(self): -- yappi.start(builtins=True) -- -- def a(): -- b() -- -- def b(): -- c() -- -- def c(): -- pass -- -- t = threading.Thread(target=a) -- t.start() -- t.join() -- yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys") -- yappi.stop() -- yappi.clear_stats() -- yappi.start(builtins=False) -- t = threading.Thread(target=a) -- t.start() -- t.join() -- yappi.get_func_stats().save("tests/ystats2.ys") -- yappi.stop() -- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") -- yappi.clear_stats() -- yappi.set_clock_type("wall") -- yappi.start() -- t = threading.Thread(target=a) -- t.start() -- t.join() -- yappi.get_func_stats().save("tests/ystats3.ys") -- self.assertRaises( -- yappi.YappiError, -- yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys" -- ) -- stats = yappi.YFuncStats(["tests/ystats1.ys", -- "tests/ystats2.ys"]).sort("name") -- fsa = utils.find_stat_by_name(stats, "a") -- fsb = utils.find_stat_by_name(stats, "b") -- fsc = utils.find_stat_by_name(stats, "c") -- self.assertEqual(fsa.ncall, 2) -- self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall) -- -- def test_merge_aabab_aabbc(self): -- _timings = { -- "a_1": 15, -- "a_2": 14, -- "b_1": 12, -- "a_3": 10, -- "b_2": 9, -- "c_1": 4 -- } -- _yappi._set_test_timings(_timings) -- -- def a(): -- if self._ncall == 1: -- self._ncall += 1 -- a() -- elif self._ncall == 5: -- self._ncall += 1 -- a() -- else: -- b() -- -- def b(): -- if self._ncall == 2: -- self._ncall += 1 -- a() -- elif self._ncall == 6: -- self._ncall += 1 -- b() -- elif self._ncall == 7: -- c() -- else: -- return -- -- def c(): -- pass -- -- self._ncall = 1 -- stats = utils.run_and_get_func_stats(a, ) -- stats.save("tests/ystats1.ys") -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- #stats.print_all() -- -- self._ncall = 5 -- stats = utils.run_and_get_func_stats(a, ) -- stats.save("tests/ystats2.ys") -- -- #stats.print_all() -- -- def a(): # same name but another function(code object) -- pass -- -- yappi.start() -- a() -- stats = yappi.get_func_stats().add( -- ["tests/ystats1.ys", "tests/ystats2.ys"] -- ) -- #stats.print_all() -- self.assertEqual(len(stats), 4) -- -- fsa = None -- for stat in stats: -- if stat.name == "a" and stat.ttot == 45: -- fsa = stat -- break -- self.assertTrue(fsa is not None) -- -- self.assertEqual(fsa.ncall, 7) -- self.assertEqual(fsa.nactualcall, 3) -- self.assertEqual(fsa.ttot, 45) -- self.assertEqual(fsa.tsub, 10) -- fsb = utils.find_stat_by_name(stats, "b") -- fsc = utils.find_stat_by_name(stats, "c") -- self.assertEqual(fsb.ncall, 6) -- self.assertEqual(fsb.nactualcall, 3) -- self.assertEqual(fsb.ttot, 36) -- self.assertEqual(fsb.tsub, 27) -- self.assertEqual(fsb.tavg, 6) -- self.assertEqual(fsc.ttot, 8) -- self.assertEqual(fsc.tsub, 8) -- self.assertEqual(fsc.tavg, 4) -- self.assertEqual(fsc.nactualcall, fsc.ncall, 2) -- -- --class MultithreadedScenarios(utils.YappiUnitTestCase): -- -- def test_issue_32(self): -- ''' -- Start yappi from different thread and we get Internal Error(15) as -- the current_ctx_id() called while enumerating the threads in start() -- and as it does not swap to the enumerated ThreadState* the THreadState_GetDict() -- returns wrong object and thus sets an invalid id for the _ctx structure. -- -- When this issue happens multiple Threads have same tid as the internal ts_ptr -- will be same for different contexts. So, let's see if that happens -- ''' -- -- def foo(): -- time.sleep(0.2) -- -- def bar(): -- time.sleep(0.1) -- -- def thread_func(): -- yappi.set_clock_type("wall") -- yappi.start() -- -- bar() -- -- t = threading.Thread(target=thread_func) -- t.start() -- t.join() -- -- foo() -- -- yappi.stop() -- -- thread_ids = set() -- for tstat in yappi.get_thread_stats(): -- self.assertTrue(tstat.tid not in thread_ids) -- thread_ids.add(tstat.tid) -- -- def test_subsequent_profile(self): -- WORKER_COUNT = 5 -- -- def a(): -- pass -- -- def b(): -- pass -- -- def c(): -- pass -- -- _timings = { -- "a_1": 3, -- "b_1": 2, -- "c_1": 1, -- } -- -- yappi.start() -- -- def g(): -- pass -- -- g() -- yappi.stop() -- yappi.clear_stats() -- _yappi._set_test_timings(_timings) -- yappi.start() -- -- _dummy = [] -- for i in range(WORKER_COUNT): -- t = threading.Thread(target=a) -- t.start() -- t.join() -- for i in range(WORKER_COUNT): -- t = threading.Thread(target=b) -- t.start() -- _dummy.append(t) -- t.join() -- for i in range(WORKER_COUNT): -- t = threading.Thread(target=a) -- t.start() -- t.join() -- for i in range(WORKER_COUNT): -- t = threading.Thread(target=c) -- t.start() -- t.join() -- yappi.stop() -- yappi.start() -- -- def f(): -- pass -- -- f() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- self.assertEqual(fsa.ncall, 10) -- self.assertEqual(fsb.ncall, 5) -- self.assertEqual(fsc.ncall, 5) -- self.assertEqual(fsa.ttot, fsa.tsub, 30) -- self.assertEqual(fsb.ttot, fsb.tsub, 10) -- self.assertEqual(fsc.ttot, fsc.tsub, 5) -- -- # MACOSx optimizes by only creating one worker thread -- self.assertTrue(len(yappi.get_thread_stats()) >= 2) -- -- def test_basic(self): -- yappi.set_clock_type('wall') -- -- def dummy(): -- pass -- -- def a(): -- time.sleep(0.2) -- -- class Worker1(threading.Thread): -- -- def a(self): -- time.sleep(0.3) -- -- def run(self): -- self.a() -- -- yappi.start(builtins=False, profile_threads=True) -- -- c = Worker1() -- c.start() -- c.join() -- a() -- stats = yappi.get_func_stats() -- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') -- fsa2 = utils.find_stat_by_name(stats, 'a') -- self.assertTrue(fsa1 is not None) -- self.assertTrue(fsa2 is not None) -- self.assertTrue(fsa1.ttot > 0.2) -- self.assertTrue(fsa2.ttot > 0.1) -- tstats = yappi.get_thread_stats() -- self.assertEqual(len(tstats), 2) -- tsa = utils.find_stat_by_name(tstats, 'Worker1') -- tsm = utils.find_stat_by_name(tstats, '_MainThread') -- dummy() # call dummy to force ctx name to be retrieved again. -- self.assertTrue(tsa is not None) -- # TODO: I put dummy() to fix below, remove the comments after a while. -- self.assertTrue( # FIX: I see this fails sometimes? -- tsm is not None, -- 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats)))) -- -- def test_ctx_stats(self): -- from threading import Thread -- DUMMY_WORKER_COUNT = 5 -- yappi.start() -- -- class DummyThread(Thread): -- pass -- -- def dummy(): -- pass -- -- def dummy_worker(): -- pass -- -- for i in range(DUMMY_WORKER_COUNT): -- t = DummyThread(target=dummy_worker) -- t.start() -- t.join() -- yappi.stop() -- stats = yappi.get_thread_stats() -- tsa = utils.find_stat_by_name(stats, "DummyThread") -- self.assertTrue(tsa is not None) -- yappi.clear_stats() -- time.sleep(1.0) -- _timings = { -- "a_1": 6, -- "b_1": 5, -- "c_1": 3, -- "d_1": 1, -- "a_2": 4, -- "b_2": 3, -- "c_2": 2, -- "d_2": 1 -- } -- _yappi._set_test_timings(_timings) -- -- class Thread1(Thread): -- pass -- -- class Thread2(Thread): -- pass -- -- def a(): -- b() -- -- def b(): -- c() -- -- def c(): -- d() -- -- def d(): -- time.sleep(0.6) -- -- yappi.set_clock_type("wall") -- yappi.start() -- t1 = Thread1(target=a) -- t1.start() -- t2 = Thread2(target=a) -- t2.start() -- t1.join() -- t2.join() -- stats = yappi.get_thread_stats() -- -- # the fist clear_stats clears the context table? -- tsa = utils.find_stat_by_name(stats, "DummyThread") -- self.assertTrue(tsa is None) -- -- tst1 = utils.find_stat_by_name(stats, "Thread1") -- tst2 = utils.find_stat_by_name(stats, "Thread2") -- tsmain = utils.find_stat_by_name(stats, "_MainThread") -- dummy() # call dummy to force ctx name to be retrieved again. -- self.assertTrue(len(stats) == 3) -- self.assertTrue(tst1 is not None) -- self.assertTrue(tst2 is not None) -- # TODO: I put dummy() to fix below, remove the comments after a while. -- self.assertTrue( # FIX: I see this fails sometimes -- tsmain is not None, -- 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats)))) -- self.assertTrue(1.0 > tst2.ttot >= 0.5) -- self.assertTrue(1.0 > tst1.ttot >= 0.5) -- -- # test sorting of the ctx stats -- stats = stats.sort("totaltime", "desc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.ttot >= stat.ttot) -- prev_stat = stat -- stats = stats.sort("totaltime", "asc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.ttot <= stat.ttot) -- prev_stat = stat -- stats = stats.sort("schedcount", "desc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.sched_count >= stat.sched_count) -- prev_stat = stat -- stats = stats.sort("name", "desc") -- prev_stat = None -- for stat in stats: -- if prev_stat: -- self.assertTrue(prev_stat.name.lower() >= stat.name.lower()) -- prev_stat = stat -- self.assertRaises( -- yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg" -- ) -- self.assertRaises( -- yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg" -- ) -- -- def test_ctx_stats_cpu(self): -- -- def get_thread_name(): -- try: -- return threading.current_thread().name -- except AttributeError: -- return "Anonymous" -- -- def burn_cpu(sec): -- t0 = yappi.get_clock_time() -- elapsed = 0 -- while (elapsed < sec): -- for _ in range(1000): -- pass -- elapsed = yappi.get_clock_time() - t0 -- -- def test(): -- -- ts = [] -- for i in (0.01, 0.05, 0.1): -- t = threading.Thread(target=burn_cpu, args=(i, )) -- t.name = "burn_cpu-%s" % str(i) -- t.start() -- ts.append(t) -- for t in ts: -- t.join() -- -- yappi.set_clock_type("cpu") -- yappi.set_context_name_callback(get_thread_name) -- -- yappi.start() -- -- test() -- -- yappi.stop() -- -- tstats = yappi.get_thread_stats() -- r1 = ''' -- burn_cpu-0.1 3 123145356058624 0.100105 8 -- burn_cpu-0.05 2 123145361313792 0.050149 8 -- burn_cpu-0.01 1 123145356058624 0.010127 2 -- MainThread 0 4321620864 0.001632 6 -- ''' -- self.assert_ctx_stats_almost_equal(r1, tstats) -- -- def test_producer_consumer_with_queues(self): -- # we currently just stress yappi, no functionality test is done here. -- yappi.start() -- if utils.is_py3x(): -- from queue import Queue -- else: -- from Queue import Queue -- from threading import Thread -- WORKER_THREAD_COUNT = 50 -- WORK_ITEM_COUNT = 2000 -- -- def worker(): -- while True: -- item = q.get() -- # do the work with item -- q.task_done() -- -- q = Queue() -- for i in range(WORKER_THREAD_COUNT): -- t = Thread(target=worker) -- t.daemon = True -- t.start() -- -- for item in range(WORK_ITEM_COUNT): -- q.put(item) -- q.join() # block until all tasks are done -- #yappi.get_func_stats().sort("callcount").print_all() -- yappi.stop() -- -- def test_temporary_lock_waiting(self): -- yappi.start() -- _lock = threading.Lock() -- -- def worker(): -- _lock.acquire() -- try: -- time.sleep(1.0) -- finally: -- _lock.release() -- -- t1 = threading.Thread(target=worker) -- t2 = threading.Thread(target=worker) -- t1.start() -- t2.start() -- t1.join() -- t2.join() -- #yappi.get_func_stats().sort("callcount").print_all() -- yappi.stop() -- -- @unittest.skipIf(os.name != "posix", "requires Posix compliant OS") -- def test_signals_with_blocking_calls(self): -- import signal, os, time -- -- # just to verify if signal is handled correctly and stats/yappi are not corrupted. -- def handler(signum, frame): -- raise Exception("Signal handler executed!") -- -- yappi.start() -- signal.signal(signal.SIGALRM, handler) -- signal.alarm(1) -- self.assertRaises(Exception, time.sleep, 2) -- stats = yappi.get_func_stats() -- fsh = utils.find_stat_by_name(stats, "handler") -- self.assertTrue(fsh is not None) -- -- @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2") -- def test_concurrent_futures(self): -- yappi.start() -- from concurrent.futures import ThreadPoolExecutor -- with ThreadPoolExecutor(max_workers=5) as executor: -- f = executor.submit(pow, 5, 2) -- self.assertEqual(f.result(), 25) -- time.sleep(1.0) -- yappi.stop() -- -- @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2") -- def test_barrier(self): -- yappi.start() -- b = threading.Barrier(2, timeout=1) -- -- def worker(): -- try: -- b.wait() -- except threading.BrokenBarrierError: -- pass -- except Exception: -- raise Exception("BrokenBarrierError not raised") -- -- t1 = threading.Thread(target=worker) -- t1.start() -- #b.wait() -- t1.join() -- yappi.stop() -- -- --class NonRecursiveFunctions(utils.YappiUnitTestCase): -- -- def test_abcd(self): -- _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1} -- _yappi._set_test_timings(_timings) -- -- def a(): -- b() -- -- def b(): -- c() -- -- def c(): -- d() -- -- def d(): -- pass -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- fsd = utils.find_stat_by_name(stats, 'd') -- cfsab = fsa.children[fsb] -- cfsbc = fsb.children[fsc] -- cfscd = fsc.children[fsd] -- -- self.assertEqual(fsa.ttot, 6) -- self.assertEqual(fsa.tsub, 1) -- self.assertEqual(fsb.ttot, 5) -- self.assertEqual(fsb.tsub, 2) -- self.assertEqual(fsc.ttot, 3) -- self.assertEqual(fsc.tsub, 2) -- self.assertEqual(fsd.ttot, 1) -- self.assertEqual(fsd.tsub, 1) -- self.assertEqual(cfsab.ttot, 5) -- self.assertEqual(cfsab.tsub, 2) -- self.assertEqual(cfsbc.ttot, 3) -- self.assertEqual(cfsbc.tsub, 2) -- self.assertEqual(cfscd.ttot, 1) -- self.assertEqual(cfscd.tsub, 1) -- -- def test_stop_in_middle(self): -- _timings = {"a_1": 6, "b_1": 4} -- _yappi._set_test_timings(_timings) -- -- def a(): -- b() -- yappi.stop() -- -- def b(): -- time.sleep(0.2) -- -- yappi.start() -- a() -- stats = yappi.get_func_stats() -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- -- self.assertEqual(fsa.ncall, 1) -- self.assertEqual(fsa.nactualcall, 0) -- self.assertEqual(fsa.ttot, 0) # no call_leave called -- self.assertEqual(fsa.tsub, 0) # no call_leave called -- self.assertEqual(fsb.ttot, 4) -- -- --class RecursiveFunctions(utils.YappiUnitTestCase): -- -- def test_fibonacci(self): -- -- def fib(n): -- if n > 1: -- return fib(n - 1) + fib(n - 2) -- else: -- return n -- -- stats = utils.run_and_get_func_stats(fib, 22) -- fs = utils.find_stat_by_name(stats, 'fib') -- self.assertEqual(fs.ncall, 57313) -- self.assertEqual(fs.ttot, fs.tsub) -- -- def test_abcadc(self): -- _timings = { -- "a_1": 20, -- "b_1": 19, -- "c_1": 17, -- "a_2": 13, -- "d_1": 12, -- "c_2": 10, -- "a_3": 5 -- } -- _yappi._set_test_timings(_timings) -- -- def a(n): -- if n == 3: -- return -- if n == 1 + 1: -- d(n) -- else: -- b(n) -- -- def b(n): -- c(n) -- -- def c(n): -- a(n + 1) -- -- def d(n): -- c(n) -- -- stats = utils.run_and_get_func_stats(a, 1) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- fsd = utils.find_stat_by_name(stats, 'd') -- self.assertEqual(fsa.ncall, 3) -- self.assertEqual(fsa.nactualcall, 1) -- self.assertEqual(fsa.ttot, 20) -- self.assertEqual(fsa.tsub, 7) -- self.assertEqual(fsb.ttot, 19) -- self.assertEqual(fsb.tsub, 2) -- self.assertEqual(fsc.ttot, 17) -- self.assertEqual(fsc.tsub, 9) -- self.assertEqual(fsd.ttot, 12) -- self.assertEqual(fsd.tsub, 2) -- cfsca = fsc.children[fsa] -- self.assertEqual(cfsca.nactualcall, 0) -- self.assertEqual(cfsca.ncall, 2) -- self.assertEqual(cfsca.ttot, 13) -- self.assertEqual(cfsca.tsub, 6) -- -- def test_aaaa(self): -- _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2} -- _yappi._set_test_timings(_timings) -- -- def d(n): -- if n == 3: -- return -- d(n + 1) -- -- stats = utils.run_and_get_func_stats(d, 0) -- fsd = utils.find_stat_by_name(stats, 'd') -- self.assertEqual(fsd.ncall, 4) -- self.assertEqual(fsd.nactualcall, 1) -- self.assertEqual(fsd.ttot, 9) -- self.assertEqual(fsd.tsub, 9) -- cfsdd = fsd.children[fsd] -- self.assertEqual(cfsdd.ttot, 7) -- self.assertEqual(cfsdd.tsub, 7) -- self.assertEqual(cfsdd.ncall, 3) -- self.assertEqual(cfsdd.nactualcall, 0) -- -- def test_abcabc(self): -- _timings = { -- "a_1": 20, -- "b_1": 19, -- "c_1": 17, -- "a_2": 13, -- "b_2": 11, -- "c_2": 9, -- "a_3": 6 -- } -- _yappi._set_test_timings(_timings) -- -- def a(n): -- if n == 3: -- return -- else: -- b(n) -- -- def b(n): -- c(n) -- -- def c(n): -- a(n + 1) -- -- stats = utils.run_and_get_func_stats(a, 1) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- self.assertEqual(fsa.ncall, 3) -- self.assertEqual(fsa.nactualcall, 1) -- self.assertEqual(fsa.ttot, 20) -- self.assertEqual(fsa.tsub, 9) -- self.assertEqual(fsb.ttot, 19) -- self.assertEqual(fsb.tsub, 4) -- self.assertEqual(fsc.ttot, 17) -- self.assertEqual(fsc.tsub, 7) -- cfsab = fsa.children[fsb] -- cfsbc = fsb.children[fsc] -- cfsca = fsc.children[fsa] -- self.assertEqual(cfsab.ttot, 19) -- self.assertEqual(cfsab.tsub, 4) -- self.assertEqual(cfsbc.ttot, 17) -- self.assertEqual(cfsbc.tsub, 7) -- self.assertEqual(cfsca.ttot, 13) -- self.assertEqual(cfsca.tsub, 8) -- -- def test_abcbca(self): -- _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1} -- _yappi._set_test_timings(_timings) -- self._ncall = 1 -- -- def a(): -- if self._ncall == 1: -- b() -- else: -- return -- -- def b(): -- c() -- -- def c(): -- if self._ncall == 1: -- self._ncall += 1 -- b() -- else: -- a() -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- cfsab = fsa.children[fsb] -- cfsbc = fsb.children[fsc] -- cfsca = fsc.children[fsa] -- self.assertEqual(fsa.ttot, 10) -- self.assertEqual(fsa.tsub, 2) -- self.assertEqual(fsb.ttot, 9) -- self.assertEqual(fsb.tsub, 4) -- self.assertEqual(fsc.ttot, 7) -- self.assertEqual(fsc.tsub, 4) -- self.assertEqual(cfsab.ttot, 9) -- self.assertEqual(cfsab.tsub, 2) -- self.assertEqual(cfsbc.ttot, 7) -- self.assertEqual(cfsbc.tsub, 4) -- self.assertEqual(cfsca.ttot, 1) -- self.assertEqual(cfsca.tsub, 1) -- self.assertEqual(cfsca.ncall, 1) -- self.assertEqual(cfsca.nactualcall, 0) -- -- def test_aabccb(self): -- _timings = { -- "a_1": 13, -- "a_2": 11, -- "b_1": 9, -- "c_1": 5, -- "c_2": 3, -- "b_2": 1 -- } -- _yappi._set_test_timings(_timings) -- self._ncall = 1 -- -- def a(): -- if self._ncall == 1: -- self._ncall += 1 -- a() -- else: -- b() -- -- def b(): -- if self._ncall == 3: -- return -- else: -- c() -- -- def c(): -- if self._ncall == 2: -- self._ncall += 1 -- c() -- else: -- b() -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- fsc = utils.find_stat_by_name(stats, 'c') -- cfsaa = fsa.children[fsa.index] -- cfsab = fsa.children[fsb] -- cfsbc = fsb.children[fsc.full_name] -- cfscc = fsc.children[fsc] -- cfscb = fsc.children[fsb] -- self.assertEqual(fsb.ttot, 9) -- self.assertEqual(fsb.tsub, 5) -- self.assertEqual(cfsbc.ttot, 5) -- self.assertEqual(cfsbc.tsub, 2) -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 4) -- self.assertEqual(cfsab.ttot, 9) -- self.assertEqual(cfsab.tsub, 4) -- self.assertEqual(cfsaa.ttot, 11) -- self.assertEqual(cfsaa.tsub, 2) -- self.assertEqual(fsc.ttot, 5) -- self.assertEqual(fsc.tsub, 4) -- -- def test_abaa(self): -- _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- if self._ncall == 1: -- b() -- elif self._ncall == 2: -- self._ncall += 1 -- a() -- else: -- return -- -- def b(): -- self._ncall += 1 -- a() -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- cfsaa = fsa.children[fsa] -- cfsba = fsb.children[fsa] -- self.assertEqual(fsb.ttot, 10) -- self.assertEqual(fsb.tsub, 1) -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 12) -- self.assertEqual(cfsaa.ttot, 5) -- self.assertEqual(cfsaa.tsub, 5) -- self.assertEqual(cfsba.ttot, 9) -- self.assertEqual(cfsba.tsub, 4) -- -- def test_aabb(self): -- _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- if self._ncall == 1: -- self._ncall += 1 -- a() -- elif self._ncall == 2: -- b() -- else: -- return -- -- def b(): -- if self._ncall == 2: -- self._ncall += 1 -- b() -- else: -- return -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- cfsaa = fsa.children[fsa] -- cfsab = fsa.children[fsb] -- cfsbb = fsb.children[fsb] -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 4) -- self.assertEqual(fsb.ttot, 9) -- self.assertEqual(fsb.tsub, 9) -- self.assertEqual(cfsaa.ttot, 10) -- self.assertEqual(cfsaa.tsub, 1) -- self.assertEqual(cfsab.ttot, 9) -- self.assertEqual(cfsab.tsub, 4) -- self.assertEqual(cfsbb.ttot, 5) -- self.assertEqual(cfsbb.tsub, 5) -- -- def test_abbb(self): -- _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- if self._ncall == 1: -- b() -- -- def b(): -- if self._ncall == 3: -- return -- self._ncall += 1 -- b() -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- cfsab = fsa.children[fsb] -- cfsbb = fsb.children[fsb] -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 3) -- self.assertEqual(fsb.ttot, 10) -- self.assertEqual(fsb.tsub, 10) -- self.assertEqual(fsb.ncall, 3) -- self.assertEqual(fsb.nactualcall, 1) -- self.assertEqual(cfsab.ttot, 10) -- self.assertEqual(cfsab.tsub, 4) -- self.assertEqual(cfsbb.ttot, 6) -- self.assertEqual(cfsbb.tsub, 6) -- self.assertEqual(cfsbb.nactualcall, 0) -- self.assertEqual(cfsbb.ncall, 2) -- -- def test_aaab(self): -- _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- if self._ncall == 3: -- b() -- return -- self._ncall += 1 -- a() -- -- def b(): -- return -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- cfsaa = fsa.children[fsa] -- cfsab = fsa.children[fsb] -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 12) -- self.assertEqual(fsb.ttot, 1) -- self.assertEqual(fsb.tsub, 1) -- self.assertEqual(cfsaa.ttot, 10) -- self.assertEqual(cfsaa.tsub, 9) -- self.assertEqual(cfsab.ttot, 1) -- self.assertEqual(cfsab.tsub, 1) -- -- def test_abab(self): -- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} -- _yappi._set_test_timings(_timings) -- -- self._ncall = 1 -- -- def a(): -- b() -- -- def b(): -- if self._ncall == 2: -- return -- self._ncall += 1 -- a() -- -- stats = utils.run_and_get_func_stats(a) -- fsa = utils.find_stat_by_name(stats, 'a') -- fsb = utils.find_stat_by_name(stats, 'b') -- cfsab = fsa.children[fsb] -- cfsba = fsb.children[fsa] -- self.assertEqual(fsa.ttot, 13) -- self.assertEqual(fsa.tsub, 8) -- self.assertEqual(fsb.ttot, 10) -- self.assertEqual(fsb.tsub, 5) -- self.assertEqual(cfsab.ttot, 10) -- self.assertEqual(cfsab.tsub, 5) -- self.assertEqual(cfsab.ncall, 2) -- self.assertEqual(cfsab.nactualcall, 1) -- self.assertEqual(cfsba.ttot, 6) -- self.assertEqual(cfsba.tsub, 5) -- -- --if __name__ == '__main__': -- # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script'] -- # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile'] -- unittest.main() -+import os -+import sys -+import time -+import threading -+import unittest -+import yappi -+import _yappi -+import tests.utils as utils -+import multiprocessing # added to fix http://bugs.python.org/issue15881 for > Py2.6 -+import subprocess -+ -+_counter = 0 -+ -+ -+class BasicUsage(utils.YappiUnitTestCase): -+ -+ def test_callback_function_int_return_overflow(self): -+ # this test is just here to check if any errors are generated, as the err -+ # is printed in C side, I did not include it here. THere are ways to test -+ # this deterministically, I did not bother -+ import ctypes -+ -+ def _unsigned_overflow_margin(): -+ return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1 -+ -+ def foo(): -+ pass -+ -+ #with utils.captured_output() as (out, err): -+ yappi.set_context_id_callback(_unsigned_overflow_margin) -+ yappi.set_tag_callback(_unsigned_overflow_margin) -+ yappi.start() -+ foo() -+ -+ def test_issue60(self): -+ -+ def foo(): -+ buf = bytearray() -+ buf += b't' * 200 -+ view = memoryview(buf)[10:] -+ view = view.tobytes() -+ del buf[:10] # this throws exception -+ return view -+ -+ yappi.start(builtins=True) -+ foo() -+ self.assertTrue( -+ len( -+ yappi.get_func_stats( -+ filter_callback=lambda x: yappi. -+ func_matches(x, [memoryview.tobytes]) -+ ) -+ ) > 0 -+ ) -+ yappi.stop() -+ -+ def test_issue54(self): -+ -+ def _tag_cbk(): -+ global _counter -+ _counter += 1 -+ return _counter -+ -+ def a(): -+ pass -+ -+ def b(): -+ pass -+ -+ yappi.set_tag_callback(_tag_cbk) -+ yappi.start() -+ a() -+ a() -+ a() -+ yappi.stop() -+ stats = yappi.get_func_stats() -+ self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given -+ stats = yappi.get_func_stats(tag=1) -+ -+ for i in range(1, 3): -+ stats = yappi.get_func_stats(tag=i) -+ stats = yappi.get_func_stats( -+ tag=i, filter_callback=lambda x: yappi.func_matches(x, [a]) -+ ) -+ -+ stat = stats.pop() -+ self.assertEqual(stat.ncall, 1) -+ -+ yappi.set_tag_callback(None) -+ yappi.clear_stats() -+ yappi.start() -+ b() -+ b() -+ stats = yappi.get_func_stats() -+ self.assertEqual(len(stats), 1) -+ stat = stats.pop() -+ self.assertEqual(stat.ncall, 2) -+ -+ def test_filter(self): -+ -+ def a(): -+ pass -+ -+ def b(): -+ a() -+ -+ def c(): -+ b() -+ -+ _TCOUNT = 5 -+ -+ ts = [] -+ yappi.start() -+ for i in range(_TCOUNT): -+ t = threading.Thread(target=c) -+ t.start() -+ ts.append(t) -+ -+ for t in ts: -+ t.join() -+ -+ yappi.stop() -+ -+ ctx_ids = [] -+ for tstat in yappi.get_thread_stats(): -+ if tstat.name == '_MainThread': -+ main_ctx_id = tstat.id -+ else: -+ ctx_ids.append(tstat.id) -+ -+ fstats = yappi.get_func_stats(filter={"ctx_id": 9}) -+ self.assertTrue(fstats.empty()) -+ fstats = yappi.get_func_stats( -+ filter={ -+ "ctx_id": main_ctx_id, -+ "name": "c" -+ } -+ ) # main thread -+ self.assertTrue(fstats.empty()) -+ -+ for i in ctx_ids: -+ fstats = yappi.get_func_stats( -+ filter={ -+ "ctx_id": i, -+ "name": "a", -+ "ncall": 1 -+ } -+ ) -+ self.assertEqual(fstats.pop().ncall, 1) -+ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"}) -+ self.assertEqual(fstats.pop().ncall, 1) -+ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"}) -+ self.assertEqual(fstats.pop().ncall, 1) -+ -+ yappi.clear_stats() -+ yappi.start(builtins=True) -+ time.sleep(0.1) -+ yappi.stop() -+ fstats = yappi.get_func_stats(filter={"module": "time"}) -+ self.assertEqual(len(fstats), 1) -+ -+ # invalid filters` -+ self.assertRaises( -+ Exception, yappi.get_func_stats, filter={'tag': "sss"} -+ ) -+ self.assertRaises( -+ Exception, yappi.get_func_stats, filter={'ctx_id': "None"} -+ ) -+ -+ def test_filter_callback(self): -+ -+ def a(): -+ time.sleep(0.1) -+ -+ def b(): -+ a() -+ -+ def c(): -+ pass -+ -+ def d(): -+ pass -+ -+ yappi.set_clock_type("wall") -+ yappi.start(builtins=True) -+ a() -+ b() -+ c() -+ d() -+ stats = yappi.get_func_stats( -+ filter_callback=lambda x: yappi.func_matches(x, [a, b]) -+ ) -+ #stats.print_all() -+ r1 = ''' -+ tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175 -+ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197 -+ ''' -+ self.assert_traces_almost_equal(r1, stats) -+ self.assertEqual(len(stats), 2) -+ stats = yappi.get_func_stats( -+ filter_callback=lambda x: yappi. -+ module_matches(x, [sys.modules[__name__]]) -+ ) -+ r1 = ''' -+ tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065 -+ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011 -+ tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002 -+ tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001 -+ ''' -+ self.assert_traces_almost_equal(r1, stats) -+ self.assertEqual(len(stats), 4) -+ -+ stats = yappi.get_func_stats( -+ filter_callback=lambda x: yappi.func_matches(x, [time.sleep]) -+ ) -+ self.assertEqual(len(stats), 1) -+ r1 = ''' -+ time.sleep 2 0.206804 0.220000 0.103402 -+ ''' -+ self.assert_traces_almost_equal(r1, stats) -+ -+ def test_print_formatting(self): -+ -+ def a(): -+ pass -+ -+ def b(): -+ a() -+ -+ func_cols = { -+ 1: ("name", 48), -+ 0: ("ncall", 5), -+ 2: ("tsub", 8), -+ } -+ thread_cols = { -+ 1: ("name", 48), -+ 0: ("ttot", 8), -+ } -+ -+ yappi.start() -+ a() -+ b() -+ yappi.stop() -+ fs = yappi.get_func_stats() -+ cs = fs[1].children -+ ts = yappi.get_thread_stats() -+ #fs.print_all(out=sys.stderr, columns={1:("name", 70), }) -+ #cs.print_all(out=sys.stderr, columns=func_cols) -+ #ts.print_all(out=sys.stderr, columns=thread_cols) -+ #cs.print_all(out=sys.stderr, columns={}) -+ -+ self.assertRaises( -+ yappi.YappiError, fs.print_all, columns={1: ("namee", 9)} -+ ) -+ self.assertRaises( -+ yappi.YappiError, cs.print_all, columns={1: ("dd", 0)} -+ ) -+ self.assertRaises( -+ yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)} -+ ) -+ -+ def test_get_clock(self): -+ yappi.set_clock_type('cpu') -+ self.assertEqual('cpu', yappi.get_clock_type()) -+ clock_info = yappi.get_clock_info() -+ self.assertTrue('api' in clock_info) -+ self.assertTrue('resolution' in clock_info) -+ -+ yappi.set_clock_type('wall') -+ self.assertEqual('wall', yappi.get_clock_type()) -+ -+ t0 = yappi.get_clock_time() -+ time.sleep(0.1) -+ duration = yappi.get_clock_time() - t0 -+ self.assertTrue(0.05 < duration < 0.3) -+ -+ def test_profile_decorator(self): -+ -+ def aggregate(func, stats): -+ fname = "tests/%s.profile" % (func.__name__) -+ try: -+ stats.add(fname) -+ except IOError: -+ pass -+ stats.save(fname) -+ raise Exception("messing around") -+ -+ @yappi.profile(return_callback=aggregate) -+ def a(x, y): -+ if x + y == 25: -+ raise Exception("") -+ return x + y -+ -+ def b(): -+ pass -+ -+ try: -+ os.remove( -+ "tests/a.profile" -+ ) # remove the one from prev test, if available -+ except: -+ pass -+ -+ # global profile is on to mess things up -+ yappi.start() -+ b() -+ -+ # assert functionality and call function at same time -+ try: -+ self.assertEqual(a(1, 2), 3) -+ except: -+ pass -+ try: -+ self.assertEqual(a(2, 5), 7) -+ except: -+ pass -+ try: -+ a(4, 21) -+ except: -+ pass -+ stats = yappi.get_func_stats().add("tests/a.profile") -+ fsa = utils.find_stat_by_name(stats, 'a') -+ self.assertEqual(fsa.ncall, 3) -+ self.assertEqual(len(stats), 1) # b() should be cleared out. -+ -+ @yappi.profile(return_callback=aggregate) -+ def count_down_rec(n): -+ if n == 0: -+ return -+ count_down_rec(n - 1) -+ -+ try: -+ os.remove( -+ "tests/count_down_rec.profile" -+ ) # remove the one from prev test, if available -+ except: -+ pass -+ -+ try: -+ count_down_rec(4) -+ except: -+ pass -+ try: -+ count_down_rec(3) -+ except: -+ pass -+ -+ stats = yappi.YFuncStats("tests/count_down_rec.profile") -+ fsrec = utils.find_stat_by_name(stats, 'count_down_rec') -+ self.assertEqual(fsrec.ncall, 9) -+ self.assertEqual(fsrec.nactualcall, 2) -+ -+ def test_strip_dirs(self): -+ -+ def a(): -+ pass -+ -+ stats = utils.run_and_get_func_stats(a, ) -+ stats.strip_dirs() -+ fsa = utils.find_stat_by_name(stats, "a") -+ self.assertEqual(fsa.module, os.path.basename(fsa.module)) -+ -+ @unittest.skipIf(os.name == "nt", "do not run on Windows") -+ def test_run_as_script(self): -+ import re -+ p = subprocess.Popen( -+ ['yappi', os.path.join('./tests', 'run_as_script.py')], -+ stdout=subprocess.PIPE -+ ) -+ out, err = p.communicate() -+ self.assertEqual(p.returncode, 0) -+ func_stats, thread_stats = re.split( -+ b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out -+ ) -+ self.assertTrue(b'FancyThread' in thread_stats) -+ -+ def test_yappi_overhead(self): -+ LOOP_COUNT = 100000 -+ -+ def a(): -+ pass -+ -+ def b(): -+ for i in range(LOOP_COUNT): -+ a() -+ -+ t0 = time.time() -+ yappi.start() -+ b() -+ yappi.stop() -+ time_with_yappi = time.time() - t0 -+ t0 = time.time() -+ b() -+ time_without_yappi = time.time() - t0 -+ if time_without_yappi == 0: -+ time_without_yappi = 0.000001 -+ -+ # in latest v0.82, I calculated this as close to "7.0" in my machine. -+ # however, %83 of this overhead is coming from tickcount(). The other %17 -+ # seems to have been evenly distributed to the internal bookkeeping -+ # structures/algorithms which seems acceptable. Note that our test only -+ # tests one function being profiled at-a-time in a short interval. -+ # profiling high number of functions in a small time -+ # is a different beast, (which is pretty unlikely in most applications) -+ # So as a conclusion: I cannot see any optimization window for Yappi that -+ # is worth implementing as we will only optimize %17 of the time. -+ sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \ -+ (time_with_yappi / time_without_yappi)) -+ -+ def test_clear_stats_while_running(self): -+ -+ def a(): -+ pass -+ -+ yappi.start() -+ a() -+ yappi.clear_stats() -+ a() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ self.assertEqual(fsa.ncall, 1) -+ -+ def test_generator(self): -+ -+ def _gen(n): -+ while (n > 0): -+ yield n -+ n -= 1 -+ -+ yappi.start() -+ for x in _gen(5): -+ pass -+ self.assertTrue( -+ yappi.convert2pstats(yappi.get_func_stats()) is not None -+ ) -+ -+ def test_slice_child_stats_and_strip_dirs(self): -+ -+ def b(): -+ for i in range(10000000): -+ pass -+ -+ def a(): -+ b() -+ -+ yappi.start(builtins=True) -+ a() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ self.assertTrue(fsa.children[0:1] is not None) -+ prev_afullname = fsa.full_name -+ prev_bchildfullname = fsa.children[fsb].full_name -+ stats.strip_dirs() -+ self.assertTrue(len(prev_afullname) > len(fsa.full_name)) -+ self.assertTrue( -+ len(prev_bchildfullname) > len(fsa.children[fsb].full_name) -+ ) -+ -+ def test_children_stat_functions(self): -+ _timings = {"a_1": 5, "b_1": 3, "c_1": 1} -+ _yappi._set_test_timings(_timings) -+ -+ def b(): -+ pass -+ -+ def c(): -+ pass -+ -+ def a(): -+ b() -+ c() -+ -+ yappi.start() -+ a() -+ b() # non-child call -+ c() # non-child call -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ childs_of_a = fsa.children.get().sort("tavg", "desc") -+ prev_item = None -+ for item in childs_of_a: -+ if prev_item: -+ self.assertTrue(prev_item.tavg > item.tavg) -+ prev_item = item -+ childs_of_a.sort("name", "desc") -+ prev_item = None -+ for item in childs_of_a: -+ if prev_item: -+ self.assertTrue(prev_item.name > item.name) -+ prev_item = item -+ childs_of_a.clear() -+ self.assertTrue(childs_of_a.empty()) -+ -+ def test_no_stats_different_clock_type_load(self): -+ -+ def a(): -+ pass -+ -+ yappi.start() -+ a() -+ yappi.stop() -+ yappi.get_func_stats().save("tests/ystats1.ys") -+ yappi.clear_stats() -+ yappi.set_clock_type("WALL") -+ yappi.start() -+ yappi.stop() -+ stats = yappi.get_func_stats().add("tests/ystats1.ys") -+ fsa = utils.find_stat_by_name(stats, 'a') -+ self.assertTrue(fsa is not None) -+ -+ def test_subsequent_profile(self): -+ _timings = {"a_1": 1, "b_1": 1} -+ _yappi._set_test_timings(_timings) -+ -+ def a(): -+ pass -+ -+ def b(): -+ pass -+ -+ yappi.start() -+ a() -+ yappi.stop() -+ yappi.start() -+ b() -+ yappi.stop() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ self.assertTrue(fsa is not None) -+ self.assertTrue(fsb is not None) -+ self.assertEqual(fsa.ttot, 1) -+ self.assertEqual(fsb.ttot, 1) -+ -+ def test_lambda(self): -+ f = lambda: time.sleep(0.3) -+ yappi.set_clock_type("wall") -+ yappi.start() -+ f() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, '') -+ self.assertTrue(fsa.ttot > 0.1) -+ -+ def test_module_stress(self): -+ self.assertEqual(yappi.is_running(), False) -+ -+ yappi.start() -+ yappi.clear_stats() -+ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") -+ -+ yappi.stop() -+ yappi.clear_stats() -+ yappi.set_clock_type("cpu") -+ self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy") -+ self.assertEqual(yappi.is_running(), False) -+ yappi.clear_stats() -+ yappi.clear_stats() -+ -+ def test_stat_sorting(self): -+ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ b() -+ -+ def b(): -+ if self._ncall == 2: -+ return -+ self._ncall += 1 -+ a() -+ -+ stats = utils.run_and_get_func_stats(a) -+ stats = stats.sort("totaltime", "desc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.ttot >= stat.ttot) -+ prev_stat = stat -+ stats = stats.sort("totaltime", "asc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.ttot <= stat.ttot) -+ prev_stat = stat -+ stats = stats.sort("avgtime", "asc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.tavg <= stat.tavg) -+ prev_stat = stat -+ stats = stats.sort("name", "asc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.name <= stat.name) -+ prev_stat = stat -+ stats = stats.sort("subtime", "asc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.tsub <= stat.tsub) -+ prev_stat = stat -+ -+ self.assertRaises( -+ yappi.YappiError, stats.sort, "invalid_func_sorttype_arg" -+ ) -+ self.assertRaises( -+ yappi.YappiError, stats.sort, "totaltime", -+ "invalid_func_sortorder_arg" -+ ) -+ -+ def test_start_flags(self): -+ self.assertEqual(_yappi._get_start_flags(), None) -+ yappi.start() -+ -+ def a(): -+ pass -+ -+ a() -+ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) -+ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) -+ self.assertEqual(len(yappi.get_thread_stats()), 1) -+ -+ def test_builtin_profiling(self): -+ -+ def a(): -+ time.sleep(0.4) # is a builtin function -+ -+ yappi.set_clock_type('wall') -+ -+ yappi.start(builtins=True) -+ a() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'sleep') -+ self.assertTrue(fsa is not None) -+ self.assertTrue(fsa.ttot > 0.3) -+ yappi.stop() -+ yappi.clear_stats() -+ -+ def a(): -+ pass -+ -+ yappi.start() -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ stats = yappi.get_func_stats() -+ -+ def test_singlethread_profiling(self): -+ yappi.set_clock_type('wall') -+ -+ def a(): -+ time.sleep(0.2) -+ -+ class Worker1(threading.Thread): -+ -+ def a(self): -+ time.sleep(0.3) -+ -+ def run(self): -+ self.a() -+ -+ yappi.start(profile_threads=False) -+ -+ c = Worker1() -+ c.start() -+ c.join() -+ a() -+ stats = yappi.get_func_stats() -+ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') -+ fsa2 = utils.find_stat_by_name(stats, 'a') -+ self.assertTrue(fsa1 is None) -+ self.assertTrue(fsa2 is not None) -+ self.assertTrue(fsa2.ttot > 0.1) -+ -+ def test_run(self): -+ -+ def profiled(): -+ pass -+ -+ yappi.clear_stats() -+ try: -+ with yappi.run(): -+ profiled() -+ stats = yappi.get_func_stats() -+ finally: -+ yappi.clear_stats() -+ -+ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) -+ -+ def test_run_recursive(self): -+ -+ def profiled(): -+ pass -+ -+ def not_profiled(): -+ pass -+ -+ yappi.clear_stats() -+ try: -+ with yappi.run(): -+ with yappi.run(): -+ profiled() -+ # Profiling stopped here -+ not_profiled() -+ stats = yappi.get_func_stats() -+ finally: -+ yappi.clear_stats() -+ -+ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) -+ self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled')) -+ -+ -+class StatSaveScenarios(utils.YappiUnitTestCase): -+ -+ def test_pstats_conversion(self): -+ -+ def pstat_id(fs): -+ return (fs.module, fs.lineno, fs.name) -+ -+ def a(): -+ d() -+ -+ def b(): -+ d() -+ -+ def c(): -+ pass -+ -+ def d(): -+ pass -+ -+ _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2} -+ _yappi._set_test_timings(_timings) -+ stats = utils.run_and_get_func_stats(a, ) -+ stats.strip_dirs() -+ stats.save("tests/a1.pstats", type="pstat") -+ fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a")) -+ fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d")) -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ stats = utils.run_and_get_func_stats(a, ) -+ stats.strip_dirs() -+ stats.save("tests/a2.pstats", type="pstat") -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ stats = utils.run_and_get_func_stats(b, ) -+ stats.strip_dirs() -+ stats.save("tests/b1.pstats", type="pstat") -+ fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b")) -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ stats = utils.run_and_get_func_stats(c, ) -+ stats.strip_dirs() -+ stats.save("tests/c1.pstats", type="pstat") -+ fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c")) -+ -+ # merge saved stats and check pstats values are correct -+ import pstats -+ p = pstats.Stats( -+ 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats', -+ 'tests/c1.pstats' -+ ) -+ p.strip_dirs() -+ # ct = ttot, tt = tsub -+ (cc, nc, tt, ct, callers) = p.stats[fsa_pid] -+ self.assertEqual(cc, nc, 2) -+ self.assertEqual(tt, 20) -+ self.assertEqual(ct, 24) -+ (cc, nc, tt, ct, callers) = p.stats[fsd_pid] -+ self.assertEqual(cc, nc, 3) -+ self.assertEqual(tt, 6) -+ self.assertEqual(ct, 6) -+ self.assertEqual(len(callers), 2) -+ (cc, nc, tt, ct) = callers[fsa_pid] -+ self.assertEqual(cc, nc, 2) -+ self.assertEqual(tt, 4) -+ self.assertEqual(ct, 4) -+ (cc, nc, tt, ct) = callers[fsb_pid] -+ self.assertEqual(cc, nc, 1) -+ self.assertEqual(tt, 2) -+ self.assertEqual(ct, 2) -+ -+ def test_merge_stats(self): -+ _timings = { -+ "a_1": 15, -+ "b_1": 14, -+ "c_1": 12, -+ "d_1": 10, -+ "e_1": 9, -+ "f_1": 7, -+ "g_1": 6, -+ "h_1": 5, -+ "i_1": 1 -+ } -+ _yappi._set_test_timings(_timings) -+ -+ def a(): -+ b() -+ -+ def b(): -+ c() -+ -+ def c(): -+ d() -+ -+ def d(): -+ e() -+ -+ def e(): -+ f() -+ -+ def f(): -+ g() -+ -+ def g(): -+ h() -+ -+ def h(): -+ i() -+ -+ def i(): -+ pass -+ -+ yappi.start() -+ a() -+ a() -+ yappi.stop() -+ stats = yappi.get_func_stats() -+ self.assertRaises( -+ NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE" -+ ) -+ stats.save("tests/ystats2.ys") -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ yappi.start() -+ a() -+ stats = yappi.get_func_stats().add("tests/ystats2.ys") -+ fsa = utils.find_stat_by_name(stats, "a") -+ fsb = utils.find_stat_by_name(stats, "b") -+ fsc = utils.find_stat_by_name(stats, "c") -+ fsd = utils.find_stat_by_name(stats, "d") -+ fse = utils.find_stat_by_name(stats, "e") -+ fsf = utils.find_stat_by_name(stats, "f") -+ fsg = utils.find_stat_by_name(stats, "g") -+ fsh = utils.find_stat_by_name(stats, "h") -+ fsi = utils.find_stat_by_name(stats, "i") -+ self.assertEqual(fsa.ttot, 45) -+ self.assertEqual(fsa.ncall, 3) -+ self.assertEqual(fsa.nactualcall, 3) -+ self.assertEqual(fsa.tsub, 3) -+ self.assertEqual(fsa.children[fsb].ttot, fsb.ttot) -+ self.assertEqual(fsa.children[fsb].tsub, fsb.tsub) -+ self.assertEqual(fsb.children[fsc].ttot, fsc.ttot) -+ self.assertEqual(fsb.children[fsc].tsub, fsc.tsub) -+ self.assertEqual(fsc.tsub, 6) -+ self.assertEqual(fsc.children[fsd].ttot, fsd.ttot) -+ self.assertEqual(fsc.children[fsd].tsub, fsd.tsub) -+ self.assertEqual(fsd.children[fse].ttot, fse.ttot) -+ self.assertEqual(fsd.children[fse].tsub, fse.tsub) -+ self.assertEqual(fse.children[fsf].ttot, fsf.ttot) -+ self.assertEqual(fse.children[fsf].tsub, fsf.tsub) -+ self.assertEqual(fsf.children[fsg].ttot, fsg.ttot) -+ self.assertEqual(fsf.children[fsg].tsub, fsg.tsub) -+ self.assertEqual(fsg.ttot, 18) -+ self.assertEqual(fsg.tsub, 3) -+ self.assertEqual(fsg.children[fsh].ttot, fsh.ttot) -+ self.assertEqual(fsg.children[fsh].tsub, fsh.tsub) -+ self.assertEqual(fsh.ttot, 15) -+ self.assertEqual(fsh.tsub, 12) -+ self.assertEqual(fsh.tavg, 5) -+ self.assertEqual(fsh.children[fsi].ttot, fsi.ttot) -+ self.assertEqual(fsh.children[fsi].tsub, fsi.tsub) -+ #stats.debug_print() -+ -+ def test_merge_multithreaded_stats(self): -+ import _yappi -+ timings = {"a_1": 2, "b_1": 1} -+ _yappi._set_test_timings(timings) -+ -+ def a(): -+ pass -+ -+ def b(): -+ pass -+ -+ yappi.start() -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ t = threading.Thread(target=b) -+ t.start() -+ t.join() -+ yappi.get_func_stats().save("tests/ystats1.ys") -+ yappi.clear_stats() -+ _yappi._set_test_timings(timings) -+ self.assertEqual(len(yappi.get_func_stats()), 0) -+ self.assertEqual(len(yappi.get_thread_stats()), 1) -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ -+ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) -+ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) -+ yappi.get_func_stats().save("tests/ystats2.ys") -+ -+ stats = yappi.YFuncStats([ -+ "tests/ystats1.ys", -+ "tests/ystats2.ys", -+ ]) -+ fsa = utils.find_stat_by_name(stats, "a") -+ fsb = utils.find_stat_by_name(stats, "b") -+ self.assertEqual(fsa.ncall, 2) -+ self.assertEqual(fsb.ncall, 1) -+ self.assertEqual(fsa.tsub, fsa.ttot, 4) -+ self.assertEqual(fsb.tsub, fsb.ttot, 1) -+ -+ def test_merge_load_different_clock_types(self): -+ yappi.start(builtins=True) -+ -+ def a(): -+ b() -+ -+ def b(): -+ c() -+ -+ def c(): -+ pass -+ -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys") -+ yappi.stop() -+ yappi.clear_stats() -+ yappi.start(builtins=False) -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ yappi.get_func_stats().save("tests/ystats2.ys") -+ yappi.stop() -+ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") -+ yappi.clear_stats() -+ yappi.set_clock_type("wall") -+ yappi.start() -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ yappi.get_func_stats().save("tests/ystats3.ys") -+ self.assertRaises( -+ yappi.YappiError, -+ yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys" -+ ) -+ stats = yappi.YFuncStats(["tests/ystats1.ys", -+ "tests/ystats2.ys"]).sort("name") -+ fsa = utils.find_stat_by_name(stats, "a") -+ fsb = utils.find_stat_by_name(stats, "b") -+ fsc = utils.find_stat_by_name(stats, "c") -+ self.assertEqual(fsa.ncall, 2) -+ self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall) -+ -+ def test_merge_aabab_aabbc(self): -+ _timings = { -+ "a_1": 15, -+ "a_2": 14, -+ "b_1": 12, -+ "a_3": 10, -+ "b_2": 9, -+ "c_1": 4 -+ } -+ _yappi._set_test_timings(_timings) -+ -+ def a(): -+ if self._ncall == 1: -+ self._ncall += 1 -+ a() -+ elif self._ncall == 5: -+ self._ncall += 1 -+ a() -+ else: -+ b() -+ -+ def b(): -+ if self._ncall == 2: -+ self._ncall += 1 -+ a() -+ elif self._ncall == 6: -+ self._ncall += 1 -+ b() -+ elif self._ncall == 7: -+ c() -+ else: -+ return -+ -+ def c(): -+ pass -+ -+ self._ncall = 1 -+ stats = utils.run_and_get_func_stats(a, ) -+ stats.save("tests/ystats1.ys") -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ #stats.print_all() -+ -+ self._ncall = 5 -+ stats = utils.run_and_get_func_stats(a, ) -+ stats.save("tests/ystats2.ys") -+ -+ #stats.print_all() -+ -+ def a(): # same name but another function(code object) -+ pass -+ -+ yappi.start() -+ a() -+ stats = yappi.get_func_stats().add( -+ ["tests/ystats1.ys", "tests/ystats2.ys"] -+ ) -+ #stats.print_all() -+ self.assertEqual(len(stats), 4) -+ -+ fsa = None -+ for stat in stats: -+ if stat.name == "a" and stat.ttot == 45: -+ fsa = stat -+ break -+ self.assertTrue(fsa is not None) -+ -+ self.assertEqual(fsa.ncall, 7) -+ self.assertEqual(fsa.nactualcall, 3) -+ self.assertEqual(fsa.ttot, 45) -+ self.assertEqual(fsa.tsub, 10) -+ fsb = utils.find_stat_by_name(stats, "b") -+ fsc = utils.find_stat_by_name(stats, "c") -+ self.assertEqual(fsb.ncall, 6) -+ self.assertEqual(fsb.nactualcall, 3) -+ self.assertEqual(fsb.ttot, 36) -+ self.assertEqual(fsb.tsub, 27) -+ self.assertEqual(fsb.tavg, 6) -+ self.assertEqual(fsc.ttot, 8) -+ self.assertEqual(fsc.tsub, 8) -+ self.assertEqual(fsc.tavg, 4) -+ self.assertEqual(fsc.nactualcall, fsc.ncall, 2) -+ -+ -+class MultithreadedScenarios(utils.YappiUnitTestCase): -+ -+ def test_issue_32(self): -+ ''' -+ Start yappi from different thread and we get Internal Error(15) as -+ the current_ctx_id() called while enumerating the threads in start() -+ and as it does not swap to the enumerated ThreadState* the THreadState_GetDict() -+ returns wrong object and thus sets an invalid id for the _ctx structure. -+ -+ When this issue happens multiple Threads have same tid as the internal ts_ptr -+ will be same for different contexts. So, let's see if that happens -+ ''' -+ -+ def foo(): -+ time.sleep(0.2) -+ -+ def bar(): -+ time.sleep(0.1) -+ -+ def thread_func(): -+ yappi.set_clock_type("wall") -+ yappi.start() -+ -+ bar() -+ -+ t = threading.Thread(target=thread_func) -+ t.start() -+ t.join() -+ -+ foo() -+ -+ yappi.stop() -+ -+ thread_ids = set() -+ for tstat in yappi.get_thread_stats(): -+ self.assertTrue(tstat.tid not in thread_ids) -+ thread_ids.add(tstat.tid) -+ -+ def test_subsequent_profile(self): -+ WORKER_COUNT = 5 -+ -+ def a(): -+ pass -+ -+ def b(): -+ pass -+ -+ def c(): -+ pass -+ -+ _timings = { -+ "a_1": 3, -+ "b_1": 2, -+ "c_1": 1, -+ } -+ -+ yappi.start() -+ -+ def g(): -+ pass -+ -+ g() -+ yappi.stop() -+ yappi.clear_stats() -+ _yappi._set_test_timings(_timings) -+ yappi.start() -+ -+ _dummy = [] -+ for i in range(WORKER_COUNT): -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ for i in range(WORKER_COUNT): -+ t = threading.Thread(target=b) -+ t.start() -+ _dummy.append(t) -+ t.join() -+ for i in range(WORKER_COUNT): -+ t = threading.Thread(target=a) -+ t.start() -+ t.join() -+ for i in range(WORKER_COUNT): -+ t = threading.Thread(target=c) -+ t.start() -+ t.join() -+ yappi.stop() -+ yappi.start() -+ -+ def f(): -+ pass -+ -+ f() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ self.assertEqual(fsa.ncall, 10) -+ self.assertEqual(fsb.ncall, 5) -+ self.assertEqual(fsc.ncall, 5) -+ self.assertEqual(fsa.ttot, fsa.tsub, 30) -+ self.assertEqual(fsb.ttot, fsb.tsub, 10) -+ self.assertEqual(fsc.ttot, fsc.tsub, 5) -+ -+ # MACOSx optimizes by only creating one worker thread -+ self.assertTrue(len(yappi.get_thread_stats()) >= 2) -+ -+ def test_basic(self): -+ yappi.set_clock_type('wall') -+ -+ def dummy(): -+ pass -+ -+ def a(): -+ time.sleep(0.2) -+ -+ class Worker1(threading.Thread): -+ -+ def a(self): -+ time.sleep(0.3) -+ -+ def run(self): -+ self.a() -+ -+ yappi.start(builtins=False, profile_threads=True) -+ -+ c = Worker1() -+ c.start() -+ c.join() -+ a() -+ stats = yappi.get_func_stats() -+ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') -+ fsa2 = utils.find_stat_by_name(stats, 'a') -+ self.assertTrue(fsa1 is not None) -+ self.assertTrue(fsa2 is not None) -+ self.assertTrue(fsa1.ttot > 0.2) -+ self.assertTrue(fsa2.ttot > 0.1) -+ tstats = yappi.get_thread_stats() -+ self.assertEqual(len(tstats), 2) -+ tsa = utils.find_stat_by_name(tstats, 'Worker1') -+ tsm = utils.find_stat_by_name(tstats, '_MainThread') -+ dummy() # call dummy to force ctx name to be retrieved again. -+ self.assertTrue(tsa is not None) -+ # TODO: I put dummy() to fix below, remove the comments after a while. -+ self.assertTrue( # FIX: I see this fails sometimes? -+ tsm is not None, -+ 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats)))) -+ -+ def test_ctx_stats(self): -+ from threading import Thread -+ DUMMY_WORKER_COUNT = 5 -+ yappi.start() -+ -+ class DummyThread(Thread): -+ pass -+ -+ def dummy(): -+ pass -+ -+ def dummy_worker(): -+ pass -+ -+ for i in range(DUMMY_WORKER_COUNT): -+ t = DummyThread(target=dummy_worker) -+ t.start() -+ t.join() -+ yappi.stop() -+ stats = yappi.get_thread_stats() -+ tsa = utils.find_stat_by_name(stats, "DummyThread") -+ self.assertTrue(tsa is not None) -+ yappi.clear_stats() -+ time.sleep(1.0) -+ _timings = { -+ "a_1": 6, -+ "b_1": 5, -+ "c_1": 3, -+ "d_1": 1, -+ "a_2": 4, -+ "b_2": 3, -+ "c_2": 2, -+ "d_2": 1 -+ } -+ _yappi._set_test_timings(_timings) -+ -+ class Thread1(Thread): -+ pass -+ -+ class Thread2(Thread): -+ pass -+ -+ def a(): -+ b() -+ -+ def b(): -+ c() -+ -+ def c(): -+ d() -+ -+ def d(): -+ time.sleep(0.6) -+ -+ yappi.set_clock_type("wall") -+ yappi.start() -+ t1 = Thread1(target=a) -+ t1.start() -+ t2 = Thread2(target=a) -+ t2.start() -+ t1.join() -+ t2.join() -+ stats = yappi.get_thread_stats() -+ -+ # the fist clear_stats clears the context table? -+ tsa = utils.find_stat_by_name(stats, "DummyThread") -+ self.assertTrue(tsa is None) -+ -+ tst1 = utils.find_stat_by_name(stats, "Thread1") -+ tst2 = utils.find_stat_by_name(stats, "Thread2") -+ tsmain = utils.find_stat_by_name(stats, "_MainThread") -+ dummy() # call dummy to force ctx name to be retrieved again. -+ self.assertTrue(len(stats) == 3) -+ self.assertTrue(tst1 is not None) -+ self.assertTrue(tst2 is not None) -+ # TODO: I put dummy() to fix below, remove the comments after a while. -+ self.assertTrue( # FIX: I see this fails sometimes -+ tsmain is not None, -+ 'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats)))) -+ self.assertTrue(1.0 > tst2.ttot >= 0.5) -+ self.assertTrue(1.0 > tst1.ttot >= 0.5) -+ -+ # test sorting of the ctx stats -+ stats = stats.sort("totaltime", "desc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.ttot >= stat.ttot) -+ prev_stat = stat -+ stats = stats.sort("totaltime", "asc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.ttot <= stat.ttot) -+ prev_stat = stat -+ stats = stats.sort("schedcount", "desc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.sched_count >= stat.sched_count) -+ prev_stat = stat -+ stats = stats.sort("name", "desc") -+ prev_stat = None -+ for stat in stats: -+ if prev_stat: -+ self.assertTrue(prev_stat.name.lower() >= stat.name.lower()) -+ prev_stat = stat -+ self.assertRaises( -+ yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg" -+ ) -+ self.assertRaises( -+ yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg" -+ ) -+ -+ def test_ctx_stats_cpu(self): -+ -+ def get_thread_name(): -+ try: -+ return threading.current_thread().name -+ except AttributeError: -+ return "Anonymous" -+ -+ def burn_cpu(sec): -+ t0 = yappi.get_clock_time() -+ elapsed = 0 -+ while (elapsed < sec): -+ for _ in range(1000): -+ pass -+ elapsed = yappi.get_clock_time() - t0 -+ -+ def test(): -+ -+ ts = [] -+ for i in (0.01, 0.05, 0.1): -+ t = threading.Thread(target=burn_cpu, args=(i, )) -+ t.name = "burn_cpu-%s" % str(i) -+ t.start() -+ ts.append(t) -+ for t in ts: -+ t.join() -+ -+ yappi.set_clock_type("cpu") -+ yappi.set_context_name_callback(get_thread_name) -+ -+ yappi.start() -+ -+ test() -+ -+ yappi.stop() -+ -+ tstats = yappi.get_thread_stats() -+ r1 = ''' -+ burn_cpu-0.1 3 123145356058624 0.100105 8 -+ burn_cpu-0.05 2 123145361313792 0.050149 8 -+ burn_cpu-0.01 1 123145356058624 0.010127 2 -+ MainThread 0 4321620864 0.001632 6 -+ ''' -+ self.assert_ctx_stats_almost_equal(r1, tstats) -+ -+ def test_producer_consumer_with_queues(self): -+ # we currently just stress yappi, no functionality test is done here. -+ yappi.start() -+ if utils.is_py3x(): -+ from queue import Queue -+ else: -+ from Queue import Queue -+ from threading import Thread -+ WORKER_THREAD_COUNT = 50 -+ WORK_ITEM_COUNT = 2000 -+ -+ def worker(): -+ while True: -+ item = q.get() -+ # do the work with item -+ q.task_done() -+ -+ q = Queue() -+ for i in range(WORKER_THREAD_COUNT): -+ t = Thread(target=worker) -+ t.daemon = True -+ t.start() -+ -+ for item in range(WORK_ITEM_COUNT): -+ q.put(item) -+ q.join() # block until all tasks are done -+ #yappi.get_func_stats().sort("callcount").print_all() -+ yappi.stop() -+ -+ def test_temporary_lock_waiting(self): -+ yappi.start() -+ _lock = threading.Lock() -+ -+ def worker(): -+ _lock.acquire() -+ try: -+ time.sleep(1.0) -+ finally: -+ _lock.release() -+ -+ t1 = threading.Thread(target=worker) -+ t2 = threading.Thread(target=worker) -+ t1.start() -+ t2.start() -+ t1.join() -+ t2.join() -+ #yappi.get_func_stats().sort("callcount").print_all() -+ yappi.stop() -+ -+ @unittest.skipIf(os.name != "posix", "requires Posix compliant OS") -+ def test_signals_with_blocking_calls(self): -+ import signal, os, time -+ -+ # just to verify if signal is handled correctly and stats/yappi are not corrupted. -+ def handler(signum, frame): -+ raise Exception("Signal handler executed!") -+ -+ yappi.start() -+ signal.signal(signal.SIGALRM, handler) -+ signal.alarm(1) -+ self.assertRaises(Exception, time.sleep, 2) -+ stats = yappi.get_func_stats() -+ fsh = utils.find_stat_by_name(stats, "handler") -+ self.assertTrue(fsh is not None) -+ -+ @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2") -+ def test_concurrent_futures(self): -+ yappi.start() -+ from concurrent.futures import ThreadPoolExecutor -+ with ThreadPoolExecutor(max_workers=5) as executor: -+ f = executor.submit(pow, 5, 2) -+ self.assertEqual(f.result(), 25) -+ time.sleep(1.0) -+ yappi.stop() -+ -+ @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2") -+ def test_barrier(self): -+ yappi.start() -+ b = threading.Barrier(2, timeout=1) -+ -+ def worker(): -+ try: -+ b.wait() -+ except threading.BrokenBarrierError: -+ pass -+ except Exception: -+ raise Exception("BrokenBarrierError not raised") -+ -+ t1 = threading.Thread(target=worker) -+ t1.start() -+ #b.wait() -+ t1.join() -+ yappi.stop() -+ -+ -+class NonRecursiveFunctions(utils.YappiUnitTestCase): -+ -+ def test_abcd(self): -+ _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1} -+ _yappi._set_test_timings(_timings) -+ -+ def a(): -+ b() -+ -+ def b(): -+ c() -+ -+ def c(): -+ d() -+ -+ def d(): -+ pass -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ fsd = utils.find_stat_by_name(stats, 'd') -+ cfsab = fsa.children[fsb] -+ cfsbc = fsb.children[fsc] -+ cfscd = fsc.children[fsd] -+ -+ self.assertEqual(fsa.ttot, 6) -+ self.assertEqual(fsa.tsub, 1) -+ self.assertEqual(fsb.ttot, 5) -+ self.assertEqual(fsb.tsub, 2) -+ self.assertEqual(fsc.ttot, 3) -+ self.assertEqual(fsc.tsub, 2) -+ self.assertEqual(fsd.ttot, 1) -+ self.assertEqual(fsd.tsub, 1) -+ self.assertEqual(cfsab.ttot, 5) -+ self.assertEqual(cfsab.tsub, 2) -+ self.assertEqual(cfsbc.ttot, 3) -+ self.assertEqual(cfsbc.tsub, 2) -+ self.assertEqual(cfscd.ttot, 1) -+ self.assertEqual(cfscd.tsub, 1) -+ -+ def test_stop_in_middle(self): -+ _timings = {"a_1": 6, "b_1": 4} -+ _yappi._set_test_timings(_timings) -+ -+ def a(): -+ b() -+ yappi.stop() -+ -+ def b(): -+ time.sleep(0.2) -+ -+ yappi.start() -+ a() -+ stats = yappi.get_func_stats() -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ -+ self.assertEqual(fsa.ncall, 1) -+ self.assertEqual(fsa.nactualcall, 0) -+ self.assertEqual(fsa.ttot, 0) # no call_leave called -+ self.assertEqual(fsa.tsub, 0) # no call_leave called -+ self.assertEqual(fsb.ttot, 4) -+ -+ -+class RecursiveFunctions(utils.YappiUnitTestCase): -+ -+ def test_fibonacci(self): -+ -+ def fib(n): -+ if n > 1: -+ return fib(n - 1) + fib(n - 2) -+ else: -+ return n -+ -+ stats = utils.run_and_get_func_stats(fib, 22) -+ fs = utils.find_stat_by_name(stats, 'fib') -+ self.assertEqual(fs.ncall, 57313) -+ self.assertEqual(fs.ttot, fs.tsub) -+ -+ def test_abcadc(self): -+ _timings = { -+ "a_1": 20, -+ "b_1": 19, -+ "c_1": 17, -+ "a_2": 13, -+ "d_1": 12, -+ "c_2": 10, -+ "a_3": 5 -+ } -+ _yappi._set_test_timings(_timings) -+ -+ def a(n): -+ if n == 3: -+ return -+ if n == 1 + 1: -+ d(n) -+ else: -+ b(n) -+ -+ def b(n): -+ c(n) -+ -+ def c(n): -+ a(n + 1) -+ -+ def d(n): -+ c(n) -+ -+ stats = utils.run_and_get_func_stats(a, 1) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ fsd = utils.find_stat_by_name(stats, 'd') -+ self.assertEqual(fsa.ncall, 3) -+ self.assertEqual(fsa.nactualcall, 1) -+ self.assertEqual(fsa.ttot, 20) -+ self.assertEqual(fsa.tsub, 7) -+ self.assertEqual(fsb.ttot, 19) -+ self.assertEqual(fsb.tsub, 2) -+ self.assertEqual(fsc.ttot, 17) -+ self.assertEqual(fsc.tsub, 9) -+ self.assertEqual(fsd.ttot, 12) -+ self.assertEqual(fsd.tsub, 2) -+ cfsca = fsc.children[fsa] -+ self.assertEqual(cfsca.nactualcall, 0) -+ self.assertEqual(cfsca.ncall, 2) -+ self.assertEqual(cfsca.ttot, 13) -+ self.assertEqual(cfsca.tsub, 6) -+ -+ def test_aaaa(self): -+ _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2} -+ _yappi._set_test_timings(_timings) -+ -+ def d(n): -+ if n == 3: -+ return -+ d(n + 1) -+ -+ stats = utils.run_and_get_func_stats(d, 0) -+ fsd = utils.find_stat_by_name(stats, 'd') -+ self.assertEqual(fsd.ncall, 4) -+ self.assertEqual(fsd.nactualcall, 1) -+ self.assertEqual(fsd.ttot, 9) -+ self.assertEqual(fsd.tsub, 9) -+ cfsdd = fsd.children[fsd] -+ self.assertEqual(cfsdd.ttot, 7) -+ self.assertEqual(cfsdd.tsub, 7) -+ self.assertEqual(cfsdd.ncall, 3) -+ self.assertEqual(cfsdd.nactualcall, 0) -+ -+ def test_abcabc(self): -+ _timings = { -+ "a_1": 20, -+ "b_1": 19, -+ "c_1": 17, -+ "a_2": 13, -+ "b_2": 11, -+ "c_2": 9, -+ "a_3": 6 -+ } -+ _yappi._set_test_timings(_timings) -+ -+ def a(n): -+ if n == 3: -+ return -+ else: -+ b(n) -+ -+ def b(n): -+ c(n) -+ -+ def c(n): -+ a(n + 1) -+ -+ stats = utils.run_and_get_func_stats(a, 1) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ self.assertEqual(fsa.ncall, 3) -+ self.assertEqual(fsa.nactualcall, 1) -+ self.assertEqual(fsa.ttot, 20) -+ self.assertEqual(fsa.tsub, 9) -+ self.assertEqual(fsb.ttot, 19) -+ self.assertEqual(fsb.tsub, 4) -+ self.assertEqual(fsc.ttot, 17) -+ self.assertEqual(fsc.tsub, 7) -+ cfsab = fsa.children[fsb] -+ cfsbc = fsb.children[fsc] -+ cfsca = fsc.children[fsa] -+ self.assertEqual(cfsab.ttot, 19) -+ self.assertEqual(cfsab.tsub, 4) -+ self.assertEqual(cfsbc.ttot, 17) -+ self.assertEqual(cfsbc.tsub, 7) -+ self.assertEqual(cfsca.ttot, 13) -+ self.assertEqual(cfsca.tsub, 8) -+ -+ def test_abcbca(self): -+ _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1} -+ _yappi._set_test_timings(_timings) -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 1: -+ b() -+ else: -+ return -+ -+ def b(): -+ c() -+ -+ def c(): -+ if self._ncall == 1: -+ self._ncall += 1 -+ b() -+ else: -+ a() -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ cfsab = fsa.children[fsb] -+ cfsbc = fsb.children[fsc] -+ cfsca = fsc.children[fsa] -+ self.assertEqual(fsa.ttot, 10) -+ self.assertEqual(fsa.tsub, 2) -+ self.assertEqual(fsb.ttot, 9) -+ self.assertEqual(fsb.tsub, 4) -+ self.assertEqual(fsc.ttot, 7) -+ self.assertEqual(fsc.tsub, 4) -+ self.assertEqual(cfsab.ttot, 9) -+ self.assertEqual(cfsab.tsub, 2) -+ self.assertEqual(cfsbc.ttot, 7) -+ self.assertEqual(cfsbc.tsub, 4) -+ self.assertEqual(cfsca.ttot, 1) -+ self.assertEqual(cfsca.tsub, 1) -+ self.assertEqual(cfsca.ncall, 1) -+ self.assertEqual(cfsca.nactualcall, 0) -+ -+ def test_aabccb(self): -+ _timings = { -+ "a_1": 13, -+ "a_2": 11, -+ "b_1": 9, -+ "c_1": 5, -+ "c_2": 3, -+ "b_2": 1 -+ } -+ _yappi._set_test_timings(_timings) -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 1: -+ self._ncall += 1 -+ a() -+ else: -+ b() -+ -+ def b(): -+ if self._ncall == 3: -+ return -+ else: -+ c() -+ -+ def c(): -+ if self._ncall == 2: -+ self._ncall += 1 -+ c() -+ else: -+ b() -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ fsc = utils.find_stat_by_name(stats, 'c') -+ cfsaa = fsa.children[fsa.index] -+ cfsab = fsa.children[fsb] -+ cfsbc = fsb.children[fsc.full_name] -+ cfscc = fsc.children[fsc] -+ cfscb = fsc.children[fsb] -+ self.assertEqual(fsb.ttot, 9) -+ self.assertEqual(fsb.tsub, 5) -+ self.assertEqual(cfsbc.ttot, 5) -+ self.assertEqual(cfsbc.tsub, 2) -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 4) -+ self.assertEqual(cfsab.ttot, 9) -+ self.assertEqual(cfsab.tsub, 4) -+ self.assertEqual(cfsaa.ttot, 11) -+ self.assertEqual(cfsaa.tsub, 2) -+ self.assertEqual(fsc.ttot, 5) -+ self.assertEqual(fsc.tsub, 4) -+ -+ def test_abaa(self): -+ _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 1: -+ b() -+ elif self._ncall == 2: -+ self._ncall += 1 -+ a() -+ else: -+ return -+ -+ def b(): -+ self._ncall += 1 -+ a() -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ cfsaa = fsa.children[fsa] -+ cfsba = fsb.children[fsa] -+ self.assertEqual(fsb.ttot, 10) -+ self.assertEqual(fsb.tsub, 1) -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 12) -+ self.assertEqual(cfsaa.ttot, 5) -+ self.assertEqual(cfsaa.tsub, 5) -+ self.assertEqual(cfsba.ttot, 9) -+ self.assertEqual(cfsba.tsub, 4) -+ -+ def test_aabb(self): -+ _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 1: -+ self._ncall += 1 -+ a() -+ elif self._ncall == 2: -+ b() -+ else: -+ return -+ -+ def b(): -+ if self._ncall == 2: -+ self._ncall += 1 -+ b() -+ else: -+ return -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ cfsaa = fsa.children[fsa] -+ cfsab = fsa.children[fsb] -+ cfsbb = fsb.children[fsb] -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 4) -+ self.assertEqual(fsb.ttot, 9) -+ self.assertEqual(fsb.tsub, 9) -+ self.assertEqual(cfsaa.ttot, 10) -+ self.assertEqual(cfsaa.tsub, 1) -+ self.assertEqual(cfsab.ttot, 9) -+ self.assertEqual(cfsab.tsub, 4) -+ self.assertEqual(cfsbb.ttot, 5) -+ self.assertEqual(cfsbb.tsub, 5) -+ -+ def test_abbb(self): -+ _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 1: -+ b() -+ -+ def b(): -+ if self._ncall == 3: -+ return -+ self._ncall += 1 -+ b() -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ cfsab = fsa.children[fsb] -+ cfsbb = fsb.children[fsb] -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 3) -+ self.assertEqual(fsb.ttot, 10) -+ self.assertEqual(fsb.tsub, 10) -+ self.assertEqual(fsb.ncall, 3) -+ self.assertEqual(fsb.nactualcall, 1) -+ self.assertEqual(cfsab.ttot, 10) -+ self.assertEqual(cfsab.tsub, 4) -+ self.assertEqual(cfsbb.ttot, 6) -+ self.assertEqual(cfsbb.tsub, 6) -+ self.assertEqual(cfsbb.nactualcall, 0) -+ self.assertEqual(cfsbb.ncall, 2) -+ -+ def test_aaab(self): -+ _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ if self._ncall == 3: -+ b() -+ return -+ self._ncall += 1 -+ a() -+ -+ def b(): -+ return -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ cfsaa = fsa.children[fsa] -+ cfsab = fsa.children[fsb] -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 12) -+ self.assertEqual(fsb.ttot, 1) -+ self.assertEqual(fsb.tsub, 1) -+ self.assertEqual(cfsaa.ttot, 10) -+ self.assertEqual(cfsaa.tsub, 9) -+ self.assertEqual(cfsab.ttot, 1) -+ self.assertEqual(cfsab.tsub, 1) -+ -+ def test_abab(self): -+ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} -+ _yappi._set_test_timings(_timings) -+ -+ self._ncall = 1 -+ -+ def a(): -+ b() -+ -+ def b(): -+ if self._ncall == 2: -+ return -+ self._ncall += 1 -+ a() -+ -+ stats = utils.run_and_get_func_stats(a) -+ fsa = utils.find_stat_by_name(stats, 'a') -+ fsb = utils.find_stat_by_name(stats, 'b') -+ cfsab = fsa.children[fsb] -+ cfsba = fsb.children[fsa] -+ self.assertEqual(fsa.ttot, 13) -+ self.assertEqual(fsa.tsub, 8) -+ self.assertEqual(fsb.ttot, 10) -+ self.assertEqual(fsb.tsub, 5) -+ self.assertEqual(cfsab.ttot, 10) -+ self.assertEqual(cfsab.tsub, 5) -+ self.assertEqual(cfsab.ncall, 2) -+ self.assertEqual(cfsab.nactualcall, 1) -+ self.assertEqual(cfsba.ttot, 6) -+ self.assertEqual(cfsba.tsub, 5) -+ -+ -+if __name__ == '__main__': -+ # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script'] -+ # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile'] -+ unittest.main() ---- a/tests/test_hooks.py -+++ b/tests/test_hooks.py -@@ -5,7 +5,7 @@ import unittest - import time - - import yappi --import utils -+import tests.utils as utils - - - def a(): ---- a/tests/test_tags.py -+++ b/tests/test_tags.py -@@ -2,7 +2,7 @@ import unittest - import yappi - import threading - import time --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io - - - class MultiThreadTests(YappiUnitTestCase): diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-test_functionality-convert-line-endings-to-Unix.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-test_functionality-convert-line-endings-to-Unix.patch new file mode 100644 index 0000000000..70d4607c29 --- /dev/null +++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0001-test_functionality-convert-line-endings-to-Unix.patch @@ -0,0 +1,3845 @@ +From 0136ca731cba8b056b3f2ff0e7df3953b94f1e87 Mon Sep 17 00:00:00 2001 +From: Tim Orling +Date: Sun, 24 Dec 2023 09:41:57 -0800 +Subject: [PATCH 1/2] test_functionality: convert line endings to Unix + +Convert the Windows line endings with dos2unix to be like the +other files in tests/* + +Upstream-Status: Submitted [https://github.com/sumerc/yappi/pull/164] + +Signed-off-by: Tim Orling +--- + tests/test_functionality.py | 3822 +++++++++++++++++------------------ + 1 file changed, 1911 insertions(+), 1911 deletions(-) + +diff --git a/tests/test_functionality.py b/tests/test_functionality.py +index 0e99c47..38bbe67 100644 +--- a/tests/test_functionality.py ++++ b/tests/test_functionality.py +@@ -1,1911 +1,1911 @@ +-import os +-import sys +-import time +-import threading +-import unittest +-import yappi +-import _yappi +-import utils +-import multiprocessing +-import subprocess +- +-_counter = 0 +- +- +-class BasicUsage(utils.YappiUnitTestCase): +- +- def test_callback_function_int_return_overflow(self): +- # this test is just here to check if any errors are generated, as the err +- # is printed in C side, I did not include it here. THere are ways to test +- # this deterministically, I did not bother +- import ctypes +- +- def _unsigned_overflow_margin(): +- return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1 +- +- def foo(): +- pass +- +- #with utils.captured_output() as (out, err): +- yappi.set_context_id_callback(_unsigned_overflow_margin) +- yappi.set_tag_callback(_unsigned_overflow_margin) +- yappi.start() +- foo() +- +- def test_issue60(self): +- +- def foo(): +- buf = bytearray() +- buf += b't' * 200 +- view = memoryview(buf)[10:] +- view = view.tobytes() +- del buf[:10] # this throws exception +- return view +- +- yappi.start(builtins=True) +- foo() +- self.assertTrue( +- len( +- yappi.get_func_stats( +- filter_callback=lambda x: yappi. +- func_matches(x, [memoryview.tobytes]) +- ) +- ) > 0 +- ) +- yappi.stop() +- +- def test_issue54(self): +- +- def _tag_cbk(): +- global _counter +- _counter += 1 +- return _counter +- +- def a(): +- pass +- +- def b(): +- pass +- +- yappi.set_tag_callback(_tag_cbk) +- yappi.start() +- a() +- a() +- a() +- yappi.stop() +- stats = yappi.get_func_stats() +- self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given +- stats = yappi.get_func_stats(tag=1) +- +- for i in range(1, 3): +- stats = yappi.get_func_stats(tag=i) +- stats = yappi.get_func_stats( +- tag=i, filter_callback=lambda x: yappi.func_matches(x, [a]) +- ) +- +- stat = stats.pop() +- self.assertEqual(stat.ncall, 1) +- +- yappi.set_tag_callback(None) +- yappi.clear_stats() +- yappi.start() +- b() +- b() +- stats = yappi.get_func_stats() +- self.assertEqual(len(stats), 1) +- stat = stats.pop() +- self.assertEqual(stat.ncall, 2) +- +- def test_filter(self): +- +- def a(): +- pass +- +- def b(): +- a() +- +- def c(): +- b() +- +- _TCOUNT = 5 +- +- ts = [] +- yappi.start() +- for i in range(_TCOUNT): +- t = threading.Thread(target=c) +- t.start() +- ts.append(t) +- +- for t in ts: +- t.join() +- +- yappi.stop() +- +- ctx_ids = [] +- for tstat in yappi.get_thread_stats(): +- if tstat.name == '_MainThread': +- main_ctx_id = tstat.id +- else: +- ctx_ids.append(tstat.id) +- +- fstats = yappi.get_func_stats(filter={"ctx_id": 9}) +- self.assertTrue(fstats.empty()) +- fstats = yappi.get_func_stats( +- filter={ +- "ctx_id": main_ctx_id, +- "name": "c" +- } +- ) # main thread +- self.assertTrue(fstats.empty()) +- +- for i in ctx_ids: +- fstats = yappi.get_func_stats( +- filter={ +- "ctx_id": i, +- "name": "a", +- "ncall": 1 +- } +- ) +- self.assertEqual(fstats.pop().ncall, 1) +- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"}) +- self.assertEqual(fstats.pop().ncall, 1) +- fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"}) +- self.assertEqual(fstats.pop().ncall, 1) +- +- yappi.clear_stats() +- yappi.start(builtins=True) +- time.sleep(0.1) +- yappi.stop() +- fstats = yappi.get_func_stats(filter={"module": "time"}) +- self.assertEqual(len(fstats), 1) +- +- # invalid filters` +- self.assertRaises( +- Exception, yappi.get_func_stats, filter={'tag': "sss"} +- ) +- self.assertRaises( +- Exception, yappi.get_func_stats, filter={'ctx_id': "None"} +- ) +- +- def test_filter_callback(self): +- +- def a(): +- time.sleep(0.1) +- +- def b(): +- a() +- +- def c(): +- pass +- +- def d(): +- pass +- +- yappi.set_clock_type("wall") +- yappi.start(builtins=True) +- a() +- b() +- c() +- d() +- stats = yappi.get_func_stats( +- filter_callback=lambda x: yappi.func_matches(x, [a, b]) +- ) +- #stats.print_all() +- r1 = ''' +- tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175 +- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197 +- ''' +- self.assert_traces_almost_equal(r1, stats) +- self.assertEqual(len(stats), 2) +- stats = yappi.get_func_stats( +- filter_callback=lambda x: yappi. +- module_matches(x, [sys.modules[__name__]]) +- ) +- r1 = ''' +- tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065 +- tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011 +- tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002 +- tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001 +- ''' +- self.assert_traces_almost_equal(r1, stats) +- self.assertEqual(len(stats), 4) +- +- stats = yappi.get_func_stats( +- filter_callback=lambda x: yappi.func_matches(x, [time.sleep]) +- ) +- self.assertEqual(len(stats), 1) +- r1 = ''' +- time.sleep 2 0.206804 0.220000 0.103402 +- ''' +- self.assert_traces_almost_equal(r1, stats) +- +- def test_print_formatting(self): +- +- def a(): +- pass +- +- def b(): +- a() +- +- func_cols = { +- 1: ("name", 48), +- 0: ("ncall", 5), +- 2: ("tsub", 8), +- } +- thread_cols = { +- 1: ("name", 48), +- 0: ("ttot", 8), +- } +- +- yappi.start() +- a() +- b() +- yappi.stop() +- fs = yappi.get_func_stats() +- cs = fs[1].children +- ts = yappi.get_thread_stats() +- #fs.print_all(out=sys.stderr, columns={1:("name", 70), }) +- #cs.print_all(out=sys.stderr, columns=func_cols) +- #ts.print_all(out=sys.stderr, columns=thread_cols) +- #cs.print_all(out=sys.stderr, columns={}) +- +- self.assertRaises( +- yappi.YappiError, fs.print_all, columns={1: ("namee", 9)} +- ) +- self.assertRaises( +- yappi.YappiError, cs.print_all, columns={1: ("dd", 0)} +- ) +- self.assertRaises( +- yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)} +- ) +- +- def test_get_clock(self): +- yappi.set_clock_type('cpu') +- self.assertEqual('cpu', yappi.get_clock_type()) +- clock_info = yappi.get_clock_info() +- self.assertTrue('api' in clock_info) +- self.assertTrue('resolution' in clock_info) +- +- yappi.set_clock_type('wall') +- self.assertEqual('wall', yappi.get_clock_type()) +- +- t0 = yappi.get_clock_time() +- time.sleep(0.1) +- duration = yappi.get_clock_time() - t0 +- self.assertTrue(0.05 < duration < 0.3) +- +- def test_profile_decorator(self): +- +- def aggregate(func, stats): +- fname = f"tests/{func.__name__}.profile" +- try: +- stats.add(fname) +- except OSError: +- pass +- stats.save(fname) +- raise Exception("messing around") +- +- @yappi.profile(return_callback=aggregate) +- def a(x, y): +- if x + y == 25: +- raise Exception("") +- return x + y +- +- def b(): +- pass +- +- try: +- os.remove( +- "tests/a.profile" +- ) # remove the one from prev test, if available +- except: +- pass +- +- # global profile is on to mess things up +- yappi.start() +- b() +- +- # assert functionality and call function at same time +- try: +- self.assertEqual(a(1, 2), 3) +- except: +- pass +- try: +- self.assertEqual(a(2, 5), 7) +- except: +- pass +- try: +- a(4, 21) +- except: +- pass +- stats = yappi.get_func_stats().add("tests/a.profile") +- fsa = utils.find_stat_by_name(stats, 'a') +- self.assertEqual(fsa.ncall, 3) +- self.assertEqual(len(stats), 1) # b() should be cleared out. +- +- @yappi.profile(return_callback=aggregate) +- def count_down_rec(n): +- if n == 0: +- return +- count_down_rec(n - 1) +- +- try: +- os.remove( +- "tests/count_down_rec.profile" +- ) # remove the one from prev test, if available +- except: +- pass +- +- try: +- count_down_rec(4) +- except: +- pass +- try: +- count_down_rec(3) +- except: +- pass +- +- stats = yappi.YFuncStats("tests/count_down_rec.profile") +- fsrec = utils.find_stat_by_name(stats, 'count_down_rec') +- self.assertEqual(fsrec.ncall, 9) +- self.assertEqual(fsrec.nactualcall, 2) +- +- def test_strip_dirs(self): +- +- def a(): +- pass +- +- stats = utils.run_and_get_func_stats(a, ) +- stats.strip_dirs() +- fsa = utils.find_stat_by_name(stats, "a") +- self.assertEqual(fsa.module, os.path.basename(fsa.module)) +- +- @unittest.skipIf(os.name == "nt", "do not run on Windows") +- def test_run_as_script(self): +- import re +- p = subprocess.Popen( +- ['yappi', os.path.join('./tests', 'run_as_script.py')], +- stdout=subprocess.PIPE +- ) +- out, err = p.communicate() +- self.assertEqual(p.returncode, 0) +- func_stats, thread_stats = re.split( +- b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out +- ) +- self.assertTrue(b'FancyThread' in thread_stats) +- +- def test_yappi_overhead(self): +- LOOP_COUNT = 100000 +- +- def a(): +- pass +- +- def b(): +- for i in range(LOOP_COUNT): +- a() +- +- t0 = time.time() +- yappi.start() +- b() +- yappi.stop() +- time_with_yappi = time.time() - t0 +- t0 = time.time() +- b() +- time_without_yappi = time.time() - t0 +- if time_without_yappi == 0: +- time_without_yappi = 0.000001 +- +- # in latest v0.82, I calculated this as close to "7.0" in my machine. +- # however, %83 of this overhead is coming from tickcount(). The other %17 +- # seems to have been evenly distributed to the internal bookkeeping +- # structures/algorithms which seems acceptable. Note that our test only +- # tests one function being profiled at-a-time in a short interval. +- # profiling high number of functions in a small time +- # is a different beast, (which is pretty unlikely in most applications) +- # So as a conclusion: I cannot see any optimization window for Yappi that +- # is worth implementing as we will only optimize %17 of the time. +- sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \ +- (time_with_yappi / time_without_yappi)) +- +- def test_clear_stats_while_running(self): +- +- def a(): +- pass +- +- yappi.start() +- a() +- yappi.clear_stats() +- a() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- self.assertEqual(fsa.ncall, 1) +- +- def test_generator(self): +- +- def _gen(n): +- while (n > 0): +- yield n +- n -= 1 +- +- yappi.start() +- for x in _gen(5): +- pass +- self.assertTrue( +- yappi.convert2pstats(yappi.get_func_stats()) is not None +- ) +- +- def test_slice_child_stats_and_strip_dirs(self): +- +- def b(): +- for i in range(10000000): +- pass +- +- def a(): +- b() +- +- yappi.start(builtins=True) +- a() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- self.assertTrue(fsa.children[0:1] is not None) +- prev_afullname = fsa.full_name +- prev_bchildfullname = fsa.children[fsb].full_name +- stats.strip_dirs() +- self.assertTrue(len(prev_afullname) > len(fsa.full_name)) +- self.assertTrue( +- len(prev_bchildfullname) > len(fsa.children[fsb].full_name) +- ) +- +- def test_children_stat_functions(self): +- _timings = {"a_1": 5, "b_1": 3, "c_1": 1} +- _yappi._set_test_timings(_timings) +- +- def b(): +- pass +- +- def c(): +- pass +- +- def a(): +- b() +- c() +- +- yappi.start() +- a() +- b() # non-child call +- c() # non-child call +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- childs_of_a = fsa.children.get().sort("tavg", "desc") +- prev_item = None +- for item in childs_of_a: +- if prev_item: +- self.assertTrue(prev_item.tavg > item.tavg) +- prev_item = item +- childs_of_a.sort("name", "desc") +- prev_item = None +- for item in childs_of_a: +- if prev_item: +- self.assertTrue(prev_item.name > item.name) +- prev_item = item +- childs_of_a.clear() +- self.assertTrue(childs_of_a.empty()) +- +- def test_no_stats_different_clock_type_load(self): +- +- def a(): +- pass +- +- yappi.start() +- a() +- yappi.stop() +- yappi.get_func_stats().save("tests/ystats1.ys") +- yappi.clear_stats() +- yappi.set_clock_type("WALL") +- yappi.start() +- yappi.stop() +- stats = yappi.get_func_stats().add("tests/ystats1.ys") +- fsa = utils.find_stat_by_name(stats, 'a') +- self.assertTrue(fsa is not None) +- +- def test_subsequent_profile(self): +- _timings = {"a_1": 1, "b_1": 1} +- _yappi._set_test_timings(_timings) +- +- def a(): +- pass +- +- def b(): +- pass +- +- yappi.start() +- a() +- yappi.stop() +- yappi.start() +- b() +- yappi.stop() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- self.assertTrue(fsa is not None) +- self.assertTrue(fsb is not None) +- self.assertEqual(fsa.ttot, 1) +- self.assertEqual(fsb.ttot, 1) +- +- def test_lambda(self): +- f = lambda: time.sleep(0.3) +- yappi.set_clock_type("wall") +- yappi.start() +- f() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, '') +- self.assertTrue(fsa.ttot > 0.1) +- +- def test_module_stress(self): +- self.assertEqual(yappi.is_running(), False) +- +- yappi.start() +- yappi.clear_stats() +- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") +- +- yappi.stop() +- yappi.clear_stats() +- yappi.set_clock_type("cpu") +- self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy") +- self.assertEqual(yappi.is_running(), False) +- yappi.clear_stats() +- yappi.clear_stats() +- +- def test_stat_sorting(self): +- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- b() +- +- def b(): +- if self._ncall == 2: +- return +- self._ncall += 1 +- a() +- +- stats = utils.run_and_get_func_stats(a) +- stats = stats.sort("totaltime", "desc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.ttot >= stat.ttot) +- prev_stat = stat +- stats = stats.sort("totaltime", "asc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.ttot <= stat.ttot) +- prev_stat = stat +- stats = stats.sort("avgtime", "asc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.tavg <= stat.tavg) +- prev_stat = stat +- stats = stats.sort("name", "asc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.name <= stat.name) +- prev_stat = stat +- stats = stats.sort("subtime", "asc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.tsub <= stat.tsub) +- prev_stat = stat +- +- self.assertRaises( +- yappi.YappiError, stats.sort, "invalid_func_sorttype_arg" +- ) +- self.assertRaises( +- yappi.YappiError, stats.sort, "totaltime", +- "invalid_func_sortorder_arg" +- ) +- +- def test_start_flags(self): +- self.assertEqual(_yappi._get_start_flags(), None) +- yappi.start() +- +- def a(): +- pass +- +- a() +- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) +- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) +- self.assertEqual(len(yappi.get_thread_stats()), 1) +- +- def test_builtin_profiling(self): +- +- def a(): +- time.sleep(0.4) # is a builtin function +- +- yappi.set_clock_type('wall') +- +- yappi.start(builtins=True) +- a() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'sleep') +- self.assertTrue(fsa is not None) +- self.assertTrue(fsa.ttot > 0.3) +- yappi.stop() +- yappi.clear_stats() +- +- def a(): +- pass +- +- yappi.start() +- t = threading.Thread(target=a) +- t.start() +- t.join() +- stats = yappi.get_func_stats() +- +- def test_singlethread_profiling(self): +- yappi.set_clock_type('wall') +- +- def a(): +- time.sleep(0.2) +- +- class Worker1(threading.Thread): +- +- def a(self): +- time.sleep(0.3) +- +- def run(self): +- self.a() +- +- yappi.start(profile_threads=False) +- +- c = Worker1() +- c.start() +- c.join() +- a() +- stats = yappi.get_func_stats() +- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') +- fsa2 = utils.find_stat_by_name(stats, 'a') +- self.assertTrue(fsa1 is None) +- self.assertTrue(fsa2 is not None) +- self.assertTrue(fsa2.ttot > 0.1) +- +- def test_run(self): +- +- def profiled(): +- pass +- +- yappi.clear_stats() +- try: +- with yappi.run(): +- profiled() +- stats = yappi.get_func_stats() +- finally: +- yappi.clear_stats() +- +- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) +- +- def test_run_recursive(self): +- +- def profiled(): +- pass +- +- def not_profiled(): +- pass +- +- yappi.clear_stats() +- try: +- with yappi.run(): +- with yappi.run(): +- profiled() +- # Profiling stopped here +- not_profiled() +- stats = yappi.get_func_stats() +- finally: +- yappi.clear_stats() +- +- self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) +- self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled')) +- +- +-class StatSaveScenarios(utils.YappiUnitTestCase): +- +- def test_pstats_conversion(self): +- +- def pstat_id(fs): +- return (fs.module, fs.lineno, fs.name) +- +- def a(): +- d() +- +- def b(): +- d() +- +- def c(): +- pass +- +- def d(): +- pass +- +- _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2} +- _yappi._set_test_timings(_timings) +- stats = utils.run_and_get_func_stats(a, ) +- stats.strip_dirs() +- stats.save("tests/a1.pstats", type="pstat") +- fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a")) +- fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d")) +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- stats = utils.run_and_get_func_stats(a, ) +- stats.strip_dirs() +- stats.save("tests/a2.pstats", type="pstat") +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- stats = utils.run_and_get_func_stats(b, ) +- stats.strip_dirs() +- stats.save("tests/b1.pstats", type="pstat") +- fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b")) +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- stats = utils.run_and_get_func_stats(c, ) +- stats.strip_dirs() +- stats.save("tests/c1.pstats", type="pstat") +- fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c")) +- +- # merge saved stats and check pstats values are correct +- import pstats +- p = pstats.Stats( +- 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats', +- 'tests/c1.pstats' +- ) +- p.strip_dirs() +- # ct = ttot, tt = tsub +- (cc, nc, tt, ct, callers) = p.stats[fsa_pid] +- self.assertEqual(cc, nc, 2) +- self.assertEqual(tt, 20) +- self.assertEqual(ct, 24) +- (cc, nc, tt, ct, callers) = p.stats[fsd_pid] +- self.assertEqual(cc, nc, 3) +- self.assertEqual(tt, 6) +- self.assertEqual(ct, 6) +- self.assertEqual(len(callers), 2) +- (cc, nc, tt, ct) = callers[fsa_pid] +- self.assertEqual(cc, nc, 2) +- self.assertEqual(tt, 4) +- self.assertEqual(ct, 4) +- (cc, nc, tt, ct) = callers[fsb_pid] +- self.assertEqual(cc, nc, 1) +- self.assertEqual(tt, 2) +- self.assertEqual(ct, 2) +- +- def test_merge_stats(self): +- _timings = { +- "a_1": 15, +- "b_1": 14, +- "c_1": 12, +- "d_1": 10, +- "e_1": 9, +- "f_1": 7, +- "g_1": 6, +- "h_1": 5, +- "i_1": 1 +- } +- _yappi._set_test_timings(_timings) +- +- def a(): +- b() +- +- def b(): +- c() +- +- def c(): +- d() +- +- def d(): +- e() +- +- def e(): +- f() +- +- def f(): +- g() +- +- def g(): +- h() +- +- def h(): +- i() +- +- def i(): +- pass +- +- yappi.start() +- a() +- a() +- yappi.stop() +- stats = yappi.get_func_stats() +- self.assertRaises( +- NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE" +- ) +- stats.save("tests/ystats2.ys") +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- yappi.start() +- a() +- stats = yappi.get_func_stats().add("tests/ystats2.ys") +- fsa = utils.find_stat_by_name(stats, "a") +- fsb = utils.find_stat_by_name(stats, "b") +- fsc = utils.find_stat_by_name(stats, "c") +- fsd = utils.find_stat_by_name(stats, "d") +- fse = utils.find_stat_by_name(stats, "e") +- fsf = utils.find_stat_by_name(stats, "f") +- fsg = utils.find_stat_by_name(stats, "g") +- fsh = utils.find_stat_by_name(stats, "h") +- fsi = utils.find_stat_by_name(stats, "i") +- self.assertEqual(fsa.ttot, 45) +- self.assertEqual(fsa.ncall, 3) +- self.assertEqual(fsa.nactualcall, 3) +- self.assertEqual(fsa.tsub, 3) +- self.assertEqual(fsa.children[fsb].ttot, fsb.ttot) +- self.assertEqual(fsa.children[fsb].tsub, fsb.tsub) +- self.assertEqual(fsb.children[fsc].ttot, fsc.ttot) +- self.assertEqual(fsb.children[fsc].tsub, fsc.tsub) +- self.assertEqual(fsc.tsub, 6) +- self.assertEqual(fsc.children[fsd].ttot, fsd.ttot) +- self.assertEqual(fsc.children[fsd].tsub, fsd.tsub) +- self.assertEqual(fsd.children[fse].ttot, fse.ttot) +- self.assertEqual(fsd.children[fse].tsub, fse.tsub) +- self.assertEqual(fse.children[fsf].ttot, fsf.ttot) +- self.assertEqual(fse.children[fsf].tsub, fsf.tsub) +- self.assertEqual(fsf.children[fsg].ttot, fsg.ttot) +- self.assertEqual(fsf.children[fsg].tsub, fsg.tsub) +- self.assertEqual(fsg.ttot, 18) +- self.assertEqual(fsg.tsub, 3) +- self.assertEqual(fsg.children[fsh].ttot, fsh.ttot) +- self.assertEqual(fsg.children[fsh].tsub, fsh.tsub) +- self.assertEqual(fsh.ttot, 15) +- self.assertEqual(fsh.tsub, 12) +- self.assertEqual(fsh.tavg, 5) +- self.assertEqual(fsh.children[fsi].ttot, fsi.ttot) +- self.assertEqual(fsh.children[fsi].tsub, fsi.tsub) +- #stats.debug_print() +- +- def test_merge_multithreaded_stats(self): +- import _yappi +- timings = {"a_1": 2, "b_1": 1} +- _yappi._set_test_timings(timings) +- +- def a(): +- pass +- +- def b(): +- pass +- +- yappi.start() +- t = threading.Thread(target=a) +- t.start() +- t.join() +- t = threading.Thread(target=b) +- t.start() +- t.join() +- yappi.get_func_stats().save("tests/ystats1.ys") +- yappi.clear_stats() +- _yappi._set_test_timings(timings) +- self.assertEqual(len(yappi.get_func_stats()), 0) +- self.assertEqual(len(yappi.get_thread_stats()), 1) +- t = threading.Thread(target=a) +- t.start() +- t.join() +- +- self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) +- self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) +- yappi.get_func_stats().save("tests/ystats2.ys") +- +- stats = yappi.YFuncStats([ +- "tests/ystats1.ys", +- "tests/ystats2.ys", +- ]) +- fsa = utils.find_stat_by_name(stats, "a") +- fsb = utils.find_stat_by_name(stats, "b") +- self.assertEqual(fsa.ncall, 2) +- self.assertEqual(fsb.ncall, 1) +- self.assertEqual(fsa.tsub, fsa.ttot, 4) +- self.assertEqual(fsb.tsub, fsb.ttot, 1) +- +- def test_merge_load_different_clock_types(self): +- yappi.start(builtins=True) +- +- def a(): +- b() +- +- def b(): +- c() +- +- def c(): +- pass +- +- t = threading.Thread(target=a) +- t.start() +- t.join() +- yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys") +- yappi.stop() +- yappi.clear_stats() +- yappi.start(builtins=False) +- t = threading.Thread(target=a) +- t.start() +- t.join() +- yappi.get_func_stats().save("tests/ystats2.ys") +- yappi.stop() +- self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") +- yappi.clear_stats() +- yappi.set_clock_type("wall") +- yappi.start() +- t = threading.Thread(target=a) +- t.start() +- t.join() +- yappi.get_func_stats().save("tests/ystats3.ys") +- self.assertRaises( +- yappi.YappiError, +- yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys" +- ) +- stats = yappi.YFuncStats(["tests/ystats1.ys", +- "tests/ystats2.ys"]).sort("name") +- fsa = utils.find_stat_by_name(stats, "a") +- fsb = utils.find_stat_by_name(stats, "b") +- fsc = utils.find_stat_by_name(stats, "c") +- self.assertEqual(fsa.ncall, 2) +- self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall) +- +- def test_merge_aabab_aabbc(self): +- _timings = { +- "a_1": 15, +- "a_2": 14, +- "b_1": 12, +- "a_3": 10, +- "b_2": 9, +- "c_1": 4 +- } +- _yappi._set_test_timings(_timings) +- +- def a(): +- if self._ncall == 1: +- self._ncall += 1 +- a() +- elif self._ncall == 5: +- self._ncall += 1 +- a() +- else: +- b() +- +- def b(): +- if self._ncall == 2: +- self._ncall += 1 +- a() +- elif self._ncall == 6: +- self._ncall += 1 +- b() +- elif self._ncall == 7: +- c() +- else: +- return +- +- def c(): +- pass +- +- self._ncall = 1 +- stats = utils.run_and_get_func_stats(a, ) +- stats.save("tests/ystats1.ys") +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- #stats.print_all() +- +- self._ncall = 5 +- stats = utils.run_and_get_func_stats(a, ) +- stats.save("tests/ystats2.ys") +- +- #stats.print_all() +- +- def a(): # same name but another function(code object) +- pass +- +- yappi.start() +- a() +- stats = yappi.get_func_stats().add( +- ["tests/ystats1.ys", "tests/ystats2.ys"] +- ) +- #stats.print_all() +- self.assertEqual(len(stats), 4) +- +- fsa = None +- for stat in stats: +- if stat.name == "a" and stat.ttot == 45: +- fsa = stat +- break +- self.assertTrue(fsa is not None) +- +- self.assertEqual(fsa.ncall, 7) +- self.assertEqual(fsa.nactualcall, 3) +- self.assertEqual(fsa.ttot, 45) +- self.assertEqual(fsa.tsub, 10) +- fsb = utils.find_stat_by_name(stats, "b") +- fsc = utils.find_stat_by_name(stats, "c") +- self.assertEqual(fsb.ncall, 6) +- self.assertEqual(fsb.nactualcall, 3) +- self.assertEqual(fsb.ttot, 36) +- self.assertEqual(fsb.tsub, 27) +- self.assertEqual(fsb.tavg, 6) +- self.assertEqual(fsc.ttot, 8) +- self.assertEqual(fsc.tsub, 8) +- self.assertEqual(fsc.tavg, 4) +- self.assertEqual(fsc.nactualcall, fsc.ncall, 2) +- +- +-class MultithreadedScenarios(utils.YappiUnitTestCase): +- +- def test_issue_32(self): +- ''' +- Start yappi from different thread and we get Internal Error(15) as +- the current_ctx_id() called while enumerating the threads in start() +- and as it does not swap to the enumerated ThreadState* the THreadState_GetDict() +- returns wrong object and thus sets an invalid id for the _ctx structure. +- +- When this issue happens multiple Threads have same tid as the internal ts_ptr +- will be same for different contexts. So, let's see if that happens +- ''' +- +- def foo(): +- time.sleep(0.2) +- +- def bar(): +- time.sleep(0.1) +- +- def thread_func(): +- yappi.set_clock_type("wall") +- yappi.start() +- +- bar() +- +- t = threading.Thread(target=thread_func) +- t.start() +- t.join() +- +- foo() +- +- yappi.stop() +- +- thread_ids = set() +- for tstat in yappi.get_thread_stats(): +- self.assertTrue(tstat.tid not in thread_ids) +- thread_ids.add(tstat.tid) +- +- def test_subsequent_profile(self): +- WORKER_COUNT = 5 +- +- def a(): +- pass +- +- def b(): +- pass +- +- def c(): +- pass +- +- _timings = { +- "a_1": 3, +- "b_1": 2, +- "c_1": 1, +- } +- +- yappi.start() +- +- def g(): +- pass +- +- g() +- yappi.stop() +- yappi.clear_stats() +- _yappi._set_test_timings(_timings) +- yappi.start() +- +- _dummy = [] +- for i in range(WORKER_COUNT): +- t = threading.Thread(target=a) +- t.start() +- t.join() +- for i in range(WORKER_COUNT): +- t = threading.Thread(target=b) +- t.start() +- _dummy.append(t) +- t.join() +- for i in range(WORKER_COUNT): +- t = threading.Thread(target=a) +- t.start() +- t.join() +- for i in range(WORKER_COUNT): +- t = threading.Thread(target=c) +- t.start() +- t.join() +- yappi.stop() +- yappi.start() +- +- def f(): +- pass +- +- f() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- self.assertEqual(fsa.ncall, 10) +- self.assertEqual(fsb.ncall, 5) +- self.assertEqual(fsc.ncall, 5) +- self.assertEqual(fsa.ttot, fsa.tsub, 30) +- self.assertEqual(fsb.ttot, fsb.tsub, 10) +- self.assertEqual(fsc.ttot, fsc.tsub, 5) +- +- # MACOSx optimizes by only creating one worker thread +- self.assertTrue(len(yappi.get_thread_stats()) >= 2) +- +- def test_basic(self): +- yappi.set_clock_type('wall') +- +- def dummy(): +- pass +- +- def a(): +- time.sleep(0.2) +- +- class Worker1(threading.Thread): +- +- def a(self): +- time.sleep(0.3) +- +- def run(self): +- self.a() +- +- yappi.start(builtins=False, profile_threads=True) +- +- c = Worker1() +- c.start() +- c.join() +- a() +- stats = yappi.get_func_stats() +- fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') +- fsa2 = utils.find_stat_by_name(stats, 'a') +- self.assertTrue(fsa1 is not None) +- self.assertTrue(fsa2 is not None) +- self.assertTrue(fsa1.ttot > 0.2) +- self.assertTrue(fsa2.ttot > 0.1) +- tstats = yappi.get_thread_stats() +- self.assertEqual(len(tstats), 2) +- tsa = utils.find_stat_by_name(tstats, 'Worker1') +- tsm = utils.find_stat_by_name(tstats, '_MainThread') +- dummy() # call dummy to force ctx name to be retrieved again. +- self.assertTrue(tsa is not None) +- # TODO: I put dummy() to fix below, remove the comments after a while. +- self.assertTrue( # FIX: I see this fails sometimes? +- tsm is not None, +- f"Could not find \"_MainThread\". Found: {', '.join(utils.get_stat_names(tstats))}") +- +- def test_ctx_stats(self): +- from threading import Thread +- DUMMY_WORKER_COUNT = 5 +- yappi.start() +- +- class DummyThread(Thread): +- pass +- +- def dummy(): +- pass +- +- def dummy_worker(): +- pass +- +- for i in range(DUMMY_WORKER_COUNT): +- t = DummyThread(target=dummy_worker) +- t.start() +- t.join() +- yappi.stop() +- stats = yappi.get_thread_stats() +- tsa = utils.find_stat_by_name(stats, "DummyThread") +- self.assertTrue(tsa is not None) +- yappi.clear_stats() +- time.sleep(1.0) +- _timings = { +- "a_1": 6, +- "b_1": 5, +- "c_1": 3, +- "d_1": 1, +- "a_2": 4, +- "b_2": 3, +- "c_2": 2, +- "d_2": 1 +- } +- _yappi._set_test_timings(_timings) +- +- class Thread1(Thread): +- pass +- +- class Thread2(Thread): +- pass +- +- def a(): +- b() +- +- def b(): +- c() +- +- def c(): +- d() +- +- def d(): +- time.sleep(0.6) +- +- yappi.set_clock_type("wall") +- yappi.start() +- t1 = Thread1(target=a) +- t1.start() +- t2 = Thread2(target=a) +- t2.start() +- t1.join() +- t2.join() +- stats = yappi.get_thread_stats() +- +- # the fist clear_stats clears the context table? +- tsa = utils.find_stat_by_name(stats, "DummyThread") +- self.assertTrue(tsa is None) +- +- tst1 = utils.find_stat_by_name(stats, "Thread1") +- tst2 = utils.find_stat_by_name(stats, "Thread2") +- tsmain = utils.find_stat_by_name(stats, "_MainThread") +- dummy() # call dummy to force ctx name to be retrieved again. +- self.assertTrue(len(stats) == 3) +- self.assertTrue(tst1 is not None) +- self.assertTrue(tst2 is not None) +- # TODO: I put dummy() to fix below, remove the comments after a while. +- self.assertTrue( # FIX: I see this fails sometimes +- tsmain is not None, +- f"Could not find \"_MainThread\". Found: {', '.join(utils.get_stat_names(stats))}") +- self.assertTrue(1.0 > tst2.ttot >= 0.5) +- self.assertTrue(1.0 > tst1.ttot >= 0.5) +- +- # test sorting of the ctx stats +- stats = stats.sort("totaltime", "desc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.ttot >= stat.ttot) +- prev_stat = stat +- stats = stats.sort("totaltime", "asc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.ttot <= stat.ttot) +- prev_stat = stat +- stats = stats.sort("schedcount", "desc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.sched_count >= stat.sched_count) +- prev_stat = stat +- stats = stats.sort("name", "desc") +- prev_stat = None +- for stat in stats: +- if prev_stat: +- self.assertTrue(prev_stat.name.lower() >= stat.name.lower()) +- prev_stat = stat +- self.assertRaises( +- yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg" +- ) +- self.assertRaises( +- yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg" +- ) +- +- def test_ctx_stats_cpu(self): +- +- def get_thread_name(): +- try: +- return threading.current_thread().name +- except AttributeError: +- return "Anonymous" +- +- def burn_cpu(sec): +- t0 = yappi.get_clock_time() +- elapsed = 0 +- while (elapsed < sec): +- for _ in range(1000): +- pass +- elapsed = yappi.get_clock_time() - t0 +- +- def test(): +- +- ts = [] +- for i in (0.01, 0.05, 0.1): +- t = threading.Thread(target=burn_cpu, args=(i, )) +- t.name = f"burn_cpu-{str(i)}" +- t.start() +- ts.append(t) +- for t in ts: +- t.join() +- +- yappi.set_clock_type("cpu") +- yappi.set_context_name_callback(get_thread_name) +- +- yappi.start() +- +- test() +- +- yappi.stop() +- +- tstats = yappi.get_thread_stats() +- r1 = ''' +- burn_cpu-0.1 3 123145356058624 0.100105 8 +- burn_cpu-0.05 2 123145361313792 0.050149 8 +- burn_cpu-0.01 1 123145356058624 0.010127 2 +- MainThread 0 4321620864 0.001632 6 +- ''' +- self.assert_ctx_stats_almost_equal(r1, tstats) +- +- def test_producer_consumer_with_queues(self): +- # we currently just stress yappi, no functionality test is done here. +- yappi.start() +- from queue import Queue +- from threading import Thread +- WORKER_THREAD_COUNT = 50 +- WORK_ITEM_COUNT = 2000 +- +- def worker(): +- while True: +- item = q.get() +- # do the work with item +- q.task_done() +- +- q = Queue() +- for i in range(WORKER_THREAD_COUNT): +- t = Thread(target=worker) +- t.daemon = True +- t.start() +- +- for item in range(WORK_ITEM_COUNT): +- q.put(item) +- q.join() # block until all tasks are done +- #yappi.get_func_stats().sort("callcount").print_all() +- yappi.stop() +- +- def test_temporary_lock_waiting(self): +- yappi.start() +- _lock = threading.Lock() +- +- def worker(): +- _lock.acquire() +- try: +- time.sleep(1.0) +- finally: +- _lock.release() +- +- t1 = threading.Thread(target=worker) +- t2 = threading.Thread(target=worker) +- t1.start() +- t2.start() +- t1.join() +- t2.join() +- #yappi.get_func_stats().sort("callcount").print_all() +- yappi.stop() +- +- @unittest.skipIf(os.name != "posix", "requires Posix compliant OS") +- def test_signals_with_blocking_calls(self): +- import signal, os, time +- +- # just to verify if signal is handled correctly and stats/yappi are not corrupted. +- def handler(signum, frame): +- raise Exception("Signal handler executed!") +- +- yappi.start() +- signal.signal(signal.SIGALRM, handler) +- signal.alarm(1) +- self.assertRaises(Exception, time.sleep, 2) +- stats = yappi.get_func_stats() +- fsh = utils.find_stat_by_name(stats, "handler") +- self.assertTrue(fsh is not None) +- +- def test_concurrent_futures(self): +- yappi.start() +- from concurrent.futures import ThreadPoolExecutor +- with ThreadPoolExecutor(max_workers=5) as executor: +- f = executor.submit(pow, 5, 2) +- self.assertEqual(f.result(), 25) +- time.sleep(1.0) +- yappi.stop() +- +- def test_barrier(self): +- yappi.start() +- b = threading.Barrier(2, timeout=1) +- +- def worker(): +- try: +- b.wait() +- except threading.BrokenBarrierError: +- pass +- except Exception: +- raise Exception("BrokenBarrierError not raised") +- +- t1 = threading.Thread(target=worker) +- t1.start() +- #b.wait() +- t1.join() +- yappi.stop() +- +- +-class NonRecursiveFunctions(utils.YappiUnitTestCase): +- +- def test_abcd(self): +- _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1} +- _yappi._set_test_timings(_timings) +- +- def a(): +- b() +- +- def b(): +- c() +- +- def c(): +- d() +- +- def d(): +- pass +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- fsd = utils.find_stat_by_name(stats, 'd') +- cfsab = fsa.children[fsb] +- cfsbc = fsb.children[fsc] +- cfscd = fsc.children[fsd] +- +- self.assertEqual(fsa.ttot, 6) +- self.assertEqual(fsa.tsub, 1) +- self.assertEqual(fsb.ttot, 5) +- self.assertEqual(fsb.tsub, 2) +- self.assertEqual(fsc.ttot, 3) +- self.assertEqual(fsc.tsub, 2) +- self.assertEqual(fsd.ttot, 1) +- self.assertEqual(fsd.tsub, 1) +- self.assertEqual(cfsab.ttot, 5) +- self.assertEqual(cfsab.tsub, 2) +- self.assertEqual(cfsbc.ttot, 3) +- self.assertEqual(cfsbc.tsub, 2) +- self.assertEqual(cfscd.ttot, 1) +- self.assertEqual(cfscd.tsub, 1) +- +- def test_stop_in_middle(self): +- _timings = {"a_1": 6, "b_1": 4} +- _yappi._set_test_timings(_timings) +- +- def a(): +- b() +- yappi.stop() +- +- def b(): +- time.sleep(0.2) +- +- yappi.start() +- a() +- stats = yappi.get_func_stats() +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- +- self.assertEqual(fsa.ncall, 1) +- self.assertEqual(fsa.nactualcall, 0) +- self.assertEqual(fsa.ttot, 0) # no call_leave called +- self.assertEqual(fsa.tsub, 0) # no call_leave called +- self.assertEqual(fsb.ttot, 4) +- +- +-class RecursiveFunctions(utils.YappiUnitTestCase): +- +- def test_fibonacci(self): +- +- def fib(n): +- if n > 1: +- return fib(n - 1) + fib(n - 2) +- else: +- return n +- +- stats = utils.run_and_get_func_stats(fib, 22) +- fs = utils.find_stat_by_name(stats, 'fib') +- self.assertEqual(fs.ncall, 57313) +- self.assertEqual(fs.ttot, fs.tsub) +- +- def test_abcadc(self): +- _timings = { +- "a_1": 20, +- "b_1": 19, +- "c_1": 17, +- "a_2": 13, +- "d_1": 12, +- "c_2": 10, +- "a_3": 5 +- } +- _yappi._set_test_timings(_timings) +- +- def a(n): +- if n == 3: +- return +- if n == 1 + 1: +- d(n) +- else: +- b(n) +- +- def b(n): +- c(n) +- +- def c(n): +- a(n + 1) +- +- def d(n): +- c(n) +- +- stats = utils.run_and_get_func_stats(a, 1) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- fsd = utils.find_stat_by_name(stats, 'd') +- self.assertEqual(fsa.ncall, 3) +- self.assertEqual(fsa.nactualcall, 1) +- self.assertEqual(fsa.ttot, 20) +- self.assertEqual(fsa.tsub, 7) +- self.assertEqual(fsb.ttot, 19) +- self.assertEqual(fsb.tsub, 2) +- self.assertEqual(fsc.ttot, 17) +- self.assertEqual(fsc.tsub, 9) +- self.assertEqual(fsd.ttot, 12) +- self.assertEqual(fsd.tsub, 2) +- cfsca = fsc.children[fsa] +- self.assertEqual(cfsca.nactualcall, 0) +- self.assertEqual(cfsca.ncall, 2) +- self.assertEqual(cfsca.ttot, 13) +- self.assertEqual(cfsca.tsub, 6) +- +- def test_aaaa(self): +- _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2} +- _yappi._set_test_timings(_timings) +- +- def d(n): +- if n == 3: +- return +- d(n + 1) +- +- stats = utils.run_and_get_func_stats(d, 0) +- fsd = utils.find_stat_by_name(stats, 'd') +- self.assertEqual(fsd.ncall, 4) +- self.assertEqual(fsd.nactualcall, 1) +- self.assertEqual(fsd.ttot, 9) +- self.assertEqual(fsd.tsub, 9) +- cfsdd = fsd.children[fsd] +- self.assertEqual(cfsdd.ttot, 7) +- self.assertEqual(cfsdd.tsub, 7) +- self.assertEqual(cfsdd.ncall, 3) +- self.assertEqual(cfsdd.nactualcall, 0) +- +- def test_abcabc(self): +- _timings = { +- "a_1": 20, +- "b_1": 19, +- "c_1": 17, +- "a_2": 13, +- "b_2": 11, +- "c_2": 9, +- "a_3": 6 +- } +- _yappi._set_test_timings(_timings) +- +- def a(n): +- if n == 3: +- return +- else: +- b(n) +- +- def b(n): +- c(n) +- +- def c(n): +- a(n + 1) +- +- stats = utils.run_and_get_func_stats(a, 1) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- self.assertEqual(fsa.ncall, 3) +- self.assertEqual(fsa.nactualcall, 1) +- self.assertEqual(fsa.ttot, 20) +- self.assertEqual(fsa.tsub, 9) +- self.assertEqual(fsb.ttot, 19) +- self.assertEqual(fsb.tsub, 4) +- self.assertEqual(fsc.ttot, 17) +- self.assertEqual(fsc.tsub, 7) +- cfsab = fsa.children[fsb] +- cfsbc = fsb.children[fsc] +- cfsca = fsc.children[fsa] +- self.assertEqual(cfsab.ttot, 19) +- self.assertEqual(cfsab.tsub, 4) +- self.assertEqual(cfsbc.ttot, 17) +- self.assertEqual(cfsbc.tsub, 7) +- self.assertEqual(cfsca.ttot, 13) +- self.assertEqual(cfsca.tsub, 8) +- +- def test_abcbca(self): +- _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1} +- _yappi._set_test_timings(_timings) +- self._ncall = 1 +- +- def a(): +- if self._ncall == 1: +- b() +- else: +- return +- +- def b(): +- c() +- +- def c(): +- if self._ncall == 1: +- self._ncall += 1 +- b() +- else: +- a() +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- cfsab = fsa.children[fsb] +- cfsbc = fsb.children[fsc] +- cfsca = fsc.children[fsa] +- self.assertEqual(fsa.ttot, 10) +- self.assertEqual(fsa.tsub, 2) +- self.assertEqual(fsb.ttot, 9) +- self.assertEqual(fsb.tsub, 4) +- self.assertEqual(fsc.ttot, 7) +- self.assertEqual(fsc.tsub, 4) +- self.assertEqual(cfsab.ttot, 9) +- self.assertEqual(cfsab.tsub, 2) +- self.assertEqual(cfsbc.ttot, 7) +- self.assertEqual(cfsbc.tsub, 4) +- self.assertEqual(cfsca.ttot, 1) +- self.assertEqual(cfsca.tsub, 1) +- self.assertEqual(cfsca.ncall, 1) +- self.assertEqual(cfsca.nactualcall, 0) +- +- def test_aabccb(self): +- _timings = { +- "a_1": 13, +- "a_2": 11, +- "b_1": 9, +- "c_1": 5, +- "c_2": 3, +- "b_2": 1 +- } +- _yappi._set_test_timings(_timings) +- self._ncall = 1 +- +- def a(): +- if self._ncall == 1: +- self._ncall += 1 +- a() +- else: +- b() +- +- def b(): +- if self._ncall == 3: +- return +- else: +- c() +- +- def c(): +- if self._ncall == 2: +- self._ncall += 1 +- c() +- else: +- b() +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- fsc = utils.find_stat_by_name(stats, 'c') +- cfsaa = fsa.children[fsa.index] +- cfsab = fsa.children[fsb] +- cfsbc = fsb.children[fsc.full_name] +- cfscc = fsc.children[fsc] +- cfscb = fsc.children[fsb] +- self.assertEqual(fsb.ttot, 9) +- self.assertEqual(fsb.tsub, 5) +- self.assertEqual(cfsbc.ttot, 5) +- self.assertEqual(cfsbc.tsub, 2) +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 4) +- self.assertEqual(cfsab.ttot, 9) +- self.assertEqual(cfsab.tsub, 4) +- self.assertEqual(cfsaa.ttot, 11) +- self.assertEqual(cfsaa.tsub, 2) +- self.assertEqual(fsc.ttot, 5) +- self.assertEqual(fsc.tsub, 4) +- +- def test_abaa(self): +- _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- if self._ncall == 1: +- b() +- elif self._ncall == 2: +- self._ncall += 1 +- a() +- else: +- return +- +- def b(): +- self._ncall += 1 +- a() +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- cfsaa = fsa.children[fsa] +- cfsba = fsb.children[fsa] +- self.assertEqual(fsb.ttot, 10) +- self.assertEqual(fsb.tsub, 1) +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 12) +- self.assertEqual(cfsaa.ttot, 5) +- self.assertEqual(cfsaa.tsub, 5) +- self.assertEqual(cfsba.ttot, 9) +- self.assertEqual(cfsba.tsub, 4) +- +- def test_aabb(self): +- _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- if self._ncall == 1: +- self._ncall += 1 +- a() +- elif self._ncall == 2: +- b() +- else: +- return +- +- def b(): +- if self._ncall == 2: +- self._ncall += 1 +- b() +- else: +- return +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- cfsaa = fsa.children[fsa] +- cfsab = fsa.children[fsb] +- cfsbb = fsb.children[fsb] +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 4) +- self.assertEqual(fsb.ttot, 9) +- self.assertEqual(fsb.tsub, 9) +- self.assertEqual(cfsaa.ttot, 10) +- self.assertEqual(cfsaa.tsub, 1) +- self.assertEqual(cfsab.ttot, 9) +- self.assertEqual(cfsab.tsub, 4) +- self.assertEqual(cfsbb.ttot, 5) +- self.assertEqual(cfsbb.tsub, 5) +- +- def test_abbb(self): +- _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- if self._ncall == 1: +- b() +- +- def b(): +- if self._ncall == 3: +- return +- self._ncall += 1 +- b() +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- cfsab = fsa.children[fsb] +- cfsbb = fsb.children[fsb] +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 3) +- self.assertEqual(fsb.ttot, 10) +- self.assertEqual(fsb.tsub, 10) +- self.assertEqual(fsb.ncall, 3) +- self.assertEqual(fsb.nactualcall, 1) +- self.assertEqual(cfsab.ttot, 10) +- self.assertEqual(cfsab.tsub, 4) +- self.assertEqual(cfsbb.ttot, 6) +- self.assertEqual(cfsbb.tsub, 6) +- self.assertEqual(cfsbb.nactualcall, 0) +- self.assertEqual(cfsbb.ncall, 2) +- +- def test_aaab(self): +- _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- if self._ncall == 3: +- b() +- return +- self._ncall += 1 +- a() +- +- def b(): +- return +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- cfsaa = fsa.children[fsa] +- cfsab = fsa.children[fsb] +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 12) +- self.assertEqual(fsb.ttot, 1) +- self.assertEqual(fsb.tsub, 1) +- self.assertEqual(cfsaa.ttot, 10) +- self.assertEqual(cfsaa.tsub, 9) +- self.assertEqual(cfsab.ttot, 1) +- self.assertEqual(cfsab.tsub, 1) +- +- def test_abab(self): +- _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} +- _yappi._set_test_timings(_timings) +- +- self._ncall = 1 +- +- def a(): +- b() +- +- def b(): +- if self._ncall == 2: +- return +- self._ncall += 1 +- a() +- +- stats = utils.run_and_get_func_stats(a) +- fsa = utils.find_stat_by_name(stats, 'a') +- fsb = utils.find_stat_by_name(stats, 'b') +- cfsab = fsa.children[fsb] +- cfsba = fsb.children[fsa] +- self.assertEqual(fsa.ttot, 13) +- self.assertEqual(fsa.tsub, 8) +- self.assertEqual(fsb.ttot, 10) +- self.assertEqual(fsb.tsub, 5) +- self.assertEqual(cfsab.ttot, 10) +- self.assertEqual(cfsab.tsub, 5) +- self.assertEqual(cfsab.ncall, 2) +- self.assertEqual(cfsab.nactualcall, 1) +- self.assertEqual(cfsba.ttot, 6) +- self.assertEqual(cfsba.tsub, 5) +- +- +-if __name__ == '__main__': +- # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script'] +- # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile'] +- unittest.main() ++import os ++import sys ++import time ++import threading ++import unittest ++import yappi ++import _yappi ++import utils ++import multiprocessing ++import subprocess ++ ++_counter = 0 ++ ++ ++class BasicUsage(utils.YappiUnitTestCase): ++ ++ def test_callback_function_int_return_overflow(self): ++ # this test is just here to check if any errors are generated, as the err ++ # is printed in C side, I did not include it here. THere are ways to test ++ # this deterministically, I did not bother ++ import ctypes ++ ++ def _unsigned_overflow_margin(): ++ return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1 ++ ++ def foo(): ++ pass ++ ++ #with utils.captured_output() as (out, err): ++ yappi.set_context_id_callback(_unsigned_overflow_margin) ++ yappi.set_tag_callback(_unsigned_overflow_margin) ++ yappi.start() ++ foo() ++ ++ def test_issue60(self): ++ ++ def foo(): ++ buf = bytearray() ++ buf += b't' * 200 ++ view = memoryview(buf)[10:] ++ view = view.tobytes() ++ del buf[:10] # this throws exception ++ return view ++ ++ yappi.start(builtins=True) ++ foo() ++ self.assertTrue( ++ len( ++ yappi.get_func_stats( ++ filter_callback=lambda x: yappi. ++ func_matches(x, [memoryview.tobytes]) ++ ) ++ ) > 0 ++ ) ++ yappi.stop() ++ ++ def test_issue54(self): ++ ++ def _tag_cbk(): ++ global _counter ++ _counter += 1 ++ return _counter ++ ++ def a(): ++ pass ++ ++ def b(): ++ pass ++ ++ yappi.set_tag_callback(_tag_cbk) ++ yappi.start() ++ a() ++ a() ++ a() ++ yappi.stop() ++ stats = yappi.get_func_stats() ++ self.assertEqual(stats.pop().ncall, 3) # aggregated if no tag is given ++ stats = yappi.get_func_stats(tag=1) ++ ++ for i in range(1, 3): ++ stats = yappi.get_func_stats(tag=i) ++ stats = yappi.get_func_stats( ++ tag=i, filter_callback=lambda x: yappi.func_matches(x, [a]) ++ ) ++ ++ stat = stats.pop() ++ self.assertEqual(stat.ncall, 1) ++ ++ yappi.set_tag_callback(None) ++ yappi.clear_stats() ++ yappi.start() ++ b() ++ b() ++ stats = yappi.get_func_stats() ++ self.assertEqual(len(stats), 1) ++ stat = stats.pop() ++ self.assertEqual(stat.ncall, 2) ++ ++ def test_filter(self): ++ ++ def a(): ++ pass ++ ++ def b(): ++ a() ++ ++ def c(): ++ b() ++ ++ _TCOUNT = 5 ++ ++ ts = [] ++ yappi.start() ++ for i in range(_TCOUNT): ++ t = threading.Thread(target=c) ++ t.start() ++ ts.append(t) ++ ++ for t in ts: ++ t.join() ++ ++ yappi.stop() ++ ++ ctx_ids = [] ++ for tstat in yappi.get_thread_stats(): ++ if tstat.name == '_MainThread': ++ main_ctx_id = tstat.id ++ else: ++ ctx_ids.append(tstat.id) ++ ++ fstats = yappi.get_func_stats(filter={"ctx_id": 9}) ++ self.assertTrue(fstats.empty()) ++ fstats = yappi.get_func_stats( ++ filter={ ++ "ctx_id": main_ctx_id, ++ "name": "c" ++ } ++ ) # main thread ++ self.assertTrue(fstats.empty()) ++ ++ for i in ctx_ids: ++ fstats = yappi.get_func_stats( ++ filter={ ++ "ctx_id": i, ++ "name": "a", ++ "ncall": 1 ++ } ++ ) ++ self.assertEqual(fstats.pop().ncall, 1) ++ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"}) ++ self.assertEqual(fstats.pop().ncall, 1) ++ fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"}) ++ self.assertEqual(fstats.pop().ncall, 1) ++ ++ yappi.clear_stats() ++ yappi.start(builtins=True) ++ time.sleep(0.1) ++ yappi.stop() ++ fstats = yappi.get_func_stats(filter={"module": "time"}) ++ self.assertEqual(len(fstats), 1) ++ ++ # invalid filters` ++ self.assertRaises( ++ Exception, yappi.get_func_stats, filter={'tag': "sss"} ++ ) ++ self.assertRaises( ++ Exception, yappi.get_func_stats, filter={'ctx_id': "None"} ++ ) ++ ++ def test_filter_callback(self): ++ ++ def a(): ++ time.sleep(0.1) ++ ++ def b(): ++ a() ++ ++ def c(): ++ pass ++ ++ def d(): ++ pass ++ ++ yappi.set_clock_type("wall") ++ yappi.start(builtins=True) ++ a() ++ b() ++ c() ++ d() ++ stats = yappi.get_func_stats( ++ filter_callback=lambda x: yappi.func_matches(x, [a, b]) ++ ) ++ #stats.print_all() ++ r1 = ''' ++ tests/test_functionality.py:98 a 2 0.000000 0.200350 0.100175 ++ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.100197 ++ ''' ++ self.assert_traces_almost_equal(r1, stats) ++ self.assertEqual(len(stats), 2) ++ stats = yappi.get_func_stats( ++ filter_callback=lambda x: yappi. ++ module_matches(x, [sys.modules[__name__]]) ++ ) ++ r1 = ''' ++ tests/test_functionality.py:98 a 2 0.000000 0.230130 0.115065 ++ tests/test_functionality.py:101 b 1 0.000000 0.120000 0.109011 ++ tests/test_functionality.py:104 c 1 0.000000 0.000002 0.000002 ++ tests/test_functionality.py:107 d 1 0.000000 0.000001 0.000001 ++ ''' ++ self.assert_traces_almost_equal(r1, stats) ++ self.assertEqual(len(stats), 4) ++ ++ stats = yappi.get_func_stats( ++ filter_callback=lambda x: yappi.func_matches(x, [time.sleep]) ++ ) ++ self.assertEqual(len(stats), 1) ++ r1 = ''' ++ time.sleep 2 0.206804 0.220000 0.103402 ++ ''' ++ self.assert_traces_almost_equal(r1, stats) ++ ++ def test_print_formatting(self): ++ ++ def a(): ++ pass ++ ++ def b(): ++ a() ++ ++ func_cols = { ++ 1: ("name", 48), ++ 0: ("ncall", 5), ++ 2: ("tsub", 8), ++ } ++ thread_cols = { ++ 1: ("name", 48), ++ 0: ("ttot", 8), ++ } ++ ++ yappi.start() ++ a() ++ b() ++ yappi.stop() ++ fs = yappi.get_func_stats() ++ cs = fs[1].children ++ ts = yappi.get_thread_stats() ++ #fs.print_all(out=sys.stderr, columns={1:("name", 70), }) ++ #cs.print_all(out=sys.stderr, columns=func_cols) ++ #ts.print_all(out=sys.stderr, columns=thread_cols) ++ #cs.print_all(out=sys.stderr, columns={}) ++ ++ self.assertRaises( ++ yappi.YappiError, fs.print_all, columns={1: ("namee", 9)} ++ ) ++ self.assertRaises( ++ yappi.YappiError, cs.print_all, columns={1: ("dd", 0)} ++ ) ++ self.assertRaises( ++ yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)} ++ ) ++ ++ def test_get_clock(self): ++ yappi.set_clock_type('cpu') ++ self.assertEqual('cpu', yappi.get_clock_type()) ++ clock_info = yappi.get_clock_info() ++ self.assertTrue('api' in clock_info) ++ self.assertTrue('resolution' in clock_info) ++ ++ yappi.set_clock_type('wall') ++ self.assertEqual('wall', yappi.get_clock_type()) ++ ++ t0 = yappi.get_clock_time() ++ time.sleep(0.1) ++ duration = yappi.get_clock_time() - t0 ++ self.assertTrue(0.05 < duration < 0.3) ++ ++ def test_profile_decorator(self): ++ ++ def aggregate(func, stats): ++ fname = f"tests/{func.__name__}.profile" ++ try: ++ stats.add(fname) ++ except OSError: ++ pass ++ stats.save(fname) ++ raise Exception("messing around") ++ ++ @yappi.profile(return_callback=aggregate) ++ def a(x, y): ++ if x + y == 25: ++ raise Exception("") ++ return x + y ++ ++ def b(): ++ pass ++ ++ try: ++ os.remove( ++ "tests/a.profile" ++ ) # remove the one from prev test, if available ++ except: ++ pass ++ ++ # global profile is on to mess things up ++ yappi.start() ++ b() ++ ++ # assert functionality and call function at same time ++ try: ++ self.assertEqual(a(1, 2), 3) ++ except: ++ pass ++ try: ++ self.assertEqual(a(2, 5), 7) ++ except: ++ pass ++ try: ++ a(4, 21) ++ except: ++ pass ++ stats = yappi.get_func_stats().add("tests/a.profile") ++ fsa = utils.find_stat_by_name(stats, 'a') ++ self.assertEqual(fsa.ncall, 3) ++ self.assertEqual(len(stats), 1) # b() should be cleared out. ++ ++ @yappi.profile(return_callback=aggregate) ++ def count_down_rec(n): ++ if n == 0: ++ return ++ count_down_rec(n - 1) ++ ++ try: ++ os.remove( ++ "tests/count_down_rec.profile" ++ ) # remove the one from prev test, if available ++ except: ++ pass ++ ++ try: ++ count_down_rec(4) ++ except: ++ pass ++ try: ++ count_down_rec(3) ++ except: ++ pass ++ ++ stats = yappi.YFuncStats("tests/count_down_rec.profile") ++ fsrec = utils.find_stat_by_name(stats, 'count_down_rec') ++ self.assertEqual(fsrec.ncall, 9) ++ self.assertEqual(fsrec.nactualcall, 2) ++ ++ def test_strip_dirs(self): ++ ++ def a(): ++ pass ++ ++ stats = utils.run_and_get_func_stats(a, ) ++ stats.strip_dirs() ++ fsa = utils.find_stat_by_name(stats, "a") ++ self.assertEqual(fsa.module, os.path.basename(fsa.module)) ++ ++ @unittest.skipIf(os.name == "nt", "do not run on Windows") ++ def test_run_as_script(self): ++ import re ++ p = subprocess.Popen( ++ ['yappi', os.path.join('./tests', 'run_as_script.py')], ++ stdout=subprocess.PIPE ++ ) ++ out, err = p.communicate() ++ self.assertEqual(p.returncode, 0) ++ func_stats, thread_stats = re.split( ++ b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out ++ ) ++ self.assertTrue(b'FancyThread' in thread_stats) ++ ++ def test_yappi_overhead(self): ++ LOOP_COUNT = 100000 ++ ++ def a(): ++ pass ++ ++ def b(): ++ for i in range(LOOP_COUNT): ++ a() ++ ++ t0 = time.time() ++ yappi.start() ++ b() ++ yappi.stop() ++ time_with_yappi = time.time() - t0 ++ t0 = time.time() ++ b() ++ time_without_yappi = time.time() - t0 ++ if time_without_yappi == 0: ++ time_without_yappi = 0.000001 ++ ++ # in latest v0.82, I calculated this as close to "7.0" in my machine. ++ # however, %83 of this overhead is coming from tickcount(). The other %17 ++ # seems to have been evenly distributed to the internal bookkeeping ++ # structures/algorithms which seems acceptable. Note that our test only ++ # tests one function being profiled at-a-time in a short interval. ++ # profiling high number of functions in a small time ++ # is a different beast, (which is pretty unlikely in most applications) ++ # So as a conclusion: I cannot see any optimization window for Yappi that ++ # is worth implementing as we will only optimize %17 of the time. ++ sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \ ++ (time_with_yappi / time_without_yappi)) ++ ++ def test_clear_stats_while_running(self): ++ ++ def a(): ++ pass ++ ++ yappi.start() ++ a() ++ yappi.clear_stats() ++ a() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ self.assertEqual(fsa.ncall, 1) ++ ++ def test_generator(self): ++ ++ def _gen(n): ++ while (n > 0): ++ yield n ++ n -= 1 ++ ++ yappi.start() ++ for x in _gen(5): ++ pass ++ self.assertTrue( ++ yappi.convert2pstats(yappi.get_func_stats()) is not None ++ ) ++ ++ def test_slice_child_stats_and_strip_dirs(self): ++ ++ def b(): ++ for i in range(10000000): ++ pass ++ ++ def a(): ++ b() ++ ++ yappi.start(builtins=True) ++ a() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ self.assertTrue(fsa.children[0:1] is not None) ++ prev_afullname = fsa.full_name ++ prev_bchildfullname = fsa.children[fsb].full_name ++ stats.strip_dirs() ++ self.assertTrue(len(prev_afullname) > len(fsa.full_name)) ++ self.assertTrue( ++ len(prev_bchildfullname) > len(fsa.children[fsb].full_name) ++ ) ++ ++ def test_children_stat_functions(self): ++ _timings = {"a_1": 5, "b_1": 3, "c_1": 1} ++ _yappi._set_test_timings(_timings) ++ ++ def b(): ++ pass ++ ++ def c(): ++ pass ++ ++ def a(): ++ b() ++ c() ++ ++ yappi.start() ++ a() ++ b() # non-child call ++ c() # non-child call ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ childs_of_a = fsa.children.get().sort("tavg", "desc") ++ prev_item = None ++ for item in childs_of_a: ++ if prev_item: ++ self.assertTrue(prev_item.tavg > item.tavg) ++ prev_item = item ++ childs_of_a.sort("name", "desc") ++ prev_item = None ++ for item in childs_of_a: ++ if prev_item: ++ self.assertTrue(prev_item.name > item.name) ++ prev_item = item ++ childs_of_a.clear() ++ self.assertTrue(childs_of_a.empty()) ++ ++ def test_no_stats_different_clock_type_load(self): ++ ++ def a(): ++ pass ++ ++ yappi.start() ++ a() ++ yappi.stop() ++ yappi.get_func_stats().save("tests/ystats1.ys") ++ yappi.clear_stats() ++ yappi.set_clock_type("WALL") ++ yappi.start() ++ yappi.stop() ++ stats = yappi.get_func_stats().add("tests/ystats1.ys") ++ fsa = utils.find_stat_by_name(stats, 'a') ++ self.assertTrue(fsa is not None) ++ ++ def test_subsequent_profile(self): ++ _timings = {"a_1": 1, "b_1": 1} ++ _yappi._set_test_timings(_timings) ++ ++ def a(): ++ pass ++ ++ def b(): ++ pass ++ ++ yappi.start() ++ a() ++ yappi.stop() ++ yappi.start() ++ b() ++ yappi.stop() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ self.assertTrue(fsa is not None) ++ self.assertTrue(fsb is not None) ++ self.assertEqual(fsa.ttot, 1) ++ self.assertEqual(fsb.ttot, 1) ++ ++ def test_lambda(self): ++ f = lambda: time.sleep(0.3) ++ yappi.set_clock_type("wall") ++ yappi.start() ++ f() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, '') ++ self.assertTrue(fsa.ttot > 0.1) ++ ++ def test_module_stress(self): ++ self.assertEqual(yappi.is_running(), False) ++ ++ yappi.start() ++ yappi.clear_stats() ++ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") ++ ++ yappi.stop() ++ yappi.clear_stats() ++ yappi.set_clock_type("cpu") ++ self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy") ++ self.assertEqual(yappi.is_running(), False) ++ yappi.clear_stats() ++ yappi.clear_stats() ++ ++ def test_stat_sorting(self): ++ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ b() ++ ++ def b(): ++ if self._ncall == 2: ++ return ++ self._ncall += 1 ++ a() ++ ++ stats = utils.run_and_get_func_stats(a) ++ stats = stats.sort("totaltime", "desc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.ttot >= stat.ttot) ++ prev_stat = stat ++ stats = stats.sort("totaltime", "asc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.ttot <= stat.ttot) ++ prev_stat = stat ++ stats = stats.sort("avgtime", "asc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.tavg <= stat.tavg) ++ prev_stat = stat ++ stats = stats.sort("name", "asc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.name <= stat.name) ++ prev_stat = stat ++ stats = stats.sort("subtime", "asc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.tsub <= stat.tsub) ++ prev_stat = stat ++ ++ self.assertRaises( ++ yappi.YappiError, stats.sort, "invalid_func_sorttype_arg" ++ ) ++ self.assertRaises( ++ yappi.YappiError, stats.sort, "totaltime", ++ "invalid_func_sortorder_arg" ++ ) ++ ++ def test_start_flags(self): ++ self.assertEqual(_yappi._get_start_flags(), None) ++ yappi.start() ++ ++ def a(): ++ pass ++ ++ a() ++ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) ++ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) ++ self.assertEqual(len(yappi.get_thread_stats()), 1) ++ ++ def test_builtin_profiling(self): ++ ++ def a(): ++ time.sleep(0.4) # is a builtin function ++ ++ yappi.set_clock_type('wall') ++ ++ yappi.start(builtins=True) ++ a() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'sleep') ++ self.assertTrue(fsa is not None) ++ self.assertTrue(fsa.ttot > 0.3) ++ yappi.stop() ++ yappi.clear_stats() ++ ++ def a(): ++ pass ++ ++ yappi.start() ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ stats = yappi.get_func_stats() ++ ++ def test_singlethread_profiling(self): ++ yappi.set_clock_type('wall') ++ ++ def a(): ++ time.sleep(0.2) ++ ++ class Worker1(threading.Thread): ++ ++ def a(self): ++ time.sleep(0.3) ++ ++ def run(self): ++ self.a() ++ ++ yappi.start(profile_threads=False) ++ ++ c = Worker1() ++ c.start() ++ c.join() ++ a() ++ stats = yappi.get_func_stats() ++ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') ++ fsa2 = utils.find_stat_by_name(stats, 'a') ++ self.assertTrue(fsa1 is None) ++ self.assertTrue(fsa2 is not None) ++ self.assertTrue(fsa2.ttot > 0.1) ++ ++ def test_run(self): ++ ++ def profiled(): ++ pass ++ ++ yappi.clear_stats() ++ try: ++ with yappi.run(): ++ profiled() ++ stats = yappi.get_func_stats() ++ finally: ++ yappi.clear_stats() ++ ++ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) ++ ++ def test_run_recursive(self): ++ ++ def profiled(): ++ pass ++ ++ def not_profiled(): ++ pass ++ ++ yappi.clear_stats() ++ try: ++ with yappi.run(): ++ with yappi.run(): ++ profiled() ++ # Profiling stopped here ++ not_profiled() ++ stats = yappi.get_func_stats() ++ finally: ++ yappi.clear_stats() ++ ++ self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled')) ++ self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled')) ++ ++ ++class StatSaveScenarios(utils.YappiUnitTestCase): ++ ++ def test_pstats_conversion(self): ++ ++ def pstat_id(fs): ++ return (fs.module, fs.lineno, fs.name) ++ ++ def a(): ++ d() ++ ++ def b(): ++ d() ++ ++ def c(): ++ pass ++ ++ def d(): ++ pass ++ ++ _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2} ++ _yappi._set_test_timings(_timings) ++ stats = utils.run_and_get_func_stats(a, ) ++ stats.strip_dirs() ++ stats.save("tests/a1.pstats", type="pstat") ++ fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a")) ++ fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d")) ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ stats = utils.run_and_get_func_stats(a, ) ++ stats.strip_dirs() ++ stats.save("tests/a2.pstats", type="pstat") ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ stats = utils.run_and_get_func_stats(b, ) ++ stats.strip_dirs() ++ stats.save("tests/b1.pstats", type="pstat") ++ fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b")) ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ stats = utils.run_and_get_func_stats(c, ) ++ stats.strip_dirs() ++ stats.save("tests/c1.pstats", type="pstat") ++ fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c")) ++ ++ # merge saved stats and check pstats values are correct ++ import pstats ++ p = pstats.Stats( ++ 'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats', ++ 'tests/c1.pstats' ++ ) ++ p.strip_dirs() ++ # ct = ttot, tt = tsub ++ (cc, nc, tt, ct, callers) = p.stats[fsa_pid] ++ self.assertEqual(cc, nc, 2) ++ self.assertEqual(tt, 20) ++ self.assertEqual(ct, 24) ++ (cc, nc, tt, ct, callers) = p.stats[fsd_pid] ++ self.assertEqual(cc, nc, 3) ++ self.assertEqual(tt, 6) ++ self.assertEqual(ct, 6) ++ self.assertEqual(len(callers), 2) ++ (cc, nc, tt, ct) = callers[fsa_pid] ++ self.assertEqual(cc, nc, 2) ++ self.assertEqual(tt, 4) ++ self.assertEqual(ct, 4) ++ (cc, nc, tt, ct) = callers[fsb_pid] ++ self.assertEqual(cc, nc, 1) ++ self.assertEqual(tt, 2) ++ self.assertEqual(ct, 2) ++ ++ def test_merge_stats(self): ++ _timings = { ++ "a_1": 15, ++ "b_1": 14, ++ "c_1": 12, ++ "d_1": 10, ++ "e_1": 9, ++ "f_1": 7, ++ "g_1": 6, ++ "h_1": 5, ++ "i_1": 1 ++ } ++ _yappi._set_test_timings(_timings) ++ ++ def a(): ++ b() ++ ++ def b(): ++ c() ++ ++ def c(): ++ d() ++ ++ def d(): ++ e() ++ ++ def e(): ++ f() ++ ++ def f(): ++ g() ++ ++ def g(): ++ h() ++ ++ def h(): ++ i() ++ ++ def i(): ++ pass ++ ++ yappi.start() ++ a() ++ a() ++ yappi.stop() ++ stats = yappi.get_func_stats() ++ self.assertRaises( ++ NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE" ++ ) ++ stats.save("tests/ystats2.ys") ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ yappi.start() ++ a() ++ stats = yappi.get_func_stats().add("tests/ystats2.ys") ++ fsa = utils.find_stat_by_name(stats, "a") ++ fsb = utils.find_stat_by_name(stats, "b") ++ fsc = utils.find_stat_by_name(stats, "c") ++ fsd = utils.find_stat_by_name(stats, "d") ++ fse = utils.find_stat_by_name(stats, "e") ++ fsf = utils.find_stat_by_name(stats, "f") ++ fsg = utils.find_stat_by_name(stats, "g") ++ fsh = utils.find_stat_by_name(stats, "h") ++ fsi = utils.find_stat_by_name(stats, "i") ++ self.assertEqual(fsa.ttot, 45) ++ self.assertEqual(fsa.ncall, 3) ++ self.assertEqual(fsa.nactualcall, 3) ++ self.assertEqual(fsa.tsub, 3) ++ self.assertEqual(fsa.children[fsb].ttot, fsb.ttot) ++ self.assertEqual(fsa.children[fsb].tsub, fsb.tsub) ++ self.assertEqual(fsb.children[fsc].ttot, fsc.ttot) ++ self.assertEqual(fsb.children[fsc].tsub, fsc.tsub) ++ self.assertEqual(fsc.tsub, 6) ++ self.assertEqual(fsc.children[fsd].ttot, fsd.ttot) ++ self.assertEqual(fsc.children[fsd].tsub, fsd.tsub) ++ self.assertEqual(fsd.children[fse].ttot, fse.ttot) ++ self.assertEqual(fsd.children[fse].tsub, fse.tsub) ++ self.assertEqual(fse.children[fsf].ttot, fsf.ttot) ++ self.assertEqual(fse.children[fsf].tsub, fsf.tsub) ++ self.assertEqual(fsf.children[fsg].ttot, fsg.ttot) ++ self.assertEqual(fsf.children[fsg].tsub, fsg.tsub) ++ self.assertEqual(fsg.ttot, 18) ++ self.assertEqual(fsg.tsub, 3) ++ self.assertEqual(fsg.children[fsh].ttot, fsh.ttot) ++ self.assertEqual(fsg.children[fsh].tsub, fsh.tsub) ++ self.assertEqual(fsh.ttot, 15) ++ self.assertEqual(fsh.tsub, 12) ++ self.assertEqual(fsh.tavg, 5) ++ self.assertEqual(fsh.children[fsi].ttot, fsi.ttot) ++ self.assertEqual(fsh.children[fsi].tsub, fsi.tsub) ++ #stats.debug_print() ++ ++ def test_merge_multithreaded_stats(self): ++ import _yappi ++ timings = {"a_1": 2, "b_1": 1} ++ _yappi._set_test_timings(timings) ++ ++ def a(): ++ pass ++ ++ def b(): ++ pass ++ ++ yappi.start() ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ t = threading.Thread(target=b) ++ t.start() ++ t.join() ++ yappi.get_func_stats().save("tests/ystats1.ys") ++ yappi.clear_stats() ++ _yappi._set_test_timings(timings) ++ self.assertEqual(len(yappi.get_func_stats()), 0) ++ self.assertEqual(len(yappi.get_thread_stats()), 1) ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ ++ self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0) ++ self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1) ++ yappi.get_func_stats().save("tests/ystats2.ys") ++ ++ stats = yappi.YFuncStats([ ++ "tests/ystats1.ys", ++ "tests/ystats2.ys", ++ ]) ++ fsa = utils.find_stat_by_name(stats, "a") ++ fsb = utils.find_stat_by_name(stats, "b") ++ self.assertEqual(fsa.ncall, 2) ++ self.assertEqual(fsb.ncall, 1) ++ self.assertEqual(fsa.tsub, fsa.ttot, 4) ++ self.assertEqual(fsb.tsub, fsb.ttot, 1) ++ ++ def test_merge_load_different_clock_types(self): ++ yappi.start(builtins=True) ++ ++ def a(): ++ b() ++ ++ def b(): ++ c() ++ ++ def c(): ++ pass ++ ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys") ++ yappi.stop() ++ yappi.clear_stats() ++ yappi.start(builtins=False) ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ yappi.get_func_stats().save("tests/ystats2.ys") ++ yappi.stop() ++ self.assertRaises(_yappi.error, yappi.set_clock_type, "wall") ++ yappi.clear_stats() ++ yappi.set_clock_type("wall") ++ yappi.start() ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ yappi.get_func_stats().save("tests/ystats3.ys") ++ self.assertRaises( ++ yappi.YappiError, ++ yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys" ++ ) ++ stats = yappi.YFuncStats(["tests/ystats1.ys", ++ "tests/ystats2.ys"]).sort("name") ++ fsa = utils.find_stat_by_name(stats, "a") ++ fsb = utils.find_stat_by_name(stats, "b") ++ fsc = utils.find_stat_by_name(stats, "c") ++ self.assertEqual(fsa.ncall, 2) ++ self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall) ++ ++ def test_merge_aabab_aabbc(self): ++ _timings = { ++ "a_1": 15, ++ "a_2": 14, ++ "b_1": 12, ++ "a_3": 10, ++ "b_2": 9, ++ "c_1": 4 ++ } ++ _yappi._set_test_timings(_timings) ++ ++ def a(): ++ if self._ncall == 1: ++ self._ncall += 1 ++ a() ++ elif self._ncall == 5: ++ self._ncall += 1 ++ a() ++ else: ++ b() ++ ++ def b(): ++ if self._ncall == 2: ++ self._ncall += 1 ++ a() ++ elif self._ncall == 6: ++ self._ncall += 1 ++ b() ++ elif self._ncall == 7: ++ c() ++ else: ++ return ++ ++ def c(): ++ pass ++ ++ self._ncall = 1 ++ stats = utils.run_and_get_func_stats(a, ) ++ stats.save("tests/ystats1.ys") ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ #stats.print_all() ++ ++ self._ncall = 5 ++ stats = utils.run_and_get_func_stats(a, ) ++ stats.save("tests/ystats2.ys") ++ ++ #stats.print_all() ++ ++ def a(): # same name but another function(code object) ++ pass ++ ++ yappi.start() ++ a() ++ stats = yappi.get_func_stats().add( ++ ["tests/ystats1.ys", "tests/ystats2.ys"] ++ ) ++ #stats.print_all() ++ self.assertEqual(len(stats), 4) ++ ++ fsa = None ++ for stat in stats: ++ if stat.name == "a" and stat.ttot == 45: ++ fsa = stat ++ break ++ self.assertTrue(fsa is not None) ++ ++ self.assertEqual(fsa.ncall, 7) ++ self.assertEqual(fsa.nactualcall, 3) ++ self.assertEqual(fsa.ttot, 45) ++ self.assertEqual(fsa.tsub, 10) ++ fsb = utils.find_stat_by_name(stats, "b") ++ fsc = utils.find_stat_by_name(stats, "c") ++ self.assertEqual(fsb.ncall, 6) ++ self.assertEqual(fsb.nactualcall, 3) ++ self.assertEqual(fsb.ttot, 36) ++ self.assertEqual(fsb.tsub, 27) ++ self.assertEqual(fsb.tavg, 6) ++ self.assertEqual(fsc.ttot, 8) ++ self.assertEqual(fsc.tsub, 8) ++ self.assertEqual(fsc.tavg, 4) ++ self.assertEqual(fsc.nactualcall, fsc.ncall, 2) ++ ++ ++class MultithreadedScenarios(utils.YappiUnitTestCase): ++ ++ def test_issue_32(self): ++ ''' ++ Start yappi from different thread and we get Internal Error(15) as ++ the current_ctx_id() called while enumerating the threads in start() ++ and as it does not swap to the enumerated ThreadState* the THreadState_GetDict() ++ returns wrong object and thus sets an invalid id for the _ctx structure. ++ ++ When this issue happens multiple Threads have same tid as the internal ts_ptr ++ will be same for different contexts. So, let's see if that happens ++ ''' ++ ++ def foo(): ++ time.sleep(0.2) ++ ++ def bar(): ++ time.sleep(0.1) ++ ++ def thread_func(): ++ yappi.set_clock_type("wall") ++ yappi.start() ++ ++ bar() ++ ++ t = threading.Thread(target=thread_func) ++ t.start() ++ t.join() ++ ++ foo() ++ ++ yappi.stop() ++ ++ thread_ids = set() ++ for tstat in yappi.get_thread_stats(): ++ self.assertTrue(tstat.tid not in thread_ids) ++ thread_ids.add(tstat.tid) ++ ++ def test_subsequent_profile(self): ++ WORKER_COUNT = 5 ++ ++ def a(): ++ pass ++ ++ def b(): ++ pass ++ ++ def c(): ++ pass ++ ++ _timings = { ++ "a_1": 3, ++ "b_1": 2, ++ "c_1": 1, ++ } ++ ++ yappi.start() ++ ++ def g(): ++ pass ++ ++ g() ++ yappi.stop() ++ yappi.clear_stats() ++ _yappi._set_test_timings(_timings) ++ yappi.start() ++ ++ _dummy = [] ++ for i in range(WORKER_COUNT): ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ for i in range(WORKER_COUNT): ++ t = threading.Thread(target=b) ++ t.start() ++ _dummy.append(t) ++ t.join() ++ for i in range(WORKER_COUNT): ++ t = threading.Thread(target=a) ++ t.start() ++ t.join() ++ for i in range(WORKER_COUNT): ++ t = threading.Thread(target=c) ++ t.start() ++ t.join() ++ yappi.stop() ++ yappi.start() ++ ++ def f(): ++ pass ++ ++ f() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ self.assertEqual(fsa.ncall, 10) ++ self.assertEqual(fsb.ncall, 5) ++ self.assertEqual(fsc.ncall, 5) ++ self.assertEqual(fsa.ttot, fsa.tsub, 30) ++ self.assertEqual(fsb.ttot, fsb.tsub, 10) ++ self.assertEqual(fsc.ttot, fsc.tsub, 5) ++ ++ # MACOSx optimizes by only creating one worker thread ++ self.assertTrue(len(yappi.get_thread_stats()) >= 2) ++ ++ def test_basic(self): ++ yappi.set_clock_type('wall') ++ ++ def dummy(): ++ pass ++ ++ def a(): ++ time.sleep(0.2) ++ ++ class Worker1(threading.Thread): ++ ++ def a(self): ++ time.sleep(0.3) ++ ++ def run(self): ++ self.a() ++ ++ yappi.start(builtins=False, profile_threads=True) ++ ++ c = Worker1() ++ c.start() ++ c.join() ++ a() ++ stats = yappi.get_func_stats() ++ fsa1 = utils.find_stat_by_name(stats, 'Worker1.a') ++ fsa2 = utils.find_stat_by_name(stats, 'a') ++ self.assertTrue(fsa1 is not None) ++ self.assertTrue(fsa2 is not None) ++ self.assertTrue(fsa1.ttot > 0.2) ++ self.assertTrue(fsa2.ttot > 0.1) ++ tstats = yappi.get_thread_stats() ++ self.assertEqual(len(tstats), 2) ++ tsa = utils.find_stat_by_name(tstats, 'Worker1') ++ tsm = utils.find_stat_by_name(tstats, '_MainThread') ++ dummy() # call dummy to force ctx name to be retrieved again. ++ self.assertTrue(tsa is not None) ++ # TODO: I put dummy() to fix below, remove the comments after a while. ++ self.assertTrue( # FIX: I see this fails sometimes? ++ tsm is not None, ++ f"Could not find \"_MainThread\". Found: {', '.join(utils.get_stat_names(tstats))}") ++ ++ def test_ctx_stats(self): ++ from threading import Thread ++ DUMMY_WORKER_COUNT = 5 ++ yappi.start() ++ ++ class DummyThread(Thread): ++ pass ++ ++ def dummy(): ++ pass ++ ++ def dummy_worker(): ++ pass ++ ++ for i in range(DUMMY_WORKER_COUNT): ++ t = DummyThread(target=dummy_worker) ++ t.start() ++ t.join() ++ yappi.stop() ++ stats = yappi.get_thread_stats() ++ tsa = utils.find_stat_by_name(stats, "DummyThread") ++ self.assertTrue(tsa is not None) ++ yappi.clear_stats() ++ time.sleep(1.0) ++ _timings = { ++ "a_1": 6, ++ "b_1": 5, ++ "c_1": 3, ++ "d_1": 1, ++ "a_2": 4, ++ "b_2": 3, ++ "c_2": 2, ++ "d_2": 1 ++ } ++ _yappi._set_test_timings(_timings) ++ ++ class Thread1(Thread): ++ pass ++ ++ class Thread2(Thread): ++ pass ++ ++ def a(): ++ b() ++ ++ def b(): ++ c() ++ ++ def c(): ++ d() ++ ++ def d(): ++ time.sleep(0.6) ++ ++ yappi.set_clock_type("wall") ++ yappi.start() ++ t1 = Thread1(target=a) ++ t1.start() ++ t2 = Thread2(target=a) ++ t2.start() ++ t1.join() ++ t2.join() ++ stats = yappi.get_thread_stats() ++ ++ # the fist clear_stats clears the context table? ++ tsa = utils.find_stat_by_name(stats, "DummyThread") ++ self.assertTrue(tsa is None) ++ ++ tst1 = utils.find_stat_by_name(stats, "Thread1") ++ tst2 = utils.find_stat_by_name(stats, "Thread2") ++ tsmain = utils.find_stat_by_name(stats, "_MainThread") ++ dummy() # call dummy to force ctx name to be retrieved again. ++ self.assertTrue(len(stats) == 3) ++ self.assertTrue(tst1 is not None) ++ self.assertTrue(tst2 is not None) ++ # TODO: I put dummy() to fix below, remove the comments after a while. ++ self.assertTrue( # FIX: I see this fails sometimes ++ tsmain is not None, ++ f"Could not find \"_MainThread\". Found: {', '.join(utils.get_stat_names(stats))}") ++ self.assertTrue(1.0 > tst2.ttot >= 0.5) ++ self.assertTrue(1.0 > tst1.ttot >= 0.5) ++ ++ # test sorting of the ctx stats ++ stats = stats.sort("totaltime", "desc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.ttot >= stat.ttot) ++ prev_stat = stat ++ stats = stats.sort("totaltime", "asc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.ttot <= stat.ttot) ++ prev_stat = stat ++ stats = stats.sort("schedcount", "desc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.sched_count >= stat.sched_count) ++ prev_stat = stat ++ stats = stats.sort("name", "desc") ++ prev_stat = None ++ for stat in stats: ++ if prev_stat: ++ self.assertTrue(prev_stat.name.lower() >= stat.name.lower()) ++ prev_stat = stat ++ self.assertRaises( ++ yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg" ++ ) ++ self.assertRaises( ++ yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg" ++ ) ++ ++ def test_ctx_stats_cpu(self): ++ ++ def get_thread_name(): ++ try: ++ return threading.current_thread().name ++ except AttributeError: ++ return "Anonymous" ++ ++ def burn_cpu(sec): ++ t0 = yappi.get_clock_time() ++ elapsed = 0 ++ while (elapsed < sec): ++ for _ in range(1000): ++ pass ++ elapsed = yappi.get_clock_time() - t0 ++ ++ def test(): ++ ++ ts = [] ++ for i in (0.01, 0.05, 0.1): ++ t = threading.Thread(target=burn_cpu, args=(i, )) ++ t.name = f"burn_cpu-{str(i)}" ++ t.start() ++ ts.append(t) ++ for t in ts: ++ t.join() ++ ++ yappi.set_clock_type("cpu") ++ yappi.set_context_name_callback(get_thread_name) ++ ++ yappi.start() ++ ++ test() ++ ++ yappi.stop() ++ ++ tstats = yappi.get_thread_stats() ++ r1 = ''' ++ burn_cpu-0.1 3 123145356058624 0.100105 8 ++ burn_cpu-0.05 2 123145361313792 0.050149 8 ++ burn_cpu-0.01 1 123145356058624 0.010127 2 ++ MainThread 0 4321620864 0.001632 6 ++ ''' ++ self.assert_ctx_stats_almost_equal(r1, tstats) ++ ++ def test_producer_consumer_with_queues(self): ++ # we currently just stress yappi, no functionality test is done here. ++ yappi.start() ++ from queue import Queue ++ from threading import Thread ++ WORKER_THREAD_COUNT = 50 ++ WORK_ITEM_COUNT = 2000 ++ ++ def worker(): ++ while True: ++ item = q.get() ++ # do the work with item ++ q.task_done() ++ ++ q = Queue() ++ for i in range(WORKER_THREAD_COUNT): ++ t = Thread(target=worker) ++ t.daemon = True ++ t.start() ++ ++ for item in range(WORK_ITEM_COUNT): ++ q.put(item) ++ q.join() # block until all tasks are done ++ #yappi.get_func_stats().sort("callcount").print_all() ++ yappi.stop() ++ ++ def test_temporary_lock_waiting(self): ++ yappi.start() ++ _lock = threading.Lock() ++ ++ def worker(): ++ _lock.acquire() ++ try: ++ time.sleep(1.0) ++ finally: ++ _lock.release() ++ ++ t1 = threading.Thread(target=worker) ++ t2 = threading.Thread(target=worker) ++ t1.start() ++ t2.start() ++ t1.join() ++ t2.join() ++ #yappi.get_func_stats().sort("callcount").print_all() ++ yappi.stop() ++ ++ @unittest.skipIf(os.name != "posix", "requires Posix compliant OS") ++ def test_signals_with_blocking_calls(self): ++ import signal, os, time ++ ++ # just to verify if signal is handled correctly and stats/yappi are not corrupted. ++ def handler(signum, frame): ++ raise Exception("Signal handler executed!") ++ ++ yappi.start() ++ signal.signal(signal.SIGALRM, handler) ++ signal.alarm(1) ++ self.assertRaises(Exception, time.sleep, 2) ++ stats = yappi.get_func_stats() ++ fsh = utils.find_stat_by_name(stats, "handler") ++ self.assertTrue(fsh is not None) ++ ++ def test_concurrent_futures(self): ++ yappi.start() ++ from concurrent.futures import ThreadPoolExecutor ++ with ThreadPoolExecutor(max_workers=5) as executor: ++ f = executor.submit(pow, 5, 2) ++ self.assertEqual(f.result(), 25) ++ time.sleep(1.0) ++ yappi.stop() ++ ++ def test_barrier(self): ++ yappi.start() ++ b = threading.Barrier(2, timeout=1) ++ ++ def worker(): ++ try: ++ b.wait() ++ except threading.BrokenBarrierError: ++ pass ++ except Exception: ++ raise Exception("BrokenBarrierError not raised") ++ ++ t1 = threading.Thread(target=worker) ++ t1.start() ++ #b.wait() ++ t1.join() ++ yappi.stop() ++ ++ ++class NonRecursiveFunctions(utils.YappiUnitTestCase): ++ ++ def test_abcd(self): ++ _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1} ++ _yappi._set_test_timings(_timings) ++ ++ def a(): ++ b() ++ ++ def b(): ++ c() ++ ++ def c(): ++ d() ++ ++ def d(): ++ pass ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ fsd = utils.find_stat_by_name(stats, 'd') ++ cfsab = fsa.children[fsb] ++ cfsbc = fsb.children[fsc] ++ cfscd = fsc.children[fsd] ++ ++ self.assertEqual(fsa.ttot, 6) ++ self.assertEqual(fsa.tsub, 1) ++ self.assertEqual(fsb.ttot, 5) ++ self.assertEqual(fsb.tsub, 2) ++ self.assertEqual(fsc.ttot, 3) ++ self.assertEqual(fsc.tsub, 2) ++ self.assertEqual(fsd.ttot, 1) ++ self.assertEqual(fsd.tsub, 1) ++ self.assertEqual(cfsab.ttot, 5) ++ self.assertEqual(cfsab.tsub, 2) ++ self.assertEqual(cfsbc.ttot, 3) ++ self.assertEqual(cfsbc.tsub, 2) ++ self.assertEqual(cfscd.ttot, 1) ++ self.assertEqual(cfscd.tsub, 1) ++ ++ def test_stop_in_middle(self): ++ _timings = {"a_1": 6, "b_1": 4} ++ _yappi._set_test_timings(_timings) ++ ++ def a(): ++ b() ++ yappi.stop() ++ ++ def b(): ++ time.sleep(0.2) ++ ++ yappi.start() ++ a() ++ stats = yappi.get_func_stats() ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ ++ self.assertEqual(fsa.ncall, 1) ++ self.assertEqual(fsa.nactualcall, 0) ++ self.assertEqual(fsa.ttot, 0) # no call_leave called ++ self.assertEqual(fsa.tsub, 0) # no call_leave called ++ self.assertEqual(fsb.ttot, 4) ++ ++ ++class RecursiveFunctions(utils.YappiUnitTestCase): ++ ++ def test_fibonacci(self): ++ ++ def fib(n): ++ if n > 1: ++ return fib(n - 1) + fib(n - 2) ++ else: ++ return n ++ ++ stats = utils.run_and_get_func_stats(fib, 22) ++ fs = utils.find_stat_by_name(stats, 'fib') ++ self.assertEqual(fs.ncall, 57313) ++ self.assertEqual(fs.ttot, fs.tsub) ++ ++ def test_abcadc(self): ++ _timings = { ++ "a_1": 20, ++ "b_1": 19, ++ "c_1": 17, ++ "a_2": 13, ++ "d_1": 12, ++ "c_2": 10, ++ "a_3": 5 ++ } ++ _yappi._set_test_timings(_timings) ++ ++ def a(n): ++ if n == 3: ++ return ++ if n == 1 + 1: ++ d(n) ++ else: ++ b(n) ++ ++ def b(n): ++ c(n) ++ ++ def c(n): ++ a(n + 1) ++ ++ def d(n): ++ c(n) ++ ++ stats = utils.run_and_get_func_stats(a, 1) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ fsd = utils.find_stat_by_name(stats, 'd') ++ self.assertEqual(fsa.ncall, 3) ++ self.assertEqual(fsa.nactualcall, 1) ++ self.assertEqual(fsa.ttot, 20) ++ self.assertEqual(fsa.tsub, 7) ++ self.assertEqual(fsb.ttot, 19) ++ self.assertEqual(fsb.tsub, 2) ++ self.assertEqual(fsc.ttot, 17) ++ self.assertEqual(fsc.tsub, 9) ++ self.assertEqual(fsd.ttot, 12) ++ self.assertEqual(fsd.tsub, 2) ++ cfsca = fsc.children[fsa] ++ self.assertEqual(cfsca.nactualcall, 0) ++ self.assertEqual(cfsca.ncall, 2) ++ self.assertEqual(cfsca.ttot, 13) ++ self.assertEqual(cfsca.tsub, 6) ++ ++ def test_aaaa(self): ++ _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2} ++ _yappi._set_test_timings(_timings) ++ ++ def d(n): ++ if n == 3: ++ return ++ d(n + 1) ++ ++ stats = utils.run_and_get_func_stats(d, 0) ++ fsd = utils.find_stat_by_name(stats, 'd') ++ self.assertEqual(fsd.ncall, 4) ++ self.assertEqual(fsd.nactualcall, 1) ++ self.assertEqual(fsd.ttot, 9) ++ self.assertEqual(fsd.tsub, 9) ++ cfsdd = fsd.children[fsd] ++ self.assertEqual(cfsdd.ttot, 7) ++ self.assertEqual(cfsdd.tsub, 7) ++ self.assertEqual(cfsdd.ncall, 3) ++ self.assertEqual(cfsdd.nactualcall, 0) ++ ++ def test_abcabc(self): ++ _timings = { ++ "a_1": 20, ++ "b_1": 19, ++ "c_1": 17, ++ "a_2": 13, ++ "b_2": 11, ++ "c_2": 9, ++ "a_3": 6 ++ } ++ _yappi._set_test_timings(_timings) ++ ++ def a(n): ++ if n == 3: ++ return ++ else: ++ b(n) ++ ++ def b(n): ++ c(n) ++ ++ def c(n): ++ a(n + 1) ++ ++ stats = utils.run_and_get_func_stats(a, 1) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ self.assertEqual(fsa.ncall, 3) ++ self.assertEqual(fsa.nactualcall, 1) ++ self.assertEqual(fsa.ttot, 20) ++ self.assertEqual(fsa.tsub, 9) ++ self.assertEqual(fsb.ttot, 19) ++ self.assertEqual(fsb.tsub, 4) ++ self.assertEqual(fsc.ttot, 17) ++ self.assertEqual(fsc.tsub, 7) ++ cfsab = fsa.children[fsb] ++ cfsbc = fsb.children[fsc] ++ cfsca = fsc.children[fsa] ++ self.assertEqual(cfsab.ttot, 19) ++ self.assertEqual(cfsab.tsub, 4) ++ self.assertEqual(cfsbc.ttot, 17) ++ self.assertEqual(cfsbc.tsub, 7) ++ self.assertEqual(cfsca.ttot, 13) ++ self.assertEqual(cfsca.tsub, 8) ++ ++ def test_abcbca(self): ++ _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1} ++ _yappi._set_test_timings(_timings) ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 1: ++ b() ++ else: ++ return ++ ++ def b(): ++ c() ++ ++ def c(): ++ if self._ncall == 1: ++ self._ncall += 1 ++ b() ++ else: ++ a() ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ cfsab = fsa.children[fsb] ++ cfsbc = fsb.children[fsc] ++ cfsca = fsc.children[fsa] ++ self.assertEqual(fsa.ttot, 10) ++ self.assertEqual(fsa.tsub, 2) ++ self.assertEqual(fsb.ttot, 9) ++ self.assertEqual(fsb.tsub, 4) ++ self.assertEqual(fsc.ttot, 7) ++ self.assertEqual(fsc.tsub, 4) ++ self.assertEqual(cfsab.ttot, 9) ++ self.assertEqual(cfsab.tsub, 2) ++ self.assertEqual(cfsbc.ttot, 7) ++ self.assertEqual(cfsbc.tsub, 4) ++ self.assertEqual(cfsca.ttot, 1) ++ self.assertEqual(cfsca.tsub, 1) ++ self.assertEqual(cfsca.ncall, 1) ++ self.assertEqual(cfsca.nactualcall, 0) ++ ++ def test_aabccb(self): ++ _timings = { ++ "a_1": 13, ++ "a_2": 11, ++ "b_1": 9, ++ "c_1": 5, ++ "c_2": 3, ++ "b_2": 1 ++ } ++ _yappi._set_test_timings(_timings) ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 1: ++ self._ncall += 1 ++ a() ++ else: ++ b() ++ ++ def b(): ++ if self._ncall == 3: ++ return ++ else: ++ c() ++ ++ def c(): ++ if self._ncall == 2: ++ self._ncall += 1 ++ c() ++ else: ++ b() ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ fsc = utils.find_stat_by_name(stats, 'c') ++ cfsaa = fsa.children[fsa.index] ++ cfsab = fsa.children[fsb] ++ cfsbc = fsb.children[fsc.full_name] ++ cfscc = fsc.children[fsc] ++ cfscb = fsc.children[fsb] ++ self.assertEqual(fsb.ttot, 9) ++ self.assertEqual(fsb.tsub, 5) ++ self.assertEqual(cfsbc.ttot, 5) ++ self.assertEqual(cfsbc.tsub, 2) ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 4) ++ self.assertEqual(cfsab.ttot, 9) ++ self.assertEqual(cfsab.tsub, 4) ++ self.assertEqual(cfsaa.ttot, 11) ++ self.assertEqual(cfsaa.tsub, 2) ++ self.assertEqual(fsc.ttot, 5) ++ self.assertEqual(fsc.tsub, 4) ++ ++ def test_abaa(self): ++ _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 1: ++ b() ++ elif self._ncall == 2: ++ self._ncall += 1 ++ a() ++ else: ++ return ++ ++ def b(): ++ self._ncall += 1 ++ a() ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ cfsaa = fsa.children[fsa] ++ cfsba = fsb.children[fsa] ++ self.assertEqual(fsb.ttot, 10) ++ self.assertEqual(fsb.tsub, 1) ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 12) ++ self.assertEqual(cfsaa.ttot, 5) ++ self.assertEqual(cfsaa.tsub, 5) ++ self.assertEqual(cfsba.ttot, 9) ++ self.assertEqual(cfsba.tsub, 4) ++ ++ def test_aabb(self): ++ _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 1: ++ self._ncall += 1 ++ a() ++ elif self._ncall == 2: ++ b() ++ else: ++ return ++ ++ def b(): ++ if self._ncall == 2: ++ self._ncall += 1 ++ b() ++ else: ++ return ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ cfsaa = fsa.children[fsa] ++ cfsab = fsa.children[fsb] ++ cfsbb = fsb.children[fsb] ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 4) ++ self.assertEqual(fsb.ttot, 9) ++ self.assertEqual(fsb.tsub, 9) ++ self.assertEqual(cfsaa.ttot, 10) ++ self.assertEqual(cfsaa.tsub, 1) ++ self.assertEqual(cfsab.ttot, 9) ++ self.assertEqual(cfsab.tsub, 4) ++ self.assertEqual(cfsbb.ttot, 5) ++ self.assertEqual(cfsbb.tsub, 5) ++ ++ def test_abbb(self): ++ _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 1: ++ b() ++ ++ def b(): ++ if self._ncall == 3: ++ return ++ self._ncall += 1 ++ b() ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ cfsab = fsa.children[fsb] ++ cfsbb = fsb.children[fsb] ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 3) ++ self.assertEqual(fsb.ttot, 10) ++ self.assertEqual(fsb.tsub, 10) ++ self.assertEqual(fsb.ncall, 3) ++ self.assertEqual(fsb.nactualcall, 1) ++ self.assertEqual(cfsab.ttot, 10) ++ self.assertEqual(cfsab.tsub, 4) ++ self.assertEqual(cfsbb.ttot, 6) ++ self.assertEqual(cfsbb.tsub, 6) ++ self.assertEqual(cfsbb.nactualcall, 0) ++ self.assertEqual(cfsbb.ncall, 2) ++ ++ def test_aaab(self): ++ _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ if self._ncall == 3: ++ b() ++ return ++ self._ncall += 1 ++ a() ++ ++ def b(): ++ return ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ cfsaa = fsa.children[fsa] ++ cfsab = fsa.children[fsb] ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 12) ++ self.assertEqual(fsb.ttot, 1) ++ self.assertEqual(fsb.tsub, 1) ++ self.assertEqual(cfsaa.ttot, 10) ++ self.assertEqual(cfsaa.tsub, 9) ++ self.assertEqual(cfsab.ttot, 1) ++ self.assertEqual(cfsab.tsub, 1) ++ ++ def test_abab(self): ++ _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1} ++ _yappi._set_test_timings(_timings) ++ ++ self._ncall = 1 ++ ++ def a(): ++ b() ++ ++ def b(): ++ if self._ncall == 2: ++ return ++ self._ncall += 1 ++ a() ++ ++ stats = utils.run_and_get_func_stats(a) ++ fsa = utils.find_stat_by_name(stats, 'a') ++ fsb = utils.find_stat_by_name(stats, 'b') ++ cfsab = fsa.children[fsb] ++ cfsba = fsb.children[fsa] ++ self.assertEqual(fsa.ttot, 13) ++ self.assertEqual(fsa.tsub, 8) ++ self.assertEqual(fsb.ttot, 10) ++ self.assertEqual(fsb.tsub, 5) ++ self.assertEqual(cfsab.ttot, 10) ++ self.assertEqual(cfsab.tsub, 5) ++ self.assertEqual(cfsab.ncall, 2) ++ self.assertEqual(cfsab.nactualcall, 1) ++ self.assertEqual(cfsba.ttot, 6) ++ self.assertEqual(cfsba.tsub, 5) ++ ++ ++if __name__ == '__main__': ++ # import sys;sys.argv = ['', 'BasicUsage.test_run_as_script'] ++ # import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile'] ++ unittest.main() +-- +2.34.1 + diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-Fix-import-of-tests.utils-to-enable-pytest.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-Fix-import-of-tests.utils-to-enable-pytest.patch new file mode 100644 index 0000000000..96dd024125 --- /dev/null +++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-Fix-import-of-tests.utils-to-enable-pytest.patch @@ -0,0 +1,101 @@ +From 28eac38566327091221aabbc164ea8e433c66e7e Mon Sep 17 00:00:00 2001 +From: Tim Orling +Date: Sun, 24 Dec 2023 09:27:50 -0800 +Subject: [PATCH 2/2] Fix import of tests.utils to enable pytest + +Running the test cases with pytest leads to importlib errors +because the "utils" module cannot be found. + +Upstream-Status: Submitted [https://github.com/sumerc/yappi/pull/164] + +Signed-off-by: Tim Orling +--- + tests/test_asyncio.py | 2 +- + tests/test_asyncio_context_vars.py | 2 +- + tests/test_functionality.py | 2 +- + tests/test_gevent.py | 2 +- + tests/test_hooks.py | 2 +- + tests/test_tags.py | 2 +- + 6 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py +index 8e9e631..bb36f4a 100644 +--- a/tests/test_asyncio.py ++++ b/tests/test_asyncio.py +@@ -2,7 +2,7 @@ import unittest + import yappi + import asyncio + import threading +-from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io ++from tests.utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io + + + async def async_sleep(sec): +diff --git a/tests/test_asyncio_context_vars.py b/tests/test_asyncio_context_vars.py +index 5bd750c..9a253c0 100644 +--- a/tests/test_asyncio_context_vars.py ++++ b/tests/test_asyncio_context_vars.py +@@ -5,7 +5,7 @@ import contextvars + import functools + import time + import os +-import utils ++import tests.utils as utils + import yappi + + async_context_id = contextvars.ContextVar('async_context_id') +diff --git a/tests/test_functionality.py b/tests/test_functionality.py +index 38bbe67..8098f17 100644 +--- a/tests/test_functionality.py ++++ b/tests/test_functionality.py +@@ -5,7 +5,7 @@ import threading + import unittest + import yappi + import _yappi +-import utils ++import tests.utils as utils + import multiprocessing + import subprocess + +diff --git a/tests/test_gevent.py b/tests/test_gevent.py +index ed9e6ae..502af5f 100644 +--- a/tests/test_gevent.py ++++ b/tests/test_gevent.py +@@ -2,7 +2,7 @@ import unittest + import _yappi + import yappi + import threading +-from utils import ( ++from tests.utils import ( + YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io, burn_io_gevent + ) + +diff --git a/tests/test_hooks.py b/tests/test_hooks.py +index 297c643..8c387fc 100644 +--- a/tests/test_hooks.py ++++ b/tests/test_hooks.py +@@ -5,7 +5,7 @@ import unittest + import time + + import yappi +-import utils ++import tests.utils as utils + + + def a(): +diff --git a/tests/test_tags.py b/tests/test_tags.py +index b0b531d..b5a4016 100644 +--- a/tests/test_tags.py ++++ b/tests/test_tags.py +@@ -2,7 +2,7 @@ import unittest + import yappi + import threading + import time +-from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io ++from tests.utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io + + + class MultiThreadTests(YappiUnitTestCase): +-- +2.34.1 + diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch deleted file mode 100644 index d40bd2b7cc..0000000000 --- a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 38afdacf526410f970afc58e147c7377c6c7112c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?S=C3=BCmer=20Cip?= -Date: Fri, 25 Nov 2022 15:58:03 +0300 -Subject: [PATCH 2/2] add 3.11 to the setup - ---- -Upstream-Status: Pending - - setup.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/setup.py b/setup.py -index d006787..96e2a66 100644 ---- a/setup.py -+++ b/setup.py -@@ -56,6 +56,7 @@ CLASSIFIERS = [ - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', -+ 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: Implementation :: CPython', - 'Operating System :: OS Independent', - 'Topic :: Software Development :: Libraries', --- -2.30.2 - diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/run-ptest b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/run-ptest index 3385d68939..8d2017d39c 100644 --- a/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/run-ptest +++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-yappi/run-ptest @@ -1,3 +1,3 @@ #!/bin/sh -pytest -o log_cli=true -o log_cli_level=INFO | sed -e 's/\[...%\]//g'| sed -e 's/PASSED/PASS/g'| sed -e 's/FAILED/FAIL/g'|sed -e 's/SKIPED/SKIP/g'| awk '{if ($NF=="PASS" || $NF=="FAIL" || $NF=="SKIP" || $NF=="XFAIL" || $NF=="XPASS"){printf "%s: %s\n", $NF, $0}else{print}}'| awk '{if ($NF=="PASS" || $NF=="FAIL" || $NF=="SKIP" || $NF=="XFAIL" || $NF=="XPASS") {$NF="";print $0}else{print}}' +pytest --automake -- cgit v1.2.3