promnesia 1.3.20241021__py3-none-any.whl → 1.4.20250909__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.
Files changed (68) hide show
  1. promnesia/__init__.py +4 -1
  2. promnesia/__main__.py +72 -59
  3. promnesia/cannon.py +90 -89
  4. promnesia/common.py +74 -62
  5. promnesia/compare.py +15 -10
  6. promnesia/config.py +22 -17
  7. promnesia/database/dump.py +1 -2
  8. promnesia/extract.py +6 -6
  9. promnesia/logging.py +27 -15
  10. promnesia/misc/install_server.py +25 -19
  11. promnesia/server.py +69 -53
  12. promnesia/sources/auto.py +65 -51
  13. promnesia/sources/browser.py +7 -2
  14. promnesia/sources/browser_legacy.py +51 -40
  15. promnesia/sources/demo.py +0 -1
  16. promnesia/sources/fbmessenger.py +0 -1
  17. promnesia/sources/filetypes.py +15 -11
  18. promnesia/sources/github.py +4 -1
  19. promnesia/sources/guess.py +4 -1
  20. promnesia/sources/hackernews.py +5 -7
  21. promnesia/sources/hpi.py +3 -1
  22. promnesia/sources/html.py +4 -2
  23. promnesia/sources/instapaper.py +1 -0
  24. promnesia/sources/markdown.py +4 -4
  25. promnesia/sources/org.py +17 -8
  26. promnesia/sources/plaintext.py +14 -11
  27. promnesia/sources/pocket.py +2 -1
  28. promnesia/sources/reddit.py +5 -8
  29. promnesia/sources/roamresearch.py +3 -1
  30. promnesia/sources/rss.py +4 -5
  31. promnesia/sources/shellcmd.py +3 -6
  32. promnesia/sources/signal.py +14 -14
  33. promnesia/sources/smscalls.py +0 -1
  34. promnesia/sources/stackexchange.py +2 -2
  35. promnesia/sources/takeout.py +14 -21
  36. promnesia/sources/takeout_legacy.py +16 -10
  37. promnesia/sources/telegram.py +7 -3
  38. promnesia/sources/telegram_legacy.py +5 -5
  39. promnesia/sources/twitter.py +1 -1
  40. promnesia/sources/vcs.py +6 -3
  41. promnesia/sources/viber.py +2 -2
  42. promnesia/sources/website.py +4 -3
  43. promnesia/sqlite.py +10 -7
  44. promnesia/tests/common.py +2 -0
  45. promnesia/tests/server_helper.py +2 -2
  46. promnesia/tests/sources/test_filetypes.py +9 -7
  47. promnesia/tests/sources/test_hypothesis.py +7 -3
  48. promnesia/tests/sources/test_org.py +7 -2
  49. promnesia/tests/sources/test_plaintext.py +9 -7
  50. promnesia/tests/sources/test_shellcmd.py +10 -9
  51. promnesia/tests/test_cannon.py +254 -237
  52. promnesia/tests/test_cli.py +8 -2
  53. promnesia/tests/test_compare.py +16 -12
  54. promnesia/tests/test_db_dump.py +4 -3
  55. promnesia/tests/test_extract.py +7 -4
  56. promnesia/tests/test_indexer.py +10 -10
  57. promnesia/tests/test_server.py +10 -10
  58. promnesia/tests/utils.py +1 -5
  59. promnesia-1.4.20250909.dist-info/METADATA +66 -0
  60. promnesia-1.4.20250909.dist-info/RECORD +80 -0
  61. {promnesia-1.3.20241021.dist-info → promnesia-1.4.20250909.dist-info}/WHEEL +1 -2
  62. promnesia/kjson.py +0 -122
  63. promnesia/sources/__init__.pyi +0 -0
  64. promnesia-1.3.20241021.dist-info/METADATA +0 -55
  65. promnesia-1.3.20241021.dist-info/RECORD +0 -83
  66. promnesia-1.3.20241021.dist-info/top_level.txt +0 -1
  67. {promnesia-1.3.20241021.dist-info → promnesia-1.4.20250909.dist-info}/entry_points.txt +0 -0
  68. {promnesia-1.3.20241021.dist-info → promnesia-1.4.20250909.dist-info/licenses}/LICENSE +0 -0
@@ -5,10 +5,10 @@ from datetime import datetime, timedelta, timezone
5
5
  from pathlib import Path
6
6
  from tempfile import TemporaryDirectory
7
7
  from typing import Any
8
+ from zoneinfo import ZoneInfo
8
9
 
9
10
  # NOTE: pytest ... -s --hypothesis-verbosity=debug is useful for seeing what hypothesis is doing
10
11
  import pytest
11
- import pytz
12
12
  from hypothesis import given, settings
13
13
  from hypothesis.strategies import from_type
14
14
 
@@ -44,7 +44,7 @@ def test_no_visits(tmp_path: Path) -> None:
44
44
 
45
45
  def test_one_visit(tmp_path: Path) -> None:
46
46
  dt = datetime.fromisoformat('2023-11-14T23:11:01')
