convoviz 0.2.8__py3-none-any.whl → 0.2.9__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.
@@ -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
- img.save(output_dir / f"{week.strftime('%Y week %W')}.png", optimize=True)
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
- img.save(output_dir / f"{month.strftime('%Y %B')}.png", optimize=True)
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)
convoviz/config.py CHANGED
@@ -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 (default)
14
- DATE = "date" # Nested by year/month/week
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):
convoviz/io/writers.py CHANGED
@@ -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/week
36
- Example: 2024/03-March/Week-02/
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
- # Week folder: "Week-01" through "Week-05" (week of the month)
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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convoviz
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: Get analytics and visualizations on your ChatGPT data!
5
5
  Keywords: markdown,chatgpt,openai,visualization,analytics,json,export,data-analysis,obsidian
6
6
  Author: Mohamed Cheikh Sidiya
@@ -2,7 +2,7 @@ convoviz/__init__.py,sha256=bQLCHO2U9EyMTGqNgsYiCtBQKTKNj4iIM3-TwIkrnRY,612
2
2
  convoviz/__main__.py,sha256=1qiGW13_SgL7wJi8iioIN-AAHGkNGnEl5q_RcPUrI0s,143
3
3
  convoviz/analysis/__init__.py,sha256=FxgH5JJpyypiLJpMQn_HlM51jnb8lQdP63_C_W3Dlx4,241
4
4
  convoviz/analysis/graphs.py,sha256=gt056UkgGcy9vCkupQmW_HjOLy-W6j4Ekxr315BXPgA,29457
5
- convoviz/analysis/wordcloud.py,sha256=ZnbA_-rcXHwXIny_xbudfJDQbIuPT7urNFfHcx6QWxQ,4673
5
+ convoviz/analysis/wordcloud.py,sha256=WLZhBo5Ha83o6XJyzjhgx4tDjgPX-Q9kizCxfmxlJ3A,4828
6
6
  convoviz/assets/colormaps.txt,sha256=59TSGz428AxY14AEvymAH2IJ2RT9Mlp7Sy0N12NEdXQ,108
7
7
  convoviz/assets/fonts/AmaticSC-Regular.ttf,sha256=83clh7a3urnTLud0_yZofuIb6BdyC2LMI9jhE6G2LvU,142696
8
8
  convoviz/assets/fonts/ArchitectsDaughter-Regular.ttf,sha256=fnrj5_N_SlY2Lj3Ehqz5aKECPZVJlJAflgsOU94_qIM,37756
@@ -37,13 +37,13 @@ convoviz/assets/fonts/YsabeauSC-Thin.ttf,sha256=hZGOZNTRrxbiUPE2VDeLbtnaRwkMOBaV
37
37
  convoviz/assets/fonts/Zeyada-Regular.ttf,sha256=fKhkrp9VHt_3Aw8JfkfkPeC2j3CilLWuPUudzBeawPQ,57468
38
38
  convoviz/assets/stopwords.txt,sha256=7_ywpxsKYOj3U5CZTh9lP4GqbbkZLMabSOjKAXFk6Wc,539
39
39
  convoviz/cli.py,sha256=TPboT0maH_b_EjiT9cWbUSyMFz4ozoqf1_R-4AzY31g,3730
40
- convoviz/config.py,sha256=5fklWzwr0aNyeEJG0NAggLhT0xI0kwgxhjyh9_zUvwM,3112
40
+ convoviz/config.py,sha256=9qB9pT2v8q0FD1CBu9yCcEwMskYvUxXMfY17-R-tKbU,3107
41
41
  convoviz/exceptions.py,sha256=bQpIKls48uOQpagEJAxpXf5LF7QoagRRfbD0MjWC7Ak,1476
42
42
  convoviz/interactive.py,sha256=VXtKgYo9tZGtsoj7zThdnbTrbjSNP5MzAZbdOs3icW4,7424
43
43
  convoviz/io/__init__.py,sha256=y70TYypJ36_kaEA04E2wa1EDaKQVjprKItoKR6MMs4M,471
44
44
  convoviz/io/assets.py,sha256=WLauNEvk9QRo0Q52KE_bPyCRFa1CjM54L1j8SsTfGwg,2894
45
45
  convoviz/io/loaders.py,sha256=RuGiGzpyNcgwTxOM-m2ehhyh2mP1-k1YamK8-VynR3g,5713
46
- convoviz/io/writers.py,sha256=UW-JF5uq91NV62qpFVqgWTYSzzOAkLv67zDpulz2iBc,5072
46
+ convoviz/io/writers.py,sha256=krGvU6UJMrDxZCqt3u_lyLA_gS0oSbeUXhYNFbY4mHo,6862
47
47
  convoviz/models/__init__.py,sha256=6gAfrk6KJT2QxdvX_v15mUdfIqEw1xKxwQlKSfyA5eI,532
48
48
  convoviz/models/collection.py,sha256=L658yKMNC6IZrfxYxZBe-oO9COP_bzVfRznnNon7tfU,4467
49
49
  convoviz/models/conversation.py,sha256=ssx1Z6LM9kJIx3OucQW8JVoAc8zCdxj1iOLtie2B3ak,5678
@@ -55,7 +55,7 @@ convoviz/renderers/__init__.py,sha256=IQgwD9NqtUgbS9zwyPBNZbBIZcFrbZ9C7WMAV-X3Xd
55
55
  convoviz/renderers/markdown.py,sha256=mpDt-xrjsPX_wt9URCDk2wicesaVv_VTWWxTHCMKiLM,7765
56
56
  convoviz/renderers/yaml.py,sha256=XG1s4VhDdx-TiqekTkgED87RZ1lVQ7IwrbA-sZHrs7k,4056
57
57
  convoviz/utils.py,sha256=IQEKYHhWOnYxlr4GwAHoquG0BXTlVRkORL80oUSaIeQ,3417
58
- convoviz-0.2.8.dist-info/WHEEL,sha256=eycQt0QpYmJMLKpE3X9iDk8R04v2ZF0x82ogq-zP6bQ,79
59
- convoviz-0.2.8.dist-info/entry_points.txt,sha256=HYsmsw5vt36yYHB05uVU48AK2WLkcwshly7m7KKuZMY,54
60
- convoviz-0.2.8.dist-info/METADATA,sha256=DeO9FBLgHoXlvRDnMiBBSM6qT-h-1bqyQSHqIKb1zrg,5757
61
- convoviz-0.2.8.dist-info/RECORD,,
58
+ convoviz-0.2.9.dist-info/WHEEL,sha256=eycQt0QpYmJMLKpE3X9iDk8R04v2ZF0x82ogq-zP6bQ,79
59
+ convoviz-0.2.9.dist-info/entry_points.txt,sha256=HYsmsw5vt36yYHB05uVU48AK2WLkcwshly7m7KKuZMY,54
60
+ convoviz-0.2.9.dist-info/METADATA,sha256=izOEPI6IMXeW8Ql4v9zjFMvn2Ljfb83wDDjZX1MirfA,5757
61
+ convoviz-0.2.9.dist-info/RECORD,,