aai-study-library 0.1.1__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.
- aai_study_library-0.1.1/PKG-INFO +30 -0
- aai_study_library-0.1.1/README.md +20 -0
- aai_study_library-0.1.1/pyproject.toml +25 -0
- aai_study_library-0.1.1/setup.cfg +4 -0
- aai_study_library-0.1.1/src/aai/__init__.py +1 -0
- aai_study_library-0.1.1/src/aai/__main__.py +4 -0
- aai_study_library-0.1.1/src/aai/cli.py +156 -0
- aai_study_library-0.1.1/src/aai/data/Part 1/E004_AAI_P1.pdf +0 -0
- aai_study_library-0.1.1/src/aai/data/Part 2/E004_AAI_P2.docx +0 -0
- aai_study_library-0.1.1/src/aai/data/Part 3/E004_AAI_P3.docx +0 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/PKG-INFO +30 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/SOURCES.txt +14 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/dependency_links.txt +1 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/entry_points.txt +2 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/requires.txt +2 -0
- aai_study_library-0.1.1/src/aai_study_library.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aai-study-library
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A terminal study library for AAI test materials
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: pypdf>=4.0
|
|
9
|
+
Requires-Dist: python-docx>=1.1
|
|
10
|
+
|
|
11
|
+
# AAI Study Library
|
|
12
|
+
|
|
13
|
+
The `aai` command opens a terminal menu with three separate parts. Choose **Read ENTIRE content in Terminal** to print the complete extractable text in one pass; it does not ask you to press `N` for each page. You can scroll through the terminal history to review the output.
|
|
14
|
+
|
|
15
|
+
PDF and DOCX text is extracted locally. Text embedded inside screenshots/images may not be extractable, so use **Open original file normally** for those visuals.
|
|
16
|
+
|
|
17
|
+
## Build and validate
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m pip install --upgrade build twine
|
|
21
|
+
python -m build
|
|
22
|
+
python -m twine check dist/*
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## After publishing to PyPI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m pip install --upgrade aai
|
|
29
|
+
aai
|
|
30
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# AAI Study Library
|
|
2
|
+
|
|
3
|
+
The `aai` command opens a terminal menu with three separate parts. Choose **Read ENTIRE content in Terminal** to print the complete extractable text in one pass; it does not ask you to press `N` for each page. You can scroll through the terminal history to review the output.
|
|
4
|
+
|
|
5
|
+
PDF and DOCX text is extracted locally. Text embedded inside screenshots/images may not be extractable, so use **Open original file normally** for those visuals.
|
|
6
|
+
|
|
7
|
+
## Build and validate
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
python -m pip install --upgrade build twine
|
|
11
|
+
python -m build
|
|
12
|
+
python -m twine check dist/*
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## After publishing to PyPI
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python -m pip install --upgrade aai
|
|
19
|
+
aai
|
|
20
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aai-study-library"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "A terminal study library for AAI test materials"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
dependencies = ["pypdf>=4.0", "python-docx>=1.1"]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
aai = "aai.cli:main"
|
|
16
|
+
|
|
17
|
+
[tool.setuptools]
|
|
18
|
+
package-dir = {"" = "src"}
|
|
19
|
+
include-package-data = true
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.packages.find]
|
|
22
|
+
where = ["src"]
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.package-data]
|
|
25
|
+
aai = ["data/**/*"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.1"
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import os
|
|
3
|
+
import platform
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import textwrap
|
|
7
|
+
|
|
8
|
+
DATA_DIR = Path(__file__).parent / "data"
|
|
9
|
+
PARTS = {
|
|
10
|
+
"1": ("Part 1", "AAI Test - Part 1"),
|
|
11
|
+
"2": ("Part 2", "AAI Test - Part 2"),
|
|
12
|
+
"3": ("Part 3", "AAI Test - Part 3"),
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
def terminal_width():
|
|
16
|
+
try:
|
|
17
|
+
return max(60, min(shutil_width(), 120))
|
|
18
|
+
except Exception:
|
|
19
|
+
return 80
|
|
20
|
+
|
|
21
|
+
def shutil_width():
|
|
22
|
+
import shutil
|
|
23
|
+
return shutil.get_terminal_size((80, 24)).columns
|
|
24
|
+
|
|
25
|
+
def clear():
|
|
26
|
+
# Avoid clearing on non-interactive output; keep terminal content simple.
|
|
27
|
+
if sys.stdout.isatty():
|
|
28
|
+
os.system("cls" if os.name == "nt" else "clear")
|
|
29
|
+
|
|
30
|
+
def header(title):
|
|
31
|
+
width = terminal_width()
|
|
32
|
+
print("=" * width)
|
|
33
|
+
print(title.center(width))
|
|
34
|
+
print("=" * width)
|
|
35
|
+
|
|
36
|
+
def wrap_text(text):
|
|
37
|
+
width = terminal_width()
|
|
38
|
+
out = []
|
|
39
|
+
for line in text.splitlines():
|
|
40
|
+
if not line.strip():
|
|
41
|
+
out.append("")
|
|
42
|
+
continue
|
|
43
|
+
# Preserve leading indentation and wrap long paragraphs without destroying structure.
|
|
44
|
+
indent = line[:len(line) - len(line.lstrip())]
|
|
45
|
+
content = line[len(indent):]
|
|
46
|
+
out.extend(textwrap.wrap(
|
|
47
|
+
content, width=max(20, width - len(indent)),
|
|
48
|
+
initial_indent=indent, subsequent_indent=indent,
|
|
49
|
+
replace_whitespace=False, drop_whitespace=True,
|
|
50
|
+
break_long_words=False, break_on_hyphens=False
|
|
51
|
+
) or [indent])
|
|
52
|
+
return "\n".join(out)
|
|
53
|
+
|
|
54
|
+
def extract_text(path):
|
|
55
|
+
suffix = path.suffix.lower()
|
|
56
|
+
if suffix == ".pdf":
|
|
57
|
+
from pypdf import PdfReader
|
|
58
|
+
reader = PdfReader(str(path))
|
|
59
|
+
pages = []
|
|
60
|
+
for i, page in enumerate(reader.pages, 1):
|
|
61
|
+
pages.append(f"\n--- PAGE {i} ---\n")
|
|
62
|
+
pages.append(page.extract_text() or "[No extractable text on this page; check the original PDF.]")
|
|
63
|
+
return "\n".join(pages)
|
|
64
|
+
if suffix == ".docx":
|
|
65
|
+
from docx import Document
|
|
66
|
+
doc = Document(str(path))
|
|
67
|
+
parts = []
|
|
68
|
+
for para in doc.paragraphs:
|
|
69
|
+
if para.text.strip():
|
|
70
|
+
parts.append(para.text)
|
|
71
|
+
for table in doc.tables:
|
|
72
|
+
parts.append("\n[TABLE]")
|
|
73
|
+
for row in table.rows:
|
|
74
|
+
parts.append(" | ".join(cell.text.replace("\n", " / ") for cell in row.cells))
|
|
75
|
+
return "\n".join(parts)
|
|
76
|
+
return path.read_text(encoding="utf-8", errors="replace")
|
|
77
|
+
|
|
78
|
+
def read_entire(path):
|
|
79
|
+
try:
|
|
80
|
+
content = extract_text(path)
|
|
81
|
+
except Exception as exc:
|
|
82
|
+
print(f"\nCould not extract this file: {exc}")
|
|
83
|
+
input("\nPress Enter to return to the menu...")
|
|
84
|
+
return
|
|
85
|
+
clear()
|
|
86
|
+
header(path.name + " — ENTIRE CONTENT")
|
|
87
|
+
# Print the complete extracted text in one pass; no page-by-page prompts.
|
|
88
|
+
print(wrap_text(content))
|
|
89
|
+
print("\n" + "=" * terminal_width())
|
|
90
|
+
print("End of extracted text. Use terminal scrollback to review earlier lines.")
|
|
91
|
+
if path.suffix.lower() in {".pdf", ".docx"}:
|
|
92
|
+
print("Note: text inside embedded screenshots/images may not be extractable; open the original file to view those images.")
|
|
93
|
+
input("\nPress Enter to return to the menu...")
|
|
94
|
+
|
|
95
|
+
def open_original(path):
|
|
96
|
+
try:
|
|
97
|
+
if sys.platform == "darwin":
|
|
98
|
+
subprocess.Popen(["open", str(path)])
|
|
99
|
+
elif os.name == "nt":
|
|
100
|
+
os.startfile(str(path))
|
|
101
|
+
else:
|
|
102
|
+
subprocess.Popen(["xdg-open", str(path)])
|
|
103
|
+
except Exception as exc:
|
|
104
|
+
print(f"Could not open file: {exc}")
|
|
105
|
+
input("Press Enter to continue...")
|
|
106
|
+
|
|
107
|
+
def select_file(part_key):
|
|
108
|
+
folder, label = PARTS[part_key]
|
|
109
|
+
files = sorted((DATA_DIR / folder).glob("*"))
|
|
110
|
+
while True:
|
|
111
|
+
clear()
|
|
112
|
+
header(label)
|
|
113
|
+
for i, path in enumerate(files, 1):
|
|
114
|
+
print(f" {i}. {path.name}")
|
|
115
|
+
print("\n 0. Back")
|
|
116
|
+
choice = input("\nSelect a file: ").strip()
|
|
117
|
+
if choice == "0":
|
|
118
|
+
return
|
|
119
|
+
if not choice.isdigit() or not (1 <= int(choice) <= len(files)):
|
|
120
|
+
input("Invalid choice. Press Enter to try again...")
|
|
121
|
+
continue
|
|
122
|
+
path = files[int(choice)-1]
|
|
123
|
+
while True:
|
|
124
|
+
clear()
|
|
125
|
+
header(path.name)
|
|
126
|
+
print(" 1. Read ENTIRE content in Terminal")
|
|
127
|
+
print(" 2. Open original file normally")
|
|
128
|
+
print(" 0. Back")
|
|
129
|
+
action = input("\nChoose an option: ").strip()
|
|
130
|
+
if action == "1":
|
|
131
|
+
read_entire(path)
|
|
132
|
+
elif action == "2":
|
|
133
|
+
open_original(path)
|
|
134
|
+
input("Press Enter to return to the menu...")
|
|
135
|
+
elif action == "0":
|
|
136
|
+
break
|
|
137
|
+
else:
|
|
138
|
+
input("Invalid choice. Press Enter to try again...")
|
|
139
|
+
|
|
140
|
+
def main():
|
|
141
|
+
while True:
|
|
142
|
+
clear()
|
|
143
|
+
header("AAI STUDY LIBRARY")
|
|
144
|
+
print("\n Select your test material:\n")
|
|
145
|
+
print(" 1. Part 1")
|
|
146
|
+
print(" 2. Part 2")
|
|
147
|
+
print(" 3. Part 3")
|
|
148
|
+
print(" 0. Exit")
|
|
149
|
+
choice = input("\nEnter choice: ").strip()
|
|
150
|
+
if choice in PARTS:
|
|
151
|
+
select_file(choice)
|
|
152
|
+
elif choice == "0":
|
|
153
|
+
print("\nGood luck with your AAI test!")
|
|
154
|
+
break
|
|
155
|
+
else:
|
|
156
|
+
input("Invalid choice. Press Enter to try again...")
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aai-study-library
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A terminal study library for AAI test materials
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: pypdf>=4.0
|
|
9
|
+
Requires-Dist: python-docx>=1.1
|
|
10
|
+
|
|
11
|
+
# AAI Study Library
|
|
12
|
+
|
|
13
|
+
The `aai` command opens a terminal menu with three separate parts. Choose **Read ENTIRE content in Terminal** to print the complete extractable text in one pass; it does not ask you to press `N` for each page. You can scroll through the terminal history to review the output.
|
|
14
|
+
|
|
15
|
+
PDF and DOCX text is extracted locally. Text embedded inside screenshots/images may not be extractable, so use **Open original file normally** for those visuals.
|
|
16
|
+
|
|
17
|
+
## Build and validate
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python -m pip install --upgrade build twine
|
|
21
|
+
python -m build
|
|
22
|
+
python -m twine check dist/*
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## After publishing to PyPI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m pip install --upgrade aai
|
|
29
|
+
aai
|
|
30
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/aai/__init__.py
|
|
4
|
+
src/aai/__main__.py
|
|
5
|
+
src/aai/cli.py
|
|
6
|
+
src/aai/data/Part 1/E004_AAI_P1.pdf
|
|
7
|
+
src/aai/data/Part 2/E004_AAI_P2.docx
|
|
8
|
+
src/aai/data/Part 3/E004_AAI_P3.docx
|
|
9
|
+
src/aai_study_library.egg-info/PKG-INFO
|
|
10
|
+
src/aai_study_library.egg-info/SOURCES.txt
|
|
11
|
+
src/aai_study_library.egg-info/dependency_links.txt
|
|
12
|
+
src/aai_study_library.egg-info/entry_points.txt
|
|
13
|
+
src/aai_study_library.egg-info/requires.txt
|
|
14
|
+
src/aai_study_library.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aai
|