@booklib/skills 1.0.0 → 1.3.0

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 (100) hide show
  1. package/CONTRIBUTING.md +122 -0
  2. package/README.md +20 -1
  3. package/ROADMAP.md +36 -0
  4. package/animation-at-work/evals/evals.json +44 -0
  5. package/animation-at-work/examples/after.md +64 -0
  6. package/animation-at-work/examples/before.md +35 -0
  7. package/animation-at-work/scripts/audit_animations.py +295 -0
  8. package/bin/skills.js +552 -42
  9. package/clean-code-reviewer/SKILL.md +109 -1
  10. package/clean-code-reviewer/evals/evals.json +121 -3
  11. package/clean-code-reviewer/examples/after.md +48 -0
  12. package/clean-code-reviewer/examples/before.md +33 -0
  13. package/clean-code-reviewer/references/api_reference.md +158 -0
  14. package/clean-code-reviewer/references/practices-catalog.md +282 -0
  15. package/clean-code-reviewer/references/review-checklist.md +254 -0
  16. package/clean-code-reviewer/scripts/pre-review.py +206 -0
  17. package/data-intensive-patterns/evals/evals.json +43 -0
  18. package/data-intensive-patterns/examples/after.md +61 -0
  19. package/data-intensive-patterns/examples/before.md +38 -0
  20. package/data-intensive-patterns/scripts/adr.py +213 -0
  21. package/data-pipelines/evals/evals.json +45 -0
  22. package/data-pipelines/examples/after.md +97 -0
  23. package/data-pipelines/examples/before.md +37 -0
  24. package/data-pipelines/scripts/new_pipeline.py +444 -0
  25. package/design-patterns/evals/evals.json +46 -0
  26. package/design-patterns/examples/after.md +52 -0
  27. package/design-patterns/examples/before.md +29 -0
  28. package/design-patterns/scripts/scaffold.py +807 -0
  29. package/domain-driven-design/SKILL.md +120 -0
  30. package/domain-driven-design/evals/evals.json +48 -0
  31. package/domain-driven-design/examples/after.md +80 -0
  32. package/domain-driven-design/examples/before.md +43 -0
  33. package/domain-driven-design/scripts/scaffold.py +421 -0
  34. package/effective-java/evals/evals.json +46 -0
  35. package/effective-java/examples/after.md +83 -0
  36. package/effective-java/examples/before.md +37 -0
  37. package/effective-java/scripts/checkstyle_setup.py +211 -0
  38. package/effective-kotlin/evals/evals.json +45 -0
  39. package/effective-kotlin/examples/after.md +36 -0
  40. package/effective-kotlin/examples/before.md +38 -0
  41. package/effective-python/SKILL.md +199 -0
  42. package/effective-python/evals/evals.json +44 -0
  43. package/effective-python/examples/after.md +56 -0
  44. package/effective-python/examples/before.md +40 -0
  45. package/effective-python/ref-01-pythonic-thinking.md +202 -0
  46. package/effective-python/ref-02-lists-and-dicts.md +146 -0
  47. package/effective-python/ref-03-functions.md +186 -0
  48. package/effective-python/ref-04-comprehensions-generators.md +211 -0
  49. package/effective-python/ref-05-classes-interfaces.md +188 -0
  50. package/effective-python/ref-06-metaclasses-attributes.md +209 -0
  51. package/effective-python/ref-07-concurrency.md +213 -0
  52. package/effective-python/ref-08-robustness-performance.md +248 -0
  53. package/effective-python/ref-09-testing-debugging.md +253 -0
  54. package/effective-python/ref-10-collaboration.md +175 -0
  55. package/effective-python/references/api_reference.md +218 -0
  56. package/effective-python/references/practices-catalog.md +483 -0
  57. package/effective-python/references/review-checklist.md +190 -0
  58. package/effective-python/scripts/lint.py +173 -0
  59. package/kotlin-in-action/evals/evals.json +43 -0
  60. package/kotlin-in-action/examples/after.md +53 -0
  61. package/kotlin-in-action/examples/before.md +39 -0
  62. package/kotlin-in-action/scripts/setup_detekt.py +224 -0
  63. package/lean-startup/evals/evals.json +43 -0
  64. package/lean-startup/examples/after.md +80 -0
  65. package/lean-startup/examples/before.md +34 -0
  66. package/lean-startup/scripts/new_experiment.py +286 -0
  67. package/microservices-patterns/SKILL.md +140 -0
  68. package/microservices-patterns/evals/evals.json +45 -0
  69. package/microservices-patterns/examples/after.md +69 -0
  70. package/microservices-patterns/examples/before.md +40 -0
  71. package/microservices-patterns/scripts/new_service.py +583 -0
  72. package/package.json +1 -1
  73. package/refactoring-ui/evals/evals.json +45 -0
  74. package/refactoring-ui/examples/after.md +85 -0
  75. package/refactoring-ui/examples/before.md +58 -0
  76. package/refactoring-ui/scripts/audit_css.py +250 -0
  77. package/skill-router/SKILL.md +142 -0
  78. package/skill-router/evals/evals.json +38 -0
  79. package/skill-router/examples/after.md +63 -0
  80. package/skill-router/examples/before.md +39 -0
  81. package/skill-router/references/api_reference.md +24 -0
  82. package/skill-router/references/routing-heuristics.md +89 -0
  83. package/skill-router/references/skill-catalog.md +156 -0
  84. package/skill-router/scripts/route.py +266 -0
  85. package/storytelling-with-data/evals/evals.json +47 -0
  86. package/storytelling-with-data/examples/after.md +50 -0
  87. package/storytelling-with-data/examples/before.md +33 -0
  88. package/storytelling-with-data/scripts/chart_review.py +301 -0
  89. package/system-design-interview/evals/evals.json +45 -0
  90. package/system-design-interview/examples/after.md +94 -0
  91. package/system-design-interview/examples/before.md +27 -0
  92. package/system-design-interview/scripts/new_design.py +421 -0
  93. package/using-asyncio-python/evals/evals.json +43 -0
  94. package/using-asyncio-python/examples/after.md +68 -0
  95. package/using-asyncio-python/examples/before.md +39 -0
  96. package/using-asyncio-python/scripts/check_blocking.py +270 -0
  97. package/web-scraping-python/evals/evals.json +46 -0
  98. package/web-scraping-python/examples/after.md +109 -0
  99. package/web-scraping-python/examples/before.md +40 -0
  100. package/web-scraping-python/scripts/new_scraper.py +231 -0
