ColabTurtlePlus 2.0.2__tar.gz → 2.1.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.
@@ -27,6 +27,12 @@ v2.0.1 Oct. 2021
27
27
  Lines drawn with drawlines() method now included in saved SVG file.
28
28
  Fixes so that graphic window is still displayed when cell executed more than once in Jupyter notebook.
29
29
 
30
+ v2.0.2 Aug. 2026
31
+ Fixed Python 3.13+ SyntaxWarning by using raw strings in regular expressions.
32
+
33
+ v2.1.0 September 2026
34
+ Added register_shape() (alias addshape) to mimic the role of the function register_shape() from Python's turtle.
35
+ This only works to add a polygonal shape. It does not work with images or components.
30
36
  """
31
37
 
32
38
  DEFAULT_WINDOW_SIZE = (800, 600)
@@ -61,12 +67,14 @@ VALID_COLORS = ('black', 'navy', 'darkblue', 'mediumblue', 'blue', 'darkgreen',
61
67
  'lightgoldenrodyellow', 'oldlace', 'red', 'fuchsia', 'magenta', 'deeppink', 'orangered', 'tomato', 'hotpink', 'coral', 'darkorange',
62
68
  'lightsalmon', 'orange', 'lightpink', 'pink', 'gold', 'peachpuff', 'navajowhite', 'moccasin', 'bisque', 'mistyrose', 'blanchedalmond',
63
69
  'papayawhip', 'lavenderblush', 'seashell', 'cornsilk', 'lemonchiffon', 'floralwhite', 'snow', 'yellow', 'lightyellow', 'ivory', 'white','none','')
64
- #VALID_COLORS_SET = set(VALID_COLORS)
70
+ VALID_COLORS_SET = set(VALID_COLORS)
65
71
  VALID_MODES = ('standard','logo','world','svg')
66
72
  DEFAULT_TURTLE_SHAPE = 'classic'
67
- VALID_TURTLE_SHAPES = ('turtle', 'ring', 'classic', 'arrow', 'square', 'triangle', 'circle', 'turtle2', 'blank')
73
+ VALID_TURTLE_SHAPES = {'turtle', 'ring', 'classic', 'arrow', 'square', 'triangle', 'circle', 'turtle2', 'blank', 'user'}
68
74
  DEFAULT_MODE = 'standard'
69
75
  DEFAULT_ANGLE_MODE = 'degrees'
76
+ DEFAULT_POINTS = '-5,-4.5 0,-2.5 5,-4.5 0,4.5'
77
+ DEFAULT_NAME = 'classic'
70
78
  SVG_TEMPLATE = """
71
79
  <svg width="{window_width}" height="{window_height}">
72
80
  <rect width="100%" height="100%" style="fill:{backcolor};stroke:{kolor};stroke-width:1"/>
@@ -86,7 +94,7 @@ TURTLE_RING_SVG_TEMPLATE = """<g id="ring" visibility="{visibility}" transform="
86
94
  <polygon points="0,5 5,0 -5,0" transform="skewX({sk}) scale({sx},{sy})" style="fill:{turtle_color};stroke:{pcolor};stroke-width:1" />
87
95
  </g>"""
88
96
  TURTLE_CLASSIC_SVG_TEMPLATE = """<g id="classic" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
89
- <polygon points="-5,-4.5 0,-2.5 5,-4.5 0,4.5" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />
97
+ <polygon points="{points}" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />
90
98
  </g>"""
91
99
  TURTLE_ARROW_SVG_TEMPLATE = """<g id="arrow" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
92
100
  <polygon points="-10,-5 0,5 10,-5" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />
@@ -103,9 +111,32 @@ TURTLE_CIRCLE_SVG_TEMPLATE = """<g id="ellipse" visibility="{visibility}" transf
103
111
  TURTLE_TURTLE2_SVG_TEMPLATE = """<g id="turtle2" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
104
112
  <polygon points="0,16 2,14 1,10 4,7 7,9 9,8 6,5 7,1 5,-3 8,-6 6,-8 4,-5 0,-7 -4,-5 -6,-8 -8,-6 -5,-3 -7,1 -6,5 -9,8 -7,9 -4,7 -1,10 -2,14" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};stroke-width:1;fill:{turtle_color}" />
105
113
  </g>"""
114
+ TURTLE_USER_SVG_TEMPLATE = """<g id="{id}" visibility="{visibility}" transform="rotate({degrees},{rotation_x},{rotation_y}) translate({turtle_x}, {turtle_y})">
115
+ <polygon points="{points}" transform="skewX({sk}) scale({sx},{sy})" style="stroke:{pcolor};fill:{turtle_color};stroke-width:{pw}" />
116
+ </g>"""
106
117
 
