Skip to content

Commit 24f813a

Browse files
committed
Regrtest bpo-33257
1 parent 55494f4 commit 24f813a

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/usr/bin/python3
2+
3+
import sys
4+
import time
5+
import threading
6+
import random
7+
import tkinter
8+
9+
import unittest
10+
class TestThreads(unittest.TestCase):
11+
def test_threads(self):
12+
import subprocess
13+
p = subprocess.Popen([sys.executable, __file__, "run"],
14+
stdout=subprocess.PIPE,
15+
stderr=subprocess.PIPE)
16+
self.addCleanup(p.stdout.close)
17+
self.addCleanup(p.stderr.close)
18+
try:
19+
#Test code is designed to complete in a few seconds
20+
stdout, stderr = p.communicate(timeout=10)
21+
except subprocess.TimeoutExpired:
22+
p.kill()
23+
stdout, stderr = p.communicate()
24+
self.fail("Test code hang. Stderr: " + repr(stderr))
25+
rc = p.returncode
26+
self.assertTrue(rc == 0,
27+
"Nonzero exit status: " + str(rc) + "; stderr:" + repr(stderr))
28+
self.assertTrue(len(stderr) == 0, "stderr: " + repr(stderr))
29+
30+
31+
32+
running = True
33+
34+
class Track(threading.Thread):
35+
"""
36+
Calculates coordinates for a ballistic track
37+
with random angle and velocity
38+
and fires the callback to draw each consecutive segment.
39+
"""
40+
def __init__(self, track_number, draw_callback):
41+
"""
42+
:param track_number: ordinal
43+
:param draw_callback: fn(track_number, x, y)
44+
that draws the extention of the specified track
45+
to the specified point. The callback must keep track
46+
of any previous coordinates itself.
47+
"""
48+
threading.Thread.__init__(self)
49+
#self.setDaemon(True)
50+
self.track_number = track_number
51+
self.draw_callback = draw_callback
52+
53+
def run(self):
54+
#starting point for the track
55+
y = 0.0001 #height
56+
x = 999.0 #range
57+
#initial velocities
58+
yVel = 400. + random.random() * 200.
59+
xVel = -200. - random.random() * 150.
60+
# Stop drawing when the track hits the ground
61+
while y > 0 and running:
62+
#How long to sleep, in seconds, between track updates
63+
time.sleep(0.01) #realism: >1 Fun: 0.01
64+
65+
yVel -= 9.8 #gravity, more or less
66+
xVel *= .9998 #air resistance
67+
68+
y += yVel
69+
x += xVel
70+
71+
if running:
72+
self.draw_callback(self.track_number, x, y)
73+
74+
75+
class App:
76+
"""
77+
The main app logic
78+
"""
79+
def __init__(self, window):
80+
self.track_no = 0 #last index of track added
81+
self.track_coordinates = {} #coords of track tips
82+
self.threads = []
83+
84+
self.window = window
85+
self.frame = tkinter.Frame(window)
86+
self.frame.pack()
87+
self.graph = tkinter.Canvas(self.frame)
88+
self.graph.pack()
89+
90+
self.t_cleanup = threading.Thread(target=self.tf_cleanup)
91+
self.window.after(0, self.add_tracks, 5)
92+
self.window.after(1000, self.t_cleanup.start)
93+
94+
def add_tracks(self,depth):
95+
if depth>0: self.window.after(5, self.add_tracks, depth-1)
96+
tracks_to_add = 40
97+
start_no = self.track_no
98+
self.track_no += tracks_to_add
99+
for self.track_no in range(start_no, self.track_no):
100+
#self.window.after(t, self.add_tracks)
101+
#self.track_no += 1 #Make a new track number
102+
#if (self.track_no > 40):
103+
t = Track(self.track_no, self.draw_track_segment)
104+
self.threads.append(t)
105+
t.start()
106+
107+
def tf_cleanup(self):
108+
global running
109+
running = False
110+
for t in self.threads: t.join()
111+
self.window.after(0,self.window.destroy)
112+
113+
def draw_track_segment(self, track_no, x, y):
114+
# x & y are virtual coordinates for the purpose of simulation.
115+
#To convert them to screen coordinates,
116+
# we scale them down so the graphs fit into the window, and move the origin.
117+
# Y is also inverted because in canvas, the UL corner is the origin.
118+
newsx, newsy = (250.+x/100., 150.-y/100.)
119+
120+
try:
121+
(oldsx, oldsy) = self.track_coordinates[track_no]
122+
except KeyError:
123+
pass
124+
else:
125+
self.graph.create_line(oldsx, oldsy,
126+
newsx, newsy)
127+
self.track_coordinates[track_no] = (newsx, newsy)
128+
129+
def go(self):
130+
self.window.mainloop()
131+
132+
tests_gui = (TestThreads,)
133+
134+
if __name__=='__main__':
135+
import sys,os
136+
if sys.argv[1:]==['run']:
137+
if os.name == 'nt':
138+
import ctypes
139+
#the bug causes crashes
140+
ctypes.windll.kernel32.SetErrorMode(3)
141+
App(tkinter.Tk()).go()
142+
else:
143+
from test.support import run_unittest
144+
run_unittest(*tests_gui)

0 commit comments

Comments
 (0)