How to program with casetta 0.3

This document aim to let any python programmer to use quickly the python package casetta. The casetta version used here is the 0.3 (current stable version).

Importing casetta

Before using any example, you must import the python package casetta, using a line like:

import casetta

If you want to use casetta 0.3 without installing it on your system, you can run python or your program with the “PYTHONPATH” variable set to the path of the package.

$ PYTHONPATH="/path/to/svn/tags/0.3.0" python

or

$ export PYTHONPATH="/path/to/svn/tags/0.3.0"
$ python

If you want any bash session to export the PYTHONPATH variable, you can add to your ~/.bashrc:

export PYTHONPATH="/path/to/svn/tags/0.3.0"

File management

A file is a set of many data like programs, pictures, backups, etc. A file may be saved and opened on a disk in a file format.

Create a new empty file

To create a empty file, just use:

my_file = casetta.data.FileData()

You will get a “FileData” object.

Open a file

my_file = casetta.data.FileData("/path/of/my/file.ext")

The format is auto-detected using the extension and in some case the content of the file. If the format is not detected a casetta.errors.FormatNotFound will be raised. In some case, a file format can only write file, and a casetta.errors.FormatCantOpen will be raised. You can catch it with:

try:
    my_file = casetta.data.FileData("/path/of/my/file.ext")
except casetta.errors.FormatNotFound:
    print "Cannot detect the format of the file"
except casetta.errors.FormatCantOpen, error:
    print "The format %s cannot open the file" % error.format.name

If you want, you can specify a particular format (to know more about formats, see the “Formats” part bellow):

my_file = casetta.data.FileData("/path/of/my/file.ext", my_format)

Import data into a file

You can import data from a file on the disk into an already opened file. Data will be merged will current data.

# Create the first file:
my_file = casetta.data.FileData("/path/of/my/file.ext")
# Import data from another file:
try:
    new_data_list = my_file.import_file("/path/of/the/second/file.ext")
except casetta.errors.FormatNotFound:
    print "Cannot detect the format of the second file"
except casetta.errors.FormatCantOpen, error:
    print "The format %s cannot open the second file" % error.format.name
# Import data from a file with a specific format:
new_data_list2 = my_file.import_file("/path/of/the/third/file.ext", my_format)

The import_file method return the list of data added into the file.

Because after an import, two data may have the same name, you should check the name of all new data (using the returned list). To know how to check a name, see the “Check a name” part bellow.

Save or export

Saving a file will save all the content of file in the disk in a file format. Export will save only some data selected (see the “Select to export” part bellow). Because file formats are very heterogeneous, some of them cannot save data (read only), and some of them cannot manage any kind of data.

# Save the my_file:
my_file.save("/path/of/the/saved/file.ext")
# You can also specify a format, like in open or import:
my_file.save("/path/of/the/saved/file.ext", format)
# Error management:
try:
    my_file.save("/path/of/the/saved/file.ext")
except casetta.errors.FormatNotFound:
    # Casetta cannot auto-detect the right format:
    print "The format cannot be detected"
except casetta.errors.FormatCantSave, error:
    # The format of the file cannot write data
    print "The format %s can only read files" % error.format.name
except casetta.errors.DataNoManaged, not_managed:
    # This exception is raised when some data are not managed by the file format
    # not_managed.data_type_list is a list of data classes (see the data part for informations about data classes)
    # not_managed.data_type_list may also be ['all'] if all data type are not managed
    if not_managed.data_type_list = ['all']:
        print "The format cannot manage any data - abort."
    else:
        print "The format cannot manage this data: %s." % ",".join([data.dType for data in not_managed.data_type_list])
        # In this case, if you want, you can save all supported data using:
        my_file.save("/path/of/the/saved/file.ext", ignore_warnings=True)

The export is like the save, you just must to set the export flag at True, like:

# Export my_file:
my_file.save("/path/of/the/saved/file.ext", export=True)

