convoviz 0.2.8__tar.gz → 0.2.9__tar.gz
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.
- {convoviz-0.2.8 → convoviz-0.2.9}/PKG-INFO +1 -1
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/analysis/wordcloud.py +5 -2
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/config.py +2 -2
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/io/writers.py +69 -9
- {convoviz-0.2.8 → convoviz-0.2.9}/pyproject.toml +1 -1
- {convoviz-0.2.8 → convoviz-0.2.9}/README.md +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/__init__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/__main__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/analysis/__init__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/analysis/graphs.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/colormaps.txt +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/AmaticSC-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/ArchitectsDaughter-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/BebasNeue-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Borel-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Courgette-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/CroissantOne-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Handjet-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/IndieFlower-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Kalam-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Lobster-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/MartianMono-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/MartianMono-Thin.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Montserrat-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Mooli-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Pacifico-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/PlayfairDisplay-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Raleway-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/RobotoMono-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/RobotoMono-Thin.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/RobotoSlab-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/RobotoSlab-Thin.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Ruwudu-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Sacramento-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/SedgwickAveDisplay-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/ShadowsIntoLight-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/TitilliumWeb-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Yellowtail-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/YsabeauOffice-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/YsabeauSC-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/YsabeauSC-Thin.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/fonts/Zeyada-Regular.ttf +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/assets/stopwords.txt +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/cli.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/exceptions.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/interactive.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/io/__init__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/io/assets.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/io/loaders.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/models/__init__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/models/collection.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/models/conversation.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/models/message.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/models/node.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/pipeline.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/py.typed +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/renderers/__init__.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/renderers/markdown.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/renderers/yaml.py +0 -0
- {convoviz-0.2.8 → convoviz-0.2.9}/convoviz/utils.py +0 -0
|
@@ -139,7 +139,8 @@ def generate_wordclouds(
|
|
|
139
139
|
text = group.plaintext("user", "assistant")
|
|
140
140
|
if text.strip():
|
|
141
141
|
img = generate_wordcloud(text, config)
|
|
142
|
-
|
|
142
|
+
# Format: 2024-W15.png (ISO week format)
|
|
143
|
+
img.save(output_dir / f"{week.strftime('%Y-W%W')}.png", optimize=True)
|
|
143
144
|
|
|
144
145
|
for month, group in tqdm(
|
|
145
146
|
month_groups.items(),
|
|
@@ -149,7 +150,8 @@ def generate_wordclouds(
|
|
|
149
150
|
text = group.plaintext("user", "assistant")
|
|
150
151
|
if text.strip():
|
|
151
152
|
img = generate_wordcloud(text, config)
|
|
152
|
-
|
|
153
|
+
# Format: 2024-03-March.png (consistent with folder naming)
|
|
154
|
+
img.save(output_dir / f"{month.strftime('%Y-%m-%B')}.png", optimize=True)
|
|
153
155
|
|
|
154
156
|
for year, group in tqdm(
|
|
155
157
|
year_groups.items(),
|
|
@@ -159,4 +161,5 @@ def generate_wordclouds(
|
|
|
159
161
|
text = group.plaintext("user", "assistant")
|
|
160
162
|
if text.strip():
|
|
161
163
|
img = generate_wordcloud(text, config)
|
|
164
|
+
# Format: 2024.png
|
|
162
165
|
img.save(output_dir / f"{year.strftime('%Y')}.png", optimize=True)
|
|
@@ -10,8 +10,8 @@ from pydantic import BaseModel, Field
|
|
|
10
10
|
class FolderOrganization(str, Enum):
|
|
11
11
|
"""How to organize markdown output files in folders."""
|
|
12
12
|
|
|
13
|
-
FLAT = "flat" # All files in one directory
|
|
14
|
-
DATE = "date" # Nested by year/month
|
|
13
|
+
FLAT = "flat" # All files in one directory
|
|
14
|
+
DATE = "date" # Nested by year/month (default)
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class AuthorHeaders(BaseModel):
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from os import utime as os_utime
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from urllib.parse import quote
|
|
5
6
|
|
|
6
7
|
from orjson import OPT_INDENT_2, dumps
|
|
7
8
|
from tqdm import tqdm
|
|
@@ -32,8 +33,8 @@ _MONTH_NAMES = [
|
|
|
32
33
|
def get_date_folder_path(conversation: Conversation) -> Path:
|
|
33
34
|
"""Get the date-based folder path for a conversation.
|
|
34
35
|
|
|
35
|
-
Creates a nested structure: year/month
|
|
36
|
-
Example: 2024/03-March/
|
|
36
|
+
Creates a nested structure: year/month
|
|
37
|
+
Example: 2024/03-March/
|
|
37
38
|
|
|
38
39
|
Args:
|
|
39
40
|
conversation: The conversation to get the path for
|
|
@@ -51,13 +52,7 @@ def get_date_folder_path(conversation: Conversation) -> Path:
|
|
|
51
52
|
month_name = _MONTH_NAMES[month_num - 1]
|
|
52
53
|
month = f"{month_num:02d}-{month_name}"
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
# Calculate which week of the month this date falls into
|
|
56
|
-
day = create_time.day
|
|
57
|
-
week_of_month = (day - 1) // 7 + 1
|
|
58
|
-
week = f"Week-{week_of_month:02d}"
|
|
59
|
-
|
|
60
|
-
return Path(year) / month / week
|
|
55
|
+
return Path(year) / month
|
|
61
56
|
|
|
62
57
|
|
|
63
58
|
def save_conversation(
|
|
@@ -115,6 +110,62 @@ def save_conversation(
|
|
|
115
110
|
return final_path
|
|
116
111
|
|
|
117
112
|
|
|
113
|
+
def _generate_year_index(year_dir: Path, year: str) -> None:
|
|
114
|
+
"""Generate a _index.md file for a year folder.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
year_dir: Path to the year directory
|
|
118
|
+
year: The year string (e.g., "2024")
|
|
119
|
+
"""
|
|
120
|
+
months = sorted(
|
|
121
|
+
[d.name for d in year_dir.iterdir() if d.is_dir()],
|
|
122
|
+
key=lambda m: int(m.split("-")[0]),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
lines = [
|
|
126
|
+
f"# {year}",
|
|
127
|
+
"",
|
|
128
|
+
"## Months",
|
|
129
|
+
"",
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
for month in months:
|
|
133
|
+
month_name = month.split("-", 1)[1] if "-" in month else month
|
|
134
|
+
lines.append(f"- [{month_name}]({month}/_index.md)")
|
|
135
|
+
|
|
136
|
+
index_path = year_dir / "_index.md"
|
|
137
|
+
index_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _generate_month_index(month_dir: Path, year: str, month: str) -> None:
|
|
141
|
+
"""Generate a _index.md file for a month folder.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
month_dir: Path to the month directory
|
|
145
|
+
year: The year string (e.g., "2024")
|
|
146
|
+
month: The month folder name (e.g., "03-March")
|
|
147
|
+
"""
|
|
148
|
+
month_name = month.split("-", 1)[1] if "-" in month else month
|
|
149
|
+
files = sorted(
|
|
150
|
+
[f.name for f in month_dir.glob("*.md") if f.name != "_index.md"]
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
lines = [
|
|
154
|
+
f"# {month_name} {year}",
|
|
155
|
+
"",
|
|
156
|
+
"## Conversations",
|
|
157
|
+
"",
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
for file in files:
|
|
161
|
+
title = file[:-3] # Remove .md extension
|
|
162
|
+
encoded_file = quote(file)
|
|
163
|
+
lines.append(f"- [{title}]({encoded_file})")
|
|
164
|
+
|
|
165
|
+
index_path = month_dir / "_index.md"
|
|
166
|
+
index_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
167
|
+
|
|
168
|
+
|
|
118
169
|
def save_collection(
|
|
119
170
|
collection: ConversationCollection,
|
|
120
171
|
directory: Path,
|
|
@@ -151,6 +202,15 @@ def save_collection(
|
|
|
151
202
|
filepath = target_dir / f"{sanitize(conv.title)}.md"
|
|
152
203
|
save_conversation(conv, filepath, config, headers, source_path=collection.source_path)
|
|
153
204
|
|
|
205
|
+
# Generate index files for date organization
|
|
206
|
+
if folder_organization == FolderOrganization.DATE:
|
|
207
|
+
for year_dir in directory.iterdir():
|
|
208
|
+
if year_dir.is_dir() and year_dir.name.isdigit():
|
|
209
|
+
for month_dir in year_dir.iterdir():
|
|
210
|
+
if month_dir.is_dir():
|
|
211
|
+
_generate_month_index(month_dir, year_dir.name, month_dir.name)
|
|
212
|
+
_generate_year_index(year_dir, year_dir.name)
|
|
213
|
+
|
|
154
214
|
|
|
155
215
|
def save_custom_instructions(
|
|
156
216
|
collection: ConversationCollection,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|