epstein-files 1.0.0__py3-none-any.whl → 1.0.1__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.
@@ -0,0 +1,57 @@
1
+ import logging
2
+ from os import environ
3
+
4
+ from rich.console import Console
5
+ from rich.highlighter import ReprHighlighter
6
+ from rich.logging import RichHandler
7
+ from rich.theme import Theme
8
+
9
+ from epstein_files.util.constant.strings import *
10
+
11
+ FILENAME_STYLE = 'gray27'
12
+
13
+ DOC_TYPE_STYLES = {
14
+ DOCUMENT_CLASS: 'grey69',
15
+ EMAIL_CLASS: 'dark_orange3',
16
+ JSON_FILE_CLASS: 'sandy_brown',
17
+ MESSENGER_LOG_CLASS: 'deep_pink4',
18
+ OTHER_FILE_CLASS: 'grey69',
19
+ }
20
+
21
+ LOG_THEME = {
22
+ f"{ReprHighlighter.base_style}{doc_type}": f"{doc_style} bold"
23
+ for doc_type, doc_style in DOC_TYPE_STYLES.items()
24
+ }
25
+
26
+ LOG_THEME[f"{ReprHighlighter.base_style}epstein_filename"] = FILENAME_STYLE
27
+ LOG_LEVEL_ENV_VAR = 'LOG_LEVEL'
28
+
29
+
30
+ class LogHighlighter(ReprHighlighter):
31
+ highlights = ReprHighlighter.highlights + [
32
+ *[fr"(?P<{doc_type}>{doc_type})" for doc_type in DOC_TYPE_STYLES.keys()],
33
+ "(?P<epstein_filename>" + FILE_NAME_REGEX.pattern + ')',
34
+ ]
35
+
36
+
37
+ log_console = Console(color_system='256', theme=Theme(LOG_THEME))
38
+ log_handler = RichHandler(console=log_console, highlighter=LogHighlighter())
39
+ logging.basicConfig(level="NOTSET", format="%(message)s", datefmt="[%X]", handlers=[log_handler])
40
+ logger = logging.getLogger("rich")
41
+
42
+
43
+ # Log levels
44
+ datefinder_logger = logging.getLogger('datefinder') # Set log level to suppress annoying output
45
+ env_log_level_str = environ.get(LOG_LEVEL_ENV_VAR) or None
46
+ env_log_level = None
47
+
48
+ if env_log_level_str:
49
+ try:
50
+ env_log_level = getattr(logging, env_log_level_str)
51
+ except Exception as e:
52
+ logger.warning(f"{LOG_LEVEL_ENV_VAR}='{env_log_level_str}' does not exist, defaulting to DEBUG")
53
+ env_log_level = logging.DEBUG
54
+
55
+ logger.warning(f"Setting log level to {env_log_level} based on {LOG_LEVEL_ENV_VAR} env var...")
56
+ logger.setLevel(env_log_level)
57
+ datefinder_logger.setLevel(env_log_level)
@@ -18,9 +18,11 @@ from epstein_files.util.constant.names import UNKNOWN
18
18
  from epstein_files.util.constant.strings import DEFAULT, EMAIL, NA, OTHER_SITE_LINK_STYLE, QUESTION_MARKS, SiteType
19
19
  from epstein_files.util.constant.urls import *
20
20
  from epstein_files.util.constants import FALLBACK_TIMESTAMP, HEADER_ABBREVIATIONS
21
- from epstein_files.util.env import args, logger
21
+ from epstein_files.util.data import json_safe
22
+ from epstein_files.util.env import args
22
23
  from epstein_files.util.file_helper import file_size_str
23
- from epstein_files.util.highlighted_group import HIGHLIGHTED_GROUPS, InterestingNamesHighlighter
24
+ from epstein_files.util.highlighted_group import ALL_HIGHLIGHTS, HIGHLIGHTED_NAMES, EpsteinHighlighter
25
+ from epstein_files.util.logging import logger
24
26
 
25
27
  TITLE_WIDTH = 50
26
28
  NUM_COLOR_KEY_COLS = 4
@@ -38,20 +40,19 @@ TITLE_STYLE = 'black on bright_white bold'
38
40
 
39
41
  HIGHLIGHTED_GROUP_COLOR_KEYS = [
40
42
  Text(highlight_group.label.replace('_', ' '), style=highlight_group.style)
41
- for highlight_group in sorted(HIGHLIGHTED_GROUPS, key=lambda hg: hg.label)
42
- if not highlight_group.is_multiline
43
+ for highlight_group in sorted(HIGHLIGHTED_NAMES, key=lambda hg: hg.label)
43
44
  ]