Send data to a device

To send data to a device, you must use a transfer tool. To know more about transfer tool, see the specific part. For the moment, we will used “Tool” as transfer tool class.

my_tool = Tool()
# Send all data in my_file:
my_file.send(my_tool)
# Send only selected-to-be-exported data:
my_file.send(my_tool, export=True)

Receive data from a device

To receive data from a device, you must use a transfer tool. To know more about transfer tool, see the specific part. For the moment, we will used “Tool” as transfer tool class.

my_tool = Tool()
received_file = my_tool.receive()

A lot of exceptions may be raised by transfer tools. See the transfer tool for a list of exceptions of each tool.

You may want to import received data into an existing file. Do do that, you can use this syntax:

my_tool = Tool()
new_data_list = older_file.add_records(my_tool.receive())

After that, you should check the name of each data in new_data_list.

Data management

Create a data

You can create data in two way: alone or inside a file. In most of cases, data will be create inside a file.

# Make a data alone
my_data = casetta.data.Data()
# The casetta.data.Data is a generic class.
# If you know the type of your data, it's better to use the corresponding class:
my_prgm = casetta.data.Program()
my_backup = casetta.data.Backup()
my_picture = casetta.data.Picture()
# To know more about data classes, see the data-kind specific part bellow.
 
# Make a data inside a file (recommended)
# This method use as argument a data class to specify the kind of data
my_new_data = my_file.new_record(casetta.data.Program)
# You can also pass initialization parameters for the class (see this parameters in the data-kind specific part):
my_new_data = my_file.new_record(casetta.data.Program, ['name of my program'], {'password': 'tux', 'use_base': True})

If you initialize you data with a name, you should check the name of the data.

Iterate data inside a file

To access to all data in a file, you can use a loop like:

for data in my_file:
    print data.get_name()

If you want more specific functions, data are stored in a list, FileData.data, so you can use all list methods to find a data.

my_prgm = my_file.new_record(casetta.data.Program)
print "my_prgm is the %ith data in the file" % my_file.data.index(my_prgm)

Select data to be exported

The list of data to be exported is used when you set to True the export flag when saving or sending data. To select some data to be exported, add the index of those data in the FileData.export list (and remove it to deselect the data).

my_data = my_file.new_record(casetta.data.Program)
# Add my_data in the export list
my_file.export.append(my_file.data.index(my_data))
# Remove my_data from the export list
my_file.export.remove(my_file.data.index(my_data))

Rename a data

The name of a data is always contain in the Data.name string. But this string is in the casio raw format, so some characters may not be ASCII characters. If you want to get or set a name in an human readable format (newcat syntax), use:

print "Raw name", my_data.name
print "Human-readable name", my_data.get_name()
# Set the name from an human-readable format:
my_data.set_name("New name")

After setting a new name, you should check the name of the data.

Check the name of a data

To check the name of a data (inside a file), you can use:

my_prgm = my_file.new_record(casetta.data.Program)
my_prgm.set_name("New name")
if my_file.check_name(my_prgm) == 1:
    print "OK, good name"
elif my_file.check_name(my_prgm) == 0:
    print 'Bad syntax (ie program name with more than 8 characters, or picture name which not follow "Picture[1-6]").'
elif my_file.check_name(my_prgm) == -1:
    print "Name already used by another data."

You should check the name of each new/imported/renamed data.

Delete a data

my_file.remove(my_data)

Warning: this will clear the export list.

Find the type of data

To know the type of data, just compare its class:

if my_data.__class__ == casetta.data.Program:
    print "my_data is a program"
elif my_data.__class__ == casetta.data.Backup:
    print "my_data is a backup"
elif my_data.__class__ == casetta.data.Picture:
    print "my_data is a picture"
elif my_data.__class__ == casetta.data.ScreenCapture:
    print "my_data is a screen capture"
else:
    print "my_data is unknown"

Get the raw data