47
- dt = pytz.timezone('Europe/Warsaw').localize(dt)
47
+ dt = dt.replace(tzinfo=ZoneInfo('Europe/Warsaw'))
48
48
  visit = DbVisit(
49
49
  norm_url='google.com',
50
50
  orig_url='https://google.com',
@@ -156,7 +156,8 @@ def test_random_visit(visit: DbVisit) -> None:
156
156
 
157
157
 
158
158
  _dt_naive = datetime.fromisoformat('2023-11-14T23:11:01')
159
- _dt_aware = pytz.timezone('America/New_York').localize(_dt_naive)
159
+ _dt_aware = _dt_naive.replace(tzinfo=ZoneInfo('America/New_York'))
160
+
160
161
 
161
162
  def make_testvisit(i: int) -> DbVisit:
162
163
  return DbVisit(
@@ -35,10 +35,12 @@ def test_urls_are_normalised() -> None:
35
35
  from ..sources import shellcmd
36
36
  from ..sources.plaintext import extract_from_path
37
37
 
38
- visits = list(extract_visits(
39
- source=Source(shellcmd.index, extract_from_path(get_testdata('normalise'))),
40
- src='whatever',
41
- ))
38
+ visits = list(
39
+ extract_visits(
40
+ source=Source(shellcmd.index, extract_from_path(get_testdata('normalise'))),
41
+ src='whatever',
42
+ )
43
+ )
42
44
  assert len(visits) == 7
43
45
 
44
46
  assert {unwrap(v).norm_url for v in visits} == {
@@ -59,6 +61,7 @@ def test_benchmark(count: int, gc_control) -> None:
59
61
  pytest.skip("test would be too slow on CI, only meant to run manually")
60
62
 
61
63
  from ..sources import demo
64
+
62
65
  source = Source(demo.index, count=count)
63
66
 
64
67
  total = ilen(extract_visits(source=source, src='whatever'))
@@ -32,7 +32,7 @@ def test_indexing_mode(tmp_path: Path, mode: str) -> None:
32
32
  from promnesia.common import Source
33
33
  from promnesia.sources import demo
34
34
 
35
- SOURCES = [
35
+ SOURCES = [ # noqa: F841
36
36
  Source(demo.index, count=10, base_dt='2000-01-01', delta=30, name='demo1'),
37
37
  Source(demo.index, count=20, base_dt='2001-01-01', delta=30, name='demo2'),
38
38
  ]
@@ -48,7 +48,7 @@ def test_indexing_mode(tmp_path: Path, mode: str) -> None:
48
48
  from promnesia.common import Source
49
49
  from promnesia.sources import demo
50
50
 
51
- SOURCES = [
51
+ SOURCES = [ # noqa: F841
52
52
  Source(demo.index, count=30, base_dt='2005-01-01', delta=30, name='demo2'),
53
53
  Source(demo.index, count=40, base_dt='2010-01-01', delta=30, name='demo3'),
54
54
  ]
@@ -73,7 +73,7 @@ def test_concurrent_indexing(tmp_path: Path) -> None:
73
73
  from promnesia.common import Source
74
74
  from promnesia.sources import demo
75
75
 
76
- SOURCES = [Source(demo.index, count=10)]
76
+ SOURCES = [Source(demo.index, count=10)] # noqa: F841
77
77
 
78
78
  cfg_fast_path = tmp_path / 'cfg_fast.py'
79
79
  write_config(cfg_fast_path, cfg_fast)
@@ -82,7 +82,7 @@ def test_concurrent_indexing(tmp_path: Path) -> None:
82
82
  from promnesia.common import Source
83
83
  from promnesia.sources import demo
84
84
 
85
- SOURCES = [Source(demo.index, count=100_000)]
85
+ SOURCES = [Source(demo.index, count=100_000)] # noqa: F841
86
86
 
87
87
  cfg_slow_path = tmp_path / 'cfg_slow.py'
88
88
  write_config(cfg_slow_path, cfg_slow)
@@ -101,7 +101,7 @@ def test_concurrent_indexing(tmp_path: Path) -> None:
101
101
  fasts = [
102
102
  Popen(promnesia_bin('index', '--config', cfg_fast_path, '--overwrite'))
103
103
  for _ in range(10)
104
- ]
104
+ ] # fmt: skip
105
105
  for fast in fasts:
106
106
  assert fast.wait() == 0, fast # should succeed
107
107
  total_runs += 1
@@ -122,11 +122,11 @@ def test_filter(tmp_path: Path, reset_filters) -> None:
122
122
  from promnesia.sources import shellcmd
123
123
  from promnesia.sources.plaintext import extract_from_path
124
124
 
125
- FILTERS = [
125
+ FILTERS = [ # noqa: F841
126
126
  domain_to_filter,
127
127
  ]
128
128
 
129
- SOURCES = [Source(shellcmd.index, extract_from_path(testdata))]
129
+ SOURCES = [Source(shellcmd.index, extract_from_path(testdata))] # noqa: F841
130
130
 
131
131
  cfg_path = tmp_path / 'config.py'
132
132
  write_config(cfg_path, cfg, testdata=testdata, domain_to_filter=domain_to_filter)
@@ -147,7 +147,7 @@ def test_weird_urls(tmp_path: Path) -> None:
147
147
  from promnesia.sources import shellcmd
148
148
  from promnesia.sources.plaintext import extract_from_path
149
149
 
150
- SOURCES = [Source(shellcmd.index, extract_from_path(testdata))]
150
+ SOURCES = [Source(shellcmd.index, extract_from_path(testdata))] # noqa: F841
151
151
 
152
152
  cfg_path = tmp_path / 'config.py'
153
153
  write_config(cfg_path, cfg, testdata=get_testdata('weird.txt'))
@@ -176,7 +176,7 @@ def test_errors_during_indexing(tmp_path: Path) -> None:
176
176
  def indexer2():
177
177
  raise RuntimeError("in this case indexer itself crashed")
178
178
 
179
- SOURCES = [Source(indexer1), Source(indexer2)]
179
+ SOURCES = [Source(indexer1), Source(indexer2)] # noqa: F841
180
180
 
181
181
  cfg_path = tmp_path / 'config.py'
182
182
  write_config(cfg_path, cfg)
@@ -194,7 +194,7 @@ def test_hook(tmp_path: Path) -> None:
194
194
  from promnesia.common import Source
195
195
  from promnesia.sources import demo
196
196
 
197
- SOURCES = [Source(demo.index, count=7, name='somename')]
197
+ SOURCES = [Source(demo.index, count=7, name='somename')] # noqa: F841
198
198
 
199
199
  from collections.abc import Iterator
200
200
  from typing import cast
@@ -33,7 +33,7 @@ def test_status_ok(tmp_path: Path) -> None:
33
33
  from promnesia.common import Source
34
34
  from promnesia.sources import demo
35
35
 
36
- SOURCES = [Source(demo.index, count=10)]
36
+ SOURCES = [Source(demo.index, count=10)] # noqa: F841
37
37
 
38
38
  cfg_path = tmp_path / 'config.py'
39
39
  write_config(cfg_path, cfg)
@@ -56,7 +56,7 @@ def test_visits(tmp_path: Path) -> None:
56
56
  from promnesia.common import Source
57
57
  from promnesia.sources import demo
58
58
 
59
- SOURCES = [Source(demo.index, base_dt='2000-01-01', delta=30 * 60)]
59
+ SOURCES = [Source(demo.index, base_dt='2000-01-01', delta=30 * 60)] # noqa: F841
60
60
 
61
61
  cfg_path = tmp_path / 'config.py'
62
62
  write_config(cfg_path, cfg)
@@ -116,7 +116,7 @@ def test_visits_hierarchy(tmp_path: Path) -> None:
116
116
  context='I am comment 1',
117
117
  )
118
118
 
119
- SOURCES = [Source(indexer)]
119
+ SOURCES = [Source(indexer)] # noqa: F841
120
120
 
121
121
  cfg_path = tmp_path / 'config.py'
122
122
  write_config(cfg_path, cfg)
@@ -138,7 +138,7 @@ def test_visited(tmp_path: Path) -> None:
138
138
  from promnesia.common import Source
139
139
  from promnesia.sources import demo
140
140
 
141
- SOURCES = [Source(demo.index, base_dt='2000-01-01', delta=30 * 60)]
141
+ SOURCES = [Source(demo.index, base_dt='2000-01-01', delta=30 * 60)] # noqa: F841
142
142
 
143
143
  cfg_path = tmp_path / 'config.py'
144
144
  write_config(cfg_path, cfg)
@@ -184,7 +184,7 @@ def test_search(tmp_path: Path) -> None:
184
184
  )
185
185
  yield from visits[3:]
186
186
 
187
- SOURCES = [Source(indexer)]
187
+ SOURCES = [Source(indexer)] # noqa: F841
188
188
 
189
189
  cfg_path = tmp_path / 'config.py'
190
190
  write_config(cfg_path, cfg)
@@ -214,7 +214,7 @@ def test_search_around(tmp_path: Path) -> None:
214
214
  from promnesia.sources import demo
215
215
 
216
216
  # generates 60 visits within 10 mins of each other -- so spanning over 10 hours
217
- SOURCES = [Source(demo.index, count=60, base_dt='2000-01-01T00:00:00+03:00', delta=10 * 60)]
217
+ SOURCES = [Source(demo.index, count=60, base_dt='2000-01-01T00:00:00+03:00', delta=10 * 60)] # noqa: F841
218
218
 
219
219
  cfg_path = tmp_path / 'config.py'
220
220
  write_config(cfg_path, cfg)
@@ -234,8 +234,8 @@ def test_search_around(tmp_path: Path) -> None:
234
234
  ).json()
235
235
  visits = rj['visits']
236
236
  assert len(visits) == 18 # 6 per hour * 3
237
- assert visits[0 ]['dt'] == '01 Jan 2000 02:00:00 +0300'
238
- assert visits[-1]['dt'] == '01 Jan 2000 04:50:00 +0300'
237
+ assert visits[0 ]['dt'] == '01 Jan 2000 02:00:00 +0300' # fmt: skip
238
+ assert visits[-1]['dt'] == '01 Jan 2000 04:50:00 +0300' # fmt: skip
239
239
 
240
240
 
241
241
  @pytest.mark.parametrize('mode', ['update', 'overwrite'])
@@ -248,7 +248,7 @@ def test_query_while_indexing(tmp_path: Path, mode: str) -> None:
248
248
  from promnesia.common import Source
249
249
  from promnesia.sources import demo
250
250
 
251
- SOURCES = [Source(demo.index, count=1_000, name=run_id)]
251
+ SOURCES = [Source(demo.index, count=1_000, name=run_id)] # noqa: F841
252
252
 
253
253
  cfg_path = tmp_path / f'config{run_id}.py'
254
254
  write_config(cfg_path, cfg, run_id=run_id)
@@ -284,7 +284,7 @@ def test_query_while_indexing(tmp_path: Path, mode: str) -> None:
284
284
  # S.EnvConfig.set(S.ServerConfig(
285
285
  # # TODO populate with test db and benchmark properly...
286
286
  # db=Path('/todo'),
287
- # timezone=pytz.utc,
287
+ # timezone=timezone.utc,
288
288
  # ))
289
289
  # links = [f'https://reddit.com/whatever{i}.html' for i in range(count)]
290
290
  # res = S.visited(links)
promnesia/tests/utils.py CHANGED
@@ -1,17 +1,13 @@
1
1
  from collections.abc import Mapping, Sequence
2
2
  from datetime import datetime, timedelta
3
3
  from pathlib import Path
4
- from typing import Optional, Union
5
4
 
6
5
  from ..common import Loc, Source, Visit
7
6
  from ..database.dump import visits_to_sqlite
8
7
  from ..extract import extract_visits
9
8
 
10
9
  # TODO a bit shit... why did I make it dict at first??
11
- Urls = Union[
12
- Mapping[str, Optional[str]],
13
- Sequence[tuple[str, Optional[str]]],
14
- ]
10
+ Urls = Mapping[str, str | None] | Sequence[tuple[str, str | None]]
15
11
 
16
12
 
17
13
  def index_urls(urls: Urls, *, source_name: str = 'test'):
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: promnesia
3
+ Version: 1.4.20250909
4
+ Summary: Enhancement of your browsing history
5
+ Project-URL: Homepage, https://github.com/karlicoss/promnesia
6
+ Author-email: "Dima Gerasimov (@karlicoss)" <karlicoss@gmail.com>
7
+ Maintainer-email: "Dima Gerasimov (@karlicoss)" <karlicoss@gmail.com>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2018 Dmitrii Gerasimov
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Requires-Python: >=3.10
31
+ Requires-Dist: more-itertools
32
+ Requires-Dist: platformdirs
33
+ Requires-Dist: promnesia[indexer]
34
+ Requires-Dist: promnesia[server]
35
+ Requires-Dist: sqlalchemy>=2.0
36
+ Requires-Dist: typing-extensions
37
+ Requires-Dist: tzlocal
38
+ Provides-Extra: all
39
+ Requires-Dist: beautifulsoup4; extra == 'all'
40
+ Requires-Dist: fastapi; extra == 'all'
41
+ Requires-Dist: hpi; extra == 'all'
42
+ Requires-Dist: logzero; extra == 'all'
43
+ Requires-Dist: lxml; extra == 'all'
44
+ Requires-Dist: mistletoe; extra == 'all'
45
+ Requires-Dist: orgparse>=0.3.0; extra == 'all'
46
+ Requires-Dist: python-magic; extra == 'all'
47
+ Requires-Dist: urlextract; extra == 'all'
48
+ Requires-Dist: uvicorn[standard]; extra == 'all'
49
+ Provides-Extra: hpi
50
+ Requires-Dist: hpi; extra == 'hpi'
51
+ Provides-Extra: html
52
+ Requires-Dist: beautifulsoup4; extra == 'html'
53
+ Requires-Dist: lxml; extra == 'html'
54
+ Provides-Extra: indexer
55
+ Requires-Dist: urlextract; extra == 'indexer'
56
+ Provides-Extra: markdown
57
+ Requires-Dist: mistletoe; extra == 'markdown'
58
+ Provides-Extra: optional
59
+ Requires-Dist: logzero; extra == 'optional'
60
+ Requires-Dist: python-magic; extra == 'optional'
61
+ Provides-Extra: org
62
+ Requires-Dist: orgparse>=0.3.0; extra == 'org'
63
+ Provides-Extra: server
64
+ Requires-Dist: fastapi; extra == 'server'
65
+ Requires-Dist: uvicorn[standard]; extra == 'server'
66
+ Provides-Extra: telegram
@@ -0,0 +1,80 @@
1
+ promnesia/__init__.py,sha256=Q7WL7vUhCs0hU3fyzCskxob6tMX37mLh8WkxMsIgTDA,468
2
+ promnesia/__main__.py,sha256=WkfigB6vaT5ySdloeI6Y-ky48F3bv8cGKPuRvKo8SUY,15488
3
+ promnesia/cannon.py,sha256=RfVuoyyXCt7z0us0wIPInwKkdYauDiAkHREpLwxQ0DI,24523
4
+ promnesia/common.py,sha256=OUvqwbgO_5-XalhaITUJdZbM944Q3rgOGHQU19RmClE,19955
5
+ promnesia/compare.py,sha256=D9CsIS3h1htH-P1EhNU7UtEKWkNr5cyKuSE2MRv6kng,4591
6
+ promnesia/compat.py,sha256=cxk8ZOv0LnSwLCab_UrsxQWcKiiZnWgf2xK13L-ql4w,456
7
+ promnesia/config.py,sha256=CIswmf9J2lt5j0_gt0W-cLotyKx_6Koi49zUY81v-qc,4774
8
+ promnesia/extract.py,sha256=zR-DR8TXIktXapzn8RgH9j6YUzRn307lHnMA69W-AVI,2815
9
+ promnesia/logging.py,sha256=8uO7kUR798j_4P7gaJ9jFC27xnT3wklO8mdNrpqicOk,6150
10
+ promnesia/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ promnesia/server.py,sha256=E5gctU6KebhCPSG2ggcZlPZWPWcQc3Pd_pD7fLKzjvg,14918
12
+ promnesia/sqlite.py,sha256=m6OqHUCu0qRIrjSBmjhpXviujy0BshFYxlZJAVPBJA4,1389
13
+ promnesia/database/common.py,sha256=9iENKM0pRL1PKrSAhGzNreDFsQNQBIGZWKuV5E8aalw,1843
14
+ promnesia/database/dump.py,sha256=ZSP-W5fBEiJ2QHgb6ejxnw9_2tDv7K2orRx8_ljgWqk,6085
15
+ promnesia/database/load.py,sha256=kP-HdNL_3q94P_Cj5pnxarHqFgCVJFrsbr0vogDRtFU,1357
16
+ promnesia/misc/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ promnesia/misc/config_example.py,sha256=MXxJCVjm9MrEwPR8SHTwkJRDcqWcqJWtfJg_M6yhRMo,364
18
+ promnesia/misc/install_server.py,sha256=6elwODITGQ8D2ACcQ_fchBCTsIojDByiqKkdaRg8qm8,4850
19
+ promnesia/sources/auto.py,sha256=yJRGfXqsaP3q9gAxrXc6a1QxIpNxFXeQR-Ofi82uq5E,11991
20
+ promnesia/sources/auto_logseq.py,sha256=1npVDEXB8wAM6XwTku0nZb57yQ9mM7vWct9albgvGxw,445
21
+ promnesia/sources/auto_obsidian.py,sha256=UoVWAkdCbh7Ij3JFIy6ylYOd6776c7-z2xaR6b8snYc,205
22
+ promnesia/sources/browser.py,sha256=6yQQB63Bmpw7RvFqbFlDH5Q87fq-HvJzMnRt1lYcnYA,3078
23
+ promnesia/sources/browser_legacy.py,sha256=v3JFpiTiblsoR3XnGz_7CdnYWyqDRZTa4nFTDxD5Cco,10637
24
+ promnesia/sources/demo.py,sha256=9am9Wo4qB1PZF62UOkUuNfeDe5Yt_cReZ65IiU-8mlc,1032
25
+ promnesia/sources/fbmessenger.py,sha256=Ubk5y3VMRJhy7Qn_koTI491CsKJyULbPdcQ7ymta3qE,996
26
+ promnesia/sources/filetypes.py,sha256=lSPncSHDjyBPJ-d4UYroMozrlk6Fj4wtIG2pecq-QV0,3663
27
+ promnesia/sources/github.py,sha256=BmRKX8cpvhS0FeudiUKJgqUGbvAzngeWrDBn8PrWrhw,2808
28
+ promnesia/sources/guess.py,sha256=5fTm1OIoXuj2TtavTgfMhQeVb7iqMJ9qbDTSTtUVIEk,807
29
+ promnesia/sources/hackernews.py,sha256=XzIZF0QEEBism9iZtJwokoVcOrBVQ4byw62FOM9r-cw,1190
30
+ promnesia/sources/hpi.py,sha256=K8cqkkEJ497Eghs7YTcSugjkoZihAoI0KUYm5yyuj8Y,397
31
+ promnesia/sources/html.py,sha256=ZmSNoIBE6TtJ-50kbvC6RtRjSfQgWebr2UbB2CtXoyQ,1281
32
+ promnesia/sources/hypothesis.py,sha256=qbiP6xJN53A6YkSUgA7hUa3ZD4KmtUnhJfAzXUHdt0o,1387
33
+ promnesia/sources/instapaper.py,sha256=4a_vsv-Z4bsvy5xN27Hk2Q8RCph1zj7D4odBuiVFhqU,989
34
+ promnesia/sources/markdown.py,sha256=nvOoqtw2zA8a_ohXcpaPRlD-6GXcV6XPaxE1_d18_1Q,3935
35
+ promnesia/sources/org.py,sha256=hghDQYHLGrZlTIbOM5GGhtUPZd4jq60EReH43ihUEk8,5849
36
+ promnesia/sources/plaintext.py,sha256=z20yVEslSh19EmVQnN1v0iI2tYuJDD2S98TNTNkNigc,3097
37
+ promnesia/sources/pocket.py,sha256=ZURxchsv5VxAN3H9j-qAVOw6yOaiDEfFvIBBk5NRhGo,1174
38
+ promnesia/sources/reddit.py,sha256=tjRGlmOivF1pOccd4p6XDalhev0sCMMkdcVNKLumdeI,5663
39
+ promnesia/sources/roamresearch.py,sha256=KgFViu-PKDjQOj3oeBefRsfc2rbYKIOR2GBkH2-XDL4,1078
40
+ promnesia/sources/rss.py,sha256=5Yy5QhoWz5WWBAa7gdQrZSv5m8PuG1gOTCnJxHp1kaw,827
41
+ promnesia/sources/shellcmd.py,sha256=56p7FMMLhkpBsTt1s9dvbfNOBCKME_Epzl8o4x-gpBk,2692
42
+ promnesia/sources/signal.py,sha256=R963RmHmskisHUOnCGmEY8GAv0ohFhv4VtFCsCIkiNM,14857
43
+ promnesia/sources/smscalls.py,sha256=h33FgASh1AJtRNZ6g2dW9DoZ0gWAWoTREEjmRs_vbnE,773
44
+ promnesia/sources/stackexchange.py,sha256=-wsdmcwe_RJXmU94Cw0DeQFIRkx-VUIz3hc7iAdaVxg,660
45
+ promnesia/sources/takeout.py,sha256=oOw7jUCYCxNfbFcMphsPnpvYZ4FlDULyXTOA9BWrGRE,7858
46
+ promnesia/sources/takeout_legacy.py,sha256=tjoXGvkH3EvHYBt6xd1swnai4VP4obLQou_gnMOBOtc,4223
47
+ promnesia/sources/telegram.py,sha256=WXmRhIHWAIlIRN_kqwbScLDvQzB79cMZ0oaIwY_tHPY,3003
48
+ promnesia/sources/telegram_legacy.py,sha256=e-wQQ8jOGJvqKQovItNiVbOaPbYagCsNlgLtUp2Indk,4521
49
+ promnesia/sources/twitter.py,sha256=Vu3xNifTkfIDYvLsOVtGV2QOa6gQ_PF7wNtABKYCGD0,1887
50
+ promnesia/sources/vcs.py,sha256=-OKOBpc4-N-9ErN4KczF8UlF9NOKygvNoCPD8o-Zo7Y,1663
51
+ promnesia/sources/viber.py,sha256=jtvRInsvaKS8mR8IXGnNEoYE9LdrV191XIv-VCryKdQ,6008
52
+ promnesia/sources/website.py,sha256=OWvO-GlrBzAmqr1v2v8Q-Zpnmx-mg01JycdOyT1CmJc,1830
53
+ promnesia/sources/zulip.py,sha256=GN8YiUmFa3jLXFmNst47YILu0U-kPawbxDKY-Mtobf0,770
54
+ promnesia/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ promnesia/tests/common.py,sha256=_pB58QT3-nVOOUYYQb96I1TFf5fbfFShWJRWANbCyK8,4094
56
+ promnesia/tests/server_helper.py,sha256=m5Fc-d3byixlKXR2EEFUoEkQ9eM7hjLVpG41-VcOk2E,2210
57
+ promnesia/tests/test_cannon.py,sha256=Q8uTi7VaJRG3tTn6o2p7Fk-jcx_h3ooSWczS38hZQIQ,13737
58
+ promnesia/tests/test_cli.py,sha256=_jDJzjPXsYk1UDqwaM1KNfNxkcC4TsmblPs_s-wzZes,1472
59
+ promnesia/tests/test_compare.py,sha256=51dKDKoU58h7SvLwAE60eFhUNaflaagkS2TUleEsAu8,1005
60
+ promnesia/tests/test_config.py,sha256=VqX2R0UcXmxp8O-p6C5Unk9W2Iv3RkIhvKe3ga84GHc,6534
61
+ promnesia/tests/test_db_dump.py,sha256=-YETzoY2CmCw9bYhettTOI80yOI_dfHjvAzkfngY48E,6787
62
+ promnesia/tests/test_extract.py,sha256=AAVHySrUo8YGuYNXhhmDHYnSAnhWpPJ9fHedycoI0v0,2367
63
+ promnesia/tests/test_extract_urls.py,sha256=Ybez16VdYoveL9b_50Ca9vbMogWHOvFqDOJPGZrzQJg,1961
64
+ promnesia/tests/test_indexer.py,sha256=0CdYLevIGIZxTJrobhviy59EovRXeaYxHzb4jrwJtpw,9120
65
+ promnesia/tests/test_server.py,sha256=doBcn791eN43B2u6P1U4kbxnLWzp8xFXXzMfW8zsBB0,10914
66
+ promnesia/tests/test_traverse.py,sha256=DUN-NbrZ8b6MKrtZaOavAnZelMPk_aqN2ylvRV7UqHo,1350
67
+ promnesia/tests/utils.py,sha256=wsqNgQBncGXVCQLr9XMkknnd3pejo5FSChaRVNpuwgY,1071
68
+ promnesia/tests/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
+ promnesia/tests/sources/test_auto.py,sha256=wWqf7x_BXeVSYTDIaD6ZXqqRvqk312biY4iOGcMa4PY,1848
70
+ promnesia/tests/sources/test_filetypes.py,sha256=v0Dpi9N2_3HTbJC7jPPfzOSaPL0QQxCxapO1kr1BhK4,1401
71
+ promnesia/tests/sources/test_hypothesis.py,sha256=E7BE6Q2n6sVIn2j4k0N3N_eJmIb2ufEZoOcCyPcmVZk,1444
72
+ promnesia/tests/sources/test_org.py,sha256=j9qsJK91HHn1cdbLQEs72Jf0rma9Z8q8mrh6WZiDwcA,2610
73
+ promnesia/tests/sources/test_plaintext.py,sha256=X5jY9dsDXFo0Dj8X4XmPw6DYlcyorQQV3NuY-m30baE,865
74
+ promnesia/tests/sources/test_shellcmd.py,sha256=yogl5hDk6Sr91TWVq35b25JZ_6h9ZIMWyYoj2jlav2g,719
75
+ promnesia/tests/sources/test_takeout.py,sha256=HVreW_4pZP8TjGNmrJva5JJfkexmOwwr7cRxwU1Qg_Q,1557
76
+ promnesia-1.4.20250909.dist-info/METADATA,sha256=ZCFCUfr4QuO-Le41FwzBCisZRCrn-i6xpF30FAwjYSE,2871
77
+ promnesia-1.4.20250909.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
78
+ promnesia-1.4.20250909.dist-info/entry_points.txt,sha256=hz1qfzQSRh4kkVkJWk4hnYqE9A1nobEbKlLG_0nNxzE,54
79
+ promnesia-1.4.20250909.dist-info/licenses/LICENSE,sha256=rgO9acPmnw53ZBxiXBdp8kfxmRcekhg_Q7HN65BPihs,1074
80
+ promnesia-1.4.20250909.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
promnesia/kjson.py DELETED
@@ -1,122 +0,0 @@
1
- """
2
- Some experimental ideas on JSON processing.
3
- This is a bit overengineered and I admit it!
4
- I'll make it more readable, but in the meantime feel free to open an issue if you're confused about something.
5
- """
6
- from __future__ import annotations
7
-
8
- from typing import Any, Union, cast
9
-
10
- JDict = dict[str, Any] # TODO not sure if we can do recursive..
11
- JList = list[Any]
12
- JPrim = Union[str, int, float] # , type(None)]
13
-
14
- Json = Union[JDict, JList, JPrim]
15
-
16
- JPathPart = tuple[Json, Union[str, int]]
17
-
18
- JPath = tuple[JPathPart, ...]
19
-
20
-
21
- class JsonProcessor:
22
- SKIP = object()
23
-
24
- def handle_dict(self, js: JDict, jp: JPath) -> Any:
25
- pass
26
-
27
- def handle_list(self, js: JList, jp: JPath) -> Any:
28
- pass
29
-
30
- def handle_str(self, js: str, jp: JPath) -> Any:
31
- pass
32
-
33
- def do_dict(self, js: JDict, jp: JPath) -> None:
34
- # pylint: disable=assignment-from-no-return
35
- res = self.handle_dict(js, jp)
36
- if res is self.SKIP:
37
- return
38
- for k, v in js.items():
39
- path = cast(JPath, jp + ((js, k), )) # noqa: RUF005
40
- self._do(v, path)
41
-
42
- def do_list(self, js: JList, jp: JPath) -> None:
43
- # pylint: disable=assignment-from-no-return
44
- res = self.handle_list(js, jp)
45
- if res is self.SKIP:
46
- return
47
- for i, x in enumerate(js):
48
- path = cast(JPath, jp + ((js, i), )) # noqa: RUF005
49
- self._do(x, path)
50
-
51
- def _do(self, js: Json, path: JPath) -> None:
52
- if isinstance(js, dict): # TODO have functions for dict like, list like etc
53
- self.do_dict(js, path)
54
- elif isinstance(js, list):
55
- self.do_list(js, path)
56
- elif isinstance(js, str):
57
- self.handle_str(js, path)
58
- elif isinstance(js, (int, bool, float, type(None))):
59
- pass # TODO process that as well
60
- else:
61
- raise RuntimeError(f'unexpected item {js} of type {type(js)}')
62
-
63
- def run(self, js: Json) -> None:
64
- path = cast(JPath, ())
65
- self._do(js, path)
66
-
67
- @classmethod
68
- def kpath(cls, path: JPath) -> tuple[JPathPart, ...]:
69
- return tuple(x[1] for x in path) # type: ignore
70
-
71
- # TODO path is a sequence of jsons and keys?
72
-
73
- def test_json_processor():
74
- handled = []
75
- class Proc(JsonProcessor):
76
- def handle_dict(self, value: JDict, path): # noqa: ARG002
77
- if 'skipme' in self.kpath(path): # type: ignore[comparison-overlap]
78
- return JsonProcessor.SKIP
79
- return None
80
-
81
- def handle_str(self, value: str, path):
82
- if 'http' in value:
83
- handled.append((value, path))
84
-
85
- j = {
86
- 'skipme': {
87
- 'x': {
88
- 'y': [
89
- 123,
90
- {
91
- 'description': 'whatever',
92
- 'link': 'http://ya.ru',
93
- },
94
- ]
95
- }
96
- },
97
- 'a': [1, 2, 3],
98
- 'x': {
99
- 'y': [
100
- 123,
101
- {
102
- 'description': 'whatever',
103
- 'link': 'http://reddit.com',
104
- },
105
- ]
106
- },
107
- }
108
-
109
- p = Proc()
110
- p.run(j)
111
- assert len(handled) > 0
112
-
113
- [h1] = handled
114
- (link, path) = h1
115
- assert link == 'http://reddit.com'
116
- pp = [p[1] for p in path]
117
- assert pp == ['x', 'y', 1, 'link']
118
-
119
-
120
- if __name__ == '__main__':
121
- test_json_processor()
122
-
File without changes
@@ -1,55 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: promnesia
3
- Version: 1.3.20241021
4
- Summary: Enhancement of your browsing history
5
- Home-page: https://github.com/karlicoss/promnesia
6
- Author: Dmitrii Gerasimov
7
- Author-email: karlicoss@gmail.com
8
- Requires-Python: >=3.9
9
- License-File: LICENSE
10
- Requires-Dist: appdirs
11
- Requires-Dist: tzlocal
12
- Requires-Dist: more-itertools
13
- Requires-Dist: typing-extensions
14
- Requires-Dist: pytz
15
- Requires-Dist: sqlalchemy >=2.0
16
- Requires-Dist: urlextract
17
- Requires-Dist: fastapi
18
- Requires-Dist: uvicorn[standard]
19
- Provides-Extra: hpi
20
- Requires-Dist: HPI ; extra == 'hpi'
21
- Provides-Extra: all
22
- Requires-Dist: logzero ; extra == 'all'
23
- Requires-Dist: python-magic ; extra == 'all'
24
- Requires-Dist: HPI ; extra == 'all'
25
- Requires-Dist: beautifulsoup4 ; extra == 'all'
26
- Requires-Dist: lxml ; extra == 'all'
27
- Requires-Dist: mistletoe ; extra == 'all'
28
- Requires-Dist: orgparse >=0.3.0 ; extra == 'all'
29
- Provides-Extra: html
30
- Requires-Dist: beautifulsoup4 ; extra == 'html'
31
- Requires-Dist: lxml ; extra == 'html'
32
- Provides-Extra: markdown
33
- Requires-Dist: mistletoe ; extra == 'markdown'
34
- Provides-Extra: optional
35
- Requires-Dist: logzero ; extra == 'optional'
36
- Requires-Dist: python-magic ; extra == 'optional'
37
- Provides-Extra: org
38
- Requires-Dist: orgparse >=0.3.0 ; extra == 'org'
39
- Provides-Extra: telegram
40
- Provides-Extra: testing
41
- Requires-Dist: pytest ; extra == 'testing'
42
- Requires-Dist: pytest-timeout ; extra == 'testing'
43
- Requires-Dist: pytest-xdist ; extra == 'testing'
44
- Requires-Dist: hypothesis ; extra == 'testing'
45
- Requires-Dist: psutil ; extra == 'testing'
46
- Requires-Dist: requests ; extra == 'testing'
47
- Requires-Dist: selenium ; extra == 'testing'
48
- Requires-Dist: click ; extra == 'testing'
49
- Requires-Dist: ruff ; extra == 'testing'
50
- Requires-Dist: mypy ; extra == 'testing'
51
- Requires-Dist: lxml ; extra == 'testing'
52
- Requires-Dist: loguru ; extra == 'testing'
53
- Provides-Extra: testing-gui
54
- Requires-Dist: pyautogui ; extra == 'testing-gui'
55
-
@@ -1,83 +0,0 @@
1
- promnesia/__init__.py,sha256=8ZrCJe2kJb0DuYIiNeiUm0XU0nsjTlctcjdFoy9DVYw,457
2
- promnesia/__main__.py,sha256=y7Jgcc1uSKbxKhFDrlBlYh75kZm_unS9vH_3HvWCpnk,15421
3
- promnesia/cannon.py,sha256=TZ4b5P0qZpo0CVKCQLthyPFtAW5DYZT5ylttr5TmikI,24522
4
- promnesia/common.py,sha256=iUQh3Z-XqWxOPqnOHL8sBHEEJcGTztITBXnYizA02zs,20098
5
- promnesia/compare.py,sha256=vREaDTOjrGG43qOZEq2E9jV7fihO0U-KBMuguUMNgnk,4572
6
- promnesia/compat.py,sha256=cxk8ZOv0LnSwLCab_UrsxQWcKiiZnWgf2xK13L-ql4w,456
7
- promnesia/config.py,sha256=hFHdFbcB2q35gU1zlmtYj6VkHR_1SSH4U2M5G4HQa_g,4721
8
- promnesia/extract.py,sha256=m6D-QVA54ldcffcAby8w2OIDg0GPmAgDSGVWhSTwA60,2810
9
- promnesia/kjson.py,sha256=GPpeIpvtXwaocBw1W1QzPWN8UJcF0USSlaMxRSEkH-U,3400
10
- promnesia/logging.py,sha256=z3Otc_JzZREnMG0QerqoOR6zFJ6Ls6ATGydczCADZSY,5923
11
- promnesia/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- promnesia/server.py,sha256=LBka2jYuzISVAyNIQaf8IRGIbcpSFo1g-vn8TI5VOhE,14647
13
- promnesia/sqlite.py,sha256=4jZhqMGviSZK5wNqd7PbVC0z-D3UWyeM0RXrabAruZ8,1378
14
- promnesia/database/common.py,sha256=9iENKM0pRL1PKrSAhGzNreDFsQNQBIGZWKuV5E8aalw,1843
15
- promnesia/database/dump.py,sha256=v5m5mdnY7Tu7Yu-mlQHAFW46Kgt4dJRIOWOGOs88gEY,6116
16
- promnesia/database/load.py,sha256=kP-HdNL_3q94P_Cj5pnxarHqFgCVJFrsbr0vogDRtFU,1357
17
- promnesia/misc/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- promnesia/misc/config_example.py,sha256=MXxJCVjm9MrEwPR8SHTwkJRDcqWcqJWtfJg_M6yhRMo,364
19
- promnesia/misc/install_server.py,sha256=NEEGvpun7_lMBGXKvRGrq5wcGT_xgMm7MvPcftR15pI,4757
20
- promnesia/sources/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- promnesia/sources/auto.py,sha256=hiecNxttUGFskR5H2W35K-6daEhhiPpH2ZRpOZBBr50,11695
22
- promnesia/sources/auto_logseq.py,sha256=1npVDEXB8wAM6XwTku0nZb57yQ9mM7vWct9albgvGxw,445
23
- promnesia/sources/auto_obsidian.py,sha256=UoVWAkdCbh7Ij3JFIy6ylYOd6776c7-z2xaR6b8snYc,205
24
- promnesia/sources/browser.py,sha256=qmuDzu0iJjpQc-WX2LEZ3TnpHhb9H-b5H-hZV7lbVkY,3087
25
- promnesia/sources/browser_legacy.py,sha256=rNZydnWnnQ3sAzgRgFYnuqQKHUg8MxS5iiAmHAh9rV8,10429
26
- promnesia/sources/demo.py,sha256=TQVVl6089TlEntiGSO-9EhqXBf9U_ipUnhsVqDCOspg,1033
27
- promnesia/sources/fbmessenger.py,sha256=Dpvxh_5_ozaqGOSHxCApoIda58Z33r0_N6Uk2BIMde8,997
28
- promnesia/sources/filetypes.py,sha256=2d6taAuGT4jvfCEqF9US8jukT6sBuN0wBEPJToCKiww,3643
29
- promnesia/sources/github.py,sha256=arDUZShPi8Dzz9EhYfk4j1OK3ugsADsjAhfXy00ng0c,2777
30
- promnesia/sources/guess.py,sha256=DMC7pj7rAA5yGZ6hMp31y4QvSugVNA9osexBLd5oCmc,803
31
- promnesia/sources/hackernews.py,sha256=zocx4XrP2QY5UW-ErSMej7lrYZH0xmotqaIBVGyNH7M,1247
32
- promnesia/sources/hpi.py,sha256=cHQlEJAH1EeTiawB1kcjXPt4UYDL1ZTNIHadBvd5QH4,383
33
- promnesia/sources/html.py,sha256=ill3XtIObZoK1a8FY6OZGoOwmqjtSiiiwmqjzSbZhQQ,1153
34
- promnesia/sources/hypothesis.py,sha256=qbiP6xJN53A6YkSUgA7hUa3ZD4KmtUnhJfAzXUHdt0o,1387
35
- promnesia/sources/instapaper.py,sha256=zIq6AClPb8Zfkdft7U4VgEgODlEeQRowygGz06DaGUQ,988
36
- promnesia/sources/markdown.py,sha256=KHHwxezCQRpcJLoyt_qB44NQwZGL7BnPT-Ehud21eR4,3871
37
- promnesia/sources/org.py,sha256=BD1DpDcxXWWjirKnrovY2tDQpgj5YAt175z45Z_o0jI,5589
38
- promnesia/sources/plaintext.py,sha256=8aYkmBYmXKnxyshWqgwUgQ03oG-OMKRi7DXsWtcgpVA,3138
39
- promnesia/sources/pocket.py,sha256=PWmjAgg8nSDubBv_4WuWmyupB6NP8SAuuKiV8ZLE4xY,1133
40
- promnesia/sources/reddit.py,sha256=u-Ou0xTZO-s9SM_GKHfNawLV5Yv7PmH4lggy_yq1XnA,5630
41
- promnesia/sources/roamresearch.py,sha256=_WKurvGea9JHMKlapQyH44Kfg-AD40fb7xse26It0Fo,1077
42
- promnesia/sources/rss.py,sha256=6Ijy6omXGjzMLkmwijq6JBRIY7ruArb-hXppRYY4ln0,824
43
- promnesia/sources/shellcmd.py,sha256=bXWfHv6XFmVUQHUUWn2E_C96tIdmIxb1-yqAQRtTYIk,2739
44
- promnesia/sources/signal.py,sha256=4ZBUXQoab0OG1r8ieZhSHpMNrzsFDomVXBhqb8hRYPA,14793
45
- promnesia/sources/smscalls.py,sha256=N6jMHHr4bUlQORQcTVeGsdrmW4ep7jpCEFSi26sRpxY,774
46
- promnesia/sources/stackexchange.py,sha256=_s8HJfhblVNspvbLEnuse5J8BvFFrboIdv5jURTZ2eE,658
47
- promnesia/sources/takeout.py,sha256=mv6j8mkDb8lJsv41iBsJBzFpbGp7jXIBWYcAFMTvdls,8017
48
- promnesia/sources/takeout_legacy.py,sha256=iaSLu73RutEx1UW4m-n3hk7-ISlVl2d-W0ZKP__20XU,4130
49
- promnesia/sources/telegram.py,sha256=hSI6zxQh2zqdBiIAGJzY2Vi5A_233jDy0tGU0Q-Q-EU,2979
50
- promnesia/sources/telegram_legacy.py,sha256=gRe6Exw-svMQZhlussmBGg0EJq81XadSa5-mh2m8ztI,4524
51
- promnesia/sources/twitter.py,sha256=_tIU0rQ3b96WXKIPJQRyRAzG7AAnPp9ANytrcVJ5Z0U,1886
52
- promnesia/sources/vcs.py,sha256=wMcgXr1Nd7DxM5j405ip4SPxJIqhdY4SePpp9qPL9q8,1654
53
- promnesia/sources/viber.py,sha256=C7e9AxN5sgC-SLyCdUapzwC3eGuA0WQUGfO8Br5r53A,5990
54
- promnesia/sources/website.py,sha256=GbDZChKK1_KLWXiLUUcZLOvep6h2AWmqECudwmupSl8,1811
55
- promnesia/sources/zulip.py,sha256=GN8YiUmFa3jLXFmNst47YILu0U-kPawbxDKY-Mtobf0,770
56
- promnesia/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- promnesia/tests/common.py,sha256=2D9YspEWhKplbG6ZrVACkBjp_NEJB7qaXzOMjWHitCY,4092
58
- promnesia/tests/server_helper.py,sha256=Z1Rc_88WmOwukCyVR5Cb4XaXg4xewHiy4vlFAxQkoBU,2199
59
- promnesia/tests/test_cannon.py,sha256=VZPWZAtcAdRzQwVJ01qUIgvxB3VJl72Gqg0GI9tr8To,12711
60
- promnesia/tests/test_cli.py,sha256=g-9mgs4_tu6bGNZz3_swP3oj1L2V_o9ycjlFzIR9WYE,1404
61
- promnesia/tests/test_compare.py,sha256=JDQzFWaIMkKCn6YYKJPrZjdbZ6LZn5ig793q62LwSFc,945
62
- promnesia/tests/test_config.py,sha256=VqX2R0UcXmxp8O-p6C5Unk9W2Iv3RkIhvKe3ga84GHc,6534
63
- promnesia/tests/test_db_dump.py,sha256=PMGiTnp_cfDxLUfzYrchKKewoF84q6TooEw445K-WiA,6766
64
- promnesia/tests/test_extract.py,sha256=kD2iNodCj2OHM7_sQ_3DTRHJMZItJ7FuE855GpxZ3jM,2340
65
- promnesia/tests/test_extract_urls.py,sha256=Ybez16VdYoveL9b_50Ca9vbMogWHOvFqDOJPGZrzQJg,1961
66
- promnesia/tests/test_indexer.py,sha256=Oo93qqPrP0xXY1XhcRQkoJuEGpREfs6qoH335f_5_dI,8981
67
- promnesia/tests/test_server.py,sha256=c1HxEKlqTxbBrKu7tmg58G8Z9E4jNcxq-YENxxfVqIQ,10786
68
- promnesia/tests/test_traverse.py,sha256=DUN-NbrZ8b6MKrtZaOavAnZelMPk_aqN2ylvRV7UqHo,1350
69
- promnesia/tests/utils.py,sha256=TsRaLYN9slHHoNJmPSKwgoP82ICHBvEjT2G4scAraIQ,1136
70
- promnesia/tests/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- promnesia/tests/sources/test_auto.py,sha256=wWqf7x_BXeVSYTDIaD6ZXqqRvqk312biY4iOGcMa4PY,1848
72
- promnesia/tests/sources/test_filetypes.py,sha256=6xhpN9hQb2U6FF4lAEIXWupk-t_HxQjNfk9A6krEnx4,1359
73
- promnesia/tests/sources/test_hypothesis.py,sha256=4anFCfBqzJueiDhhg2WtvITMIofAWRMB2-Ja1Cb2beY,1400
74
- promnesia/tests/sources/test_org.py,sha256=cefCAc7JVtrzHblbLHYB28tsjzfV1b4h80_JRO1Zamk,2572
75
- promnesia/tests/sources/test_plaintext.py,sha256=Bn7v2HhL1FSLqCKPy-BX5OLy1PlWIyYjvRTLAWrXVWg,827
76
- promnesia/tests/sources/test_shellcmd.py,sha256=K4hDQl3yd4t-6JFeDtB1gtH2XFImSYdYe1pG0UOO-Uw,678
77
- promnesia/tests/sources/test_takeout.py,sha256=HVreW_4pZP8TjGNmrJva5JJfkexmOwwr7cRxwU1Qg_Q,1557
78
- promnesia-1.3.20241021.dist-info/LICENSE,sha256=rgO9acPmnw53ZBxiXBdp8kfxmRcekhg_Q7HN65BPihs,1074
79
- promnesia-1.3.20241021.dist-info/METADATA,sha256=YLJgGCkJ4LTXKid3Ieq-hBk5aJVc3c000Diutdk-RlI,1903
80
- promnesia-1.3.20241021.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
81
- promnesia-1.3.20241021.dist-info/entry_points.txt,sha256=hz1qfzQSRh4kkVkJWk4hnYqE9A1nobEbKlLG_0nNxzE,54
82
- promnesia-1.3.20241021.dist-info/top_level.txt,sha256=7yvIpooFiuNLf9yLdu9MTADz57z0YTAqSu7aSG9ujSU,10
83
- promnesia-1.3.20241021.dist-info/RECORD,,