np2 1.0.0__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.
- np2-1.0.0/.gitignore +1 -0
- np2-1.0.0/PKG-INFO +150 -0
- np2-1.0.0/README.md +141 -0
- np2-1.0.0/pyproject.toml +19 -0
- np2-1.0.0/src/np2/__init__.py +215 -0
- np2-1.0.0/src/np2/__main__.py +2 -0
- np2-1.0.0/src/np2/data/commands.json +1207 -0
- np2-1.0.0/src/np2/data/definitions.json +877 -0
- np2-1.0.0/src/np2/data/source-command-sheet.txt +601 -0
- np2-1.0.0/src/np2/data/topics.json +650 -0
- np2-1.0.0/src/np2/data/unit1.txt +4197 -0
- np2-1.0.0/src/np2/data/unit2.txt +4348 -0
- np2-1.0.0/src/np2/data/unit3.txt +3627 -0
- np2-1.0.0/src/np2/data/unit4.txt +4557 -0
- np2-1.0.0/src/np2/data/unit5.txt +3956 -0
- np2-1.0.0/src/np2/data/units.json +42 -0
- np2-1.0.0/tests/test_installed.py +63 -0
np2-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*
|
np2-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: np2
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Offline IMAP revision: commands with use cases and unit-wise definitions
|
|
5
|
+
Author: Kanishk Thakar
|
|
6
|
+
Keywords: django,docker,imap,revision,study
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# NP2 — IMAP revision in Python
|
|
11
|
+
|
|
12
|
+
A small, offline, zero-runtime-dependency study package based on the supplied
|
|
13
|
+
**IMAP Exam Bible**. Python 3.9 or newer. Import name: `np2`.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
python -m pip install np2
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install the supplied wheel from its containing folder:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
python -m pip install ./np2-1.0.0-py3-none-any.whl
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `python3` instead of `python` where needed. This project uses distribution
|
|
28
|
+
name `np2` and import name `np2`. The local wheel works without an index or
|
|
29
|
+
runtime dependency downloads.
|
|
30
|
+
|
|
31
|
+
## The two sections
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import np2
|
|
35
|
+
np2.show() # compact two-section menu
|
|
36
|
+
np2.show(1) # all commands + use cases
|
|
37
|
+
np2.show(1, group="git") # Git only
|
|
38
|
+
np2.show(1, group="github") # GitHub CLI supplement
|
|
39
|
+
np2.show(1, group="docker") # Docker
|
|
40
|
+
np2.show(1, group="compose") # Docker Compose
|
|
41
|
+
np2.show(2) # all unit-wise definitions
|
|
42
|
+
np2.show(2, unit=1) # just Unit 1
|
|
43
|
+
np2.unit(5) # just Unit 5
|
|
44
|
+
np2.show("all", pager=True) # both sections with terminal paging
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If you prefer uppercase:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import np2 as NP2
|
|
51
|
+
NP2.show()
|
|
52
|
+
NP2.show(1)
|
|
53
|
+
NP2.show(2, unit=3)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Commands are examples printed as text, **never executed** by this package.
|
|
57
|
+
Commands include prerequisites and notes for destructive operations. Replace
|
|
58
|
+
angle-bracket placeholders. Read the group label: SQL statements belong in a
|
|
59
|
+
SQL client, ORM expressions in a configured Django shell, MongoDB expressions
|
|
60
|
+
in mongosh, and Dockerfile instructions in a Dockerfile. Tools such as Git,
|
|
61
|
+
Docker, Node, AWS CLI and GitHub CLI must be installed separately if you want
|
|
62
|
+
to execute examples yourself. They are not installed by NP2.
|
|
63
|
+
|
|
64
|
+
## Coverage
|
|
65
|
+
|
|
66
|
+
- Section 1: 241 command/examples with use cases, grouped as Git, GitHub CLI,
|
|
67
|
+
Python/pip, Django, ORM, SQL/PostgreSQL, MongoDB, React/npm, Docker, Compose,
|
|
68
|
+
Dockerfile, cloud/SSH/AWS and HTTP.
|
|
69
|
+
- Section 2: 175 concise concept definitions across all five units.
|
|
70
|
+
- Full extracted text for Units 1–5 (PDF pages 18–378) and a 108-subsection
|
|
71
|
+
topic index. The concise glossary groups related concepts; it is not a
|
|
72
|
+
claim that every word in the book is separately defined.
|
|
73
|
+
|
|
74
|
+
| Unit | Subject |
|
|
75
|
+
|---|---|
|
|
76
|
+
| 1 | HTML, CSS, JavaScript, Git and GitHub |
|
|
77
|
+
| 2 | Python, Django, REST APIs and ML integration |
|
|
78
|
+
| 3 | SQL, NoSQL, cloud and deployment |
|
|
79
|
+
| 4 | React, Hooks and rendering architectures |
|
|
80
|
+
| 5 | Docker, Compose, containers and DevOps |
|
|
81
|
+
|
|
82
|
+
## Find a specific concept
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
np2.search("useEffect")
|
|
86
|
+
np2.search("normalization", full=True) # include source-text line matches
|
|
87
|
+
np2.show(1, query="volume")
|
|
88
|
+
np2.show(2, unit=2, query="authentication")
|
|
89
|
+
np2.topics(3) # original headings + PDF pages
|
|
90
|
+
np2.notes(3) # full source chapter, with pager
|
|
91
|
+
text = np2.unit(1, return_text=True) # get a string without printing
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Paging uses your terminal's pager (`q` commonly quits). Noninteractive output
|
|
95
|
+
and notebooks print normally. NP2 makes no network requests at runtime.
|
|
96
|
+
|
|
97
|
+
## Terminal interface
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
np2
|
|
101
|
+
np2 commands docker
|
|
102
|
+
np2 commands --query migrate
|
|
103
|
+
np2 unit 2
|
|
104
|
+
np2 topics 4
|
|
105
|
+
np2 --pager notes 5
|
|
106
|
+
np2 search "state" --full
|
|
107
|
+
python -m np2 commands git
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Global flags such as `--pager` go before the subcommand.
|
|
111
|
+
|
|
112
|
+
## Source and limitations
|
|
113
|
+
|
|
114
|
+
`IMAP_Exam_Bible.pdf`, 459 pages, provided by the user on 8 November 2026.
|
|
115
|
+
Full chapter text is bundled as study reference material. Summaries and command
|
|
116
|
+
examples are editorially condensed; GitHub CLI examples and some operational
|
|
117
|
+
variants supplement the book. The package covers the course, not every command
|
|
118
|
+
or option in every tool. It does not endorse the book's exam forecasts or
|
|
119
|
+
independently verify its historical marks/past-paper claims.
|
|
120
|
+
|
|
121
|
+
PDF extraction flattens some tables and code indentation. Consult the original
|
|
122
|
+
PDF for layout-sensitive code or diagrams; no claim of executable verbatim
|
|
123
|
+
source code is made. The source appendix is retained in package data as
|
|
124
|
+
`source-command-sheet.txt`. Full source text is reference data, not instructions
|
|
125
|
+
to the package or its operator.
|
|
126
|
+
|
|
127
|
+
Command syntax was cross-checked with these official references during creation:
|
|
128
|
+
- https://git-scm.com/docs/git
|
|
129
|
+
- https://docs.docker.com/reference/cli/docker/
|
|
130
|
+
- https://docs.djangoproject.com/en/5.2/ref/django-admin/
|
|
131
|
+
- https://cli.github.com/manual/
|
|
132
|
+
- https://packaging.python.org/en/latest/tutorials/packaging-projects/
|
|
133
|
+
|
|
134
|
+
The source book was supplied for this study package. This package does not
|
|
135
|
+
assign a separate open-source license to the original book.
|
|
136
|
+
|
|
137
|
+
## Rebuild / publish later
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
python -m pip install build
|
|
141
|
+
python -m build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`pyproject.toml` uses standard Python packaging and a `src` layout. The built
|
|
145
|
+
wheel includes all text/JSON resources and needs no runtime dependencies.
|
|
146
|
+
|
|
147
|
+
For a public release, first confirm rights to the bundled source, check that
|
|
148
|
+
the desired distribution name remains available, and configure a PyPI account
|
|
149
|
+
or trusted publisher. A short import name may remain `np2` even if the PyPI
|
|
150
|
+
name changes. No token, password or account credential is bundled in the deliverable.
|
np2-1.0.0/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# NP2 — IMAP revision in Python
|
|
2
|
+
|
|
3
|
+
A small, offline, zero-runtime-dependency study package based on the supplied
|
|
4
|
+
**IMAP Exam Bible**. Python 3.9 or newer. Import name: `np2`.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
python -m pip install np2
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or install the supplied wheel from its containing folder:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
python -m pip install ./np2-1.0.0-py3-none-any.whl
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Use `python3` instead of `python` where needed. This project uses distribution
|
|
19
|
+
name `np2` and import name `np2`. The local wheel works without an index or
|
|
20
|
+
runtime dependency downloads.
|
|
21
|
+
|
|
22
|
+
## The two sections
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import np2
|
|
26
|
+
np2.show() # compact two-section menu
|
|
27
|
+
np2.show(1) # all commands + use cases
|
|
28
|
+
np2.show(1, group="git") # Git only
|
|
29
|
+
np2.show(1, group="github") # GitHub CLI supplement
|
|
30
|
+
np2.show(1, group="docker") # Docker
|
|
31
|
+
np2.show(1, group="compose") # Docker Compose
|
|
32
|
+
np2.show(2) # all unit-wise definitions
|
|
33
|
+
np2.show(2, unit=1) # just Unit 1
|
|
34
|
+
np2.unit(5) # just Unit 5
|
|
35
|
+
np2.show("all", pager=True) # both sections with terminal paging
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
If you prefer uppercase:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import np2 as NP2
|
|
42
|
+
NP2.show()
|
|
43
|
+
NP2.show(1)
|
|
44
|
+
NP2.show(2, unit=3)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Commands are examples printed as text, **never executed** by this package.
|
|
48
|
+
Commands include prerequisites and notes for destructive operations. Replace
|
|
49
|
+
angle-bracket placeholders. Read the group label: SQL statements belong in a
|
|
50
|
+
SQL client, ORM expressions in a configured Django shell, MongoDB expressions
|
|
51
|
+
in mongosh, and Dockerfile instructions in a Dockerfile. Tools such as Git,
|
|
52
|
+
Docker, Node, AWS CLI and GitHub CLI must be installed separately if you want
|
|
53
|
+
to execute examples yourself. They are not installed by NP2.
|
|
54
|
+
|
|
55
|
+
## Coverage
|
|
56
|
+
|
|
57
|
+
- Section 1: 241 command/examples with use cases, grouped as Git, GitHub CLI,
|
|
58
|
+
Python/pip, Django, ORM, SQL/PostgreSQL, MongoDB, React/npm, Docker, Compose,
|
|
59
|
+
Dockerfile, cloud/SSH/AWS and HTTP.
|
|
60
|
+
- Section 2: 175 concise concept definitions across all five units.
|
|
61
|
+
- Full extracted text for Units 1–5 (PDF pages 18–378) and a 108-subsection
|
|
62
|
+
topic index. The concise glossary groups related concepts; it is not a
|
|
63
|
+
claim that every word in the book is separately defined.
|
|
64
|
+
|
|
65
|
+
| Unit | Subject |
|
|
66
|
+
|---|---|
|
|
67
|
+
| 1 | HTML, CSS, JavaScript, Git and GitHub |
|
|
68
|
+
| 2 | Python, Django, REST APIs and ML integration |
|
|
69
|
+
| 3 | SQL, NoSQL, cloud and deployment |
|
|
70
|
+
| 4 | React, Hooks and rendering architectures |
|
|
71
|
+
| 5 | Docker, Compose, containers and DevOps |
|
|
72
|
+
|
|
73
|
+
## Find a specific concept
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
np2.search("useEffect")
|
|
77
|
+
np2.search("normalization", full=True) # include source-text line matches
|
|
78
|
+
np2.show(1, query="volume")
|
|
79
|
+
np2.show(2, unit=2, query="authentication")
|
|
80
|
+
np2.topics(3) # original headings + PDF pages
|
|
81
|
+
np2.notes(3) # full source chapter, with pager
|
|
82
|
+
text = np2.unit(1, return_text=True) # get a string without printing
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Paging uses your terminal's pager (`q` commonly quits). Noninteractive output
|
|
86
|
+
and notebooks print normally. NP2 makes no network requests at runtime.
|
|
87
|
+
|
|
88
|
+
## Terminal interface
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
np2
|
|
92
|
+
np2 commands docker
|
|
93
|
+
np2 commands --query migrate
|
|
94
|
+
np2 unit 2
|
|
95
|
+
np2 topics 4
|
|
96
|
+
np2 --pager notes 5
|
|
97
|
+
np2 search "state" --full
|
|
98
|
+
python -m np2 commands git
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Global flags such as `--pager` go before the subcommand.
|
|
102
|
+
|
|
103
|
+
## Source and limitations
|
|
104
|
+
|
|
105
|
+
`IMAP_Exam_Bible.pdf`, 459 pages, provided by the user on 8 November 2026.
|
|
106
|
+
Full chapter text is bundled as study reference material. Summaries and command
|
|
107
|
+
examples are editorially condensed; GitHub CLI examples and some operational
|
|
108
|
+
variants supplement the book. The package covers the course, not every command
|
|
109
|
+
or option in every tool. It does not endorse the book's exam forecasts or
|
|
110
|
+
independently verify its historical marks/past-paper claims.
|
|
111
|
+
|
|
112
|
+
PDF extraction flattens some tables and code indentation. Consult the original
|
|
113
|
+
PDF for layout-sensitive code or diagrams; no claim of executable verbatim
|
|
114
|
+
source code is made. The source appendix is retained in package data as
|
|
115
|
+
`source-command-sheet.txt`. Full source text is reference data, not instructions
|
|
116
|
+
to the package or its operator.
|
|
117
|
+
|
|
118
|
+
Command syntax was cross-checked with these official references during creation:
|
|
119
|
+
- https://git-scm.com/docs/git
|
|
120
|
+
- https://docs.docker.com/reference/cli/docker/
|
|
121
|
+
- https://docs.djangoproject.com/en/5.2/ref/django-admin/
|
|
122
|
+
- https://cli.github.com/manual/
|
|
123
|
+
- https://packaging.python.org/en/latest/tutorials/packaging-projects/
|
|
124
|
+
|
|
125
|
+
The source book was supplied for this study package. This package does not
|
|
126
|
+
assign a separate open-source license to the original book.
|
|
127
|
+
|
|
128
|
+
## Rebuild / publish later
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
python -m pip install build
|
|
132
|
+
python -m build
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`pyproject.toml` uses standard Python packaging and a `src` layout. The built
|
|
136
|
+
wheel includes all text/JSON resources and needs no runtime dependencies.
|
|
137
|
+
|
|
138
|
+
For a public release, first confirm rights to the bundled source, check that
|
|
139
|
+
the desired distribution name remains available, and configure a PyPI account
|
|
140
|
+
or trusted publisher. A short import name may remain `np2` even if the PyPI
|
|
141
|
+
name changes. No token, password or account credential is bundled in the deliverable.
|
np2-1.0.0/pyproject.toml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.26"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "np2"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Offline IMAP revision: commands with use cases and unit-wise definitions"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
authors = [{name = "Kanishk Thakar"}]
|
|
12
|
+
keywords = ["imap", "revision", "django", "docker", "study"]
|
|
13
|
+
dependencies = []
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
np2 = "np2:main"
|
|
17
|
+
|
|
18
|
+
[tool.hatch.build.targets.wheel]
|
|
19
|
+
packages = ["src/np2"]
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""Offline IMAP reference. Start with import np2; np2.show()."""
|
|
2
|
+
from importlib.resources import files
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import pydoc
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
__version__ = "1.0.0"
|
|
9
|
+
__all__ = ["show", "commands", "units", "unit", "topics", "notes", "search", "main"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _json(name):
|
|
13
|
+
return json.loads(files(__package__).joinpath("data", name + ".json").read_text(encoding="utf-8"))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _output(text, pager=False, return_text=False):
|
|
17
|
+
if return_text:
|
|
18
|
+
return text
|
|
19
|
+
if pager and sys.stdout.isatty():
|
|
20
|
+
pydoc.pager(text)
|
|
21
|
+
else:
|
|
22
|
+
print(text)
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _unit_number(value):
|
|
27
|
+
if isinstance(value, bool) or str(value) not in {"1", "2", "3", "4", "5"}:
|
|
28
|
+
raise ValueError("Unit must be an integer from 1 to 5.")
|
|
29
|
+
return int(value)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _match(query, *values):
|
|
33
|
+
return query.casefold() in " ".join(str(v) for v in values).casefold()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def commands(group=None, query=None, *, pager=False, return_text=False):
|
|
37
|
+
"""Display command examples and their use cases. Never execute examples."""
|
|
38
|
+
rows = _json("commands")
|
|
39
|
+
groups = list(dict.fromkeys(r["group"] for r in rows))
|
|
40
|
+
aliases = {"pip": "python", "npm": "react", "drf": "django", "postgres": "sql", "aws": "cloud", "ssh": "cloud"}
|
|
41
|
+
if group:
|
|
42
|
+
group = aliases.get(str(group).casefold(), str(group).casefold())
|
|
43
|
+
if group not in groups:
|
|
44
|
+
raise ValueError("Unknown group. Choose: " + ", ".join(groups))
|
|
45
|
+
rows = [r for r in rows if r["group"] == group]
|
|
46
|
+
if query:
|
|
47
|
+
rows = [r for r in rows if _match(query, r["group"], r["command"], r["use"])]
|
|
48
|
+
lines = ["SECTION 1 - COMMANDS AND USE CASES", "Examples only; replace <placeholders>. Commands are never executed.",
|
|
49
|
+
"Shell commands, SQL, ORM expressions and Dockerfile instructions are labelled separately."]
|
|
50
|
+
previous = None
|
|
51
|
+
for r in rows:
|
|
52
|
+
if r["group"] != previous:
|
|
53
|
+
previous = r["group"]
|
|
54
|
+
lines += ["", "[" + previous.upper() + "]"]
|
|
55
|
+
lines += [r["command"], " Use: " + r["use"]]
|
|
56
|
+
if not rows:
|
|
57
|
+
lines.append("No matching commands.")
|
|
58
|
+
return _output("\n".join(lines), pager, return_text)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def units(number=None, query=None, *, pager=False, return_text=False):
|
|
62
|
+
"""Display all concise definitions, optionally filtered to a unit or phrase."""
|
|
63
|
+
number = _unit_number(number) if number is not None else None
|
|
64
|
+
rows = _json("definitions")
|
|
65
|
+
titles = {r["unit"]: r["title"] for r in _json("units")}
|
|
66
|
+
rows = [r for r in rows if (number is None or r["unit"] == number) and
|
|
67
|
+
(not query or _match(query, r["term"], r["definition"]))]
|
|
68
|
+
lines = ["SECTION 2 - UNIT-WISE DEFINITIONS", "Concise revision glossary; use notes() for full source explanations and code."]
|
|
69
|
+
previous = None
|
|
70
|
+
for r in rows:
|
|
71
|
+
if r["unit"] != previous:
|
|
72
|
+
previous = r["unit"]
|
|
73
|
+
lines += ["", f"UNIT {previous}: {titles[previous]}"]
|
|
74
|
+
lines += [r["term"], " " + r["definition"]]
|
|
75
|
+
if not rows:
|
|
76
|
+
lines.append("No matching definitions.")
|
|
77
|
+
return _output("\n".join(lines), pager, return_text)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
unit = units
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def topics(number=None, *, pager=False, return_text=False):
|
|
84
|
+
"""List every numbered source subsection and its original PDF page."""
|
|
85
|
+
number = _unit_number(number) if number is not None else None
|
|
86
|
+
rows = [r for r in _json("topics") if number is None or r["unit"] == number]
|
|
87
|
+
text = "SOURCE TOPICS\n" + "\n".join(f'{r["id"]:5} {r["title"]} (PDF p. {r["page"]})' for r in rows)
|
|
88
|
+
return _output(text, pager, return_text)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def notes(number, *, pager=True, return_text=False):
|
|
92
|
+
"""Display the complete extracted chapter for a unit (including examples).
|
|
93
|
+
|
|
94
|
+
Source wording is preserved, not independently fact-checked. PDF extraction
|
|
95
|
+
can flatten tables/code indentation. Original PDF page numbers are retained.
|
|
96
|
+
"""
|
|
97
|
+
number = _unit_number(number)
|
|
98
|
+
text = files(__package__).joinpath("data", f"unit{number}.txt").read_text(encoding="utf-8")
|
|
99
|
+
header = "FULL SOURCE NOTES - UNIT " + str(number) + "\nPDF text extraction; table/code layout may differ.\n"
|
|
100
|
+
return _output(header + text, pager, return_text)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def search(query, *, full=False, pager=False, return_text=False):
|
|
104
|
+
"""Search commands, definitions and topic headings; full=True adds source lines."""
|
|
105
|
+
if not isinstance(query, str) or not query.strip():
|
|
106
|
+
raise ValueError("Provide a non-empty search phrase.")
|
|
107
|
+
parts = []
|
|
108
|
+
for r in _json("commands"):
|
|
109
|
+
if _match(query, r["group"], r["command"], r["use"]):
|
|
110
|
+
parts.append(f'[command/{r["group"]}] {r["command"]}\n {r["use"]}')
|
|
111
|
+
for r in _json("definitions"):
|
|
112
|
+
if _match(query, r["term"], r["definition"]):
|
|
113
|
+
parts.append(f'[unit {r["unit"]}] {r["term"]}\n {r["definition"]}')
|
|
114
|
+
for r in _json("topics"):
|
|
115
|
+
if _match(query, r["title"], r["id"]):
|
|
116
|
+
parts.append(f'[topic {r["id"]}, PDF p. {r["page"]}] {r["title"]}')
|
|
117
|
+
if full:
|
|
118
|
+
for number in range(1, 6):
|
|
119
|
+
page = "?"
|
|
120
|
+
text = files(__package__).joinpath("data", f"unit{number}.txt").read_text(encoding="utf-8")
|
|
121
|
+
for line in text.splitlines():
|
|
122
|
+
if line.startswith("--- PDF page "):
|
|
123
|
+
page = line.split()[3]
|
|
124
|
+
elif _match(query, line):
|
|
125
|
+
parts.append(f'[source unit {number}, PDF p. {page}] {line.strip()}')
|
|
126
|
+
return _output("\n\n".join(parts) if parts else "No matches found.", pager, return_text)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def show(section=None, *, unit=None, group=None, query=None, pager=False, return_text=False):
|
|
130
|
+
"""show(): two-section menu; show(1): commands; show(2): definitions.
|
|
131
|
+
|
|
132
|
+
Examples: show(1, group='docker'); show(2, unit=3); show('all').
|
|
133
|
+
"""
|
|
134
|
+
key = str(section).casefold() if section is not None else None
|
|
135
|
+
if key in {"1", "commands", "command"}:
|
|
136
|
+
if unit is not None:
|
|
137
|
+
raise ValueError("Use unit= with section 2; use group= with section 1.")
|
|
138
|
+
return commands(group, query, pager=pager, return_text=return_text)
|
|
139
|
+
if key in {"2", "units", "unit", "definitions"} or (key is None and unit is not None):
|
|
140
|
+
if group is not None:
|
|
141
|
+
raise ValueError("Use group= with section 1.")
|
|
142
|
+
return units(unit, query, pager=pager, return_text=return_text)
|
|
143
|
+
if key == "all":
|
|
144
|
+
text = commands(group, query, return_text=True) + "\n\n" + units(unit, query, return_text=True)
|
|
145
|
+
return _output(text, pager, return_text)
|
|
146
|
+
if key is None and group is not None:
|
|
147
|
+
return commands(group, query, pager=pager, return_text=return_text)
|
|
148
|
+
if key is None and query:
|
|
149
|
+
return search(query, pager=pager, return_text=return_text)
|
|
150
|
+
if key is not None:
|
|
151
|
+
raise ValueError("Section must be 1/'commands', 2/'units', or 'all'.")
|
|
152
|
+
counts = (len(_json("commands")), len(_json("definitions")), len(_json("topics")))
|
|
153
|
+
menu = f'''NP2 - OFFLINE IMAP REVISION ({__version__})
|
|
154
|
+
{counts[0]} command examples | {counts[1]} definitions | {counts[2]} source topics | 5 units
|
|
155
|
+
|
|
156
|
+
1. COMMANDS + USE CASES
|
|
157
|
+
np2.show(1) All commands, grouped by tool
|
|
158
|
+
np2.show(1, group="git") Git commands
|
|
159
|
+
np2.show(1, group="docker") Docker commands
|
|
160
|
+
np2.show(1, group="compose") Compose commands
|
|
161
|
+
np2.show(1, query="migrate") Filter command examples
|
|
162
|
+
|
|
163
|
+
2. UNIT-WISE DEFINITIONS
|
|
164
|
+
np2.show(2) Definitions for all five units
|
|
165
|
+
np2.show(2, unit=1) Definitions for Unit 1
|
|
166
|
+
np2.unit(4) Shortcut for Unit 4
|
|
167
|
+
np2.topics(4) Source subsection/page index
|
|
168
|
+
np2.notes(4) Full Unit 4 text and code
|
|
169
|
+
|
|
170
|
+
np2.search("promise") Search both sections
|
|
171
|
+
np2.search("promise", full=True) Also search complete unit text
|
|
172
|
+
np2.show("all", pager=True) Read both sections with paging
|
|
173
|
+
|
|
174
|
+
Units: 1 Web/Git | 2 Python/Django | 3 Databases/Cloud | 4 React | 5 Docker
|
|
175
|
+
Use import np2 as NP2 if you prefer NP2.show().
|
|
176
|
+
This is an offline study reference. It does not run the displayed commands.'''
|
|
177
|
+
return _output(menu, pager, return_text)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def main(argv=None):
|
|
181
|
+
"""Command-line interface: np2 commands docker; np2 unit 1; np2 search hooks."""
|
|
182
|
+
parser = argparse.ArgumentParser(prog="np2", description="Offline IMAP study reference")
|
|
183
|
+
parser.add_argument("--version", action="version", version=__version__)
|
|
184
|
+
parser.add_argument("--pager", action="store_true", help="Page output in an interactive terminal")
|
|
185
|
+
sub = parser.add_subparsers(dest="action")
|
|
186
|
+
cmd = sub.add_parser("commands", help="Section 1: commands with use cases")
|
|
187
|
+
cmd.add_argument("group", nargs="?")
|
|
188
|
+
cmd.add_argument("--query")
|
|
189
|
+
unt = sub.add_parser("unit", aliases=["units"], help="Section 2: unit definitions")
|
|
190
|
+
unt.add_argument("number", nargs="?", type=int)
|
|
191
|
+
unt.add_argument("--query")
|
|
192
|
+
top = sub.add_parser("topics", help="Source subsection index")
|
|
193
|
+
top.add_argument("number", nargs="?", type=int)
|
|
194
|
+
note = sub.add_parser("notes", help="Complete source chapter")
|
|
195
|
+
note.add_argument("number", type=int)
|
|
196
|
+
find = sub.add_parser("search", help="Search all reference entries")
|
|
197
|
+
find.add_argument("query")
|
|
198
|
+
find.add_argument("--full", action="store_true")
|
|
199
|
+
sub.add_parser("all", help="Show both complete sections")
|
|
200
|
+
args = parser.parse_args(argv)
|
|
201
|
+
try:
|
|
202
|
+
if args.action == "commands":
|
|
203
|
+
commands(args.group, args.query, pager=args.pager)
|
|
204
|
+
elif args.action in {"unit", "units"}:
|
|
205
|
+
units(args.number, args.query, pager=args.pager)
|
|
206
|
+
elif args.action == "topics":
|
|
207
|
+
topics(args.number, pager=args.pager)
|
|
208
|
+
elif args.action == "notes":
|
|
209
|
+
notes(args.number, pager=args.pager)
|
|
210
|
+
elif args.action == "search":
|
|
211
|
+
search(args.query, full=args.full, pager=args.pager)
|
|
212
|
+
else:
|
|
213
|
+
show("all" if args.action == "all" else None, pager=args.pager)
|
|
214
|
+
except ValueError as error:
|
|
215
|
+
parser.error(str(error))
|