Selfie
Loading...
Searching...
No Matches
CommentTracker.py
Go to the documentation of this file.
1import threading
2from collections.abc import Iterable
3from enum import Enum, auto
4
5from .Slice import Slice
6from .TypedPath import TypedPath
7from .WriteTracker import CallStack, SnapshotFileLayout
8
9
10class WritableComment(Enum):
11 NO_COMMENT = auto()
12 ONCE = auto()
13 FOREVER = auto()
14
15 @property
16 def writable(self) -> bool:
17 return self != WritableComment.NO_COMMENT
18
19
21 def __init__(self):
22 self.cache: dict[TypedPath, WritableComment] = {}
23 self.lock = threading.Lock()
24
25 def paths_with_once(self) -> Iterable[TypedPath]:
26 with self.lock:
27 return [
28 path
29 for path, comment in self.cache.items()
30 if comment == WritableComment.ONCE
31 ]
32
33 def hasWritableComment(self, call: CallStack, layout: SnapshotFileLayout) -> bool:
34 path = layout.sourcefile_for_call(call.location)
35 with self.lock:
36 if path in self.cache:
37 return self.cache[path].writable
38 else:
39 new_comment, _ = self.__commentAndLine(path)
40 self.cache[path] = new_comment
41 return new_comment.writable
42
43 @staticmethod
44 def commentString(typedPath: TypedPath) -> tuple[str, int]:
45 comment, line = CommentTracker.__commentAndLine(typedPath)
46 if comment == WritableComment.NO_COMMENT:
47 raise ValueError("No writable comment found")
48 elif comment == WritableComment.ONCE:
49 return ("#selfieonce", line)
50 elif comment == WritableComment.FOREVER:
51 return ("#SELFIEWRITE", line)
52 else:
53 raise ValueError("Invalid comment type")
54
55 @staticmethod
56 def __commentAndLine(typedPath: TypedPath) -> tuple[WritableComment, int]:
57 with open(typedPath.absolute_path, encoding="utf-8") as file:
58 content = Slice(file.read())
59 for comment_str in [
60 "# selfieonce",
61 "#selfieonce",
62 "# SELFIEWRITE",
63 "#SELFIEWRITE",
64 ]:
65 index = content.indexOf(comment_str)
66 if index != -1:
67 lineNumber = content.baseLineAtOffset(index)
68 comment = (
69 WritableComment.ONCE
70 if "once" in comment_str
71 else WritableComment.FOREVER
72 )
73 return (comment, lineNumber)
74 return (WritableComment.NO_COMMENT, -1)
tuple[WritableComment, int] __commentAndLine(TypedPath typedPath)
Iterable[TypedPath] paths_with_once(self)
bool hasWritableComment(self, CallStack call, SnapshotFileLayout layout)
tuple[str, int] commentString(TypedPath typedPath)