pythoncharmers-meta 0.7.3__tar.gz → 0.7.5__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.
@@ -0,0 +1,189 @@
1
+ # Markdown Cell Magic Implementation Design
2
+
3
+ ## Problem Statement
4
+
5
+ Training participants need a way to copy Markdown cells from trainer notebooks during live sessions. Unlike code cells which have visible execution counts, Markdown cells lack visible identifiers, making them difficult to reference.
6
+
7
+ ## Design Considerations
8
+
9
+ ### Current Magic Commands
10
+ - %code (formerly %nb): Handles code cells (identified by execution_count)
11
+ - %md: Handles markdown cells with flexible syntax (by index or relative to code cells)
12
+ - %nb: Kept as alias for %code for backward compatibility
13
+
14
+ ### Challenges with Markdown Cells
15
+ 1. **No visible numbering**: Markdown cells don't have execution counts
16
+ 2. **Cell IDs not user-friendly**: Internal IDs exist but aren't visible in the UI
17
+ 3. **Mixed cell types**: Notebooks interleave code and Markdown cells
18
+ 4. **Cell type conversion**: Content retrieved needs manual conversion from Code to Markdown
19
+
20
+ ## Proposed Solutions
21
+
22
+ ### Solution 1: Between Code Cells (Fence Method)
23
+ **Syntax**: `%md 1 2` - Get all Markdown cells between code cells 1 and 2
24
+
25
+ **Pros**:
26
+ - Uses existing visible code cell numbers
27
+ - Intuitive for contiguous Markdown sections
28
+
29
+ **Cons**:
30
+ - Ambiguous for non-contiguous selections
31
+ - Doesn't work for Markdown at notebook start/end
32
+ - May return multiple cells when only one is needed
33
+
34
+ ### Solution 2: Position-Based Reference
35
+ **Syntax**: `%md after:3` or `%md before:5` - Get Markdown cell(s) after/before code cell
36
+
37
+ **Pros**:
38
+ - Precise single-cell selection
39
+ - Clear intent
40
+ - Works at notebook boundaries
41
+
42
+ **Cons**:
43
+ - Requires multiple commands for multiple cells
44
+ - User needs to know exact positions
45
+
46
+ ### Solution 3: Content Pattern Matching
47
+ **Syntax**: `%md "# Section Title"` - Find Markdown cells containing pattern
48
+
49
+ **Pros**:
50
+ - Natural for users who can see content
51
+ - Works without knowing cell positions
52
+ - Can use distinctive headers/keywords
53
+
54
+ **Cons**:
55
+ - Pattern might not be unique
56
+ - Requires exact string matching or regex
57
+
58
+ ### Solution 4: Hybrid Cell Magic (Recommended)
59
+ **Syntax**: `%%md 3` - Cell magic that fetches Markdown after code cell 3
60
+
61
+ **Pros**:
62
+ - Automatically converts cell type to Markdown
63
+ - No manual cleanup needed
64
+ - Clear one-to-one mapping
65
+ - Can extend to support ranges
66
+
67
+ **Cons**:
68
+ - Different from line magic pattern
69
+ - Requires cell magic implementation
70
+
71
+ ### Solution 5: Smart Sequential Indexing (Recommended Alternative)
72
+ **Syntax**: `%md 3` or `%md 3-5` - Use sequential index for all Markdown cells
73
+
74
+ **Implementation**:
75
+ - Build index of all Markdown cells in order
76
+ - Reference by position (1st, 2nd, 3rd Markdown cell)
77
+ - Optional: `%md --list` to show available Markdown cells with previews
78
+
79
+ **Pros**:
80
+ - Simple, consistent interface
81
+ - Works like %nb for code cells
82
+ - No ambiguity
83
+ - Can show preview list
84
+
85
+ **Cons**:
86
+ - Users need to count Markdown cells
87
+ - Numbers change if trainer adds cells
88
+
89
+ ## Implemented Solution
90
+
91
+ The `%md` command now supports **unified syntax** for both index-based and code-relative selection:
92
+
93
+ ### Markdown Index Syntax
94
+ ```python
95
+ %md m1 # Get 1st Markdown cell
96
+ %md m3-m5 # Get 3rd through 5th Markdown cells
97
+ %md m7- # Get 7th cell onwards
98
+ %md -m3 # Get cells 1 through 3
99
+ %md --list # List all Markdown cells with m-prefixed numbers
100
+ ```
101
+
102
+ ### Code-Relative Syntax (uses last occurrence if duplicates exist)
103
+ ```python
104
+ %md -3 # All Markdown cells before code cell 3
105
+ %md 5- # All Markdown cells after code cell 5
106
+ %md 3-5 # All Markdown between code cells 3 and 5
107
+ ```
108
+
109
+ ### Combined Usage
110
+ ```python
111
+ %md -1 m3 5- # Before code 1, markdown cell 3, after code 5
112
+ ```
113
+
114
+ ## Implementation Details
115
+
116
+ ### Cell Type Handling
117
+ - Unlike %nb, the %md and %mdat magics do NOT add a comment header
118
+ - Content is inserted directly without any prefix
119
+ - Users manually convert cell type (Ctrl+M, M in Jupyter)
120
+ - Future: Investigate IPython API for automatic cell type conversion
121
+
122
+ ### Preview Feature
123
+ ```python
124
+ %md --list
125
+ # Output:
126
+ # 1: # Introduction
127
+ # This notebook covers...
128
+ # 2: ## Data Loading
129
+ # We'll use pandas to...
130
+ # 3: ### Important Notes
131
+ # Remember to check...
132
+ ```
133
+
134
+ ### Error Handling
135
+ - Clear messages for invalid ranges
136
+ - Warnings when no Markdown cells found
137
+ - Handle notebooks without code cells gracefully
138
+
139
+ ## Alternative Approaches Considered
140
+
141
+ ### Invisible Anchors
142
+ Add hidden HTML comments as anchors in Markdown cells:
143
+ ```markdown
144
+ <!-- md-anchor: section1 -->
145
+ # Introduction
146
+ ```
147
+ **Rejected**: Requires modifying trainer notebooks
148
+
149
+ ### Visual Cell Numbers
150
+ Propose Jupyter enhancement to show Markdown cell numbers in UI.
151
+ **Rejected**: Outside our control, long-term solution
152
+
153
+ ### Dual Output
154
+ Return both code and Markdown versions, let user choose.
155
+ **Rejected**: Clutters interface, still requires manual work
156
+
157
+ ## Migration Path
158
+
159
+ 1. Renamed `%nb` to `%code` as the canonical command for code cells
160
+ 2. Kept `%nb` as an alias for backward compatibility
161
+ 3. Implemented unified `%md` command with both index and position-based syntax
162
+ 4. Removed separate `%mdat` command (functionality merged into `%md`)
163
+ 5. Updated all documentation and help text
164
+
165
+ ## Usage Examples
166
+
167
+ ### Trainer notebook structure:
168
+ ```
169
+ [Code 1] Import statements
170
+ [Markdown] # Data Analysis Workshop
171
+ [Markdown] ## Prerequisites
172
+ [Code 2] Load data
173
+ [Markdown] ### Understanding the dataset
174
+ [Code 3] Explore data
175
+ ```
176
+
177
+ ### Participant commands:
178
+ ```python
179
+ %code 1 # Get code cell 1 (preferred)
180
+ %nb 1 # Same as %code 1 (backward compatibility)
181
+ %md m1 # Get "# Data Analysis Workshop"
182
+ %md m2-m3 # Get "## Prerequisites" and "### Understanding the dataset"
183
+ %md 1- # Get markdown after code cell 1
184
+ %md -2 # Get markdown before code cell 2
185
+ ```
186
+
187
+ ## Conclusion
188
+
189
+ The unified `%md` command provides a powerful and flexible interface for selecting markdown cells. By supporting both index-based (`m1`, `m2-m5`) and code-relative (`-1`, `2-`, `3-5`) syntax in a single command, users have maximum flexibility without needing to remember multiple commands. The implementation handles edge cases like duplicate code cell numbers (using the last occurrence) and provides clear error messages for invalid selections.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythoncharmers-meta
3
- Version: 0.7.3
3
+ Version: 0.7.5
4
4
  Summary: Meta package with dependencies for Python Charmers training courses
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pythoncharmers-meta"
3
- version = "0.7.3"
3
+ version = "0.7.5"
4
4
  description = "Meta package with dependencies for Python Charmers training courses"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -0,0 +1,23 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python3:*)",
