Skip to content

Commit

Permalink
Add support for UCS-2 strings (#648)
Browse files Browse the repository at this point in the history
* feat: add support for UCS-2 strings

rebased commit: dcf703b

* tests: add a test to ensure py-spy does not fails on cyrillic (ucs-2) strings

* tests: fix `test_cyrillic` test for python 2

---------

Co-authored-by: Ben Frederickson <[email protected]>
  • Loading branch information
nariman and benfred authored Feb 27, 2024
1 parent e0cbd46 commit 8dd5492
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/python_data_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ pub fn copy_string<T: StringObject, P: ProcessMemory>(
Ok(chars.iter().collect())
}
(2, _) => {
// UCS2 strings aren't used internally after v3.3: https://www.python.org/dev/peps/pep-0393/
// TODO: however with python 2.7 they could be added with --enable-unicode=ucs2 configure flag.
// or with python 3.2 --with-wide-unicode=ucs2
Err(format_err!("ucs2 strings aren't supported yet!"))
#[allow(clippy::cast_ptr_alignment)]
let chars = unsafe {
std::slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len() / 2)
};
Ok(String::from_utf16(chars)?)
}
(1, true) => Ok(String::from_utf8(bytes)?),
(1, false) => Ok(bytes.iter().map(|&b| b as char).collect()),
Expand Down
28 changes: 28 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,34 @@ fn test_unicode() {
assert!(!traces[0].owns_gil);
}

#[test]
fn test_cyrillic() {
#[cfg(target_os = "macos")]
{
if unsafe { libc::geteuid() } != 0 {
return;
}
}

// Identifiers with characters outside the ASCII range are supported from Python 3
let runner = TestRunner::new(Config::default(), "./tests/scripts/longsleep.py");
if runner.spy.version.major == 2 {
return;
}

let mut runner = TestRunner::new(Config::default(), "./tests/scripts/cyrillic.py");

let traces = runner.spy.get_stack_traces().unwrap();
assert_eq!(traces.len(), 1);
let trace = &traces[0];

assert_eq!(trace.frames[0].name, "кириллица");
assert_eq!(trace.frames[0].line, 4);

assert_eq!(trace.frames[1].name, "<module>");
assert_eq!(trace.frames[1].line, 7);
}

#[test]
fn test_local_vars() {
#[cfg(target_os = "macos")]
Expand Down
7 changes: 7 additions & 0 deletions tests/scripts/cyrillic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import time

def кириллица(seconds):
time.sleep(seconds)

if __name__ == "__main__":
кириллица(100)

0 comments on commit 8dd5492

Please sign in to comment.