clipsy 1.7.0__py3-none-any.whl → 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clipsy/__init__.py +1 -1
- clipsy/__main__.py +1 -0
- clipsy/app.py +9 -1
- clipsy/config.py +12 -1
- clipsy/models.py +2 -0
- clipsy/monitor.py +118 -70
- clipsy/storage.py +26 -27
- {clipsy-1.7.0.dist-info → clipsy-1.8.0.dist-info}/METADATA +9 -2
- clipsy-1.8.0.dist-info/RECORD +15 -0
- clipsy-1.7.0.dist-info/RECORD +0 -15
- {clipsy-1.7.0.dist-info → clipsy-1.8.0.dist-info}/WHEEL +0 -0
- {clipsy-1.7.0.dist-info → clipsy-1.8.0.dist-info}/entry_points.txt +0 -0
- {clipsy-1.7.0.dist-info → clipsy-1.8.0.dist-info}/licenses/LICENSE +0 -0
- {clipsy-1.7.0.dist-info → clipsy-1.8.0.dist-info}/top_level.txt +0 -0
clipsy/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.8.0"
|
|
2
2
|
__app_name__ = "Clipsy"
|
clipsy/__main__.py
CHANGED
clipsy/app.py
CHANGED
|
@@ -120,6 +120,7 @@ class ClipsyApp(rumps.App):
|
|
|
120
120
|
|
|
121
121
|
try:
|
|
122
122
|
from AppKit import NSPasteboard, NSPasteboardTypePNG, NSPasteboardTypeString
|
|
123
|
+
from Foundation import NSData
|
|
123
124
|
|
|
124
125
|
pb = NSPasteboard.generalPasteboard()
|
|
125
126
|
|
|
@@ -128,11 +129,18 @@ class ClipsyApp(rumps.App):
|
|
|
128
129
|
if entry.content_type == ContentType.TEXT and entry.text_content:
|
|
129
130
|
pb.clearContents()
|
|
130
131
|
pb.setString_forType_(entry.text_content, NSPasteboardTypeString)
|
|
132
|
+
if entry.rtf_data:
|
|
133
|
+
rtf_ns_data = NSData.dataWithBytes_length_(entry.rtf_data, len(entry.rtf_data))
|
|
134
|
+
if rtf_ns_data:
|
|
135
|
+
pb.setData_forType_(rtf_ns_data, "public.rtf")
|
|
136
|
+
if entry.html_data:
|
|
137
|
+
html_ns_data = NSData.dataWithBytes_length_(entry.html_data, len(entry.html_data))
|
|
138
|
+
if html_ns_data:
|
|
139
|
+
pb.setData_forType_(html_ns_data, "public.html")
|
|
131
140
|
self._monitor.sync_change_count()
|
|
132
141
|
copied = True
|
|
133
142
|
|
|
134
143
|
elif entry.content_type == ContentType.IMAGE and entry.image_path:
|
|
135
|
-
from Foundation import NSData
|
|
136
144
|
img_data = NSData.dataWithContentsOfFile_(entry.image_path)
|
|
137
145
|
if img_data:
|
|
138
146
|
pb.clearContents()
|
clipsy/config.py
CHANGED
|
@@ -11,6 +11,17 @@ MAX_ENTRIES = 500 # auto-purge threshold
|
|
|
11
11
|
MAX_TEXT_SIZE = 1_000_000 # 1MB text limit
|
|
12
12
|
MAX_IMAGE_SIZE = 10_000_000 # 10MB image limit
|
|
13
13
|
PREVIEW_LENGTH = 60 # characters shown in menu item
|
|
14
|
-
|
|
14
|
+
def _parse_menu_display_count() -> int:
|
|
15
|
+
raw = os.environ.get("CLIPSY_MENU_DISPLAY_COUNT")
|
|
16
|
+
if raw is None:
|
|
17
|
+
return 10
|
|
18
|
+
try:
|
|
19
|
+
value = int(raw)
|
|
20
|
+
except ValueError:
|
|
21
|
+
return 10
|
|
22
|
+
return max(5, min(50, value))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
MENU_DISPLAY_COUNT = _parse_menu_display_count()
|
|
15
26
|
THUMBNAIL_SIZE = (32, 32) # pixels, for menu icon display
|
|
16
27
|
REDACT_SENSITIVE = True # mask sensitive data in preview (API keys, passwords, etc.)
|
clipsy/models.py
CHANGED
clipsy/monitor.py
CHANGED
|
@@ -5,6 +5,16 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
from AppKit import NSPasteboard, NSPasteboardTypePNG, NSPasteboardTypeTIFF, NSPasteboardTypeString, NSFilenamesPboardType
|
|
7
7
|
|
|
8
|
+
try:
|
|
9
|
+
from AppKit import NSPasteboardTypeRTF
|
|
10
|
+
except ImportError:
|
|
11
|
+
NSPasteboardTypeRTF = "public.rtf"
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from AppKit import NSPasteboardTypeHTML
|
|
15
|
+
except ImportError:
|
|
16
|
+
NSPasteboardTypeHTML = "public.html"
|
|
17
|
+
|
|
8
18
|
from clipsy.config import IMAGE_DIR, MAX_IMAGE_SIZE, MAX_TEXT_SIZE, PREVIEW_LENGTH, REDACT_SENSITIVE, THUMBNAIL_SIZE
|
|
9
19
|
from clipsy.models import ClipboardEntry, ContentType
|
|
10
20
|
from clipsy.redact import detect_sensitive, mask_text
|
|
@@ -57,84 +67,122 @@ class ClipboardMonitor:
|
|
|
57
67
|
return None
|
|
58
68
|
|
|
59
69
|
if NSPasteboardTypeString in types:
|
|
60
|
-
|
|
61
|
-
if
|
|
62
|
-
|
|
63
|
-
if len(text_bytes) <= MAX_TEXT_SIZE:
|
|
64
|
-
content_hash = compute_hash(text_bytes)
|
|
65
|
-
preview = truncate_text(text, PREVIEW_LENGTH)
|
|
66
|
-
|
|
67
|
-
# Detect sensitive data
|
|
68
|
-
is_sensitive = False
|
|
69
|
-
masked_preview = None
|
|
70
|
-
if REDACT_SENSITIVE:
|
|
71
|
-
matches = detect_sensitive(text)
|
|
72
|
-
if matches:
|
|
73
|
-
is_sensitive = True
|
|
74
|
-
masked_preview = truncate_text(mask_text(text, matches), PREVIEW_LENGTH)
|
|
75
|
-
|
|
76
|
-
return ClipboardEntry(
|
|
77
|
-
id=None,
|
|
78
|
-
content_type=ContentType.TEXT,
|
|
79
|
-
text_content=text,
|
|
80
|
-
image_path=None,
|
|
81
|
-
preview=preview,
|
|
82
|
-
content_hash=content_hash,
|
|
83
|
-
byte_size=len(text_bytes),
|
|
84
|
-
created_at=datetime.now(),
|
|
85
|
-
is_sensitive=is_sensitive,
|
|
86
|
-
masked_preview=masked_preview,
|
|
87
|
-
)
|
|
70
|
+
entry = self._read_text()
|
|
71
|
+
if entry:
|
|
72
|
+
return entry
|
|
88
73
|
|
|
89
74
|
for img_type in (NSPasteboardTypePNG, NSPasteboardTypeTIFF):
|
|
90
75
|
if img_type in types:
|
|
91
|
-
|
|
92
|
-
if
|
|
93
|
-
|
|
94
|
-
img_bytes = bytes(data)
|
|
95
|
-
if len(img_bytes) > MAX_IMAGE_SIZE:
|
|
96
|
-
logger.warning("Image too large (%d bytes), skipping", len(img_bytes))
|
|
97
|
-
return None
|
|
98
|
-
content_hash = compute_hash(img_bytes)
|
|
99
|
-
is_png = img_type == NSPasteboardTypePNG
|
|
100
|
-
image_path, thumbnail_path = self._save_image(img_bytes, content_hash, is_png)
|
|
101
|
-
width, height = get_image_dimensions(img_bytes)
|
|
102
|
-
preview = f"[Image: {width}x{height}]" if width > 0 else "[Image]"
|
|
103
|
-
return ClipboardEntry(
|
|
104
|
-
id=None,
|
|
105
|
-
content_type=ContentType.IMAGE,
|
|
106
|
-
text_content=None,
|
|
107
|
-
image_path=str(image_path),
|
|
108
|
-
preview=preview,
|
|
109
|
-
content_hash=content_hash,
|
|
110
|
-
byte_size=len(img_bytes),
|
|
111
|
-
created_at=datetime.now(),
|
|
112
|
-
thumbnail_path=str(thumbnail_path) if thumbnail_path else None,
|
|
113
|
-
)
|
|
76
|
+
entry = self._read_image(img_type)
|
|
77
|
+
if entry:
|
|
78
|
+
return entry
|
|
114
79
|
|
|
115
80
|
if NSFilenamesPboardType in types:
|
|
116
|
-
|
|
117
|
-
if filenames:
|
|
118
|
-
file_list = list(filenames)
|
|
119
|
-
text = "\n".join(file_list)
|
|
120
|
-
content_hash = compute_hash(text)
|
|
121
|
-
if len(file_list) == 1:
|
|
122
|
-
preview = truncate_text(Path(file_list[0]).name, PREVIEW_LENGTH)
|
|
123
|
-
else:
|
|
124
|
-
preview = truncate_text(f"{len(file_list)} files: {Path(file_list[0]).name}, ...", PREVIEW_LENGTH)
|
|
125
|
-
return ClipboardEntry(
|
|
126
|
-
id=None,
|
|
127
|
-
content_type=ContentType.FILE,
|
|
128
|
-
text_content=text,
|
|
129
|
-
image_path=None,
|
|
130
|
-
preview=preview,
|
|
131
|
-
content_hash=content_hash,
|
|
132
|
-
byte_size=len(text.encode("utf-8")),
|
|
133
|
-
created_at=datetime.now(),
|
|
134
|
-
)
|
|
81
|
+
return self._read_files()
|
|
135
82
|
|
|
136
83
|
return None
|
|
137
84
|
|
|
85
|
+
def _read_text(self) -> ClipboardEntry | None:
|
|
86
|
+
text = self._pasteboard.stringForType_(NSPasteboardTypeString)
|
|
87
|
+
if not text:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
text_bytes = text.encode("utf-8")
|
|
91
|
+
if len(text_bytes) > MAX_TEXT_SIZE:
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
content_hash = compute_hash(text_bytes)
|
|
95
|
+
preview = truncate_text(text, PREVIEW_LENGTH)
|
|
96
|
+
|
|
97
|
+
rtf_data = None
|
|
98
|
+
html_data = None
|
|
99
|
+
types = self._pasteboard.types()
|
|
100
|
+
if types:
|
|
101
|
+
if NSPasteboardTypeRTF in types:
|
|
102
|
+
data = self._pasteboard.dataForType_(NSPasteboardTypeRTF)
|
|
103
|
+
if data:
|
|
104
|
+
rtf_data = bytes(data)
|
|
105
|
+
if NSPasteboardTypeHTML in types:
|
|
106
|
+
data = self._pasteboard.dataForType_(NSPasteboardTypeHTML)
|
|
107
|
+
if data:
|
|
108
|
+
html_data = bytes(data)
|
|
109
|
+
|
|
110
|
+
is_sensitive = False
|
|
111
|
+
masked_preview = None
|
|
112
|
+
if REDACT_SENSITIVE:
|
|
113
|
+
matches = detect_sensitive(text)
|
|
114
|
+
if matches:
|
|
115
|
+
is_sensitive = True
|
|
116
|
+
masked_preview = truncate_text(mask_text(text, matches), PREVIEW_LENGTH)
|
|
117
|
+
|
|
118
|
+
return ClipboardEntry(
|
|
119
|
+
id=None,
|
|
120
|
+
content_type=ContentType.TEXT,
|
|
121
|
+
text_content=text,
|
|
122
|
+
image_path=None,
|
|
123
|
+
preview=preview,
|
|
124
|
+
content_hash=content_hash,
|
|
125
|
+
byte_size=len(text_bytes),
|
|
126
|
+
created_at=datetime.now(),
|
|
127
|
+
is_sensitive=is_sensitive,
|
|
128
|
+
masked_preview=masked_preview,
|
|
129
|
+
rtf_data=rtf_data,
|
|
130
|
+
html_data=html_data,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def _read_image(self, img_type) -> ClipboardEntry | None:
|
|
134
|
+
data = self._pasteboard.dataForType_(img_type)
|
|
135
|
+
if data is None:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
img_bytes = bytes(data)
|
|
139
|
+
if len(img_bytes) > MAX_IMAGE_SIZE:
|
|
140
|
+
logger.warning("Image too large (%d bytes), skipping", len(img_bytes))
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
content_hash = compute_hash(img_bytes)
|
|
144
|
+
is_png = img_type == NSPasteboardTypePNG
|
|
145
|
+
image_path, thumbnail_path = self._save_image(img_bytes, content_hash, is_png)
|
|
146
|
+
width, height = get_image_dimensions(img_bytes)
|
|
147
|
+
preview = f"[Image: {width}x{height}]" if width > 0 else "[Image]"
|
|
148
|
+
|
|
149
|
+
return ClipboardEntry(
|
|
150
|
+
id=None,
|
|
151
|
+
content_type=ContentType.IMAGE,
|
|
152
|
+
text_content=None,
|
|
153
|
+
image_path=str(image_path),
|
|
154
|
+
preview=preview,
|
|
155
|
+
content_hash=content_hash,
|
|
156
|
+
byte_size=len(img_bytes),
|
|
157
|
+
created_at=datetime.now(),
|
|
158
|
+
thumbnail_path=str(thumbnail_path) if thumbnail_path else None,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
def _read_files(self) -> ClipboardEntry | None:
|
|
162
|
+
filenames = self._pasteboard.propertyListForType_(NSFilenamesPboardType)
|
|
163
|
+
if not filenames:
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
file_list = list(filenames)
|
|
167
|
+
text = "\n".join(file_list)
|
|
168
|
+
content_hash = compute_hash(text)
|
|
169
|
+
|
|
170
|
+
if len(file_list) == 1:
|
|
171
|
+
preview = truncate_text(Path(file_list[0]).name, PREVIEW_LENGTH)
|
|
172
|
+
else:
|
|
173
|
+
preview = truncate_text(f"{len(file_list)} files: {Path(file_list[0]).name}, ...", PREVIEW_LENGTH)
|
|
174
|
+
|
|
175
|
+
return ClipboardEntry(
|
|
176
|
+
id=None,
|
|
177
|
+
content_type=ContentType.FILE,
|
|
178
|
+
text_content=text,
|
|
179
|
+
image_path=None,
|
|
180
|
+
preview=preview,
|
|
181
|
+
content_hash=content_hash,
|
|
182
|
+
byte_size=len(text.encode("utf-8")),
|
|
183
|
+
created_at=datetime.now(),
|
|
184
|
+
)
|
|
185
|
+
|
|
138
186
|
def _save_image(self, img_bytes: bytes, content_hash: str, is_png: bool) -> tuple[Path, Path | None]:
|
|
139
187
|
ext = ".png" if is_png else ".tiff"
|
|
140
188
|
filename = content_hash[:12] + ext
|
clipsy/storage.py
CHANGED
|
@@ -20,7 +20,9 @@ CREATE TABLE IF NOT EXISTS clipboard_entries (
|
|
|
20
20
|
source_app TEXT,
|
|
21
21
|
thumbnail_path TEXT,
|
|
22
22
|
is_sensitive INTEGER NOT NULL DEFAULT 0,
|
|
23
|
-
masked_preview TEXT
|
|
23
|
+
masked_preview TEXT,
|
|
24
|
+
rtf_data BLOB,
|
|
25
|
+
html_data BLOB
|
|
24
26
|
);
|
|
25
27
|
|
|
26
28
|
CREATE INDEX IF NOT EXISTS idx_created_at ON clipboard_entries(created_at DESC);
|
|
@@ -70,12 +72,24 @@ class StorageManager:
|
|
|
70
72
|
self._conn.execute("ALTER TABLE clipboard_entries ADD COLUMN is_sensitive INTEGER NOT NULL DEFAULT 0")
|
|
71
73
|
if "masked_preview" not in columns:
|
|
72
74
|
self._conn.execute("ALTER TABLE clipboard_entries ADD COLUMN masked_preview TEXT")
|
|
75
|
+
if "rtf_data" not in columns:
|
|
76
|
+
self._conn.execute("ALTER TABLE clipboard_entries ADD COLUMN rtf_data BLOB")
|
|
77
|
+
if "html_data" not in columns:
|
|
78
|
+
self._conn.execute("ALTER TABLE clipboard_entries ADD COLUMN html_data BLOB")
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def _delete_files(image_path: str | None, thumbnail_path: str | None) -> None:
|
|
82
|
+
for file_path in (image_path, thumbnail_path):
|
|
83
|
+
if file_path:
|
|
84
|
+
p = Path(file_path)
|
|
85
|
+
if p.exists():
|
|
86
|
+
p.unlink()
|
|
73
87
|
|
|
74
88
|
def add_entry(self, entry: ClipboardEntry) -> int:
|
|
75
89
|
cursor = self._conn.execute(
|
|
76
90
|
"""INSERT INTO clipboard_entries
|
|
77
|
-
(content_type, text_content, image_path, preview, content_hash, byte_size, created_at, pinned, source_app, thumbnail_path, is_sensitive, masked_preview)
|
|
78
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
|
91
|
+
(content_type, text_content, image_path, preview, content_hash, byte_size, created_at, pinned, source_app, thumbnail_path, is_sensitive, masked_preview, rtf_data, html_data)
|
|
92
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
|
79
93
|
(
|
|
80
94
|
entry.content_type.value,
|
|
81
95
|
entry.text_content,
|
|
@@ -89,6 +103,8 @@ class StorageManager:
|
|
|
89
103
|
entry.thumbnail_path,
|
|
90
104
|
int(entry.is_sensitive),
|
|
91
105
|
entry.masked_preview,
|
|
106
|
+
entry.rtf_data,
|
|
107
|
+
entry.html_data,
|
|
92
108
|
),
|
|
93
109
|
)
|
|
94
110
|
self._conn.commit()
|
|
@@ -124,14 +140,7 @@ class StorageManager:
|
|
|
124
140
|
def delete_entry(self, entry_id: int) -> None:
|
|
125
141
|
entry = self.get_entry(entry_id)
|
|
126
142
|
if entry:
|
|
127
|
-
|
|
128
|
-
path = Path(entry.image_path)
|
|
129
|
-
if path.exists():
|
|
130
|
-
path.unlink()
|
|
131
|
-
if entry.thumbnail_path:
|
|
132
|
-
thumb = Path(entry.thumbnail_path)
|
|
133
|
-
if thumb.exists():
|
|
134
|
-
thumb.unlink()
|
|
143
|
+
self._delete_files(entry.image_path, entry.thumbnail_path)
|
|
135
144
|
self._conn.execute("DELETE FROM clipboard_entries WHERE id = ?", (entry_id,))
|
|
136
145
|
self._conn.commit()
|
|
137
146
|
|
|
@@ -169,14 +178,7 @@ class StorageManager:
|
|
|
169
178
|
|
|
170
179
|
deleted = 0
|
|
171
180
|
for row in rows:
|
|
172
|
-
|
|
173
|
-
path = Path(row["image_path"])
|
|
174
|
-
if path.exists():
|
|
175
|
-
path.unlink()
|
|
176
|
-
if row["thumbnail_path"]:
|
|
177
|
-
thumb = Path(row["thumbnail_path"])
|
|
178
|
-
if thumb.exists():
|
|
179
|
-
thumb.unlink()
|
|
181
|
+
self._delete_files(row["image_path"], row["thumbnail_path"])
|
|
180
182
|
self._conn.execute("DELETE FROM clipboard_entries WHERE id = ?", (row["id"],))
|
|
181
183
|
deleted += 1
|
|
182
184
|
|
|
@@ -201,14 +203,7 @@ class StorageManager:
|
|
|
201
203
|
"SELECT image_path, thumbnail_path FROM clipboard_entries WHERE image_path IS NOT NULL OR thumbnail_path IS NOT NULL"
|
|
202
204
|
).fetchall()
|
|
203
205
|
for row in rows:
|
|
204
|
-
|
|
205
|
-
path = Path(row["image_path"])
|
|
206
|
-
if path.exists():
|
|
207
|
-
path.unlink()
|
|
208
|
-
if row["thumbnail_path"]:
|
|
209
|
-
thumb = Path(row["thumbnail_path"])
|
|
210
|
-
if thumb.exists():
|
|
211
|
-
thumb.unlink()
|
|
206
|
+
self._delete_files(row["image_path"], row["thumbnail_path"])
|
|
212
207
|
self._conn.execute("DELETE FROM clipboard_entries")
|
|
213
208
|
self._conn.commit()
|
|
214
209
|
|
|
@@ -241,6 +236,8 @@ class StorageManager:
|
|
|
241
236
|
thumbnail_path = row["thumbnail_path"] if "thumbnail_path" in keys else None
|
|
242
237
|
is_sensitive = bool(row["is_sensitive"]) if "is_sensitive" in keys else False
|
|
243
238
|
masked_preview = row["masked_preview"] if "masked_preview" in keys else None
|
|
239
|
+
rtf_data = bytes(row["rtf_data"]) if "rtf_data" in keys and row["rtf_data"] is not None else None
|
|
240
|
+
html_data = bytes(row["html_data"]) if "html_data" in keys and row["html_data"] is not None else None
|
|
244
241
|
return ClipboardEntry(
|
|
245
242
|
id=row["id"],
|
|
246
243
|
content_type=ContentType(row["content_type"]),
|
|
@@ -255,4 +252,6 @@ class StorageManager:
|
|
|
255
252
|
thumbnail_path=thumbnail_path,
|
|
256
253
|
is_sensitive=is_sensitive,
|
|
257
254
|
masked_preview=masked_preview,
|
|
255
|
+
rtf_data=rtf_data,
|
|
256
|
+
html_data=html_data,
|
|
258
257
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clipsy
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.0
|
|
4
4
|
Summary: Lightweight clipboard history manager for macOS
|
|
5
5
|
Author-email: Brendan Conrad <brendan.conrad@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -59,7 +59,14 @@ A lightweight clipboard history manager for macOS. Runs as a menu bar icon — n
|
|
|
59
59
|
|
|
60
60
|
## Installation
|
|
61
61
|
|
|
62
|
-
### Via
|
|
62
|
+
### Via Homebrew (recommended)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
brew install brencon/clipsy/clipsy
|
|
66
|
+
clipsy
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Via pipx
|
|
63
70
|
|
|
64
71
|
```bash
|
|
65
72
|
brew install pipx
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
clipsy/__init__.py,sha256=2M96CO-qBjhCYnYgi1FZuen5WyQOvlbtLUIIPCDsES0,46
|
|
2
|
+
clipsy/__main__.py,sha256=AzUjrEhnuVX5Mkk3QhfmAO17cyvIYOABsz7QWYmw1r8,4991
|
|
3
|
+
clipsy/app.py,sha256=e987geHCfDs3_9GulTZaS2iJT-BUL_iwpNtAmt6kPW8,7786
|
|
4
|
+
clipsy/config.py,sha256=YetSNZkSkSOHYnCZpty6sGeG99MajbN4goL8UkzJ62A,913
|
|
5
|
+
clipsy/models.py,sha256=9wuaq1t9HhaH8QYuieN7fEVM_RTYEvv6ZUCM_InOMKk,632
|
|
6
|
+
clipsy/monitor.py,sha256=PBTxK53arFm5VVCHIYlxz8eoYQrgTwWsIWNE49IE7oU,6904
|
|
7
|
+
clipsy/redact.py,sha256=EU2nq8oEDYLZ_I_9tX2bXACIF971a0V_ApKdvpN4VGY,7284
|
|
8
|
+
clipsy/storage.py,sha256=ZcuW2uFvJM0Cd3UQEWIMSZYH2DYWM6lD6yol6VpM5io,10047
|
|
9
|
+
clipsy/utils.py,sha256=rztT20cXYJ7633q3oLwt6Fv0Ubq9hm5bPPKDkWyvxdI,2208
|
|
10
|
+
clipsy-1.8.0.dist-info/licenses/LICENSE,sha256=bZ7uVihgPnLGryi5ugUgkVrEoho0_hFAd3bVdhYXGqs,1071
|
|
11
|
+
clipsy-1.8.0.dist-info/METADATA,sha256=UMKIznK4wUar5eV0ic7QVLuoRdZN4fMT6AL34BbuHdE,5884
|
|
12
|
+
clipsy-1.8.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
+
clipsy-1.8.0.dist-info/entry_points.txt,sha256=ISIoWU3Zj-4NEuj2pJW96LxpsvjRJJH73otv9gA9YSs,48
|
|
14
|
+
clipsy-1.8.0.dist-info/top_level.txt,sha256=trxprVJk4ZMudCshc7PD0N9iFgQO4Tq4sW5L5wLduns,7
|
|
15
|
+
clipsy-1.8.0.dist-info/RECORD,,
|
clipsy-1.7.0.dist-info/RECORD
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
clipsy/__init__.py,sha256=5B_3MB6DYDXcJfVxDSzafJY1_-IM-eLcNadIWCMyJTc,46
|
|
2
|
-
clipsy/__main__.py,sha256=Ipb_HlLKeG5TPKdaAd4FALgrvCX9PPw9TuMF1BH0AAQ,4962
|
|
3
|
-
clipsy/app.py,sha256=_IKuZgA-DvAE3KDsDN00S0aaMIxwBpiv_P1fpzwQFqU,7299
|
|
4
|
-
clipsy/config.py,sha256=E9NCsGMeT2H0YXYCq5xYwbd27VkksV4S9txZSMX0RmE,672
|
|
5
|
-
clipsy/models.py,sha256=i3KjD4Dcp7y_gTXkIBr2xZxFIIC6kHaMWmv6cSIDABM,563
|
|
6
|
-
clipsy/monitor.py,sha256=UUKZToYcZ5pzu7LfiuJ_nnE4AA-d3uLW-WdQU_XrDME,6288
|
|
7
|
-
clipsy/redact.py,sha256=EU2nq8oEDYLZ_I_9tX2bXACIF971a0V_ApKdvpN4VGY,7284
|
|
8
|
-
clipsy/storage.py,sha256=QNox2-spkVx_gMPSWqKgF_yj-SMpRJ4UAT6yd9l6rVY,9794
|
|
9
|
-
clipsy/utils.py,sha256=rztT20cXYJ7633q3oLwt6Fv0Ubq9hm5bPPKDkWyvxdI,2208
|
|
10
|
-
clipsy-1.7.0.dist-info/licenses/LICENSE,sha256=bZ7uVihgPnLGryi5ugUgkVrEoho0_hFAd3bVdhYXGqs,1071
|
|
11
|
-
clipsy-1.7.0.dist-info/METADATA,sha256=xO1ksDaZw867EM92OS3AsH8yakCtH1doeytarvNCAtQ,5811
|
|
12
|
-
clipsy-1.7.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
-
clipsy-1.7.0.dist-info/entry_points.txt,sha256=ISIoWU3Zj-4NEuj2pJW96LxpsvjRJJH73otv9gA9YSs,48
|
|
14
|
-
clipsy-1.7.0.dist-info/top_level.txt,sha256=trxprVJk4ZMudCshc7PD0N9iFgQO4Tq4sW5L5wLduns,7
|
|
15
|
-
clipsy-1.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|