Skip to content

Commit c13fcff

Browse files
Add 3.12 release video
1 parent 00fd985 commit c13fcff

9 files changed

+284
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ James and his team are available for consulting, contracting, code reviews, and
1212

1313
| N | Code | Video |
1414
|-----| --- |--- |
15+
| 130 | [src](videos/130_python_312_release) | [Python 3.12 is HERE!](https://youtu.be/8l4UWz48Elc) |
1516
| 129 | [src](videos/129_lambda_in_a_loop_is_a_code_smell) | [Lambda in a Loop is a Code Smell](https://youtu.be/fZE6ZWde-Os) |
1617
| 128 | [src](videos/128_id_mapping) | [A forbidden Python technique to put ANYTHING in a dict or set.](https://youtu.be/NpdNDTncxwA) |
1718
| 127 | [src](videos/127_accidentally_quadratic_unique_sum) | [Don't make this big O mistake!](https://youtu.be/PXWL_Xzyrp4) |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// From cpython/Include/pybuffer.h
2+
3+
typedef struct {
4+
void *buf;
5+
PyObject *obj;
6+
Py_ssize_t len;
7+
Py_ssize_t itemsize;
8+
int readonly;
9+
int ndim;
10+
char *format;
11+
Py_ssize_t *shape;
12+
Py_ssize_t *strides;
13+
Py_ssize_t *suboffsets;
14+
void *internal;
15+
} Py_buffer;
16+
17+
typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
18+
typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
19+
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Example from PEP 688
2+
3+
import inspect
4+
5+
# Implements __buffer__, __release_buffer__
6+
class MyBuffer:
7+
def __init__(self, data: bytes):
8+
self.data = bytearray(data)
9+
self.view = None
10+
11+
def __buffer__(self, flags: int) -> memoryview:
12+
if flags != inspect.BufferFlags.FULL_RO:
13+
raise TypeError("Only BufferFlags.FULL_RO supported")
14+
if self.view is not None:
15+
raise RuntimeError("Buffer already held")
16+
self.view = memoryview(self.data)
17+
return self.view
18+
19+
def __release_buffer__(self, view: memoryview) -> None:
20+
assert self.view is view # guaranteed to be true
21+
self.view.release()
22+
self.view = None
23+
24+
def extend(self, b: bytes) -> None:
25+
if self.view is not None:
26+
raise RuntimeError("Cannot extend held buffer")
27+
self.data.extend(b)
28+
29+
def main():
30+
buffer = MyBuffer(b"capybara")
31+
32+
# __buffer__ called here in memoryview:
33+
# vvvvvvvvvvvvvvvvvv
34+
with memoryview(buffer) as view:
35+
view[0] = ord("C")
36+
# __release_buffer__ called exiting with block
37+
38+
# buffer now contains b"Capybara"
39+
40+
if __name__ == "__main__":
41+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import itertools
2+
3+
4+
def print_batches():
5+
data = [1, 2, 3, 4, 5, 6, 7, 8]
6+
for batch in itertools.batched(data, 3):
7+
print(batch)
8+
# (1, 2, 3)
9+
# (4, 5, 6)
10+
# (7, 8)
11+
12+
def main():
13+
print_batches()
14+
15+
if __name__ == '__main__':
16+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import sys
2+
3+
def my_trace_call(code, instruction_offset, call, arg0):
4+
print("Event: call")
5+
6+
def my_trace_line(code, line_number):
7+
print("Event: line")
8+
9+
def setup_monitoring():
10+
mo = sys.monitoring
11+
events = mo.events
12+
mo.use_tool_id(0, "my_debugger")
13+
mo.set_events(0, events.CALL | events.LINE)
14+
mo.register_callback(0, events.CALL, my_trace_call)
15+
mo.register_callback(0, events.LINE, my_trace_line)
16+
17+
def main():
18+
for x in range(5):
19+
print(x)
20+
21+
if __name__ == "__main__":
22+
setup_monitoring()
23+
main()
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
3+
def main():
4+
count = sys.getrefcount(None)
5+
print(f"0b{count:b}")
6+
7+
8+
if __name__ == "__main__":
9+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import sys
2+
3+
def main():
4+
my_list = [1, 2, 3]
5+
print(sys.getrefcount(my_list)) # 2
6+
use_list(my_list)
7+
8+
def use_list(lst):
9+
print(sys.getrefcount(lst)) # 3
10+
11+
12+
if __name__ == "__main__":
13+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import sys
2+
3+
def my_trace(frame, event, arg):
4+
print(f"Event: {event}")
5+
return my_trace
6+
7+
def main():
8+
for x in range(5):
9+
print(x)
10+
11+
if __name__ == "__main__":
12+
sys.settrace(my_trace)
13+
main()
14+
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# -*- coding: utf-8 -*-
2+
import collections
3+
import itertools
4+
import os
5+
import pathlib
6+
import sys
7+
import time
8+
9+
import numpy as np
10+
11+
# For Linux/Wayland users.
12+
if os.getenv("XDG_SESSION_TYPE") == "wayland":
13+
os.environ["XDG_SESSION_TYPE"] = "x11"
14+
15+
import glfw
16+
import OpenGL.GL as gl
17+
import imgui
18+
from imgui.integrations.glfw import GlfwRenderer
19+
20+
DRIFT_SPEED = 100
21+
TAIL_LENGTH = 1000
22+
23+
frame_time = 0.0
24+
25+
26+
def tick():
27+
global frame_time
28+
frame_time = time.perf_counter()
29+
30+
31+
bm = collections.deque([np.array([0., 0.])] * 10, maxlen=TAIL_LENGTH)
32+
33+
IS_DEBUG = (sys.gettrace() is not None)
34+
35+
36+
def frame_commands():
37+
last_time = frame_time
38+
tick()
39+
curr_time = frame_time
40+
dt = curr_time - last_time
41+
try:
42+
fps = int(1 / dt)
43+
except ZeroDivisionError:
44+
fps = 0
45+
46+
io = imgui.get_io()
47+
48+
if io.key_ctrl and io.keys_down[glfw.KEY_Q]:
49+
sys.exit(0)
50+
51+
with imgui.begin_main_menu_bar() as main_menu_bar:
52+
if main_menu_bar.opened:
53+
with imgui.begin_menu("File", True) as file_menu:
54+
if file_menu.opened:
55+
clicked_quit, selected_quit = imgui.menu_item("Quit", "Ctrl+Q")
56+
if clicked_quit:
57+
sys.exit(0)
58+
59+
with imgui.begin("FPS"):
60+
imgui.text(f"Debug: ")
61+
imgui.same_line()
62+
if IS_DEBUG:
63+
imgui.text_colored("ON", 0., 1., 0.)
64+
else:
65+
imgui.text_colored("OFF", 1., 0., 0.)
66+
imgui.text(f"FPS: {fps}")
67+
68+
scale = np.sqrt(dt) * 200
69+
dbm = np.random.multivariate_normal(mean=(0.0, 0.0), cov=scale * np.eye(2))
70+
next_bm = bm[len(bm) - 1] + dbm
71+
next_bm = np.maximum(next_bm, 0.0)
72+
next_bm = np.minimum(next_bm, np.array(glfw.get_window_size(glfw.get_current_context())))
73+
bm.append(next_bm)
74+
if tuple(io.mouse_pos) != (-1, -1):
75+
drift = (np.array(io.mouse_pos) - next_bm) / DRIFT_SPEED
76+
next_bm += drift
77+
draw_list = imgui.get_overlay_draw_list()
78+
for idx, ((x1, y1), (x2, y2)) in enumerate(itertools.pairwise(bm)):
79+
color = imgui.get_color_u32_rgba(1., 1., 1., idx / (len(bm) - 1))
80+
draw_list.add_line(x1, y1, x2, y2, color, thickness=1.0)
81+
82+
83+
def render_frame(impl, window, font):
84+
glfw.poll_events()
85+
impl.process_inputs()
86+
imgui.new_frame()
87+
88+
gl.glClearColor(0.1, 0.1, 0.1, 1)
89+
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
90+
91+
imgui.push_font(font)
92+
frame_commands()
93+
imgui.pop_font()
94+
95+
imgui.render()
96+
impl.render(imgui.get_draw_data())
97+
glfw.swap_buffers(window)
98+
99+
100+
def impl_glfw_init():
101+
width, height = 600, 600
102+
window_name = "Brownian motion demo"
103+
104+
if not glfw.init():
105+
print("Could not initialize OpenGL context")
106+
sys.exit(1)
107+
108+
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
109+
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
110+
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
111+
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, gl.GL_TRUE)
112+
113+
window = glfw.create_window(int(width), int(height), window_name, None, None)
114+
glfw.make_context_current(window)
115+
glfw.swap_interval(0)
116+
117+
if not window:
118+
glfw.terminate()
119+
print("Could not initialize Window")
120+
sys.exit(1)
121+
122+
return window
123+
124+
125+
def main():
126+
imgui.create_context()
127+
window = impl_glfw_init()
128+
129+
impl = GlfwRenderer(window)
130+
131+
font_path = pathlib.Path(__file__).with_name("Montserrat-ExtraBold.ttf")
132+
try:
133+
font = imgui.get_io().fonts.add_font_from_file_ttf(str(font_path), 80)
134+
except imgui.ImGuiError:
135+
font = imgui.get_io().fonts.add_font_default()
136+
impl.refresh_font_texture()
137+
138+
while not glfw.window_should_close(window):
139+
render_frame(impl, window, font)
140+
141+
impl.shutdown()
142+
glfw.terminate()
143+
144+
145+
if __name__ == "__main__":
146+
main()

0 commit comments

Comments
 (0)