107
118
  SPEED_TO_SEC_MAP = {0: 0, 1: 1.0, 2: 0.8, 3: 0.5, 4: 0.3, 5: 0.25, 6: 0.20, 7: 0.15, 8: 0.125, 9: 0.10, 10: 0.08, 11: 0.04, 12: 0.02, 13: 0.005}
108
119
 
120
+ shapeDict = {"turtle":TURTLE_TURTLE_SVG_TEMPLATE,
121
+ "ring":TURTLE_RING_SVG_TEMPLATE,
122
+ "classic":TURTLE_CLASSIC_SVG_TEMPLATE,
123
+ "arrow":TURTLE_ARROW_SVG_TEMPLATE,
124
+ "square":TURTLE_SQUARE_SVG_TEMPLATE,
125
+ "triangle":TURTLE_TRIANGLE_SVG_TEMPLATE,
126
+ "circle":TURTLE_CIRCLE_SVG_TEMPLATE,
127
+ "turtle2":TURTLE_TURTLE2_SVG_TEMPLATE,
128
+ "user":TURTLE_USER_SVG_TEMPLATE,
129
+ "blank":""}
130
+ pointsDict = {"turtle":"",
131
+ "ring":"",
132
+ "classic":"",
133
+ "arrow":"",
134
+ "square":"",
135
+ "triangle":"",
136
+ "circle":"",
137
+ "turtle2":"",
138
+ "user":"",
139
+ "blank":""}
109
140
  #------------------------------------------------------------------------------------------------
110
141
 
111
142
  def Screen():
@@ -178,7 +209,7 @@ class _Screen:
178
209
  else:
179
210
  degrees -= 90
180
211
 
181
- svg = turtle.shapeDict[turtle.turtle_shape].format(
212
+ svg = shapeDict[turtle.turtle_shape].format(
182
213
  turtle_color=turtle.fill_color,
183
214
  pcolor=turtle.pen_color,
184
215
  turtle_x=turtle_x,
@@ -193,7 +224,9 @@ class _Screen:
193
224
  cy=-(10*turtle.stretchfactor[1]+4),
194
225
  pw = turtle.outline_width,
195
226
  rotation_x=turtle.turtle_pos[0],
196
- rotation_y=turtle.turtle_pos[1])
227
+ rotation_y=turtle.turtle_pos[1],
228
+ points=pointsDict[turtle.turtle_shape],
229
+ id = turtle.turtle_shape)
197
230
  return svg
198
231
 
199
232
  # helper function for linking svg strings of text
@@ -312,6 +345,46 @@ class _Screen:
312
345
  text_file.write(output)
313
346
  text_file.close()
314
347
 
348
+ def register_shape(self, name, points=None):
349
+ """Adds a polygonal turtle shape to to the shape list.
350
+
351
+ Arg:
352
+ name is an arbitrary string
353
+ points is a list or tuple of pairs of coordinates that define the polygon.
354
+
355
+ Installs the corresponding polygon shape.
356
+ If no points are given, the turtle shape will be blank.
357
+ Note: This version does NOT include shapes that are images or components.
358
+ """
359
+
360
+ if not isinstance(name,str):
361
+ raise TypeError("The name must be a string")
362
+ if points is None:
363
+ self.points = None
364
+ else:
365
+ if not isinstance(points, (list, tuple)):
366
+ raise TypeError("The points must be a list or tuple of coordinate pairs.")
367
+ if len(points) < 2:
368
+ raise ValueError("The points must contain at least 2 coordinate pairs.")
369
+ for i, point in enumerate(points):
370
+ if not isinstance(point, (list, tuple)):
371
+ raise TypeError(
372
+ f"The point[{i}] must be a coordinate pair."
373
+ )
374
+ if len(point) != 2:
375
+ raise ValueError(
376
+ f"The point[{i}] must contain exactly two coordinates."
377
+ )
378
+ if not all(isinstance(x, (int, float)) for x in point):
379
+ raise TypeError(
380
+ f"The point[{i}] must contain numeric coordinates."
381
+ )
382
+ name = name.lower()
383
+ VALID_TURTLE_SHAPES.add(name)
384
+ pointsDict[name] = " ".join(f"{x},{y}" for x, y in points)
385
+ shapeDict[name] = TURTLE_USER_SVG_TEMPLATE
386
+ addshape=register_shape
387
+
315
388
  #=========================
316
389
  # screen drawing functions
317
390
  #=========================
@@ -710,8 +783,8 @@ class _Screen:
710
783
 
711
784
  def turtles(self):