44
45
 
45
46
  THEME_STYLES = {
46
47
  DEFAULT: 'wheat4',
47
48
  TEXT_LINK: 'deep_sky_blue4 underline',
48
- **{hg.theme_style_name: hg.style for hg in HIGHLIGHTED_GROUPS}, # Inject style names for HighlightedGroups
49
+ **{hg.theme_style_name: hg.style for hg in ALL_HIGHLIGHTS},
49
50
  }
50
51
 
51
52
  # Instantiate console object
52
53
  CONSOLE_ARGS = {
53
54
  'color_system': '256',
54
- 'highlighter': InterestingNamesHighlighter(),
55
+ 'highlighter': EpsteinHighlighter(),
55
56
  'record': args.build,
56
57
  'safe_box': False,
57
58
  'theme': Theme(THEME_STYLES),
@@ -121,7 +122,7 @@ def print_centered_link(url: str, link_text: str, style: str | None = None) -> N
121
122
  print_centered(link_markup(url, link_text, style or ARCHIVE_LINK_COLOR))
122
123
 
123
124
 
124
- def print_color_key(_key_type: Literal["Groups", "People"] = "Groups") -> None:
125
+ def print_color_key() -> None:
125
126
  color_table = Table(title=f'Rough Guide to Highlighted Colors', show_header=False)
126
127
  num_colors = len(HIGHLIGHTED_GROUP_COLOR_KEYS)
127
128
  row_number = 0
@@ -153,13 +154,13 @@ def print_header(epstein_files: 'EpsteinFiles') -> None:
153
154
 
154
155
 
155
156
  def print_json(label: str, obj: object, skip_falsey: bool = False) -> None:
157
+ print(obj)
158
+
156
159
  if isinstance(obj, dict):
157
160
  if skip_falsey:
158
161
  obj = {k: v for k, v in obj.items() if v}
159
162
 
160
- if None in obj:
161
- obj = {k or UNKNOWN: v for k, v in obj.items()}
162
-
163
+ obj = json_safe(obj)
163
164
 
164
165
  console.line()
165
166
  console.print(Panel(label, expand=False))
@@ -219,6 +220,10 @@ def print_other_site_link(is_header: bool = True) -> None:
219
220
  word_count_link = link_text_obj(WORD_COUNT_URL, 'site showing the most frequently used words in these communiques', OTHER_SITE_LINK_STYLE)
220
221
  print_centered(parenthesize(word_count_link))
221
222
 
223
+ if is_header:
224
+ metadata_link = link_text_obj(JSON_METADATA_URL, 'file metadata containing author attribution explanations', OTHER_SITE_LINK_STYLE)
225
+ print_centered(parenthesize(metadata_link))
226
+
222
227
 
223
228
  def print_page_title(expand: bool = True, width: int | None = None) -> None:
224
229
  title_panel = Panel(Text(PAGE_TITLE, justify='center'), expand=expand, style=TITLE_STYLE, width=width)
@@ -292,7 +297,7 @@ def write_html(output_path: Path) -> None:
292
297
  logger.warning(f"Not writing HTML because args.build={args.build}.")
293
298
  return
294
299
 
295
- console.save_html(output_path, code_format=CONSOLE_HTML_FORMAT, theme=HTML_TERMINAL_THEME)
300
+ console.save_html(str(output_path), code_format=CONSOLE_HTML_FORMAT, theme=HTML_TERMINAL_THEME)
296
301
  logger.warning(f"Wrote {file_size_str(output_path)} to '{output_path}'")
297
302
 
298
303
 
@@ -320,5 +325,5 @@ def _print_external_links() -> None:
320
325
  print_centered(link_markup(EPSTEIN_WEB_URL) + " (character summaries)")
321
326
 
322
327
 
323
- if args.deep_debug:
324
- print_json('THEME_STYLES', THEME_STYLES)
328
+ # if args.deep_debug:
329
+ # print_json('THEME_STYLES', THEME_STYLES)
@@ -1,15 +1,23 @@
1
1
  from dataclasses import dataclass
2
2
 
3
3
  from rich.text import Text
4
+ # from epstein_files.documents.document import type Document
4
5
 
5
- from epstein_files.documents.document import Document
6
+
7
+ @dataclass
8
+ class MatchedLine:
9
+ line: str
10
+ line_number: int
11
+
12
+ def __rich__(self) -> Text:
13
+ return Text('').append(str(self.line_number), style='cyan').append(f":{self.line}")
14
+
15
+ def __str__(self) -> str:
16
+ return f"{self.line_number}:{self.line}"
6
17
 
7
18
 
8
19
  @dataclass
9
20
  class SearchResult:
10
21
  """Simple class used for collecting documents that match a given search term."""
11
- document: Document
12
- lines: list[Text] # The lines that match the search
13
-
14
- def unprefixed_lines(self) -> list[str]:
15
- return [line.plain.split(':', 1)[1] for line in self.lines]
22
+ document: 'Document'
23
+ lines: list[MatchedLine]
@@ -0,0 +1,24 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+
4
+ from epstein_files.util.logging import logger
5
+
6
+
7
+ @dataclass
8
+ class Timer:
9
+ started_at: float = field(default_factory=lambda: time.perf_counter())
10
+ checkpoint_at: float = field(default_factory=lambda: time.perf_counter())
11
+ decimals: int = 2
12
+
13
+ def print_at_checkpoint(self, msg: str) -> None:
14
+ logger.warning(f"{msg} in {self.seconds_since_checkpoint_str()}")
15
+ self.checkpoint_at = time.perf_counter()
16
+
17
+ def seconds_since_checkpoint_str(self) -> str:
18
+ return f"{(time.perf_counter() - self.checkpoint_at):.{self.decimals}f} seconds"
19
+
20
+ def seconds_since_start(self) -> float:
21
+ return time.perf_counter() - self.started_at
22
+
23
+ def seconds_since_start_str(self) -> str:
24
+ return f"{self.seconds_since_start():.{self.decimals}f} seconds"
@@ -12,7 +12,8 @@ from epstein_files.documents.emails.email_header import EmailHeader
12
12
  from epstein_files.util.constant.common_words import COMMON_WORDS, UNSINGULARIZABLE_WORDS
13
13
  from epstein_files.util.constant.names import OTHER_NAMES
14
14
  from epstein_files.util.data import ALL_NAMES, flatten, sort_dict
15
- from epstein_files.util.env import args, logger
15
+ from epstein_files.util.env import args
16
+ from epstein_files.util.logging import logger
16
17
  from epstein_files.util.rich import highlighter
17
18
  from epstein_files.util.search_result import SearchResult
18
19
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: epstein-files
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: Tools for working with the Jeffrey Epstein documents released in November 2025.
5
5
  Author: Michel de Cryptadamus
6
6
  Requires-Python: >=3.11,<4.0
@@ -20,7 +20,8 @@ Description-Content-Type: text/markdown
20
20
  * The Epstein text messages (and some of the emails along with summary counts of sent emails to/from Epstein) generated by this code can be viewed [here](https://michelcrypt4d4mus.github.io/epstein_text_messages/).
21
21
  * All of His Emails can be read at another page also generated by this code [here](https://michelcrypt4d4mus.github.io/epstein_emails_house_oversight/).
22
22
  * Word counts for the emails and text messages are [here](https://michelcrypt4d4mus.github.io/epstein_text_messages/epstein_emails_word_count.html).
23
- * Configuration variables assigning specific `HOUSE_OVERSIGHT_XXXXXX.txt` file IDs (the `111111` part) as being emails to or from particular people based on various research and contributions can be found in the [constants.py](./epstein_files/util/constants.py) file in this repo.
23
+ * Metadata containing what I have figured out about who sent or received the communications in a given file (and a brief explanation for how I figured it out for each file) is deployed [here](https://michelcrypt4d4mus.github.io/epstein_text_messages/epstein_files_nov_2025_cryptadamus_metadata.json)
24
+ * Configuration variables assigning specific `HOUSE_OVERSIGHT_XXXXXX.txt` file IDs (the `111111` part) as being emails to or from particular people based on various research and contributions can be found in [constants.py](./epstein_files/util/constants.py). Everything in `constants.py` should also appear in the JSON metadata.
24
25
 
25
26
 
26
27
  ### Usage
@@ -0,0 +1,30 @@
1
+ epstein_files/__init__.py,sha256=HKOGWVzyiEl0II8s7qnO33wcTZPw8dr3HDfT7_VnY2U,7831
2
+ epstein_files/documents/communication.py,sha256=SunZdjMhR9v6y8LlQ6jhIu8vYjSndaBK0Su1mKnhfj0,2060
3
+ epstein_files/documents/document.py,sha256=E2VUuHSoam8r8pyRbWy68_cVFU9DJ0irbtYULaDBYzE,16378
4
+ epstein_files/documents/email.py,sha256=IpKeOuLTmHWowBvUUEp-tyTC8pwEmXg3XgLJkplQZWg,37717
5
+ epstein_files/documents/emails/email_header.py,sha256=wkPfSLbmzkAeQwvhf0bAeFDLPbQT-EeG0v8vNNLYktM,7502
6
+ epstein_files/documents/imessage/text_message.py,sha256=DMdd__L7UPad0YS49MJf_3bTVyE1BLfWafQbDQierC8,3272
7
+ epstein_files/documents/json_file.py,sha256=Vf9iHiEhUqk-hEh6lGZX_mJNWZUUQWeT-UI3FhKW0hw,1101
8
+ epstein_files/documents/messenger_log.py,sha256=-hSMFH_dyrjGLdph4SU2xQK4RpXOhkR3R_nqRrz3e1w,5620
9
+ epstein_files/documents/other_file.py,sha256=JbKDtNrQ1Ua5vGPlZayON5Kgy0oJ-gHcdO9l9Iv9wRo,8930
10
+ epstein_files/epstein_files.py,sha256=ruhl24FgOpEdcqbMcIpgyYlqEBi1ZeztQ7QmZMYANp0,17856
11
+ epstein_files/util/constant/common_words.py,sha256=aR0UjoWmxyR49XS-DtHECQ1CiA_bK8hNP6CQ1TS9yZA,3696
12
+ epstein_files/util/constant/html.py,sha256=9U098TGzlghGg4WfxLYHyub5JGR17Dv7VP5i2MSu8Kk,1415
13
+ epstein_files/util/constant/names.py,sha256=eSgHnOqMAy7Czfw1vJ3lvniDST7QpfuQ8XgzttXpAi8,10191
14
+ epstein_files/util/constant/strings.py,sha256=3JTqD0luJrC3NbGXn4q6P-gIaaNVx36P1oCmp92gAoM,1750
15
+ epstein_files/util/constant/urls.py,sha256=P_nnb5cIrJ2NCbd4CoRfilZ5jrOzFs30jNK50F7IjZw,5483
16
+ epstein_files/util/constants.py,sha256=l0TrpncCJcecar5geggLVfOJVhicWcu3zws-62Cslzg,102472
17
+ epstein_files/util/data.py,sha256=s7EgmQ6SC6MoUMhP8GaxglJOJpU_nRmwI-T2inLl8hs,3329
18
+ epstein_files/util/doc_cfg.py,sha256=AFLBp9PO2tBUYhTeNztpkWs69VPr41fCuA22IesM59g,9914
19
+ epstein_files/util/env.py,sha256=9wM4mKPZoJO9J5VKLP67ZR1IEMkH2UaGdIaYm2tptMQ,4581
20
+ epstein_files/util/file_helper.py,sha256=ea428og2gyUsMWd2GFldmAGvuqGNNHaTc7gGGSM_0aI,3827
21
+ epstein_files/util/highlighted_group.py,sha256=UO0pqQH29JHiOMK2psIozIeA0zinDkql-NYDGRmFUzA,35173
22
+ epstein_files/util/logging.py,sha256=0mABrI5TvodLDe-9svHv3YaIdSyr8PXFcu4nntW1WsI,1858
23
+ epstein_files/util/rich.py,sha256=cLkiSg3f68bUxobzRiBRfrgS7Ya-FK7ltpQcZXNHMX4,13317
24
+ epstein_files/util/search_result.py,sha256=1fxe0KPBQXBk4dLfu6m0QXIzYfZCzvaSkWqvghJGzxY,567
25
+ epstein_files/util/timer.py,sha256=8hxW4Y1JcTUfnBrHh7sL2pM9xu1sL4HFQM4CmmzTarU,837
26
+ epstein_files/util/word_count.py,sha256=XTINgLm01jFQlNgdiLCcVFCodXAIb1dNbaAvznoRb1o,6757
27
+ epstein_files-1.0.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
28
+ epstein_files-1.0.1.dist-info/METADATA,sha256=IK5B-ltx_L0-EK2Oq2Q2gVXWlhYqKoYw6HCFisqitvQ,3587
29
+ epstein_files-1.0.1.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
30
+ epstein_files-1.0.1.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- epstein_files/__init__.py,sha256=JlGEliI8H5TqdGuCTtGIwLiM7GutbyND-IURG5Z-gAA,7442
2
- epstein_files/documents/communication.py,sha256=XybnJDqyK00RTeEkbLWgrVDkZS7pmC8EoftX1_G4OIM,2066
3
- epstein_files/documents/document.py,sha256=6av_KLTm70KIABl9Fl7DL9jKkvqdN18OLmECj2PAkEs,15223
4
- epstein_files/documents/email.py,sha256=rzgyVMBlKo9ytRdE6Eif_8zF4fecaMduIgPQkvRmmk0,34283
5
- epstein_files/documents/emails/email_header.py,sha256=JqcSqa-amdombgszE_cjXBrvZKE0HxU2mNAoD44Ekh4,7479
6
- epstein_files/documents/imessage/text_message.py,sha256=zU46FHeHKG6vbIZ-qLDdZC-1f3VmXW73fKo-BKOCgq8,3199
7
- epstein_files/documents/json_file.py,sha256=sL99E_34X9BIwQ27vE0Afy446oiyCmPLYdsJ6-OGMHU,611
8
- epstein_files/documents/messenger_log.py,sha256=HbtqthtkzXhkY7DxwxFOBy6xx6gPmmXIxZ4bsloLHEg,2995
9
- epstein_files/documents/other_file.py,sha256=_Z8EVLLy1u8RuEr5iPTKJdYZjQHFHp0o-mBErBYsRXg,4699
10
- epstein_files/epstein_files.py,sha256=Fb-SPwRlHZPB7iL48dL3Da4nPyzF9_Rk5nNpVnfku2U,20131
11
- epstein_files/util/constant/common_words.py,sha256=aR0UjoWmxyR49XS-DtHECQ1CiA_bK8hNP6CQ1TS9yZA,3696
12
- epstein_files/util/constant/html.py,sha256=9U098TGzlghGg4WfxLYHyub5JGR17Dv7VP5i2MSu8Kk,1415
13
- epstein_files/util/constant/names.py,sha256=_iNHJsr4sdUXG1cozllRy8yV6SYXgsr6oTPHTCbrpj0,9967
14
- epstein_files/util/constant/strings.py,sha256=B5RpaGCc1EqiDKF-3BabNy4dJU6n4kXytx96aanHIDA,1115
15
- epstein_files/util/constant/urls.py,sha256=pks5frfWXmFwEkfB33Uy7IR1mn0DaAI_8kDjA_g03yg,5089
16
- epstein_files/util/constants.py,sha256=jErrj2r_K8pbFNih7WxlcP0sPO7ZyzrLxH3MlSw5xR4,106137
17
- epstein_files/util/data.py,sha256=7yz3osIlpjV9nbPEvRBmExokBsgm20kitSfqNpaYWj4,3746
18
- epstein_files/util/env.py,sha256=T-sd1lPfw-L6WXvpIv-cqGTqBfZvacZvniW1OKOdkrU,4624
19
- epstein_files/util/file_cfg.py,sha256=E7VVxVZ_cSN18HgI6q8e6UwTApMWuPC9qTqb3_tXCqs,7183
20
- epstein_files/util/file_helper.py,sha256=EHVRFxcWmc0RD1VUeLFCcmM-82c5FISIUBIwg4TodsY,2727
21
- epstein_files/util/highlighted_group.py,sha256=0MpzBYVaGfyUZQwFP7EVrLHDYU57qnnmNDC56gVxq2Q,33091
22
- epstein_files/util/rich.py,sha256=Z28-etKpZdc6aPxdmAxNe9ZvMWK28iubYASt50VxtJ4,13194
23
- epstein_files/util/search_result.py,sha256=5nkR-YzUiR52FmGIad_Uw0XaU2E_FfHZBHgc8dm3sAs,429
24
- epstein_files/util/word_count.py,sha256=L1T6zjShaPZo1ilpM0dSAT3X-EgaZ4YEigHNLxjKit4,6719
25
- epstein_files-1.0.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
26
- epstein_files-1.0.0.dist-info/METADATA,sha256=dGc412CXHc2EHOd0C7HuEa2qFQFh42dNbDw5CiH0Ny4,3239
27
- epstein_files-1.0.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
28
- epstein_files-1.0.0.dist-info/RECORD,,