diff --git a/.github/workflows/lint_and_docs.yml b/.github/workflows/lint_and_docs.yml new file mode 100644 index 00000000..d04f62c1 --- /dev/null +++ b/.github/workflows/lint_and_docs.yml @@ -0,0 +1,29 @@ +name: Lint and docs + +on: [push, pull_request] + +jobs: + lint_and_docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Set up dependencies + run: | + sudo apt-get update + sudo apt-get install -qy libdw-dev libelf-dev + npm install -g prettier + - name: Install Python dependencies + run: | + python3 -m pip install -r requirements-extra.txt + - name: Install Package + run: | + python3 -m pip install -e . + - name: Lint sources + run: | + make lint + - name: Build docs + run: | + make docs diff --git a/src/pystack/__main__.py b/src/pystack/__main__.py index e22429ef..a88eb610 100644 --- a/src/pystack/__main__.py +++ b/src/pystack/__main__.py @@ -10,6 +10,7 @@ from typing import Dict from typing import NoReturn from typing import Optional +from typing import Set from pystack.errors import InvalidPythonProcess from pystack.process import is_elf @@ -342,7 +343,7 @@ def process_core(parser: argparse.ArgumentParser, args: argparse.Namespace) -> N if args.lib_search_path: lib_search_path = args.lib_search_path if args.lib_search_root: - library_dirs = set() + library_dirs: Set[str] = set() for pattern in {"**/*.so", "**/*.so.*"}: library_dirs.update( str(file.parent) diff --git a/src/pystack/_pystack/elf_common.cpp b/src/pystack/_pystack/elf_common.cpp index c602a0ea..e20c5b03 100644 --- a/src/pystack/_pystack/elf_common.cpp +++ b/src/pystack/_pystack/elf_common.cpp @@ -215,8 +215,7 @@ CoreFileAnalyzer::resolveLibraries() module.path.c_str(), -1, module.addr, - false)) - { + false)) { LOG(ERROR) << "Failed to report module " << module.modname << ": " << dwfl_errmsg(dwfl_errno()); throw ElfAnalyzerError("Failed to report ELF modules for core file"); diff --git a/src/pystack/_pystack/elf_common.h b/src/pystack/_pystack/elf_common.h index 63776a58..2004c00c 100644 --- a/src/pystack/_pystack/elf_common.h +++ b/src/pystack/_pystack/elf_common.h @@ -73,7 +73,7 @@ class CoreFileAnalyzer : public Analyzer elf_unique_ptr d_elf; std::vector d_missing_modules{}; -private: + private: void removeModuleIf(std::function predicate) const; void resolveLibraries(); }; diff --git a/src/pystack/_pystack/process.cpp b/src/pystack/_pystack/process.cpp index 9c9d3a36..2be2daf6 100644 --- a/src/pystack/_pystack/process.cpp +++ b/src/pystack/_pystack/process.cpp @@ -514,7 +514,8 @@ AbstractProcessManager::minorVersion() const return d_minor; } -const python_v& AbstractProcessManager::offsets() const +const python_v& +AbstractProcessManager::offsets() const { return *d_py_v; } diff --git a/src/pystack/_pystack/pythread.cpp b/src/pystack/_pystack/pythread.cpp index 5fdd8fd1..6c9654ef 100644 --- a/src/pystack/_pystack/pythread.cpp +++ b/src/pystack/_pystack/pythread.cpp @@ -139,7 +139,8 @@ PyThread::PyThread(const std::shared_ptr& manager, } d_addr = addr; - remote_addr_t candidate_next_addr = manager->versionedThreadField(ts); + remote_addr_t candidate_next_addr = + manager->versionedThreadField(ts); d_next_addr = candidate_next_addr == addr ? (remote_addr_t) nullptr : candidate_next_addr; d_pthread_id = manager->versionedThreadField(ts); @@ -217,7 +218,8 @@ PyThread::getFrameAddr( { if (manager->majorVersion() > 3 || (manager->majorVersion() == 3 && manager->minorVersion() >= 11)) { Python3_11::CFrame cframe; - remote_addr_t cframe_addr = manager->versionedThreadField(ts); + remote_addr_t cframe_addr = + manager->versionedThreadField(ts); if (!manager->isAddressValid(cframe_addr)) { return reinterpret_cast(nullptr); } @@ -288,8 +290,7 @@ PyThread::calculateGilStatus(const std::shared_ptr static const size_t MAX_RUNTIME_OFFSET = 2048; for (void** raddr = (void**)pyruntime; (void*)raddr < (void*)(pyruntime + MAX_RUNTIME_OFFSET); - raddr++) - { + raddr++) { manager->copyObjectFromProcess((remote_addr_t)raddr, &thread_addr); if (thread_addr == d_addr && ++hits == 2) { LOG(DEBUG) << "GIL status correctly determined: HELD"; @@ -376,7 +377,8 @@ getThreadFromInterpreterState( PyInterpreterState is; manager->copyObjectFromProcess(addr, &is); - auto thread_addr = manager->versionedInterpreterStateField(is); + auto thread_addr = + manager->versionedInterpreterStateField(is); return std::make_shared(manager, thread_addr); } diff --git a/src/pystack/_pystack/pytypes.cpp b/src/pystack/_pystack/pytypes.cpp index 9ae72839..6db860b0 100644 --- a/src/pystack/_pystack/pytypes.cpp +++ b/src/pystack/_pystack/pytypes.cpp @@ -617,7 +617,6 @@ Object::objectType() const const long subclass_flags = d_flags & subclass_mask; - if (subclass_flags == Pystack_TPFLAGS_BYTES_SUBCLASS) { return d_manager->majorVersion() > 2 ? ObjectType::BYTES : ObjectType::STRING; } else if (subclass_flags == Pystack_TPFLAGS_UNICODE_SUBCLASS) { diff --git a/src/pystack/maps.py b/src/pystack/maps.py index cf06d4e3..3983f7f5 100644 --- a/src/pystack/maps.py +++ b/src/pystack/maps.py @@ -69,7 +69,7 @@ def is_private(self) -> bool: def size(self) -> int: return self.end - self.start - def __repr__(self): + def __repr__(self) -> str: start = f"0x{self.start:016x}" end = f"0x{self.end:016x}" filesize = f"0x{self.filesize:x}"