Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt/tautils.py
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2010-10-10 22:22:37 (GMT)
committer Walter Bender <walter@sugarlabs.org>2010-10-10 22:22:37 (GMT)
commitdcd7408d2f4c18e9342119829aa039693c276b31 (patch)
treef6643d1d4c1ba72409727a9f9b7f84d2c5a56173 /TurtleArt/tautils.py
parentaf3be3449aefad988cc6d733182a970eda0da764 (diff)
pep8 cleanup
Diffstat (limited to 'TurtleArt/tautils.py')
-rw-r--r--TurtleArt/tautils.py133
1 files changed, 93 insertions, 40 deletions
diff --git a/TurtleArt/tautils.py b/TurtleArt/tautils.py
index 8229166..9e9d2c3 100644
--- a/TurtleArt/tautils.py
+++ b/TurtleArt/tautils.py
@@ -44,20 +44,24 @@ from gettext import gettext as _
import logging
_logger = logging.getLogger('turtleart-activity')
+
class pythonerror(Exception):
+
def __init__(self, value):
self.value = value
+
def __str__(self):
return repr(self.value)
-'''
-The strategy for mixing numbers and strings is to first try
-converting the string to a float; then if the string is a single
-character, try converting it to an ord; finally, just treat it as a
-string. Numbers appended to strings are first trreated as ints, then
-floats.
-'''
+
def convert(x, fn, try_ord=True):
+ '''
+ The strategy for mixing numbers and strings is to first try
+ converting the string to a float; then if the string is a single
+ character, try converting it to an ord; finally, just treat it as a
+ string. Numbers appended to strings are first trreated as ints, then
+ floats.
+ '''
try:
return fn(x)
except ValueError:
@@ -67,6 +71,7 @@ def convert(x, fn, try_ord=True):
return fn(xx)
return x
+
def chr_to_ord(x):
""" Try to comvert a string to an ord """
if strtype(x) and len(x) == 1:
@@ -76,6 +81,7 @@ def chr_to_ord(x):
return x, False
return x, False
+
def strtype(x):
""" Is x a string type? """
if type(x) == str:
@@ -84,10 +90,12 @@ def strtype(x):
return True
return False
+
def magnitude(pos):
""" Calculate the magnitude of the distance between to blocks. """
x, y = pos
- return x*x+y*y
+ return x * x + y * y
+
def json_load(text):
""" Load JSON data using what ever resources are available. """
@@ -96,12 +104,13 @@ def json_load(text):
else:
# strip out leading and trailing whitespace, nulls, and newlines
text = text.lstrip()
- text = text.replace('\12','')
- text = text.replace('\00','')
+ text = text.replace('\12', '')
+ text = text.replace('\00', '')
_io = StringIO(text.rstrip())
_listdata = jload(_io)
# json converts tuples to lists, so we need to convert back,
- return _tuplify(_listdata)
+ return _tuplify(_listdata)
+
def _tuplify(tup):
""" Convert to tuples """
@@ -109,12 +118,14 @@ def _tuplify(tup):
return tup
return tuple(map(_tuplify, tup))
+
def get_id(connection):
""" Get a connection block ID. """
if connection is None:
return None
return connection.id
+
def json_dump(data):
""" Save data using available JSON tools. """
if OLD_SUGAR_SYSTEM is True:
@@ -124,35 +135,34 @@ def json_dump(data):
jdump(data, _io)
return _io.getvalue()
+
def get_load_name(suffix, load_save_folder):
""" Open a load file dialog. """
_dialog = gtk.FileChooserDialog("Load...", None,
- gtk.FILE_CHOOSER_ACTION_OPEN,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
- gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+ gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_OPEN, gtk.RESPONSE_OK))
_dialog.set_default_response(gtk.RESPONSE_OK)
return do_dialog(_dialog, suffix, load_save_folder)
-
+
+
def get_save_name(suffix, load_save_folder, save_file_name):
""" Open a save file dialog. """
_dialog = gtk.FileChooserDialog("Save...", None,
- gtk.FILE_CHOOSER_ACTION_SAVE,
- (gtk.STOCK_CANCEL,
- gtk.RESPONSE_CANCEL,
- gtk.STOCK_SAVE,
- gtk.RESPONSE_OK))
+ gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_SAVE, gtk.RESPONSE_OK))
_dialog.set_default_response(gtk.RESPONSE_OK)
if save_file_name is not None:
- _dialog.set_current_name(save_file_name+suffix)
+ _dialog.set_current_name(save_file_name + suffix)
return do_dialog(_dialog, suffix, load_save_folder)
-#
-# We try to maintain read-compatibility with all versions of Turtle Art.
-# Try pickle first; then different versions of json.
-#
+
def data_from_file(ta_file):
""" Open the .ta file, ignoring any .png file that might be present. """
file_handle = open(ta_file, "r")
+ #
+ # We try to maintain read-compatibility with all versions of Turtle Art.
+ # Try pickle first; then different versions of json.
+ #
try:
_data = pickle.load(file_handle)
except:
@@ -163,25 +173,29 @@ def data_from_file(ta_file):
file_handle.close()
return _data
+
def data_from_string(text):
""" JSON load data from a string. """
return json_load(text.replace(']],\n', ']], '))
+
def data_to_file(data, ta_file):
""" Write data to a file. """
file_handle = file(ta_file, "w")
file_handle.write(data_to_string(data))
file_handle.close()
+
def data_to_string(data):
""" JSON dump a string. """
return json_dump(data).replace(']], ', ']],\n')
+
def do_dialog(dialog, suffix, load_save_folder):
""" Open a file dialog. """
_result = None
file_filter = gtk.FileFilter()
- file_filter.add_pattern('*'+suffix)
+ file_filter.add_pattern('*' + suffix)
file_filter.set_name("Turtle Art")
dialog.add_filter(file_filter)
dialog.set_current_folder(load_save_folder)
@@ -192,6 +206,7 @@ def do_dialog(dialog, suffix, load_save_folder):
dialog.destroy()
return _result, load_save_folder
+
def save_picture(canvas, file_name=''):
""" Save the canvas to a file. """
_pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, canvas.width,
@@ -203,12 +218,14 @@ def save_picture(canvas, file_name=''):
_pixbuf.save(file_name, 'png')
return _pixbuf
+
def save_svg(string, file_name):
""" Write a string to a file. """
file_handle = file(file_name, "w")
file_handle.write(string)
file_handle.close()
+
def get_pixbuf_from_journal(dsobject, w, h):
""" Load a pixbuf from a Journal object. """
try:
@@ -226,7 +243,8 @@ def get_pixbuf_from_journal(dsobject, w, h):
_pixbuf = None
return _pixbuf
-def get_path(activity, subpath ):
+
+def get_path(activity, subpath):
""" Find a Rainbow-approved place for temporary files. """
try:
return(os.path.join(activity.get_activity_root(), subpath))
@@ -235,6 +253,7 @@ def get_path(activity, subpath ):
return(os.path.join(os.environ['HOME'], ".sugar/default",
"org.laptop.TurtleArtActivity", subpath))
+
def image_to_base64(pixbuf, activity):
""" Convert an image to base64 """
_file_name = os.path.join(get_path(activity, 'instance'), 'imagetmp.png')
@@ -248,22 +267,28 @@ def image_to_base64(pixbuf, activity):
_file_handle.close()
return _data
+
def movie_media_type(name):
""" Is it movie media? """
return name.endswith(('.ogv', '.vob', '.mp4', '.wmv', '.mov', '.mpeg'))
-def audio_media_type(name):
+
+def audio_media_type(name):
""" Is it audio media? """
return name.endswith(('.ogg', '.oga', '.m4a'))
+
def image_media_type(name):
""" Is it image media? """
return name.endswith(('.png', '.jpg', '.jpeg', '.gif', '.tiff', '.tif',
'.svg'))
+
+
def text_media_type(name):
""" Is it text media? """
return name.endswith(('.txt', '.py', '.lg', '.doc', '.rtf'))
+
def round_int(num):
""" Remove trailing decimal places if number is an int """
try:
@@ -275,14 +300,15 @@ def round_int(num):
if int(float(num)) == num:
return int(num)
else:
- if float(num)<0:
- _nn = int((float(num)-0.005)*100)/100.
+ if float(num) < 0:
+ _nn = int((float(num) - 0.005) * 100) / 100.
else:
- _nn = int((float(num)+0.005)*100)/100.
+ _nn = int((float(num) + 0.005) * 100) / 100.
if int(float(_nn)) == _nn:
return int(_nn)
return _nn
+
def calc_image_size(spr):
""" Calculate the maximum size for placing an image onto a sprite. """
return int(max(spr.label_safe_width(), 1)), \
@@ -290,12 +316,14 @@ def calc_image_size(spr):
# Collapsible stacks live between 'sandwichtop' and 'sandwichbottom' blocks
+
def reset_stack_arm(top):
""" When we undock, retract the 'arm' that extends from 'sandwichtop'. """
if top is not None and top.name in ['sandwichtop', 'sandwichtop_no_label']:
if top.ey > 0:
top.reset_y()
+
def grow_stack_arm(top):
""" When we dock, grow an 'arm' from 'sandwichtop'. """
if top is not None and top.name in ['sandwichtop', 'sandwichtop_no_label']:
@@ -307,11 +335,12 @@ def grow_stack_arm(top):
_ty = top.spr.get_xy()[1]
_th = top.spr.get_dimensions()[1]
_by = _bot.spr.get_xy()[1]
- _dy = _by-(_ty + _th)
+ _dy = _by - (_ty + _th)
if _dy > 0:
- top.expand_in_y(_dy/top.scale)
+ top.expand_in_y(_dy / top.scale)
top.refresh()
+
def find_sandwich_top(blk):
""" Find the sandwich top above this block. """
# Always follow the main branch of a flow: the first connection.
@@ -329,6 +358,7 @@ def find_sandwich_top(blk):
_blk = _blk.connections[0]
return None
+
def find_sandwich_bottom(blk):
""" Find the sandwich bottom below this block. """
# Always follow the main branch of a flow: the last connection.
@@ -342,10 +372,11 @@ def find_sandwich_bottom(blk):
_blk = _blk.connections[len(_blk.connections) - 1]
return None
+
def find_sandwich_top_below(blk):
""" Find the sandwich top below this block. """
- if blk.name in ['sandwichtop', 'sandwichtop_no_label', 'sandwichtop_no_arm',
- 'sandwichtop_no_arm_no_label']:
+ if blk.name in ['sandwichtop', 'sandwichtop_no_label',
+ 'sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']:
return blk
# Always follow the main branch of a flow: the last connection.
_blk = blk.connections[len(blk.connections) - 1]
@@ -356,6 +387,7 @@ def find_sandwich_top_below(blk):
_blk = _blk.connections[len(_blk.connections) - 1]
return None
+
def restore_stack(top):
""" Restore the blocks between the sandwich top and sandwich bottom. """
_group = find_group(top.connections[len(top.connections) - 1])
@@ -403,6 +435,7 @@ def restore_stack(top):
top.refresh()
grow_stack_arm(top)
+
def uncollapse_forks(top, looping=False):
""" From the top, find and restore any collapsible stacks on forks. """
if top == None:
@@ -410,7 +443,7 @@ def uncollapse_forks(top, looping=False):
if looping and top.name in ['sandwichtop_no_arm',
'sandwichtop_no_arm_no_label']:
restore_stack(top)
- return
+ return
if len(top.connections) == 0:
return
_blk = top.connections[len(top.connections) - 1]
@@ -418,22 +451,24 @@ def uncollapse_forks(top, looping=False):
if _blk.name in COLLAPSIBLE:
return
if _blk.name in ['sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']:
- restore_stack(_blk)
+ restore_stack(_blk)
return
# Follow a fork
- if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', 'until']:
+ if _blk.name in ['repeat', 'if', 'ifelse', 'forever', 'while',
+ 'until']:
top = find_sandwich_top_below(
- _blk.connections[len(_blk.connections) - 2])
+ _blk.connections[len(_blk.connections) - 2])
if top is not None:
uncollapse_forks(top, True)
if _blk.name == 'ifelse':
top = find_sandwich_top_below(
- _blk.connections[len(_blk.connections) - 3])
+ _blk.connections[len(_blk.connections) - 3])
if top is not None:
uncollapse_forks(top, True)
_blk = _blk.connections[len(_blk.connections) - 1]
return
+
def collapse_stack(top):
""" Hide all the blocks between the sandwich top and sandwich bottom. """
# First uncollapse any nested stacks
@@ -489,6 +524,7 @@ def collapse_stack(top):
top.name = 'sandwichtop_no_arm_no_label'
top.refresh()
+
def collapsed(blk):
""" Is this stack collapsed? """
if blk is not None and blk.name in COLLAPSIBLE and\
@@ -496,6 +532,7 @@ def collapsed(blk):
return True
return False
+
def collapsible(blk):
""" Can this stack be collapsed? """
if blk is None or blk.name not in COLLAPSIBLE:
@@ -504,6 +541,7 @@ def collapsible(blk):
return False
return True
+
def hide_button_hit(spr, x, y):
""" Did the sprite's hide (contract) button get hit? """
_red, _green, _blue, _alpha = spr.get_pixel((x, y))
@@ -512,6 +550,7 @@ def hide_button_hit(spr, x, y):
else:
return False
+
def show_button_hit(spr, x, y):
""" Did the sprite's show (expand) button get hit? """
_red, _green, _blue, _alpha = spr.get_pixel((x, y))
@@ -520,12 +559,14 @@ def show_button_hit(spr, x, y):
else:
return False
+
def numeric_arg(value):
""" Dock test: looking for a numeric value """
if type(convert(value, float)) is float:
return True
return False
+
def zero_arg(value):
""" Dock test: looking for a zero argument """
if numeric_arg(value):
@@ -533,6 +574,7 @@ def zero_arg(value):
return True
return False
+
def neg_arg(value):
""" Dock test: looking for a negative argument """
if numeric_arg(value):
@@ -540,6 +582,7 @@ def neg_arg(value):
return True
return False
+
def dock_dx_dy(block1, dock1n, block2, dock2n):
""" Find the distance between the dock points of two blocks. """
_dock1 = block1.docks[dock1n]
@@ -572,6 +615,7 @@ def dock_dx_dy(block1, dock1n, block2, dock2n):
(_b2x, _b2y) = block2.spr.get_xy()
return ((_b1x + _d1x) - (_b2x + _d2x), (_b1y + _d1y) - (_b2y + _d2y))
+
def journal_check(blk1, blk2, dock1, dock2):
""" Dock blocks only if arg is Journal block """
if blk1 == None or blk2 == None:
@@ -582,6 +626,7 @@ def journal_check(blk1, blk2, dock1, dock2):
return False
return True
+
def arithmetic_check(blk1, blk2, dock1, dock2):
""" Dock strings only if they convert to numbers. Avoid /0 and root(-1)"""
if blk1 == None or blk2 == None:
@@ -656,6 +701,7 @@ def arithmetic_check(blk1, blk2, dock1, dock2):
return False
return True
+
def xy(event):
""" Where is the mouse event? """
return map(int, event.get_coords())
@@ -664,6 +710,7 @@ def xy(event):
Utilities related to finding blocks in stacks.
"""
+
def find_block_to_run(blk):
""" Find a stack to run (any stack without a 'def action'on the top). """
_top = find_top_block(blk)
@@ -672,6 +719,7 @@ def find_block_to_run(blk):
else:
return False
+
def find_top_block(blk):
""" Find the top block in a stack. """
if blk is None:
@@ -682,6 +730,7 @@ def find_top_block(blk):
blk = blk.connections[0]
return blk
+
def find_start_stack(blk):
""" Find a stack with a 'start' block on top. """
if blk is None:
@@ -691,6 +740,7 @@ def find_start_stack(blk):
else:
return False
+
def find_group(blk):
""" Find the connected group of block in a stack. """
if blk is None:
@@ -702,6 +752,7 @@ def find_group(blk):
_group.extend(find_group(_blk2))
return _group
+
def find_blk_below(blk, name):
""" Find a specific block below this block. """
if blk == None or len(blk.connections) == 0:
@@ -712,11 +763,13 @@ def find_blk_below(blk, name):
return _gblk
return None
+
def olpc_xo_1():
""" Is the an OLPC XO-1 or XO-1.5? """
return os.path.exists('/etc/olpc-release') or \
os.path.exists('/sys/power/olpc-pm')
+
def walk_stack(tw, blk):
""" Convert blocks to logo psuedocode. """
top = find_top_block(blk)