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).
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"
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.
To create a empty file, just use:
my_file = casetta.data.FileData()
You will get a “FileData” object.
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)
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.
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)
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)
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.
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.
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)
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))
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.
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.
my_file.remove(my_data)
Warning: this will clear the export list.
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"
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
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()
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 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 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()
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
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})
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
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.
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)
new_pallet = ['g', 'b', 'w', 'o'] my_picture.change_pallet(new_pallet) my_screen_capture.change_pallet(new_pallet)
my_prgm = casetta.data.Program() my_prgr.set_text(my_picture.get_program())
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
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]$'
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
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
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
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
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)
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()
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]
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"
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.
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 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)
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)
# 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)