@@ -0,0 +1,175 @@
1
+ # Chapter 10: Collaboration (Items 86-90)
2
+
3
+ ## Item 86: Consider Module-Scoped Code to Configure Deployment Environments
4
+ ```python
5
+ # config.py
6
+ import sys
7
+
8
+ # Module-scoped code runs at import time
9
+ if sys.platform == 'win32':
10
+ DB_PATH = r'C:\data\mydb.sqlite'
11
+ else:
12
+ DB_PATH = '/data/mydb.sqlite'
13
+
14
+ # Use environment variables for deployment config
15
+ import os
16
+ ENVIRONMENT = os.environ.get('APP_ENV', 'development')
17
+
18
+ if ENVIRONMENT == 'production':
19
+ DEBUG = False
20
+ DATABASE_URL = os.environ['DATABASE_URL']
21
+ else:
22
+ DEBUG = True
23
+ DATABASE_URL = 'sqlite:///dev.db'
24
+ ```
25
+
26
+ - Module-level code executes once at import time
27
+ - Use it for deployment configuration, feature flags
28
+ - Keep it minimal — complex logic at import time slows startup
29
+ - Prefer environment variables over hardcoded conditions
30
+
31
+ ## Item 87: Define a Root Exception to Insulate Callers from APIs
32
+ ```python
33
+ # mypackage/exceptions.py
34
+ class Error(Exception):
35
+ """Base class for all exceptions in this package."""
36
+
37
+ class InvalidInputError(Error):
38
+ """Raised when input validation fails."""
39
+
40
+ class AuthenticationError(Error):
41
+ """Raised when authentication fails."""
42
+
43
+ class InternalError(Error):
44
+ """Raised for unexpected internal errors."""
45
+
46
+ # Callers can catch all package errors
47
+ try:
48
+ result = mypackage.do_something()
49
+ except mypackage.Error:
50
+ # Catches any error from this package
51
+ logging.exception('Error from mypackage')
52
+ except Exception:
53
+ # Catches unexpected errors (bugs)
54
+ logging.exception('Unexpected error')
55
+ raise
56
+ ```
57
+
58
+ - Define a root `Error` class for your package/module
59
+ - All custom exceptions inherit from it
60
+ - Callers can catch the root to handle all your errors
61
+ - Three levels: root error (known API errors), specific errors, Exception (bugs)
62
+ - This insulates callers from internal changes to your exception hierarchy
63
+
64
+ ## Item 88: Know How to Break Circular Dependencies
65
+ ```python
66
+ # BAD — circular import
67
+ # module_a.py
68
+ from module_b import B
69
+ class A:
70
+ def use_b(self):
71
+ return B()
72
+
73
+ # module_b.py
74
+ from module_a import A # ImportError: circular!
75
+ class B:
76
+ def use_a(self):
77
+ return A()
78
+
79
+ # FIX 1 — import at function call time
80
+ # module_a.py
81
+ class A:
82
+ def use_b(self):
83
+ from module_b import B # lazy import
84
+ return B()
85
+
86
+ # FIX 2 — restructure to remove the cycle
87
+ # Move shared code to a third module
88
+
89
+ # FIX 3 — use import module, not from module import
90
+ import module_b
91
+ class A:
92
+ def use_b(self):
93
+ return module_b.B()
94
+ ```
95
+
96
+ **Strategies (in order of preference):**
97
+ 1. **Restructure** — move shared code to a common module
98
+ 2. **Import at use time** — put import inside the function
99
+ 3. **Import the module** — use `import module` instead of `from module import name`
100
+
101
+ ## Item 89: Consider warnings to Refactor and Migrate Usage
102
+ ```python
103
+ import warnings
104
+
105
+ def old_function():
106
+ """Deprecated: use new_function instead."""
107
+ warnings.warn(
108
+ 'old_function is deprecated, use new_function',
109
+ DeprecationWarning,
110
+ stacklevel=2 # point to caller, not this function
111
+ )
112
+ return new_function()
113
+
114
+ # Callers see:
115
+ # DeprecationWarning: old_function is deprecated, use new_function
116
+ # result = old_function() # <-- points to their code
117
+ ```
118
+
119
+ - Use `DeprecationWarning` for API migrations
120
+ - `stacklevel=2` makes the warning point to the caller's code
121
+ - Use `warnings.filterwarnings` to control warning behavior
122
+ - In tests, use `warnings.catch_warnings` to verify warnings are raised:
123
+ ```python
124
+ with warnings.catch_warnings(record=True) as w:
125
+ warnings.simplefilter('always')
126
+ old_function()
127
+ assert len(w) == 1
128
+ assert issubclass(w[0].category, DeprecationWarning)
129
+ ```
130
+
131
+ ## Item 90: Consider Static Analysis via typing to Obviate Bugs
132
+ ```python
133
+ from typing import List, Dict, Optional, Tuple, Union
134
+ from typing import Protocol # Python 3.8+
135
+
136
+ # Basic type annotations
137
+ def greet(name: str) -> str:
138
+ return f'Hello, {name}'
139
+
140
+ # Collections
141
+ def process(items: List[int]) -> Dict[str, int]:
142
+ return {'total': sum(items)}
143
+
144
+ # Optional (can be None)
145
+ def find(name: str) -> Optional[str]:
146
+ ...
147
+
148
+ # Protocol for structural typing (duck typing)
149
+ class Readable(Protocol):
150
+ def read(self) -> str:
151
+ ...
152
+
153
+ def process_input(source: Readable) -> str:
154
+ return source.read()
155
+
156
+ # Generic classes
157
+ from typing import Generic, TypeVar
158
+ T = TypeVar('T')
159
+
160
+ class Stack(Generic[T]):
161
+ def __init__(self) -> None:
162
+ self._items: List[T] = []
163
+
164
+ def push(self, item: T) -> None:
165
+ self._items.append(item)
166
+
167
+ def pop(self) -> T:
168
+ return self._items.pop()
169
+ ```
170
+
171
+ - Use type annotations for documentation and static analysis
172
+ - Run `mypy` for type checking: `mypy --strict mymodule.py`
173
+ - Use `Protocol` for structural typing (no inheritance needed)
174
+ - Type hints are not enforced at runtime (use `mypy` to check)
175
+ - Modern syntax (Python 3.10+): `list[int]` instead of `List[int]`, `X | Y` instead of `Union[X, Y]`
@@ -0,0 +1,218 @@
1
+ # Effective Python — All 90 Items Quick Reference
2
+
3
+ Complete reference table for all 90 items from *Effective Python: 90 Specific Ways
4
+ to Write Better Python* (2nd Edition) by Brett Slatkin.
5
+
6
+ ---
7
+
8
+ ## Chapter 1 — Pythonic Thinking (Items 1–10)
9
+
10
+ | Item | Name | Chapter | Summary |
11
+ |------|------|---------|---------|
12
+ | 1 | Know Which Version of Python You're Using | Pythonic Thinking | Verify the runtime version; write code for Python 3; avoid Python 2 patterns |
13
+ | 2 | Follow the PEP 8 Style Guide | Pythonic Thinking | snake_case functions/variables, PascalCase classes, 4-space indent, 79-char lines |
14
+ | 3 | Know the Differences Between bytes and str | Pythonic Thinking | Be explicit about encoding boundaries; never mix bytes and str operations |
15
+ | 4 | Prefer Interpolated F-Strings Over C-style Format Strings and str.format | Pythonic Thinking | Use f-strings for all string formatting; they're more readable and expressive |
16
+ | 5 | Write Helper Functions Instead of Complex Expressions | Pythonic Thinking | When an expression needs a comment, extract it into a descriptively named helper function |
17
+ | 6 | Prefer Multiple Assignment Unpacking Over Indexing | Pythonic Thinking | Unpack sequences into named variables instead of accessing by index |
18
+ | 7 | Prefer enumerate Over range | Pythonic Thinking | Use `enumerate(seq)` instead of `range(len(seq))` when index and value are both needed |
19
+ | 8 | Use zip to Process Iterators in Parallel | Pythonic Thinking | Use `zip()` for parallel iteration; `itertools.zip_longest` when lengths may differ |
20
+ | 9 | Avoid else Blocks After for and while Loops | Pythonic Thinking | Loop else blocks are counterintuitive; use a flag variable or restructure instead |
21
+ | 10 | Prevent Repetition with Assignment Expressions | Pythonic Thinking | Use `:=` (walrus) to assign and test in one expression; avoid in places that hurt clarity |
22
+
23
+ ---
24
+
25
+ ## Chapter 2 — Lists and Dicts (Items 11–18)
26
+
27
+ | Item | Name | Chapter | Summary |
28
+ |------|------|---------|---------|
29
+ | 11 | Know How to Slice Sequences | Lists and Dicts | Omit start/end in slices at boundaries; prefer `a[:5]` over `a[0:5]` |
30
+ | 12 | Avoid Striding and Slicing in a Single Expression | Lists and Dicts | Never combine start, stop, and stride in one slice; use two operations for clarity |
31
+ | 13 | Prefer Catch-All Unpacking Over Slicing | Lists and Dicts | Use starred expressions `first, *rest = items` to split sequences without slicing |
32
+ | 14 | Sort by Complex Criteria Using the key Parameter | Lists and Dicts | Use `key=` function with `sort()` and `sorted()`; never use the removed `cmp=` parameter |
33
+ | 15 | Be Cautious When Relying on dict Insertion Ordering | Lists and Dicts | In Python 3.7+ dicts preserve insertion order; don't write code that requires a specific order from arbitrary kwargs |
34
+ | 16 | Prefer get Over in and KeyError to Handle Missing Dict Keys | Lists and Dicts | Use `dict.get(key, default)` for simple cases; use `setdefault` for initialization |
35
+ | 17 | Prefer defaultdict Over setdefault to Handle Missing Items in Internal State | Lists and Dicts | Use `collections.defaultdict` for dicts where missing keys need automatic initialization |
36
+ | 18 | Know How to Construct Key-Dependent Default Values with __missing__ | Lists and Dicts | Subclass `dict` and implement `__missing__` when the default value depends on the key |
37
+
38
+ ---
39
+
40
+ ## Chapter 3 — Functions (Items 19–26)
41
+
42
+ | Item | Name | Chapter | Summary |
43
+ |------|------|---------|---------|
44
+ | 19 | Never Unpack More Than Three Variables When Functions Return Multiple Values | Functions | Tuples of 4+ are unreadable; use `namedtuple` or a small class instead |
45
+ | 20 | Prefer Raising Exceptions to Returning None | Functions | `None` is silently ignored; exceptions are explicit and force callers to handle failure |
46
+ | 21 | Know How Closures Interact with Variable Scope | Functions | Closures can read enclosing scope; use `nonlocal` to write to it; prefer class state for complex cases |
47
+ | 22 | Reduce Visual Noise with Variable Positional Arguments | Functions | Use `*args` to accept variable positional arguments; watch out for generator exhaustion |
48
+ | 23 | Provide Optional Behavior with Keyword Arguments | Functions | Use keyword arguments for optional parameters; provide sensible defaults |
49
+ | 24 | Use None and Docstrings to Specify Dynamic Default Arguments | Functions | Never use mutable or dynamic values as defaults; use `None` and initialize inside the body |
50
+ | 25 | Enforce Clarity with Keyword-Only and Positional-Only Arguments | Functions | Use `*` to force keyword-only args; use `/` to enforce positional-only args |
51
+ | 26 | Define Function Decorators with functools.wraps | Functions | Always use `@functools.wraps(func)` in decorators to preserve metadata |
52
+
53
+ ---
54
+
55
+ ## Chapter 4 — Comprehensions and Generators (Items 27–36)
56
+
57
+ | Item | Name | Chapter | Summary |
58
+ |------|------|---------|---------|
59
+ | 27 | Use Comprehensions Instead of map and filter | Comprehensions & Generators | List/dict/set comprehensions are clearer than `map(lambda...)` and `filter(lambda...)` |
60
+ | 28 | Avoid More Than Two Control Subexpressions in Comprehensions | Comprehensions & Generators | At most one loop and one condition in a comprehension; use a regular loop for anything more |
61
+ | 29 | Avoid Repeated Work in Comprehensions by Using the Walrus Operator | Comprehensions & Generators | Use `:=` in comprehensions to avoid calling the same function twice in loop and condition |
62
+ | 30 | Consider Generators Instead of Returning Lists | Comprehensions & Generators | Use `yield` to produce sequences lazily; avoids building the full list in memory |
63
+ | 31 | Be Defensive When Iterating Over Arguments | Comprehensions & Generators | Iterators are exhausted after one pass; containers can be iterated multiple times |
64
+ | 32 | Consider Generator Expressions for Large List Comprehensions | Comprehensions & Generators | Use `(x for x in ...)` instead of `[x for x in ...]` for large sequences to avoid memory overhead |
65
+ | 33 | Compose Multiple Generators with yield from | Comprehensions & Generators | Use `yield from` to delegate to a sub-generator instead of a manual `for/yield` loop |
66
+ | 34 | Avoid Injecting Data into Generators with send | Comprehensions & Generators | `generator.send()` is confusing; prefer passing parameters to generator functions |
67
+ | 35 | Avoid Causing State Transitions in Generators with throw | Comprehensions & Generators | `generator.throw()` complicates flow; prefer class-based stateful iteration |
68
+ | 36 | Consider itertools for Working with Iterators and Generators | Comprehensions & Generators | Use `itertools.chain`, `islice`, `tee`, `zip_longest`, `product`, `groupby` instead of hand-rolling |
69
+
70
+ ---
71
+
72
+ ## Chapter 5 — Classes and Interfaces (Items 37–43)
73
+
74
+ | Item | Name | Chapter | Summary |
75
+ |------|------|---------|---------|
76
+ | 37 | Compose Classes Instead of Nesting Many Levels of Built-in Types | Classes & Interfaces | When data has more than two nesting levels, define helper classes or use dataclass |
77
+ | 38 | Accept Functions Instead of Classes for Simple Interfaces | Classes & Interfaces | Pass functions (or callables) rather than defining single-method interfaces |
78
+ | 39 | Use @classmethod Polymorphism to Construct Objects Generically | Classes & Interfaces | Use `@classmethod` for alternative constructors; enables polymorphic creation |
79
+ | 40 | Initialize Parent Classes with super() | Classes & Interfaces | Always call `super().__init__()` to handle MRO correctly in multiple inheritance |
80
+ | 41 | Consider Composing Functionality with Mix-in Classes | Classes & Interfaces | Mix-ins provide reusable behavior via inheritance without state or `__init__` |
81
+ | 42 | Prefer Public Attributes Over Private Ones | Classes & Interfaces | Use `self.value` by default; use `_protected` by convention; use `__private` only for subclass collision prevention |
82
+ | 43 | Inherit from collections.abc for Custom Container Types | Classes & Interfaces | Inherit from `Sequence`, `Mapping`, `Set` etc. to get correct interface enforcement |
83
+
84
+ ---
85
+
86
+ ## Chapter 6 — Metaclasses and Attributes (Items 44–51)
87
+
88
+ | Item | Name | Chapter | Summary |
89
+ |------|------|---------|---------|
90
+ | 44 | Use Plain Attributes Instead of Setter and Getter Methods | Metaclasses & Attributes | Public attributes are Pythonic; getter/setter pairs are Java idiom and should be avoided |
91
+ | 45 | Consider @property Instead of Refactoring Attributes | Metaclasses & Attributes | Use `@property` to add behavior to attribute access without changing the caller's interface |
92
+ | 46 | Use Descriptive Attributes for Lazy Attributes | Metaclasses & Attributes | Use `@property` for lazy computation; avoid surprising side effects in getters |
93
+ | 47 | Use __set_name__ to Annotate Class Attributes | Metaclasses & Attributes | Descriptors with `__set_name__` learn their attribute name automatically at class creation |
94
+ | 48 | Know How to Use __getattr__, __getattribute__, and __setattr__ for On-demand Attribute Access | Metaclasses & Attributes | Use `__getattr__` for missing attributes (lazy init); avoid `__getattribute__` unless truly needed |
95
+ | 49 | Register Class Existence with __init_subclass__ | Metaclasses & Attributes | Use `__init_subclass__` to validate or register subclasses without a metaclass |
96
+ | 50 | Annotate Class Attributes with __set_name__ | Metaclasses & Attributes | Descriptors use `__set_name__` to capture the name they're assigned to, eliminating boilerplate |
97
+ | 51 | Prefer Class Decorators Over Metaclasses for Composable Class Extensions | Metaclasses & Attributes | Class decorators are simpler than metaclasses for most class-level transformations |
98
+
99
+ ---
100
+
101
+ ## Chapter 7 — Concurrency and Parallelism (Items 52–64)
102
+
103
+ | Item | Name | Chapter | Summary |
104
+ |------|------|---------|---------|
105
+ | 52 | Use subprocess to Manage Child Processes | Concurrency & Parallelism | Manage child processes with `subprocess.run()` or `Popen`; avoid `os.system()` |
106
+ | 53 | Use Threads for Blocking I/O, Avoid for Parallelism | Concurrency & Parallelism | GIL prevents thread-based CPU parallelism; threads are for I/O only |
107
+ | 54 | Use Lock to Prevent Data Races in Threads | Concurrency & Parallelism | Protect all shared mutable state with `threading.Lock` using `with lock:` |
108
+ | 55 | Use Queue to Coordinate Work Between Threads | Concurrency & Parallelism | Use `queue.Queue` for thread-safe producer-consumer coordination |
109
+ | 56 | Know How to Recognize When Concurrency Is Necessary | Concurrency & Parallelism | Identify fan-out (spawning work) and fan-in (collecting results) patterns |
110
+ | 57 | Avoid Creating New Thread Instances for On-demand Fan-out | Concurrency & Parallelism | Creating threads on demand is costly; use a thread pool instead |
111
+ | 58 | Understand How Using Queue for Concurrency Requires Refactoring | Concurrency & Parallelism | Queue-based concurrency requires rethinking data flow across thread boundaries |
112
+ | 59 | Consider ThreadPoolExecutor When Threads Are Necessary for Concurrency | Concurrency & Parallelism | Use `concurrent.futures.ThreadPoolExecutor` for managed thread pools with futures |
113
+ | 60 | Achieve Highly Concurrent I/O with Coroutines | Concurrency & Parallelism | Use `asyncio` coroutines for large numbers of concurrent I/O operations |
114
+ | 61 | Know How to Port Threaded I/O to asyncio | Concurrency & Parallelism | Replace blocking calls with `await`; restructure sync code to async incrementally |
115
+ | 62 | Mix Threads and Coroutines to Ease the Transition to asyncio | Concurrency & Parallelism | Use `asyncio.run_in_executor` to call blocking code from async context during migration |
116
+ | 63 | Avoid Blocking the asyncio Event Loop to Maximize Responsiveness | Concurrency & Parallelism | Never call blocking I/O, `time.sleep`, or CPU-heavy code directly in `async def` functions |
117
+ | 64 | Consider concurrent.futures for True Parallelism | Concurrency & Parallelism | Use `ProcessPoolExecutor` for CPU-bound parallelism that bypasses the GIL |
118
+
119
+ ---
120
+
121
+ ## Chapter 8 — Robustness and Performance (Items 65–79)
122
+
123
+ | Item | Name | Chapter | Summary |
124
+ |------|------|---------|---------|
125
+ | 65 | Take Advantage of Each Block in try/except/else/finally | Robustness & Performance | Use `else` for success code and `finally` for cleanup; keep `try` narrow |
126
+ | 66 | Consider contextlib and with Statements for Reusable try/finally Behavior | Robustness & Performance | Use `@contextlib.contextmanager` to package setup/teardown as a context manager |
127
+ | 67 | Use datetime Instead of time for Local Clocks | Robustness & Performance | Use `datetime` with `pytz` or `zoneinfo` for timezone-aware time; avoid the `time` module |
128
+ | 68 | Make pickle Reliable with copyreg | Robustness & Performance | Use `copyreg` to version pickle data and handle class evolution over time |
129
+ | 69 | Use decimal When Precision Is Paramount | Robustness & Performance | Use `decimal.Decimal` for monetary or exact decimal arithmetic; never float for money |
130
+ | 70 | Profile Before Optimizing | Robustness & Performance | Use `cProfile` to find real bottlenecks before optimizing; intuition is often wrong |
131
+ | 71 | Prefer deque for Producer-Consumer Queues | Robustness & Performance | `collections.deque` appends/pops from both ends in O(1); `list.pop(0)` is O(n) |
132
+ | 72 | Consider Searching Sorted Lists with bisect | Robustness & Performance | Use `bisect.bisect_left` and `insort` for O(log n) search and insertion in sorted lists |
133
+ | 73 | Know How to Use heapq for Priority Queues | Robustness & Performance | Use `heapq.heappush`/`heappop` for O(log n) priority queue; avoid re-sorting a list |
134
+ | 74 | Consider memoryview and bytearray for Zero-Copy Interactions with bytes | Robustness & Performance | Use `memoryview` for zero-copy slicing of bytes; use `bytearray` for mutable bytes |
135
+ | 75 | Use repr Strings for Debugging Output | Robustness & Performance | Use `repr()` in debug output to get unambiguous string representations |
136
+ | 76 | Verify Related Behaviors in TestCase Subclasses | Robustness & Performance | Group related test cases into a single `TestCase` subclass for shared setup |
137
+ | 77 | Isolate Tests from Each Other with setUp, tearDown, setUpModule, and tearDownModule | Robustness & Performance | Use `setUp`/`tearDown` for per-test isolation and module-level equivalents for expensive setup |
138
+ | 78 | Use Mocks to Test Code with Complex Dependencies | Robustness & Performance | Use `unittest.mock.Mock`/`patch` to isolate tests from filesystem, network, and time |
139
+ | 79 | Encapsulate Dependencies to Facilitate Mocking and Testing | Robustness & Performance | Inject dependencies (pass them as args or set as attributes) to make code testable |
140
+
141
+ ---
142
+
143
+ ## Chapter 9 — Testing and Debugging (Items 80–85)
144
+
145
+ | Item | Name | Chapter | Summary |
146
+ |------|------|---------|---------|
147
+ | 80 | Consider Interactive Debugging with pdb | Testing & Debugging | Use `breakpoint()` to drop into pdb; step through code interactively |
148
+ | 81 | Use tracemalloc to Understand Memory Usage and Leaks | Testing & Debugging | Use `tracemalloc` to capture memory snapshots and trace allocation sources |
149
+ | 82 | Consider warnings to Refactor and Migrate Usage | Testing & Debugging | Use `warnings.warn` to communicate deprecations without breaking existing callers |
150
+ | 83 | Consider Static Analysis via typing to Obviate Testing | Testing & Debugging | Add type annotations and use `mypy` to catch type errors before runtime |
151
+ | 84 | Write Docstrings for Every Function, Class, and Module | Testing & Debugging | Docstrings define the contract; every public symbol should have one |
152
+ | 85 | Use Packages to Organize Modules and Provide Stable APIs | Testing & Debugging | Use packages with `__init__.py` to namespace and expose a clean public API |
153
+
154
+ ---
155
+
156
+ ## Chapter 10 — Collaboration (Items 86–90)
157
+
158
+ | Item | Name | Chapter | Summary |
159
+ |------|------|---------|---------|
160
+ | 86 | Consider Module-Scoped Code to Configure Deployment Environments | Collaboration | Use module-level code and environment variables to configure behavior per deployment |
161
+ | 87 | Define a Root Exception to Insulate Callers from APIs | Collaboration | Define a package-specific root exception so callers can catch all package errors in one clause |
162
+ | 88 | Know How to Break Circular Dependencies | Collaboration | Resolve circular imports by restructuring, using `TYPE_CHECKING`, or importing inside functions |
163
+ | 89 | Consider warnings to Refactor and Migrate Usage | Collaboration | Use the `warnings` module for deprecation notices; filter warnings in tests |
164
+ | 90 | Consider Static Analysis via typing to Obviate Testing | Collaboration | Add type hints (`str`, `int`, `list[str]`, `Optional[T]`) and run `mypy` in CI |
165
+
166
+ ---
167
+
168
+ ## Chapter Coverage Summary
169
+
170
+ | Chapter | Items | Core Theme |
171
+ |---------|-------|-----------|
172
+ | 1 — Pythonic Thinking | 1–10 | Follow PEP 8, use f-strings, unpacking, enumerate, zip, walrus |
173
+ | 2 — Lists and Dicts | 11–18 | Slicing, sorting with key=, defaultdict, __missing__ |
174
+ | 3 — Functions | 19–26 | Exceptions over None, closures, *args, keyword-only args, functools.wraps |
175
+ | 4 — Comprehensions & Generators | 27–36 | Comprehensions over map/filter, generators with yield, itertools |
176
+ | 5 — Classes & Interfaces | 37–43 | Compose classes, @classmethod, super(), mix-ins, collections.abc |
177
+ | 6 — Metaclasses & Attributes | 44–51 | Plain attributes, @property, descriptors, __init_subclass__, class decorators |
178
+ | 7 — Concurrency & Parallelism | 52–64 | subprocess, threads for I/O only, Lock, Queue, asyncio coroutines |
179
+ | 8 — Robustness & Performance | 65–79 | try/except/else/finally, datetime, Decimal, profiling, deque, heapq |
180
+ | 9 — Testing & Debugging | 80–85 | pdb, tracemalloc, type annotations, docstrings, packages |
181
+ | 10 — Collaboration | 86–90 | Root exceptions, circular imports, warnings, static analysis |
182
+
183
+ ---
184
+
185
+ ## Highest-Impact Items by Priority
186
+
187
+ ### Critical — Correctness and Safety
188
+
189
+ | Item | Name | Why Critical |
190
+ |------|------|-------------|
191
+ | 20 | Raise exceptions instead of returning None | Silent failures cause debugging nightmares |
192
+ | 24 | Use None for dynamic defaults | Mutable defaults cause shared-state bugs |
193
+ | 40 | Initialize parent classes with super() | Direct parent call breaks multiple inheritance |
194
+ | 53 | Threads for I/O only | Threads for CPU give no speedup due to GIL |
195
+ | 54 | Use Lock for thread safety | Compound operations are not atomic without a Lock |
196
+ | 65 | Use try/except/else/finally correctly | Overly broad try blocks catch unintended exceptions |
197
+
198
+ ### Important — Maintainability
199
+
200
+ | Item | Name | Why Important |
201
+ |------|------|--------------|
202
+ | 2 | Follow PEP 8 | Consistent style makes code readable by the whole team |
203
+ | 4 | Prefer f-strings | Most readable string formatting; avoids format string bugs |
204
+ | 25 | Keyword-only and positional-only arguments | Prevents argument confusion at call sites |
205
+ | 26 | functools.wraps on decorators | Missing this breaks introspection and debugging |
206
+ | 44 | Plain attributes over getters/setters | Pythonic API that can migrate to @property transparently |
207
+ | 84 | Docstrings for all public APIs | Enables tooling, onboarding, and API stability |
208
+
209
+ ### Suggestions — Polish and Optimization
210
+
211
+ | Item | Name | Why Useful |
212
+ |------|------|-----------|
213
+ | 7 | enumerate over range | Cleaner index+value iteration |
214
+ | 8 | zip for parallel iteration | Removes index arithmetic and prevents IndexError |
215
+ | 27 | Comprehensions over map/filter | More readable and Pythonic |
216
+ | 30 | Generators instead of lists | Reduces memory for large sequences |
217
+ | 70 | Profile before optimizing | Prevents wasted effort on non-bottlenecks |
218
+ | 71 | deque for queues | O(1) appends/pops vs O(n) for list.pop(0) |