In any data type, you can access to the raw data using the Data.raw_data string. But in many data types, specific functions can convert raw data into more usable data.

# Get raw_data
raw_data = my_data.raw_data
# Set raw_data
my_data.raw_data = raw_data

Get the date property

Each data have a date property, which represent the data of the receiving of the data. It's very useful for backups. If the data is unknown (almost all file format cannot save this data), its value is None. In other case, it's a datetime.data object.

import datetime
# Get the date
if my_data.date != None:
    print my_data.date
# Set the date
my_data.date = datetime.date.today()

Program-specific properties

Initialization

When you initialize a program, you can set several informations:

my_program = casetta.data.Program(name = '', raw_data = '', date = None, password = "", use_base = False)
# or
my_program = my_file.new_record(casetta.data.Program, arg_dic = {name:'', raw_data:'', date:None, password:"", use_base:False})

Get the program

# Get the raw program
raw_prgm = my_program.raw_data
# Set the raw program
my_program.raw_data = raw_prgm
 
# Get the program in a human readable format (newcat syntax)
prgm = my_program.get_text()
# Set the program from a human readable format
my_program.set_text(prgm)

Get the password

# Get the raw password
raw_pass = my_program.password
# Set the raw password
my_program.password = raw_pass
 
# Get the password in a human readable format (newcat syntax)
password = my_program.get_password()
# Set the password in a human readable format
my_program.set_password()

The base option

This option set if the program use base operations.

# Get if the program use base:
if my_program.use_base:
    print "This program use base"
# Set use base to True:
my_program.use_base = True

Backup-specific properties

Initialization

When you initialize a backup, you can set several informations:

my_backup = casetta.data.Backup(name = '', raw_data = '', date = None)
# or
my_backup = my_file.new_record(casetta.data.Backup, arg_dic = {name:'', raw_data:'', date:None})

Get programs from the backup

If you want to extract programs from a backup, you can use a code like this:

prgm_list = my_backup.find_program_list()
# prgm_list = [ ["Name1", use_base1, "offset1", "password1"], ["Name2", use_base2, "offset2", "password2"], ...]
# use_base1 is a boolean (True if the program use base calculation, False else)
 
# Get the first program
name = prgm_list[0][0]
my_program = my_backup.get_program_by_name(name)
# my_program is a Program object

Picture or Screen capture specific properties

Initialization

When you initialize a picture or a screen capture, you can set several informations:

# Picture:
my_picture = casetta.data.Picture(name = '', raw_data = '', date = None, pallet = None, color_byte = None)
# or
my_picture = my_file.new_record(casetta.data.Picture, arg_dic = {name:'', raw_data:'', date:None, pallet:None, color_byte:None})
 
# Screen Capture:
my_screen_capture = casetta.data.ScreenCapture(name = '', raw_data = '', date = None, pallet = None, color_byte = None)
# or
my_screen_capture = my_file.new_record(casetta.data.ScreenCapture, arg_dic = {name:'', raw_data:'', date:None, pallet:None, color_byte:None})

pallet is a list like ['b', 'g', 'o', 'w'] (b for blue, g for green, o for orange, w for white). This list explain the role of each sheet of the picture, and depend of the format of the picture. color_byte specify the index of the first byte of each sheet. In most case, color_byte = 0.

Get picture data

You can get a list of pixels (each pixel is a list of RGB values) from the raw data:

# Get data:
pix_list = my_picture.get_picture()
pix_list2 = my_screen_capture.get_picture()
 
# Set data:
my_picture.set_picture(pix_list)
my_screen_capture.set_picture(pix_list2)

Change the pallet of a picture

new_pallet = ['g', 'b', 'w', 'o']
my_picture.change_pallet(new_pallet)
my_screen_capture.change_pallet(new_pallet)

Get a program to draw the picture

my_prgm = casetta.data.Program()
my_prgr.set_text(my_picture.get_program())

About data classes

Get the data classes list