5
+ "Bash(cd:*)",
6
+ "Bash(cd:*)",
7
+ "Bash(rm:*)",
8
+ "Bash(git add:*)",
9
+ "Bash(cd:*)",
10
+ "Bash(cd:*)",
11
+ "Bash(cd:*)",
12
+ "Bash(cd:*)",
13
+ "Bash(cd:*)",
14
+ "Bash(cd:*)",
15
+ "Bash(cd:*)",
16
+ "Bash(cd:*)",
17
+ "Bash(cd:*)",
18
+ "Bash(python test:*)"
19
+ ],
20
+ "deny": [],
21
+ "ask": []
22
+ }
23
+ }
@@ -0,0 +1,79 @@
1
+ """
2
+ Python Charmers meta-package.
3
+
4
+ This package is for use in Python Charmers training courses.
5
+
6
+ You can load the IPython extension like so:
7
+
8
+ %load_ext pythoncharmers_meta
9
+
10
+ assuming the pythoncharmers_meta packages has been installed system-wide.
11
+
12
+ This package depends on packages used in Python Charmers training courses. It
13
+ also provides an IPython extension that enables several magic commands:
14
+
15
+ - %code: Grab code cells from a notebook
16
+ - %md: Grab markdown cells (by index or relative to code cells)
17
+ - %nb: Alias for %code (for backward compatibility)
18
+ - %ai: Invoke the `llm` package for quick use of an LLM like gpt-4o-mini
19
+
20
+ The %code and %md magics grab cells from a notebook on the filesystem,
21
+ defaulting to the most recently modified notebook in the latest ~/Trainer_XYZ folder.
22
+
23
+ For help on the magics, add a trailing question mark. For example:
24
+
25
+ %code?
26
+ %md?
27
+ %ai?
28
+
29
+ Two additional magics are available for getting and setting the current
30
+ path and/or file that %code and %md query. To get help on these, run:
31
+
32
+ %nbfile?
33
+ %nbpath?
34
+
35
+ """
36
+
37
+ # Import version from package metadata (single source of truth)
38
+ try:
39
+ from importlib.metadata import version, PackageNotFoundError
40
+ try:
41
+ __version__ = version("pythoncharmers-meta")
42
+ except PackageNotFoundError:
43
+ # Package is not installed, likely in development mode
44
+ # Fall back to reading from pyproject.toml if needed
45
+ __version__ = "unknown"
46
+ except ImportError:
47
+ # Python < 3.8 fallback
48
+ try:
49
+ import pkg_resources
50
+ __version__ = pkg_resources.get_distribution("pythoncharmers-meta").version
51
+ except Exception:
52
+ __version__ = "unknown"
53
+
54
+ # Public API
55
+ __all__ = ["__version__", "load_ipython_extension", "NotebookMagic"]
56
+
57
+ from .nb_magic import NotebookMagic
58
+
59
+ try:
60
+ from .ai_magic import AIMagic
61
+ __all__.append("AIMagic")
62
+ except Exception as e:
63
+ print(e)
64
+
65
+
66
+ def load_ipython_extension(ipython):
67
+ """
68
+ Any module file that defines a function named `load_ipython_extension`
69
+ can be loaded via `%load_ext module.path` or be configured to be
70
+ autoloaded by IPython at startup time.
71
+ """
72
+ # You can register the class itself without instantiating it. IPython will
73
+ # call the default constructor on it.
74
+ ipython.register_magics(NotebookMagic)
75
+
76
+ try:
77
+ ipython.register_magics(AIMagic)
78
+ except Exception as e:
79
+ print(e)