API¶
This is the documentation for Kurt’s interface, mostly the data structures for storing and accessing the information contained in Scratch files.
kurt
A Python module for reading and writing Scratch project files.
Scratch is created by the Lifelong Kindergarten Group at the MIT Media Lab. See their website: http://scratch.mit.edu/
Classes¶
The main interface:
The following Actors
may be found on the project stage:
The two Scriptables
(Stage
and Sprite
)
have instances of the following contained in their attributes:
Scripts use the following classes:
Media files use the following classes:
File Formats¶
Supported file formats:
Format Name Description Extension "scratch14"
Scratch 1.4 .sb
"scratch20"
Scratch 2.0 .sb2
Pass “Format name” as the argument to Project.convert
.
Kurt provides a superset of the information in each individual format, but will only convert features between a subset of formats.
-
class
kurt.
Project
[source]¶ Bases:
object
The main kurt class. Stores the contents of a project file.
Contents include global variables and lists, the
stage
andsprites
, each with their ownscripts
,costumes
,sounds
,variables
andlists
.A Project can be loaded from or saved to disk in a format which can be read by a Scratch program or one of its derivatives.
Loading a project:
p = kurt.Project.load("tests/game.sb")
Getting all the scripts:
for scriptable in p.sprites + [p.stage]: for script in scriptable.scripts: print script
Creating a new project:
p = kurt.Project()
Converting between formats:
p = kurt.Project.load("tests/game.sb") p.convert("scratch20") # [] p.save() # 'tests/game.sb2'
-
name
= None¶ The name of the project.
May be displayed to the user. Doesn’t have to match the filename in
path
. May not be saved for some formats.
-
path
= None¶ The path to the project file.
-
sprites
= None¶ List of
Sprites
.Use
get_sprite
to get a sprite by name.
-
actors
= None¶ List of each
Actor
on the stage.Includes
Watchers
as well asSprites
.Sprites in
sprites
but not in actors will be added to actors on save.
-
tempo
= None¶ The tempo in BPM used for note blocks.
-
notes
= None¶ Notes about the project, aka project comments.
Displayed on the website next to the project.
Line endings will be converted to
\n
.
The username of the project’s author, eg.
'blob8108'
.
-
get_sprite
(name)[source]¶ Get a sprite from
sprites
by name.Returns None if the sprite isn’t found.
-
format
¶ The file format of the project.
Project
is mainly a universal representation, and so a project has no specfic format. This is the format the project was loaded with. To convert to a different format, usesave()
.
-
classmethod
load
(path, format=None)[source]¶ Load project from file.
Use
format
to specify the file format to use.Path can be a file-like object, in which case format is required. Otherwise, can guess the appropriate format from the extension.
If you pass a file-like object, you’re responsible for closing the file.
Parameters: - path – Path or file pointer.
- format –
KurtFileFormat.name
eg."scratch14"
. Overrides the extension.
Raises: UnknownFormat
if the extension is unrecognised.Raises: ValueError
if the format doesn’t exist.
-
convert
(format)[source]¶ Convert the project in-place to a different file format.
Returns a list of
UnsupportedFeature
objects, which may give warnings about the conversion.Parameters: format – KurtFileFormat.name
eg."scratch14"
.Raises: ValueError
if the format doesn’t exist.
-
save
(path=None, debug=False)[source]¶ Save project to file.
Parameters: - path –
Path or file pointer.
If you pass a file pointer, you’re responsible for closing it.
If path is not given, the
path
attribute is used, usually the original path given toload()
.If path has the extension of an existing plugin, the project will be converted using
convert
. Otherwise, the extension will be replaced with the extension of the current plugin.(Note that log output for the conversion will be printed to stdout. If you want to deal with the output, call
convert
directly.)If the path ends in a folder instead of a file, the filename is based on the project’s
name
. - debug – If true, return debugging information from the format plugin instead of the path.
Raises: ValueError
if there’s no path or name.Returns: path to the saved file.
- path –
-
-
class
kurt.
UnsupportedFeature
(feature, obj)[source]¶ Bases:
object
The plugin doesn’t support this Feature.
Output once by Project.convert for each occurence of the feature.
-
exception
kurt.
UnknownFormat
[source]¶ Bases:
exceptions.Exception
The file extension is not recognised.
Raised when
Project
can’t find a valid format plugin to handle the file extension.
-
exception
kurt.
UnknownBlock
[source]¶ Bases:
exceptions.Exception
A
Block
with the given command or type cannot be found.Raised by
BlockType.get
.
-
exception
kurt.
BlockNotSupported
[source]¶ Bases:
exceptions.Exception
The plugin doesn’t support this Block.
Raised by
Block.convert
when it can’t find aPluginBlockType
for the given plugin.
-
exception
kurt.
VectorImageError
[source]¶ Bases:
exceptions.Exception
Tried to construct a raster image from a vector format image file.
You shouldn’t usally get this error, because Feature(“Vector Images”) will give a warning instead when the Project is converted.
-
class
kurt.
Scriptable
(project)[source]¶ Bases:
object
Superclass for all scriptable objects.
Subclasses are
Stage
andSprite
.-
scripts
= None¶ The contents of the scripting area.
List containing
Scripts
andComments
.Will be sorted by y position on load/save.
-
custom_blocks
= None¶ Scripts for custom blocks, indexed by
CustomBlockType
.
-
costume
= None¶ The currently selected
Costume
.Defaults to the first costume in
self.costumes
on save.If a sprite doesn’t have a costume, a black 1x1 pixel square will be used.
-
volume
= None¶ The volume in percent used for note and sound blocks.
-
parse
(text)[source]¶ Parse the given code and add it to
scripts
.The syntax matches
Script.stringify()
. Seekurt.text
for reference.
-
-
class
kurt.
Stage
(project)[source]¶ Bases:
kurt.Scriptable
Represents the background of the project. The stage is similar to a
Sprite
, but has a fixed position. The stage has a fixed size of480x360
pixels.The stage does not require a costume. If none is given, it is assumed to be white (#FFF).
Not all formats have stage-specific variables and lists. Global variables and lists are stored on the
Project
.Parameters: project – The Project
this Stage belongs to. Note that you still need to setProject.stage
to this Stage instance.-
name
= 'Stage'¶
-
is_draggable
= False¶
-
is_visible
= True¶
-
SIZE
= (480, 360)¶
-
COLOR
= (255, 255, 255)¶
-
backgrounds
¶ Alias for
costumes
.
-
-
class
kurt.
Sprite
(project, name)[source]¶ Bases:
kurt.Scriptable
,kurt.Actor
A scriptable object displayed on the project stage. Can be moved and rotated, unlike the
Stage
.Sprites require a
costume
, and will raise an error when saving without one.Parameters: project – The Project
this Sprite belongs to. Note that you still need to add this sprite toProject.sprites
.-
name
= None¶ The name of the sprite, as referred to from scripts and displayed in the Scratch interface.
-
position
= None¶ The
(x, y)
position of the centre of the sprite in Scratch co-ordinates.
-
direction
= None¶ The angle in degrees the sprite is rotated to.
-
rotation_style
= None¶ How the sprite’s costume rotates with the sprite. Valid values are:
'normal'
- Continuous rotation with
direction
. The default. 'leftRight'
- Don’t rotate. Instead, flip the costume for directions with x component < 0. Useful for side-views.
'none'
- Don’t rotate with direction.
-
size
= None¶ The scale factor of the sprite in percent. Defaults to 100.
-
is_draggable
= None¶ True if the sprite can be dragged using the mouse in the player/presentation mode.
-
is_visible
= None¶ Whether the sprite is shown on the stage. False if the sprite is hidden.
-
-
class
kurt.
Watcher
(target, block, style='normal', is_visible=True, pos=None)[source]¶ Bases:
kurt.Actor
A monitor for displaying a data value on the stage.
Some formats won’t save hidden watchers, and so their position won’t be remembered.
-
target
= None¶ The
Scriptable
orProject
the watcher belongs to.
-
block
= None¶ The
Block
to evaluate ontarget
.For variables:
kurt.Block('readVariable', 'variable name')
For lists:
kurt.Block('contentsOfList:', 'list name')
-
style
= None¶ How the watcher should appear.
Valid values:
'normal'
- The name of the data is displayed next to its value. The only valid value for list watchers.
'large'
- The data is displayed in a larger font with no describing text.
'slider'
- Like the normal style, but displayed with a slider that can change the variable’s value. Not valid for reporter block watchers.
-
pos
= None¶ (x, y)
position of the top-left of the watcher from the top-left of the stage in pixels. None if not specified.
-
is_visible
= None¶ Whether the watcher is displayed on the screen.
Some formats won’t save hidden watchers, and so their position won’t be remembered.
-
slider_min
= None¶ Minimum value for slider. Only applies to
"slider"
style.
-
slider_max
= None¶ Maximum value for slider. Only applies to
"slider"
style.
-
-
class
kurt.
Variable
(value=0, is_cloud=False)[source]¶ Bases:
object
A memory value used in scripts.
There are both
global variables
andsprite-specific variables
.Some formats also have
stage-specific variables
.-
value
= None¶ The value of the variable, usually a number or a string.
For some formats, variables can take list values, and
List
is not used.
-
is_cloud
= None¶ Whether the value of the variable is shared with other users.
For Scratch 2.0.
-
-
class
kurt.
List
(items=None, is_cloud=False)[source]¶ Bases:
object
A sequence of items used in scripts.
Each item takes a
Variable
-like value.Lists cannot be nested. However, for some formats, variables can take list values, and this class is not used.
-
items
= None¶ The items contained in the list. A Python list of unicode strings.
-
is_cloud
= None¶ Whether the value of the list is shared with other users.
For Scratch 2.0.
-
-
class
kurt.
Color
(r, g=None, b=None)[source]¶ Bases:
object
A 24-bit RGB color value.
Accepts tuple or hexcode arguments:
>>> kurt.Color('#f08') kurt.Color(255, 0, 136) >>> kurt.Color((255, 0, 136)) kurt.Color(255, 0, 136) >>> kurt.Color('#f0ffee') kurt.Color(240, 255, 238)
-
r
= None¶ Red component, 0-255
-
g
= None¶ Green component, 0-255
-
b
= None¶ Blue component, 0-255
-
value
¶ Return
(r, g, b)
tuple.
-
-
class
kurt.
Insert
(shape, kind=None, default=None, name=None, unevaluated=None)[source]¶ Bases:
object
The specification for an argument to a
BlockType
.-
SHAPE_DEFAULTS
= {'color': kurt.Color(255, 0, 0), 'inline': 'nil', 'number-menu': 0, 'number': 0, 'stack': []}¶
-
SHAPE_FMTS
= {'number-menu': '(%s v)', 'boolean': '<%s>', 'string': '[%s]', 'readonly-menu': '[%s v]', 'color': '[%s]', 'inline': '%s', 'number': '(%s)', 'block': '{%s}', 'stack': '\n %s\n'}¶
-
KIND_OPTIONS
= {'attribute': ['x position', 'y position', 'direction', 'costume #', 'size', 'volume'], 'booleanSensor': ['button pressed', 'A connected', 'B connected', 'C connected', 'D connected'], 'listDeleteItem': ['last', 'all'], 'mathOp': ['abs', 'floor', 'ceiling', 'sqrt', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'ln', 'log', 'e ^', '10 ^'], 'spriteOrStage': ['Stage'], 'timeAndDate': ['year', 'month', 'date', 'day of week', 'hour', 'minute', 'second'], 'note': [], 'instrument': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], 'motorDirection': ['this way', 'that way', 'reverse'], 'var': [], 'sensor': ['slider', 'light', 'sound', 'resistance-A', 'resistance-B', 'resistance-C', 'resistance-D'], 'videoMotionType': ['motion', 'direction'], 'direction': [], 'videoState': ['off', 'on', 'on-flipped'], 'stop': ['all', 'this script', 'other scripts in sprite'], 'effect': ['color', 'fisheye', 'whirl', 'pixelate', 'mosaic', 'brightness', 'ghost'], 'broadcast': [], 'touching': ['mouse-pointer', 'edge'], 'spriteOrMouse': ['mouse-pointer'], 'listItem': ['last', 'random'], 'key': ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'space', 'left arrow', 'right arrow', 'up arrow', 'down arrow'], 'sound': [], 'stageOrThis': ['Stage'], 'drum': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], 'triggerSensor': ['loudness', 'timer', 'video motion'], 'list': [], 'rotationStyle': ['left-right', "don't rotate", 'all around'], 'spriteOnly': ['myself'], 'backdrop': [], 'costume': []}¶
-
shape
= None¶ What kind of values this argument accepts.
Shapes that accept a simple data value or a reporter block:
'number'
- An integer or float number. Defaults to
0
. 'string'
- A unicode text value.
'readonly-menu'
A choice of string value from a menu.
Some readonly inserts do not accept reporter blocks.
'number-menu'
Either a number value, or a choice of special value from a menu.
Defaults to
0
.'color'
- A
Color
value. Defaults to a random color.
Shapes that only accept blocks with the corresponding
shape
:'boolean'
- Accepts a boolean block.
'stack'
Accepts a list of stack blocks. Defaults to
[]
.The block is rendered with a “mouth” into which blocks can be inserted.
Special shapes:
'inline'
- Not actually an insert – used for variable and list reporters.
'block'
- Used for the argument to the “define ...” hat block.
-
kind
= None¶ Valid arguments for a “menu”-shaped insert. Default is
None
.Valid values include:
'attribute'
'booleanSensor'
'broadcast'
'costume'
'direction'
'drum'
'effect'
'instrument'
'key'
'list'
'listDeleteItem'
'listItem'
'mathOp'
'motorDirection'
'note'
'sensor'
'sound'
'spriteOrMouse'
'spriteOrStage'
'touching'
'var'
Scratch 2.0-specific:
'backdrop'
'rotationStyle'
'spriteOnly'
'stageOrThis'
'stop'
'timeAndDate'
'triggerSensor'
'videoMotionType'
'videoState'
-
default
= None¶ The default value for the insert.
-
unevaluated
= None¶ True if the interpreter should evaluate the argument to the block.
Defaults to True for ‘stack’ inserts, False for all others.
-
name
= None¶ The name of the parameter to a
CustomBlockType
.Not used for
BlockTypes
.
-
-
class
kurt.
BaseBlockType
(shape, parts)[source]¶ Bases:
object
Base for
BlockType
andPluginBlockType
.Defines common attributes.
-
SHAPE_FMTS
= {'boolean': '<%s>', 'reporter': '(%s)'}¶
-
shape
= None¶ The shape of the block. Valid values:
'stack'
- The default. Can connect to blocks above and below. Appear jigsaw-shaped.
'cap'
- Stops the script executing after this block. No blocks can be connected below them.
'hat'
- A block that starts a script, such as by responding to an event. Can connect to blocks below.
'reporter'
- Return a value. Can be placed into insert slots of other blocks as an argument to that block. Appear rounded.
'boolean'
- Like reporter blocks, but return a true/false value. Appear hexagonal.
“C”-shaped blocks with “mouths” for stack blocks, such as
"doIf"
, are specified by addingInsert('stack')
to the end ofparts
.
-
parts
= None¶ A list describing the text and arguments of the block.
Contains strings, which are part of the text displayed on the block, and
Insert
instances, which are arguments to the block.
-
text
¶ The text displayed on the block.
String containing
"%s"
in place of inserts.eg.
'say %s for %s secs'
-
defaults
¶ Default values for block inserts. (See
Block.args
.)
-
stripped_text
¶ The
text
, with spaces and inserts removed.Used by
BlockType.get
to look up blocks.
-
-
class
kurt.
BlockType
(pbt)[source]¶ Bases:
kurt.BaseBlockType
The specification for a type of
Block
.These are initialiased by
Kurt
by combiningPluginBlockType
objects from individual format plugins to create a singleBlockType
for each command.-
convert
(plugin=None)[source]¶ Return a
PluginBlockType
for the given plugin name.If plugin is
None
, return the first registered plugin.
-
conversions
¶ Return the list of
PluginBlockType
instances.
-
shape
¶
-
parts
¶
-
classmethod
get
(block_type)[source]¶ Return a
BlockType
instance from the given parameter.- If it’s already a BlockType instance, return that.
- If it exactly matches the command on a
PluginBlockType
, return the corresponding BlockType. - If it loosely matches the text on a PluginBlockType, return the corresponding BlockType.
- If it’s a PluginBlockType instance, look for and return the corresponding BlockType.
-
-
class
kurt.
PluginBlockType
(category, shape, command, parts, match=None)[source]¶ Bases:
kurt.BaseBlockType
Holds plugin-specific
BlockType
attributes.For each block concept,
Kurt
builds a single BlockType that references a corresponding PluginBlockType for each plugin that supports that block.Note that whichever plugin is loaded first takes precedence.
-
format
= None¶ The format plugin the block belongs to.
-
command
= None¶ The method name from the source code, used to identify the block.
eg.
'say:duration:elapsed:from:'
-
category
= None¶ Where the block is found in the interface.
The same blocks may have different categories in different formats.
Possible values include:
'motion', 'looks', 'sound', 'pen', 'control', 'events', 'sensing', 'operators', 'data', 'variables', 'list', 'more blocks', 'motor', 'sensor', 'wedo', 'midi', 'obsolete'
-
-
class
kurt.
CustomBlockType
(shape, parts)[source]¶ Bases:
kurt.BaseBlockType
A user-specified
BlockType
.The script defining the custom block starts with:
kurt.Block("procDef", <CustomBlockType>)
And the scripts definining the block follow.
The same CustomBlockType instance can then be used in a block in another script:
kurt.Block(<CustomBlocktype>, [args ...,])
-
is_atomic
= None¶ True if the block should run without screen refresh.
-
-
class
kurt.
Block
(block_type, *args)[source]¶ Bases:
object
A statement in a graphical programming language. Blocks can connect together to form sequences of commands, which are stored in a
Script
. Blocks perform different commands depending on their type.Parameters: - type – A
BlockType
instance, used to identify the command the block performs. Will also exact match acommand
or loosely matchtext
. - *args – List of the block’s arguments. Arguments can be numbers, strings, Blocks, or lists of Blocks (for ‘stack’ shaped Inserts).
The following constructors are all equivalent:
>>> block = kurt.Block('say:duration:elapsed:from:', 'Hello!', 2) >>> block = kurt.Block("say %s for %s secs", "Hello!", 2) >>> block = kurt.Block("sayforsecs", "Hello!", 2)
Using BlockType:
>>> block.type <kurt.BlockType('say [Hello!] for (2) secs', 'stack')> >>> block.args ['Hello!', 2] >>> block2 = kurt.Block(block.type, "Goodbye!", 5) >>> block.stringify() 'say [Hello!] for (2) secs' >>> block2.stringify() 'say [Goodbye!] for (5) secs'
-
comment
= None¶ The text of the comment attached to the block. Empty if no comment is attached.
Comments can only be attached to stack blocks.
-
args
= None¶ List of arguments to the block.
The block’s parameters are found in
type.inserts
. Default values come fromtype.defaults <BlockType.defaults
.
- type – A
-
class
kurt.
Script
(blocks=None, pos=None)[source]¶ Bases:
object
A single sequence of blocks. Each
Scriptable
can have many Scripts.The first block,
self.blocks[0]
is usually a “when” block, eg. an EventHatMorph.Scripts implement the
list
interface, so can be indexed directly, eg.script[0]
. All other methods likeappend
also work.-
pos
= None¶ (x, y)
position from the top-left of the script area in pixels.
-
-
class
kurt.
Comment
(text, pos=None)[source]¶ Bases:
object
A free-floating comment in
Scriptable.scripts
.-
text
= None¶ The text of the comment.
-
pos
= None¶ (x, y)
position from the top-left of the script area in pixels.
-
-
class
kurt.
Costume
(name, image, rotation_center=None)[source]¶ Bases:
object
Describes the look of a sprite.
The raw image data is stored in
image
.-
name
= None¶ Name used by scripts to refer to this Costume.
-
rotation_center
= None¶ (x, y)
position from the top-left corner of the point about which the image rotates.Defaults to the center of the image.
-
classmethod
load
(path)[source]¶ Load costume from image file.
Uses
Image.load
, but will set the Costume’s name based on the image filename.
-
save
(path)[source]¶ Save the costume to an image file at the given path.
Uses
Image.save
, but if the path ends in a folder instead of a file, the filename is based on the costume’sname
.The image format is guessed from the extension. If path has no extension, the image’s
format
is used.Returns: Path to the saved file.
-
-
class
kurt.
Image
(contents, format=None)[source]¶ Bases:
object
The contents of an image file.
Constructing from raw file contents:
Image(file_contents, "JPEG")
Constructing from a
PIL.Image.Image
instance:pil_image = PIL.Image.new("RGBA", (480, 360)) Image(pil_image)
Loading from file path:
Image.load("path/to/image.jpg")
Images are immutable. If you want to modify an image, get a
PIL.Image.Image
instance frompil_image
, modify that, and use it to construct a new Image. Modifying images in-place may break things.The reason for having multiple constructors is so that kurt can implement lazy loading of image data – in many cases, a PIL image will never need to be created.
-
pil_image
¶ A
PIL.Image.Image
instance containing the image data.
-
contents
¶ The raw file contents as a string.
-
format
¶ The format of the image file.
An uppercase string corresponding to the
PIL.ImageFile.ImageFile.format
attribute. Valid values include"JPEG"
and"PNG"
.
-
size
¶ (width, height)
in pixels.
-
width
¶
-
height
¶
-
convert
(*formats)[source]¶ Return an Image instance with the first matching format.
For each format in
*args
: If the image’sformat
attribute is the same as the format, return self, otherwise try the next format.If none of the formats match, return a new Image instance with the last format.
-
save
(path)[source]¶ Save image to file path.
The image format is guessed from the extension. If path has no extension, the image’s
format
is used.Returns: Path to the saved file.
-
-
class
kurt.
Sound
(name, waveform)[source]¶ Bases:
object
A sound a
Scriptable
can play.The raw sound data is stored in
waveform
.-
name
= None¶ Name used by scripts to refer to this Sound.
-
classmethod
load
(path)[source]¶ Load sound from wave file.
Uses
Waveform.load
, but will set the Waveform’s name based on the sound filename.
-
save
(path)[source]¶ Save the sound to a wave file at the given path.
Uses
Waveform.save
, but if the path ends in a folder instead of a file, the filename is based on the project’sname
.Returns: Path to the saved file.
-
-
class
kurt.
Waveform
(contents, rate=None, sample_count=None)[source]¶ Bases:
object
The contents of a wave file. Only WAV format files are supported.
Constructing from raw file contents:
Sound(file_contents)
Loading from file path:
Sound.load("path/to/sound.wav")
Waveforms are immutable.
-
extension
= '.wav'¶
-
contents
¶ The raw file contents as a string.
-
rate
¶ The sampling rate of the sound.
-
sample_count
¶ The number of samples in the sound.
-