Each data type is a data class from the casetta.data module. To know what are the available data in your casetta version, you can use:

for data_type in casetta.data.data_type_list:
    # Data.dType is the name of the data type
    print data_type, "is the class of", data_type.dType
 
print "Available types:", casetta.data.data_type_dic.keys()
for name in casetta.data.data_type_dic:
    print casetta.data.data_type_dic[name], "is the class of", name

Name rules

Each data type has some rules about his name (those rules are used to check the syntax of the name). Rules are in fact regular expression. Examples:

>>> casetta.data.Program.name_rule
'^.{1,8}$'
>>> casetta.data.Picture.name_rule
'^Picture[1-6]$'

About format classes

Get the list of available formats

Each file format is a class. You can get the list of formats available in casetta using:

# Print the list of formats:
print casetta.formats.format_list
# Each format has a string identifier, its name:
for format in casetta.formats.format_list:
    print format.name
 
# There is also a dictionary with names:
for format_name in casetta.formats.format_dic:
    print casetta.formats.format_dic[format_name], "is the class of", format_name

Know if the format can read or write

You can use the read and the write properties to test what a format class can do:

if a_format.read:
    print "Files in the %s format can be opened." % a_format.name
 
if a_format.write:
    print "Files in the %s format can be saved." % a_format.name

Know managed data types

Some file formats don't manage all data type, so each file format has a list of managed data types. Almost all file format manage the same data types in read and write, but this list is only the list of managed data types for writing.

# Print the list of data classes managed by a_format for writing:
print a_format.managed_data

File extensions

In almost all cases, casetta will auto-detect the format of a file using its extension. Each file format has a list of managed extensions. You can get it using:

# Print the list of extensions (strings, without the dot):
print a_format.list_ext

Use a format without FileData

Normally, you should use file formats inside methods of FileData (see before). But you can use a format alone, like this:

format = MyFormat("/path/to/the/file.ext")
 
# Open the file (will return a FileData object):
my_file_data = format.open_file()
 
# Save the file (take a list of data):
format.save(my_file_data.data)

More about format classes

A format class is a class like:

class MyFormat:
    """my format manager."""
 
    name = 'my'
    managed_data = [casetta.data.Program, casetta.data.Backup]
    read = True
    write = True
    list_ext = ['my']
    def __init__(self, filename = None):
        """Make a myformat file object with filename"""
        self.filename = filename
 
    def open_file(self):
        """Open a file in the My Format"""
        file_data = casetta.data.FileData()
        my_file = open(self.filename, 'r')
        #
        # My format file parser
        #
        return file_data
 
    def save(self, data_list):
        """Save a file in the My Format"""
        my_file = open(self.filename, 'w')
        # For each data, save it in the My Format
        for data in data_list:
            #
            # Code to write data inside the my_file object
            #
        my_file.close()

About transfer tool classes

Get the list of available transfer tools

Each transfer tool is a class. You can get the list of available transfer tools in casetta with:

for tool in casetta.devices.tool_list:
    # The name property is a string identifier
    print tool.name
 
# You can also use a dictionary of tools with names as keys:
for tool_name in casetta.devices.tool_dic:
    print tool_name, "is the name of", casetta.devices.tool_dic[tool_name]

Managed data

You can get the list of data types managed by a transfer tool. Warning: the other transfer tool managed data depend of the format used, see the other transfer tool part for more details.

for data_type in my_tool.managed_data:
    print data_type.dType, "is managed by this tool"

Initialization

Because each tool can be very different, the initialization depend of the tool. Here, we'll describe the initialization of the three casetta 0.3 transfer tool: serial, cafix and other.

serial initialization

The serial transfer tool is an internal transfer tool for Casio Graph 35/65. It work with the Fx-Interface link, and maybe with others. This tool is recommended by the casetta project. This tool need two interface functions, a status function which display the state of the transfer, and an overwrite function which ask the user to overwrite a data if needed. If you omit those functions, the status will be printed on the standard output.

