This repository has been archived by the owner on Apr 4, 2024. It is now read-only.
forked from diffplug/selfie
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
2 changed files
with
126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from typing import List, Optional | ||
from selfie_lib.CommentTracker import SnapshotFileLayout | ||
import inspect | ||
from functools import total_ordering | ||
|
||
|
||
@total_ordering | ||
class CallLocation: | ||
def __init__(self, file_name: Optional[str], line: int): | ||
self._file_name = file_name | ||
self._line = line | ||
|
||
@property | ||
def file_name(self) -> Optional[str]: | ||
return self._file_name | ||
|
||
@property | ||
def line(self) -> int: | ||
return self._line | ||
|
||
def with_line(self, line: int) -> "CallLocation": | ||
return CallLocation(self._file_name, line) | ||
|
||
def ide_link(self, layout: "SnapshotFileLayout") -> str: | ||
return f"File: {self._file_name}, Line: {self._line}" | ||
|
||
def same_path_as(self, other: "CallLocation") -> bool: | ||
if not isinstance(other, CallLocation): | ||
return False | ||
return self._file_name == other.file_name | ||
|
||
def source_filename_without_extension(self) -> str: | ||
if self._file_name is not None: | ||
return self._file_name.rsplit(".", 1)[0] | ||
return "" | ||
|
||
def __lt__(self, other) -> bool: | ||
if not isinstance(other, CallLocation): | ||
return NotImplemented | ||
return (self._file_name, self._line) < (other.file_name, other.line) | ||
|
||
def __eq__(self, other) -> bool: | ||
if not isinstance(other, CallLocation): | ||
return NotImplemented | ||
return (self._file_name, self._line) == (other.file_name, other.line) | ||
|
||
|
||
class CallStack: | ||
def __init__(self, location: CallLocation, rest_of_stack: List[CallLocation]): | ||
self.location = location | ||
self.rest_of_stack = rest_of_stack | ||
|
||
def ide_link(self, layout: "SnapshotFileLayout") -> str: | ||
links = [self.location.ide_link(layout)] + [ | ||
loc.ide_link(layout) for loc in self.rest_of_stack | ||
] | ||
return "\n".join(links) | ||
|
||
|
||
def recordCall(callerFileOnly: bool = False) -> CallStack: | ||
stack_frames = inspect.stack()[1:] | ||
|
||
if callerFileOnly: | ||
caller_file = stack_frames[0].filename | ||
stack_frames = [ | ||
frame for frame in stack_frames if frame.filename == caller_file | ||
] | ||
|
||
call_locations = [ | ||
CallLocation(frame.filename, frame.lineno) for frame in stack_frames | ||
] | ||
|
||
location = call_locations[0] | ||
rest_of_stack = call_locations[1:] | ||
|
||
return CallStack(location, rest_of_stack) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from unittest.mock import Mock | ||
from selfie_lib.WriteTracker import CallLocation, CallStack, recordCall | ||
import os | ||
|
||
|
||
def test_call_location_ide_link(): | ||
layout = Mock() | ||
location = CallLocation(file_name="example.py", line=10) | ||
expected_link = "File: example.py, Line: 10" | ||
|
||
assert location.ide_link(layout) == expected_link | ||
|
||
|
||
def test_call_stack_ide_link(): | ||
layout = Mock() | ||
location1 = CallLocation(file_name="example1.py", line=10) | ||
location2 = CallLocation(file_name="example2.py", line=20) | ||
call_stack = CallStack(location=location1, rest_of_stack=[location2]) | ||
|
||
expected_links = "File: example1.py, Line: 10\nFile: example2.py, Line: 20" | ||
assert call_stack.ide_link(layout) == expected_links | ||
|
||
|
||
def test_record_call_with_caller_file_only_false(): | ||
call_stack = recordCall(False) | ||
|
||
assert ( | ||
len(call_stack.rest_of_stack) > 0 | ||
), "Expected the rest of stack to contain more than one CallLocation" | ||
|
||
expected_call_location_str = "File: RecordCall_test.py, Line: 25" | ||
|
||
if call_stack.location.file_name is not None: | ||
actual_file_name = os.path.basename(call_stack.location.file_name) | ||
actual_call_location_str = ( | ||
f"File: {actual_file_name}, Line: {call_stack.location.line}" | ||
) | ||
else: | ||
actual_call_location_str = "File name is None" | ||
|
||
assert ( | ||
actual_call_location_str == expected_call_location_str | ||
), f"Expected call location to be '{expected_call_location_str}' but was '{actual_call_location_str}'" | ||
|
||
|
||
def test_record_call_with_caller_file_only_true(): | ||
call_stack = recordCall(True) | ||
assert ( | ||
len(call_stack.rest_of_stack) >= 0 | ||
), "Expected the rest of stack to potentially contain only the caller's file location" |