712
785
  """Return the list of turtles on the screen."""
713
- return self._turtles
714
-
786
+ return self._turtles
787
+
715
788
  def initializescreen(self,window=DEFAULT_WINDOW_SIZE,mode=DEFAULT_MODE):
716
789
  """Initializes the drawing window
717
790
 
@@ -821,16 +894,9 @@ class RawTurtle:
821
894
  self.stampdictT = {}
822
895
  self.stampnum = 0
823
896
  self.stamplist=[]
824
- self.shapeDict = {"turtle":TURTLE_TURTLE_SVG_TEMPLATE,
825
- "ring":TURTLE_RING_SVG_TEMPLATE,
826
- "classic":TURTLE_CLASSIC_SVG_TEMPLATE,
827
- "arrow":TURTLE_ARROW_SVG_TEMPLATE,
828
- "square":TURTLE_SQUARE_SVG_TEMPLATE,
829
- "triangle":TURTLE_TRIANGLE_SVG_TEMPLATE,
830
- "circle":TURTLE_CIRCLE_SVG_TEMPLATE,
831
- "turtle2":TURTLE_TURTLE2_SVG_TEMPLATE,
832
- "blank":""}
833
- if screen._mode == "svg": self.shapeDict.update({"circle":TURTLE_RING_SVG_TEMPLATE})
897
+ self.points = DEFAULT_POINTS
898
+
899
+ if screen._mode == "svg": shapeDict.update({"circle":TURTLE_RING_SVG_TEMPLATE})
834
900
  screen._add(self)
835
901
 
836
902
 
@@ -906,7 +972,7 @@ class RawTurtle:
906
972
  self.screen._updateDrawing(turtle=self)
907
973
  elif self.turtle_shape != 'ring' and self.stretchfactor[0]==self.stretchfactor[1]:
908
974
  stretchfactor_orig = self.stretchfactor
909
- template = self.shapeDict[self.turtle_shape]
975
+ template = shapeDict[self.turtle_shape]
910
976
  tmp = """<animateTransform id = "one" attributeName="transform"
911
977
  type="scale"
912
978
  from="1 1" to="{sx} {sy}"
@@ -923,13 +989,13 @@ class RawTurtle:
923
989
  fill="freeze"
924
990
  /></g>""".format(extent=deg, t=self.timeout*abs(deg)/90, sx=self.stretchfactor[0], sy=self.stretchfactor[1])
925
991
  newtemplate = template.replace("</g>",tmp)
926
- self.shapeDict.update({self.turtle_shape:newtemplate})
992
+ shapeDict.update({self.turtle_shape:newtemplate})
927
993
  self.stretchfactor = 1,1
928
994
  self.timeout = self.timeout*abs(deg)/90+0.001
929
- self.screen._updateDrawing(self)
995
+ #self.screen._updateDrawing(self)
930
996
  self.turtle_degree = (self.turtle_degree + deg) % 360
931
997
  self.turtle_orient = self._turtleOrientation()
932
- self.shapeDict.update({self.turtle_shape:template})
998
+ shapeDict.update({self.turtle_shape:template})
933
999
  self.stretchfactor = stretchfactor_orig
934
1000
  self.timeout = timeout_orig
935
1001
  else: #_turtle_shape == 'ring' or _stretchfactor[0] != _stretchfactor[1]
@@ -2109,10 +2175,11 @@ class RawTurtle:
2109
2175
  #==========================
2110
2176
  # Turtle State - Appearance
2111
2177
  #==========================
2112
-
2178
+
2113
2179
  # Set turtle shape to shape with given name or, if name is not given, return name of current shape
2114
2180
  def shape(self, name=None):
2115
2181
  """Sets turtle shape to shape with given name / return current shapename.
2182
+ Can also create a user-defined custom polygonal shape
2116
2183
 
2117
2184
  Args:
2118
2185
  name: an optional string, which is a valid shapename
@@ -2125,6 +2192,8 @@ class RawTurtle:
2125
2192
  The 'turtle' shape is the one that Tolga Atam included in his original
2126
2193
  ColabTurtle version. Use 'turtle2' for the polygonal turtle shape form
2127
2194
  turtle.py. The circle shape from the original ColabTurtle was renamed 'ring'.