To initialize this tool, use a code like this:

# Get the Serial class:
Serial = casetta.devices.tool_dic['serial']
 
# Build settings for serial:
port = 0 # port may be a integer (from 0), or the path of a serial port (example: "/dev/ttyS0" or "COM1")
 
def status_fun(data_name, current_size, total_size, is_header = False):
    """This function is called each time the status change"""
    # data_name is the name of the current transferred data
    # current_size is the number of bytes already transferred
    # total_size is the number total of bytes
    # is_header indicate if the current data is an header (in this case,
    #    the data_name variable hasn't really sense.
    pass
 
def overwrite_fun(data_name):
    """This function is called each time a data already exist. It must return True or False"""
    # Return always True: the data will always be replaced.
    return True
 
# Initialize the serial tool:
tool = Serial(port, status_fun, overwrite_fun)

cafix initialization

Cafix is the old software used for transfer in casetta 0.1 and 0.2. This tool has some bugs, didn't manage all data types, and work only on GNU/Linux systems.

The port of the serial link must be choice by making a symbolic link from your port to /dev/casio. You can use (as root) the cafix-setup program, or a command like ln -s /dev/ttyS0 /dev/casio.

You can initialize Cafix without any parameter, casetta will use default interface using the standard input/output.

# Get the Cafix class:
Cafix = casetta.devices.tool_dic['cafix']
 
# Build settings for cafix:
 
def send_interface(tmp_dir):
    """This function must send all data in tmp_dir using cafix"""
    # You must run this command:
    command = "cd " + tmp_dir + " && cafix -s *"
    # But you can run this command in several ways: in a terminal,
    # by getting the output of cafix, etc.
    # Example (using the standard output):
    import os
    os.system(command)
 
def receive_interface(tmp_dir):
    """This function must receive all data in tmp_dir using cafix"""
    # You must run this command:
    command = "cd " + tmp_dir + " && cafix -r"
    # But as for the send_interface function, you can run it as you want.
    # Example:
    import os
    os.system(command)
 
# Initialize the cafix transfer tool:
tool = Cafix(receive_interface, send_interface)

other tool initialization

The other tool is a generic wrapper for an external program. The other tool will save data in a file and run a command to send the content of this file, or open the result of a command an import all data in casetta.

You can omit receive_interface and send_interface, default functions will be used.

# Get the Other class:
Other = casetta.devices.tool_dic['other']
 
# Build settings:
format = a_format # Set the format class which will be used to save/open temporary files
port = '/dev/ttyS0' # The syntax of the port depend of the custom program.
 
receive_command = "my_prgm --receive %port %file" # Set the command which will be run to receive data
send_command = "my_prgm --send %port %file" # Set the command which will be run to send data
# In this command, you can use %port, which will be replaced by the port setting,
# and %file, which is the temporary file in the wanted format.
 
def receive_interface(cmd_line):
    """This function must run cmd_line."""
    # Here you can code how you want cmd_line be run to receive data
    # Example:
    import os
    os.system(cmd_line)
 
def send_interface(cmd_line):
    """This function must run cmd_line."""
    # Here you can code how you want cmd_line be run to send data
    # Example:
    import os
    os.system(cmd_line)
 
tool = Other(format, receive_command, send_command, port, receive_interface, send_interface)

Using transfer tool

# We assume that tool is an initialized transfer tool.
 
# How to receive data from a transfer tool:
received_data = tool.receive()
# If you want to add it to an existing FileData:
new_data_list = older_file.add_records(received_data)
#After that, you should check the name of each data in new_data_list. 
 
# How to send data to a device:
# Send all data in my_file:
my_file.send(tool)
# Send only selected-to-be-exported data:
my_file.send(tool, export=True)
 

Powered by PHP Valid XHTML 1.0 strict Valid CSS Driven by DokuWiki

The content of this website is, without another mention, under the GNU Free Documentation License.