Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/static_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
uses: Flamefire/clang-format-lint-action@master
with:
source: src
exclude: "src/scorepy/pythoncapi_compat.h"
clangFormatVersion: 9

Python:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.9", "3.10", "3.11", "3.12", "3.13", 'pypy-2.7', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10', 'pypy-3.11']
python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", 'pypy-2.7', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9', 'pypy-3.10', 'pypy-3.11']
fail-fast: false

steps:
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Operating System :: POSIX",
Expand Down
61 changes: 47 additions & 14 deletions src/scorepy/pythonHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,78 @@
#include "pathUtils.hpp"
#include "pythoncapi_compat.h"

#include <cstdio>
#include <sstream>
#include <stdlib.h>
#include <string>

namespace scorepy
{

static PyObject* get_self_from_frame(PyFrameObject* frame)
{
PyObject* self = nullptr;

#if PY_VERSION_HEX >= 0x030C0000 // Python 3.12+
// Added in 3.12: directly fetch a local variable by name.
self = PyFrame_GetVarString(frame, "self");
if (!self && PyErr_Occurred())
PyErr_Clear();
#else
PyObject* locals = PyFrame_GetLocals(frame); // New reference
if (locals)
{
PyObject* tmp = PyDict_GetItemString(locals, "self"); // Borrowed
if (tmp)
{
Py_INCREF(tmp);
self = tmp;
}
Py_DECREF(locals);
}
#endif
return self;
}

std::string get_module_name(PyFrameObject& frame)
{
const char* self_name = nullptr;
PyObject* locals = PyFrame_GetLocals(&frame);
PyObject* self = PyDict_GetItemString(locals, "self");

PyObject* self = get_self_from_frame(&frame);
if (self)
{
Py_INCREF(self);
PyTypeObject* type = Py_TYPE(self);
self_name = _PyType_Name(type);
Py_DECREF(self);
}
Py_DECREF(locals);

PyObject* globals = PyFrame_GetGlobals(&frame);
PyObject* module_name = PyDict_GetItemString(globals, "__name__");
Py_DECREF(globals);
// --- get module name from globals ---------------------------------------
PyObject* globals = PyFrame_GetGlobals(&frame); // New reference
PyObject* module_name = globals ? PyDict_GetItemString(globals, "__name__") // Borrowed
:
nullptr;
if (globals)
Py_DECREF(globals);

if (module_name)
{
std::stringstream result;
// compat::get_string_as_utf_8() is assumed to convert PyObject* → UTF-8 std::string
result << compat::get_string_as_utf_8(module_name);
if (self_name)
result << '.' << self_name;
return std::move(result).str();
return result.str();
}

// this is a NUMPY special situation, see NEP-18, and Score-P issue #63
// TODO: Use string_view/C-String to avoid creating 2 std::strings
// --- special-case NumPy internal frames ---------------------------------
PyCodeObject* code = PyFrame_GetCode(&frame);
std::string_view filename = compat::get_string_as_utf_8(code->co_filename);
Py_DECREF(code);
if ((filename.size() > 0) && (filename == "<__array_function__ internals>"))
return std::move(std::string("numpy.__array_function__"));
else
return std::move(std::string("unkown"));

if (filename == "<__array_function__ internals>")
return "numpy.__array_function__";

return "unknown";
}

std::string get_file_name(PyFrameObject& frame)
Expand All @@ -57,4 +89,5 @@ std::string get_file_name(PyFrameObject& frame)
const auto full_file_name = abspath(compat::get_string_as_utf_8(filename));
return !full_file_name.empty() ? std::move(full_file_name) : "ErrorPath";
}

} // namespace scorepy
Loading
Loading