2195
+
2196
+ Use register_shape (alias addshape) to create a polygonal shape with a chosen name.
2128
2197
  """
2129
2198
 
2130
2199
  if name is None:
@@ -2133,7 +2202,7 @@ class RawTurtle:
2133
2202
  raise ValueError('Shape is invalid. Valid options are: ' + str(VALID_TURTLE_SHAPES))
2134
2203
  self.turtle_shape = name.lower()
2135
2204
  self.screen._updateDrawing(turtle=self)
2136
-
2205
+
2137
2206
  # Scale the size of the turtle
2138
2207
  # stretch_wid scales perpendicular to orientation
2139
2208
  # stretch_len scales in direction of turtle's orientation
@@ -2376,8 +2445,8 @@ def getcolor(n):
2376
2445
  return VALID_COLORS[n]
2377
2446
 
2378
2447
 
2379
- _tg_screen_functions = ['bgcolor', 'clearscreen', 'drawline', 'hideborder',
2380
- 'initializescreen','initializeTurtle', 'showSVG', 'saveSVG', 'line', 'mode', 'resetscreen', 'setup',
2448
+ _tg_screen_functions = ['addshape', 'bgcolor', 'clearscreen', 'drawline', 'hideborder',
2449
+ 'initializescreen','initializeTurtle', 'showSVG', 'saveSVG', 'line', 'mode', 'register_shape', 'resetscreen', 'setup',
2381
2450
  'setworldcoordinates', 'showborder', 'turtles', 'window_width', 'window_height' ]
2382
2451
 
2383
2452
  _tg_turtle_functions = ['animationOff', 'animationOn', 'bk', 'back', 'backward', 'begin_fill',
@@ -2385,7 +2454,7 @@ _tg_turtle_functions = ['animationOff', 'animationOn', 'bk', 'back', 'backward',
2385
2454
  'dot', 'down', 'end_fill', 'face', 'fd', 'fillcolor', 'filling', 'fillopacity', 'fillrule', 'forward',
2386
2455
  'getheading', 'getx', 'gety', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
2387
2456
  'isvisible', 'jumpto', 'left', 'lt', 'pd', 'pen', 'pencolor', 'pensize', 'pendown', 'penup', 'pos',
2388
- 'position', 'pu', 'radians', 'regularPolygon', 'reset', 'right', 'rt', 'setheading', 'seth',
2457
+ 'position', 'pu', 'radians', 'regularPolygon', 'reset', 'right', 'rt', 'setheading', 'seth',
2389
2458
  'setpos', 'setposition', 'settiltangle', 'setx','sety', 'shape', 'shapesize', 'shearfactor',
2390
2459
  'showturtle', 'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'turtlesize', 'towards', 'up', 'update',
2391
2460
  'width', 'write', 'xcor', 'ycor' ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ColabTurtlePlus
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: An HTML based Turtle implementation with classes for Google Colab and Jupyter Labs
5
5
  Home-page: https://github.com/mathriddle/ColabTurtlePlus
6
6
  Author: Larry Riddle
@@ -33,6 +33,10 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
33
33
 
34
34
  To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
35
35
 
36
+ What's New:
37
+ ----
38
+ Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images or components.
39
+
36
40
  Installation
37
41
  ----
38
42
  Create an empty code cell and type:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ColabTurtlePlus
3
- Version: 2.0.2
3
+ Version: 2.1.0
4
4
  Summary: An HTML based Turtle implementation with classes for Google Colab and Jupyter Labs
5
5
  Home-page: https://github.com/mathriddle/ColabTurtlePlus
6
6
  Author: Larry Riddle
@@ -33,6 +33,10 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
33
33
 
34
34
  To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
35
35
 
36
+ What's New:
37
+ ----
38
+ Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images or components.
39
+
36
40
  Installation
37
41
  ----
38
42
  Create an empty code cell and type:
@@ -8,6 +8,10 @@ The ColabTurtlePlus module provides turtle graphics primitives, in both object-o
8
8
 
9
9
  To use multiple turtles on a screen one has to use the object-oriented interface for the turtles.
10
10
 
11
+ What's New:
12
+ ----
13
+ Sept. 2026: Version 2.1.0 adds a register_shape (alias addshape) function to create a polygonal turtle shape. It does not work with images or components.
14
+
11
15
  Installation
12
16
  ----
13
17
  Create an empty code cell and type:
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = ColabTurtlePlus
3
- version = 2.0.2
3
+ version = 2.1.0
4
4
  author = Larry Riddle
5
5
  author_email = lriddle@agnesscott.edu
6
6
  description = 'An HTML based Turtle implementation with classes for Google Colab and Jupyter Labs'
@@ -9,7 +9,7 @@ README = (HERE / "README.md").read_text()
9
9
 
10
10
  setup(
11
11
  name='ColabTurtlePlus',
12
- version='2.0.2',
12
+ version='2.1.0',
13
13
  packages=['ColabTurtlePlus'],
14
14
  url='https://github.com/mathriddle/ColabTurtlePlus',
15
15
  license='MIT',
File without changes