Symbian developer community

 
wiki

PyS60 Standalone Applications (Python on Symbian)

From Symbian Developer Community

Jump to: navigation, search
Original Author: Hamish Willee, Pankaj, Marcelo Barros

Standalone applications are delivered in easy to install SIS files that usually bundle everything needed to run the application so that the user doesn't have to do anything else to get started. Once installed, a standalone application can be launched by selecting its icon on the phone's user interface. Overall, this approach makes your python scripts much more accessible to normal phone users.

This chapter explains how standalone applications work and how you create them using the simple and intuitive "PyS60 Application Packager" tool. As part of that discussion we'll cover application signing (and platform security) which is essential distributing your application. Lastly, we'll look at what you can do to protect your application from being pirated and how to add multilingual support.

Contents

Application Packager

The PyS60 Application Packager makes it very easy to create standalone applications from your Python scripts; it creates the SIS files for you, adding everything needed to allow your script to be launched from the phone user interface.

The Packager is delivered as part of the Python Windows Installation package (i.e. PythonForS60_1.9.6_Setup.exe) or in the Mac/Linux archive. As the packager is itself a Python application, you will first need to install Python 2.5.x (or later) on your computer (from http://www.python.org/download/releases/2.5.4/). Once Python is installed, you can launch the Packager from the Windows Start button: Start | PythonForS60 1.9.6 | PyS60 Application Packager, or by selecting it in the file system: \PythonForS60\ensymble_gui.py.

Tip
The Application Packager can be also be used on Linux or Mac, but you'll have to execute ensymble_gui.py directly as there is no start bar shortcut. Ensymble has been tested on the following systems (from the release notes):
  • Debian GNU/Linux Sid (i386) with Python v2.3.5, v2.4.5 and v2.5.2
  • Red Hat Linux release 9 (i386) with Python v2.2.2
  • Red Hat Enterprise Linux AS release 3 (i386) with Python v2.2.3
  • Red Hat Enterprise Linux AS release 4 (i386) with Python v2.3.4
  • Apple OS X Tiger (G4) with Python v2.3.5
  • Apple OS X Leopard (i386) with Python v2.5
  • Microsoft Windows XP, SP2 with Python v2.5

The Application Packager opens in a minimal view, as shown in Figure 3. You can specify either a single script or a folder that you want to package as an application, and whether you want the packager to continue if it can't find a dependency of your script(s). If you're specifying a folder you will need to ensure that it contains a script default.py which can be used to start your application.

Figure 3: The Application Packager

Press Create to create the SIS file. The packager will then give you the option to install the application or to open the folder in which it is located.

The tool creates the SIS (\Script/Folder location\ScriptFileOrFolderName_v1_0_0.sis) using suitable default values for a standalone application intended for testing on your own phone.

You will probably want to change some the settings if your application is to be distributed in order to:

  • Give the application its icon instead of the python logo
  • Use a certificate that asserts you wrote the code.

You will need to modify some settings if your application uses protected APIs that cannot be granted by the user or if you want to be Symbian Signed.

Access to edit the settings can be edited by pressing the More button as shown in Figure 4. Some of the settings are specified as "commands" entered in the field Additional Options

Figure 4: The application packager window (expanded)

We discuss the fields in the following section (#Packager Options & Default Values), highlighting those that you're likely to want to change and the default values. You can get more information on each of the fields by pressing the Help button, and for the commands by pressing the Options button.

We discuss the fields that you need to change in order to Symbian Sign your application in the section #Platform Security & Symbian Signed

Packager Options & Default Values

The Application Packager fields are listed below, along with their default values. The fields that you are most likely to want to edit are marked in bold text.

Table1: Packager GUI Options
Field Description
Application title Name used to described the application during installation and for the application caption (if a caption has not been specified).

Default value: The script file name (without the .py extension) or folder name.

Version Application major version, minor version, build number separated by a period or comma. You may find it convenient to specify the version number (anywhere) in your script using the SIS_VERSION keyword (e.g. SIS_VERSION = "1.0.0").

Default value: 1.0.0

UID Every application has a unique UID. If you want to commercially distribute your application you will need to specify a UID in the protected range from symbiansigned.com. The UID can be specified anywhere in your script with the SYMBIAN_UID keyword (e.g. SYMBIAN_UID = UID).

Default value: A UID in the development range based on a cryptographic hash of the script file name (suitable for development and using Open Signed Online).

Certificate, Private Key, Pass Phrase Certificates are used to digitally sign the application. You will probably want to specify your own certificate (with associated key and pass phrase) in order to assert that you are the vendor. If you are going to Symbian Sign the application (which you will need to do to if you want to remove the installer warning message that your application is untrusted, or if you want additional capabilities) then you will need to sign the application using your company Publisher ID for submission.

Default value: A default certificate is used to self-sign the SIS file; even if you are not going to distribute your application commercially you will

Additional Options Other parameters, for example the icon and additional capabilities, can be specified. These are discussed below.
Profile You can specify whether your application is a GUI or console application. Console applications print text to their own console (in the same way that scripts run in the PyS60 script shell print to its console).

Default value: GUI application.

Heap Size The minimum heap to reserve for your application, and the most that the heap can be allowed to grow to.

Default value: The default settings should be suitable for most applications; however this can be changed if you have scripts or extensions that use significant memory.

Package As (Byte or Source code) Whether or not your scripts are compiled to byte code (Python compiled scripts - PYC) before packaging. Byte code will run somewhat faster and additionally provide some anti-piracy protection for your script. Please remember that your SIS file must always contain a default.py file. You cannot package that as default.pyc.

Default value: Scripts are converted to byte code.

1.4.x compatibility mode If you're using the older Python runtime (1.4.5) specify this setting to ensure that the correct modules are bundled with your SIS file.

Default value: Not 1.4.x compatibility mode.


The Additional Options field allows you to specify additional configuration settings (these are passed through to the underlying command line tool Ensymble). You can get a brief overview of what the options do by pressing the Options button. If you need more information the Ensymble release notes contain very detailed explanations of what each command does - these are are included in the root of your PyS60 installation: PythonForS60\README.

We just cover the few you are most likely to need below:

Table2: Packager Additional Options
Command Description
icon The icon used for your application in the phone UI, in SVG-Tiny format[1]. Note that you must include the full path, and it can't have any spaces.

Default value: The Python logo

textfile A text file (or files) to be displayed during installation. There is a special format for specifying a set of language-specific text files (discussed in the multilingual section below).
vendor Your company name. The use of vendor name in a mulitlingual application is discussed below. This is mandatory for signed applications.

Default value: "Ensymble".

caps Capabilities required by your application. The packager automatically gives your application those capabilities that can be granted by the user (see default value below). If you need other capabilities then you can specify this keyword followed by all needed capabilities, separated by "+" (e.g. caps +ReadUserData+WriteUserData)

Default value: LocalServices, NetworkServices, ReadUserData, WriteUserData and UserEnvironment

extrasdir If your application needs to make some files available in a public area of the phone filesystem - for example an icon editor application might install some demonstration icons, you can specify these in a location under drive root.

Default value: Not used.

autostart Application is registered to start on each device boot
runinstall Application is automatically started after installation
drive Drive where the package will be installed. There is usually no reason to change this.

Default value: Applications can be installed to any drive

The keywords lang, shortcaption, and caption (and a little more about vendor and textfile) are discussed in the section #Multilingual Applications

What Can't You do with the Application Packager?

The Application Packager (and Ensymble) use sensible default options for application and packager settings, providing the ability to override values where necessary. However a few settings are non-configurable, and there are some installation and application configuration options that are simply not available.

This section outlines settings that are currently only possible through the C++ development toolchain or through the Ensymble command line.


Note
The Application Packager and Ensymble are still under development; you should check the current release notes at time of use to confirm what functionality is available


Application configuration

Application settings are configured through the application registration file. A version of this file is created by the Application Packager to define the application icon and caption.

Additional settings which might be useful for some developers include:

  • Run your application in the background (using the hidden attribute)
  • Start application in the background (using the launch attribute)
  • Register application as default handler for files with a particular MIME type.

The possible settings are documented in the Application Reference.

SIS Configuration

The following installer options are not available through the Application Packager:

  • Conditional installation behaviour based on the device, platform, files on the device, properties of other installed software, or properties of the device.
  • Displaying text on application removal
  • Displaying a logo during installation (Note that this installer option does not work on current devices).
  • Upgrades and patches to existing installation files
  • Platform and product dependencies. Applications are automatically set as compatible with all S60 3rd Edition and later devices; however there is no mechanism provided to modify these settings for finer grained control.
  • Component dependencies. It is not possible to package binaries in a dependent SIS and specify your installation should fail if this is not present on the device. Note that the most important dependency - on the PyS60 Runtime - is automatically specified on your behalf.

Include other SIS files

The Application Packager cannot directly include other SIS files.

However you can merge SIS files through the Ensymble command line tool using the mergesis option. The Ensymble release notes (\your PyS60 root\README) provides detailed information on usage and limitations of this mechanism.

Automation & Batching

The application packager does not store values you enter between sessions. You reduce the amount of information you need to renter by using a script name that you are happy to also use for your "application name", and by storing your version and UID (if default one is not acceptable) in the script using the SIS_VERSION and SYMBIAN_UID keywords. However if you want the application to have its own icon, certificate, more powerful capabilities, or use any of the other features of the packager, these would need to be manually entered.

For very complicated configurations, you may find it easier to use Ensymble directly. You can then save the command line, and even run it from a batch file if necessary.

How does the Application Packager Work?

A standalone PyS60 application consists of (non exhaustive list):

  • Icon
  • Registration file containing application settings including captions, links to its icon(s), etc
  • Python script files, including at least default.py
  • Other files and resources
  • a stub executable file (exe)

The application registration file contains th information about what caption and icon to display, and what executable to launch to start the application. When the icon/caption is selected the application launcher runs the stub EXE in a new process. The EXE loads the python runtime, which in turn loads and interprets the Python script default.py.

The properties of this new process are defined in the exe's header file, and include: UID, capabilities, secure ID, the amount of heap to reserve for the process and the maximum it can grow etc.


Note
Symbian C++ developers will recognise that the standalone PyS60 application uses the same files as native applications; the difference being that for PyS60 the EXE is just a mechanism for loading the runtime and python script.


The Application packager writes the header information to the stub EXE, creates an icon file from the SVG-tiny file supplied (in the platform specific format), then writes an application registration file specifying the captions, icons and any other information needed. If a single script file was was specified then it also renames that file default.py', the name of the file to be launched by the stub exe.

The packager then bundles all the files in a SIS and signs it using either the default certificate (self signed) or another certificate supplied by the user.

Delivering the Python Runtime with your Application

Python applications are dependent on the Python runtime, which can be delivered (in its own SIS file) either as part of your application SIS file or separately.

We recommend you include the runtime SIS as part of your installation file as this will give your users the best possible installation experience. Bundling the runtime SIS file will increase the size of your installation files by about 3Mb (about the size of a typical song in mp3 format). However if you do not include the runtime (and it is not already on their mobile device), then potential users may choose to abandon the installation rather than take the time needed to locate the runtime.


Note
The runtime is only installed if it isn't already present; even though the installation file is bigger, your application won't necessarily use up this amount of phone memory.


Unfortunately the Application Packager does not automatically include the Python runtime; instead it defines an install-time dependency so that the installation will fail if the PyS60 runtime is not already present on the device.

Merging SIS files is supported through the underlying Ensymble command line tool using the mergesis option. The base file into which other SIS files are merged loses any existing certificate (the embedded files keep their certificates). The Ensymble release notes (\your PyS60 root\README) provides detailed information on usage.

Warning
Ensymble can't merge SIS files that themselves embed other SIS files. For the mechanism described above to work the Python runtime, PIPS, and the PIPS RPipe Support need to be in separate SIS files. Since at time of writing the Runtime SIS includes all the dependency files, you will not be able to use this mechanism - you may instead need to use the C++ packaging toolchain, including makesis and signsis.

Platform Security & Symbian Signed

This section provides a brief overview of Platform Security and Application Signing (Symbian Signed), with specific reference to how they affect Python applications. Note that Platform security is pervasive; even though we've chosen to document the effects here in the chapter on Python standalone applications, the discussion also applies to console applications and indeed to Native C++ applications. There is a lot more information on this topic on http://developer.symbian.org and http://www.symbiansigned.com.

What is Platform Security

Platform security is the system-wide mechanism used to control access to sensitive functions, and areas of the file system. There are two main concepts - "The capability model" and "data caging".

Capabilities

The capability model enables access to sensitive functions through the use of access tokens, called capabilities. In order to call a sensitive function an application must first declare that it wants to use the capability that protects the API, and then the SIS must be granted the capabilities declared in all the executables it contains. The user can grant some capabilities at install time - just those capabilities for which the risks are obvious. If an application uses more sensitive capabilities, then approval can only be granted by a signing authority (Symbian Signed) applying a trusted certificate to the SIS file.

If the application has not been granted approval for its declared capabilities then it cannot be installed. If an application tries to use an API protected by a capability that it has not declared, then it will be crashed by the operating system and the user will see a system error with number (-46).

Table 5 below lists all the capabilities (sorted by "group") with their descriptions. The Manufacturer capabilities are shown in grey to indicate that they are unavailable to PyS60 applications. The Signing Options required to access each capability are also listed; these are discussed further in #What is Application Signing?.

Table 5: Capabilities vs Signing Options

Capability Group Capability Name Description Self-Signed Open Signed Online Open Signed Offline Express Signed Certified Signed
User Capabilities LocalServicesAccess to local services, such as bluetooth, USB, or infrared connections. Yes (with user install-time confirmation) Yes Yes Yes Yes
LocationAccess to the phone's current location via the Location API.
NetworkServicesAccess to remote services (e.g. dialing a number, SMS, WLAN, GPRS). Services may incur a cost for the mobile device user.
ReadUserDataAccess to read confidential user data (e.g contact information)
WriteUserDataAccess to write confidential user data (e.g contact information)
UserEnvironmentAccess to services that provide data from users' physical surroundings (e.g. record audio, camera)
System Capabilities PowerMgmtGrants the right to kill any process in the system or to switch machine state (turn the phone off). No Yes Yes Yes Yes
ProtServGrants the right to a server to register with a protected name (starting with an “!”). Protected servers cannot be impersonated.
ReadDeviceDataRead confidential network and phone data/settings (e.g. Cell IDs, mobile phone IMEI, and device settings like the list of installed applications.)
WriteDeviceDataWrite sensitive settings that control the behavior of the mobile device.
SurroundingsDDAccess to logical device drivers that provide input information about the surroundings of the phone.
SwEventGet Software Events (e.g. read keypresses, send messages to other applications etc.)
TrustedUIGrants the right to display dialogs in a secure UI environment
Restricted Capabilities CommDDAccess to all communications equipment device drivers (e.g. WiFi, USB and serial device drivers etc). No No Yes No Yes
DiskAdminAccess to file system administration operations that affect overall file-system integrity (e.g. mounting and unmounting a drive partition.)
NetworkControlThe ability to modify or access network protocol controls (e.g. change the behaviour of all existing and future connections)
MultimediaDDAccess to multimedia device drivers and priority access to multimedia APIs (e.g. sound, camera, video, etc.)
Device Manufacturer Capabilities AllFilesGrants visibility and write access to all files in the system No No No No See Symbian Signed
DRMGrants access to alter DRM-protected content (not required for playback)
TCBWrite access to executables and shared read-only resources. This is the most critical capability as it allows write access to executables, which contain the capabilities that define the security attributes of a process.

Data Caging

Data Caging is a mechanism for controlling access to areas of the file system. Some areas are marked as read only, and others are completely opaque. Processes that have been granted the AllFiles capability have full access to all areas.

Every application gets its own private directory in the file system (\private\application-specific-UID\) based on its UID (actually its SECURE ID, but for Python Applications, these are treated the same). The application can read and write to this area as though it were public; it is opaque to other code.

Python scripts are installed to their private directory; If a script folder is specified to the Application Packager, then the whole folder structure is installed as a sub-folder.

What is Application Signing?

Platform security allow us to ensure that only trusted applications can access sensitive functions and areas of the file system. Application Signing programs help us decide which applications deserve that trust (and with what capabilities).

When the signing program is satisfied that an application meets certain criteria it signs the installation file with a tamper-proof certificate that indicates the level of trust. The application installer then grants access to the phone based on the level of trust.

Table 6 describes each of the signing options. Note that Table 5 shows the mapping between the capabilities that are available and the signing options below.

Table 6: Signing Options
Self-Signed

Free
  • SIS file installs on any phone (with "application untrusted" warnings). The user is asked whether or not they want to install the application based on the capabilities used.
  • Grants access to the 5 "User Grantable" capabilities.
  • Application is signed with a certificate created by the developer.
  • User identity unknown (no basis for trust).
Open Signed Online

Free
  • SIS file installs on a single phone (with "application untrusted" warnings). The phone user must sign the SIS prior to installation.
  • Grants 13 capabilities.
  • Application is signed on the Symbian Signed website
  • Signer identity unknown (no basis for trust).
  • Risk is low (application is locked to single phone, so reduced chance for malicious software to spread)
Open Signed Offline

Not free
  • SIS file installs on (large) specified set of phones (with "application untrusted" warnings).
  • Signer identity known (basis for trust)
  • Risk is low (application locked to set of IMEIs)
  • The certificate grants 17 capabilities.
  • Developer Certificate used for signing is free, but in order to get this you must first purchase a publisher ID.
Express Signed

Not free
  • SIS file installs any phone without warnings.
  • The certificate grants 13 capabilities.
  • Application is signed on the Symbian Signed website
  • Signer identity known (basis for trust)
  • Risk is low (application is regularly audited and certificate may be revoked if necessary)
  • Developer must pay for publisher ID and signing
Certified Signed

Not free
  • SIS file installs any phone without warnings.
  • Application is signed on the Symbian Signed website
  • Signer identity known (basis for trust)
  • Risk is low (application is tested and certificate may be revoked if necessary)
  • The certificate grants 17 capabilities (also basis for getting the Manufacturer capabilities, but these are not available for PyS60 applications)
  • Developer must pay for publisher ID, testing and signing

What Capabilities Should I Give My Applications

As a general rule you should give your applications the minimal set of capabilities you need to call the relevant functionality. Determining which capabilities you need is fairly easy because:

  • Only 17 capabilities are available to Python (the manufacturer capabilities are not available)
  • Capabilities control access to broad scope of functionality. It is usually easy to guess which you need based on what your application does.
  • None of the capabilities are required to call standard Python functions.
  • There is only limited access to native functionality; the modules (listed below) clearly document what capabilities are needed. Note that any file operation that attempts to access a protected area of the file system (e.g. another processes private directory) will only succeed if the process has the AllFiles capability.
Table 3: Capabilities needed in order to use specific modules
Description Function or Module Required Capabilities
Global Key Capture KeyCapture Module SwEvent
Reading the GSM Location Location Module(location.gsm_location()) Location, ReadDeviceData
Reading the internal GPS Location Positioning Module Location

While it may seem to be easiest just to request all capabilities, you may then find that your distribution options are more limited, or your signing options more expensive. For example, you can self-sign an application and freely distribute it if you only need the user grantable capabilities. If you specify the system capabilities then you will need to use Open Signed Online to get the necessary approval - this will force your users go through an extra step to sign the application (which will possibly put them off continuing!).

Note that the discussion also applies to the PyS60 script shell. The default SIS installer has been self signed with only user grantable capabilities. If your scripts needs higher capabilities then you'll have to sign the High capability version (perhaps with open signed online).

What Capabilities Should I give My Python Native Extensions?

Python Native extensions provide a python layer over native code. The native C++ layer is written as a DLL which is loaded into the Python runtime (which is itself loaded into the standalone stub exe process, or the PyS60 shell script exe).

In the previous discussion on capabilities, we've been talking using the term application synonymously with "process" or exe. For a process you need all the capabilities of all the functions you plan to call. For a DLL its different; A DLL can only be loaded into a process for which it has the same subset of capabilities or more. That means you should grant your extension all the capability that you can, in order that it can be loaded into as many processes as possible.

Signing PyS60 Applications

PyS60 applications can be signed using the same mechanisms and test criteria as any native application. The only issue is that if you want to Express or Certify Sign your application then you need to supply a .PKG file in your submission .zip file; and unfortunately the Application Packager doesn't use or create one.

The workaround is to use the dumpsis command line tool from the Symbian platform C++ SDK (\Epoc32\tools\dumpsis.exe):

dumpsis filename.sis

The above command extracts the files from the sis into a subdirectory with the same name as the original SIS file name. You can use the package file generated in your Symbian Signed submission.

In addition, PyS60, and indeed any application can be submitted as "Passive" content if it doesn't have any capabilities. This means that you can avoid the requirement to test your applications if you don't call any protected APIs. Note that the Application packager requests the "user grantable" capabilities by default, so you'll need to use the Additional Options command cap to remove these.

Multilingual Applications

Making your application multi-lingual can expand its potential user base significantly.

The Application Packager allows you to specify translations for all strings and files that appear on the phone user interface, including application captions, vendor names and text files displayed during installation. The phone will display the appropriate text and files for the current phone language at install time. It will also display the application caption in the current phone language (and change it if the phone language changes). The platform is smart enough to use sensible fall-back languages; for example if you supply your files in Spanish, then these will be used even if the platform language is Latin American Spanish.


Note
The Application Packager does not provide access to Symbian platform features like locale-specific application icons, and conditional installation of files based on the current locale. You don't need them!


PyS60 itself does not provide explicit support for localising your scripts, and there is (at time of writing) no extension to get the current locale from the phone. It is however good practice to separate your translations from the rest of your code; we outline a simple method in the following section to show you how to keep translation files as separate Python modules, and load them based on a filename convention.

Application Packaging

The Packager allows you to define the languages your installation will support, and the translated strings for the application's caption, short caption and the vendor name. You don't have to specify the caption, short caption and vendor name translations, but if you do, then you need to specify them as comma separated values in the same order as your initial language list.

Tip
The Application Packager creates default localisation values based on your language language codes. Unlike users of the C++ developer toolchain, you won't be stuck for hours ensuring that you've got the right number of strings for the all the values

The translations are specified as Additional Options using the following commands:

Command Description
lang Comma separated list of two-character language codes. A few common codes are: English UK (EN), French (FR), German (GE), Spanish (SP), Italian (IT), Japanese (JA), Chinese PRC (ZH). The full list can be found in the Application Reference

Example: to specify that the package support English, French and German you would add the following additional option:

--lang=EN,FR,GE
caption Caption, or a comma separated list of (long) captions in all the supported languages. Note that the order is the same specified in the lang command:
--caption="English Caption","French Caption","German Caption"
shortcaption Short caption, or a comma separated list of short captions in all the supported languages. Short captions are used in views where there isn't sufficient space to use the normal caption. Note the declaration order is the same as specified in the lang command:
--shortcaption="EngCapt","FncCapt","GmCpt"
vendor Vendor name or a comma separated list of all supported vendor names. Note the declaration order is the same as specified in the lang command:
--vendor="BigCorp","French Big Corp","German Big Corp"

The Application Packager also allows you to specify a text file (in UTF8 Encoding) that is to be displayed during installation. You can create a file containing different translation for each supported language and the application will bundle these in the SIS file.

The format is something like:

--textfile=mytext_%C.txt

In our example above, this tells the packager to bundle files with names mytext_EN.txt, mytext_FR.txt and mytext_GE.txt. You can also specify different patterns, e.g.:

%%           - literal %
%n           - language number (01 - 99)
%c           - two-character language code in lowercase letters
%C           - two-character language code in capital letters
%l           - language name in English, using only lowercase letters
%l           - language name in English, using mixed case letters

The language number is a number assigned to each language, that can be used instead of the code. The numbers are also documented in the Application Reference

Localising Python Scripts

Since PyS60 itself does not provide explicit support for localising your scripts, we will present a strategy for supporting multiple languages in a PyS60 [2]. Using this strategy it is possible to define the default language and additional translations may be added whenever needed. Moreover, missing translations are replaced by the default translation, allowing incremental translations without breaking the code.

The strategy is composed of a main script file (wm_locale.py) used for dynamic loading of the desired language, and for localisation files that contain the translations. The localisation files are also Python files and they are imported as modules. Using Python introspection, the translation may be loaded and missing translations are replaced by the default language. The main script is below.

wm_locale.py

 
# -*- coding: utf-8 -*-
 
__all__ = [ "Locale" ]
 
class Loc_Data(object):
"Translation data holder"
pass
 
class Default(object):
"Default language support"
def __init__(self):
self.loc = Loc_Data()
self.loc.zero = u'Zero'
self.loc.one = u'One'
self.loc.two = u'Two'
self.loc.three = u'Three'
self.loc.four = u'Four'
self.loc.five = u'Five'
self.loc.six = u'Six'
self.loc.seven = u'Seven'
self.loc.eight = u'Eight'
self.loc.nine = u'Nine'
self.loc.change_language = u'Change Language'
self.loc.english_us = u'English (USA)'
self.loc.finnish = u'Finnish'
self.loc.hungarian = u'Hungarian'
self.loc.portuguese_br = u'Portuguese (Brazil)'
self.loc.about = u'About'
self.loc.exit = u'Exit'
 
class Locale(Default):
"Multiple language support class"
 
LOC_MODULE = "wm_locale_%s"
 
def __init__(self,lang = ""):
"Load all locale strings for one specific language or default if empty"
self.set_locale(lang)
 
def set_locale(self,lang = ""):
"Load all locale strings for one specific language or default if empty"
Default.__init__(self)
 
try:
lang_mod = __import__( self.LOC_MODULE % ( lang ) )
except ImportError:
pass
else:
self.merge_locale(lang_mod)
 
def merge_locale(self, lang_mod):
"Merge new location string into default locale"
 
# replace existing strings and keep old ones
# if it is missing in the locale module
for k,v in self.loc.__dict__.iteritems():
if hasattr(lang_mod,k):
nv = lang_mod.__getattribute__(k)
self.loc.__setattr__(k,nv)
 

All default translations are defined in class Default() using the attribute self.loc. Each string in your program should be represented by a different attribute in self.loc. Localisation modules are loaded dynamically and the files are named according to certain conventions. This is represented by the following expression:

 
LOC_MODULE = "wm_locale_%s"
 

So, if you have a pt_BR translation, create a file called wm_locale_pt_BR.py. Inside this module, translate all strings in class Default(), removing any class or self.loc references. For instance, the pt_BR translation would be:

wm_locale_pt_BR.py

 
# -*- coding: utf-8 -*-
zero = u'Zero'
one = u'Um'
two = u'Dois'
three = u'Três'
four = u'Quatro'
five = u'Cinco'
six = u'Seis'
seven = u'Sete'
eight = u'Oito'
nine = u'Nove'
change_language = u'Mudar idioma'
english_us = u'Inglês (EUA)'
finnish = u'Finlandês'
hungarian = u'Húngaro'
portuguese_br = u'Português (Brasil)'
about = u'Sobre'
exit = u'Sair'
 

The next code snippet demonstrates how the locale class can be used.

wm_locale_demo.py

 
# -*- coding: utf-8 -*-
import sys
sys.path.append(r'e:\python')
 
import appuifw
import e32
import wm_locale
 
class Locale_Demo(object):
def __init__(self):
appuifw.app.exit_key_handler = self.close
appuifw.app.title = u"Locale Demo"
self.update_locale()
self.app_lock = e32.Ao_lock()
 
def close(self):
self.app_lock.signal()
 
def about(self):
appuifw.note( u"Locale Demo", "info" )
 
def update_locale(self,lang=""):
self.labels = wm_locale.Locale(lang)
self.refresh()
 
def refresh(self):
entries = [
self.labels.loc.zero,
self.labels.loc.one,
self.labels.loc.two,
self.labels.loc.three,
self.labels.loc.four,
self.labels.loc.five,
self.labels.loc.six,
self.labels.loc.seven,
self.labels.loc.eight,
self.labels.loc.nine
]
 
self.body = appuifw.Listbox(entries)
 
self.menu = [
(self.labels.loc.change_language, (
(self.labels.loc.english_us, lambda: self.update_locale("en_US")),
(self.labels.loc.finnish, lambda: self.update_locale("fi")),
(self.labels.loc.hungarian, lambda: self.update_locale("hu")),
(self.labels.loc.portuguese_br, lambda: self.update_locale("pt_BR"))
)
),
(self.labels.loc.about, self.about),
(self.labels.loc.exit, self.close)
]
 
appuifw.app.menu = self.menu
appuifw.app.body = self.body
 
def run(self):
self.app_lock.wait()
appuifw.app.menu = []
appuifw.app.body = None
appuifw.app.set_exit()
 
if __name__ == "__main__":
 
ld = Locale_Demo()
ld.run()
 

If you have more translation files, just add them to your project. Translations below were copied from [2] and you can see that there are missing translations.

wm_locale_en_US.py

 
zero = u'Zero'
one = u'One'
two = u'Two'
three = u'Three'
four = u'Four'
five = u'Five'
six = u'Six'
seven = u'Seven'
eight = u'Eight'
nine = u'Nine'
change_language = u'Change Language'
english_us = u'English (USA)'
finnish = u'Finnish'
hungarian = u'Hungarian'
portuguese_br = u'Portuguese (Brazil)'
about = u'About'
exit = u'Exit'
 

wm_locale_fi.py

 
zero = u'nolla'
one = u'yksi'
two = u'kaksi'
three = u'kolme'
four = u'neljä'
five = u'viisi'
six = u'kuusi'
seven = u'seitsemän'
eight = u'kahdeksan'
nine = u'yhdeksän'
change_language = u'Vaihda kieli'
english_us = u'englanti'
finnish = u'suomi'
hungarian = u'unkari'
about = u'Tietoja'
exit = u'Poistu'
 

wm_locale_hu.py

 
zero = u'nulla'
one = u'egy'
two = u'kett\u0151'
three = u'három'
four = u'négy'
five = u'öt'
six = u'hat'
seven = u'hét'
eight = u'nyolc'
nine = u'kilenc'
change_language = u'Nyelv változtatás'
english_us = u'angol'
finnish = u'finn'
hungarian = u'magyar'
about = u'Információ'
exit = u'Kijárat'
 

Some screenshots:

Image:MBA_locale_demo01.jpg Image:MBA_locale_demo02.jpg

Commercial applications

Commercial applications can be developed in PyS60, as using other development technologies. The only drawback which holds back the high scale commercial development of PyS60 applications is that the PyS60 runtime is not pre-embedded into S60/Symbian devices. The end-users need to download and install the PyS60 runtime by themselves, to enable themselves using PyS60 applications. However, with PyS60 2.0, the runtime is available through Software update application on Nokia devices.

For a commercial application, a registration algorithm is required to be implemented in the application, so that end-users can buy the license for the application. A valid registration code can be used to unlock the application for use or activate the application from trial mode to full version. The registration code can be verified at runtime on the device, or on the server side using SMS or by using a GPRS/Data connection.

Registration code

In this section we shall understand a simple and minimalistic approach of implementing a registration code algorithm using a dummy application. The following code snippet has the registration code algorithm implemented.

 
import appuifw
import e32
import os
import sysinfo
 
pathtoapp=os.path.dirname(appuifw.app.full_name())
 
is_registered=0
 
timer = e32.Ao_timer()
app_lock = e32.Ao_lock()
 
phone_imei=sysinfo.imei()
reg_code = phone_imei[2]+phone_imei[0]+phone_imei[0]+phone_imei[8]
 
 
def write_settings():
# Write registration flag
global is_registered
REG_DIR='C:\\system\\data\\registration'
CONFIG_FILE=os.path.join(REG_DIR,'confg.set')
if not os.path.isdir(REG_DIR):
os.makedirs(REG_DIR)
REG_FILE=os.path.join(REG_DIR,'confg.set')
config={}
config['is_registered']= is_registered
f=open(REG_FILE,'wt')
f.write(repr(config))
f.close()
 
def read_settings():
# Read registration flag
global is_registered
REG_FILE='C:\\system\\data\\registration\\confg.set'
print "read settings 2"
try:
print "read settings 3"
f=open(REG_FILE,'rt')
try:
content = f.read()
config=eval(content)
f.close()
is_registered=config.get('is_registered','')
except:
appuifw.note(u"Cannot read settings file", "error")
except:
print "read settings 4"
appuifw.note(u"Creating settings file", "info")
 
def exit_key_handler():
write_settings()
appuifw.app.set_exit()
 
 
def quit():
write_settings()
appuifw.app.set_exit()
 
L_Unregistered = [u"Register",u"About", u"Exit"]
 
L_Registered = [u"About", u"Exit"]
 
def start_application():
# On start check if the application is registered or not and accordingly give menu pop-up
options
global is_registered
if is_registered == 0:
appuifw.app.title = u"Not Registered"
index = appuifw.popup_menu(L_Unregistered)
if index == 0:
register_application()
elif index == 1:
about()
elif index == 2:
quit()
else:
pass
elif is_registered == 1:
appuifw.app.title = u"Registered"
index = appuifw.popup_menu(L_Registered)
if index == 0:
about()
elif index == 1:
quit()
else:
pass
else:
pass
 
def about():
# About the application
appuifw.note(u"Registration Example\nPython on Symbian", "info")
start_application()
 
def promt_user():
# Prompt user for registration code
global is_registered
if is_registered == 0:
appuifw.note(u"Application not registered!", "info")
 
def register_application():
# Ask and check for registration
global is_registered
if is_registered == 0:
appuifw.note(u"Please enter the registration code", "info")
regtry = appuifw.query(u"Enter Registration code", "text")
if regtry == reg_code:
is_registered = 1 # Successfully registered!
appuifw.note(u"Thanks for registering!","info")
else:
appuifw.note(u"Invalid Registration Code!","error") # Registration failed!
else:
appuifw.note(u"Registered Application!","info")
 
start_application()
 
 
 
appuifw.app.exit_key_handler = exit_key_handler
appuifw.app.screen='normal'
 
read_settings() # Check if registered or not
promt_user() # Prompt user if not registered
start_application() # Show application to user, accordingly
 

Lets go through the above code in pieces. As observed, we call the 3 functions - read_settings, prompt_user and start_application in the mentioned order.

The machine registration code is generated at the start of the application, from the IMEI of the device by the following code.

phone_imei=sysinfo.imei()
reg_code = phone_imei[2]+phone_imei[0]+phone_imei[0]+phone_imei[8]

read_settings checks whether the application is registered or not. This is done by checking the registration flag from the configuration file. The registration flag is stored in is_registered variable and used in the forthcoming functions.

 
def read_settings():
# Read registration flag
global is_registered
REG_FILE='C:\\system\\data\\registration\\confg.set'
try:
f=open(REG_FILE,'rt')
try:
content = f.read()
config=eval(content)
f.close()
is_registered=config.get('is_registered','')
except:
appuifw.note(u"Cannot read settings file", "error")
except:
appuifw.note(u"Creating settings file", "info")
 

prompt_user function displays a note to the user if the application is not registered.

 
def promt_user():
# Prompt user for registration code
global is_registered
if is_registered == 0:
appuifw.note(u"Application not registered!", "info")
 

start_application checks the registration flag (is_registered) read from the file in read_settings function. If the application is found to be registered the application is activated with the application softkey menus. On the other hand, if the application is not registered, the softkey menu shows the registration option and the other options are not shown.

 
def start_application():
# On start check if the application is registered or not and accordingly give menu pop-up
options
global is_registered
if is_registered == 0:
appuifw.app.title = u"Not Registered"
index = appuifw.popup_menu(L_Unregistered)
if index == 0:
register_application()
elif index == 1:
about()
elif index == 2:
quit()
else:
pass
elif is_registered == 1:
appuifw.app.title = u"Registered"
index = appuifw.popup_menu(L_Registered)
if index == 0:
about()
elif index == 1:
quit()
else:
pass
else:
pass
 

If the user selects the "register" option he is asked to enter the registration code. If the registration code is successful, the "Thanks for registration" note is shown, the registration flag (is_registered) flag is stored in the configuration file and the application is activated. If a wrong registration code is provided, the application is not activated and the user is not able to use the application unless he/she registers.

 
def register_application():
# Ask and check for registration
global is_registered
if is_registered == 0:
appuifw.note(u"Please enter the registration code", "info")
regtry = appuifw.query(u"Enter Registration code", "text")
if regtry == reg_code:
is_registered = 1 # Successfully registered!
appuifw.note(u"Thanks for registering!","info")
else:
appuifw.note(u"Invalid Registration Code!","error") # Registration failed!
else:
appuifw.note(u"Registered Application!","info")
 
start_application()
 

In the above sample application, we used the IMEI of the device to generate the machine registration code for comparing with the user input registration code. However, this means that an IMEI is required at the time of purchase of the application license and the provided registration code has to be generated at the time of purchase. Alternatively, validation of the application license (registration code) can be done using on a server using SMS or GPRS/Data connection and there are many ways of doing it. Infact, the registration by SMS or GPRS/Data connection is necessary to use device (IMEI) independent registration code algorithms and prevent a same registration code to be used on multiple devices.

So can you figure out how could register a PyS60 application using SMS/GPRS? Well, its left as a exercise for readers.

Further Information

  1. InkScape (www.inkscape.org) is an excellent open source SVG-Tiny based illustrator
  2. 2.0 2.1 Forum Nokia:Localization_Example_for_PyS60 Localization Example for PyS60

Open Issues

  1. How do multilingual icons work though the packager? These are defined in the package file format as part of the multilingual caption, so presumably its possible
  2. 4369:Application caption/short name behaviour incorrect. NOTE: I need to test response from defect: appname - is for application title, shortcaption - is for application name in the Phone GUI shell, caption - is used for referring the application name in the installer.
  3. 4370:Icon SVG path needs to be fully qualified, and can't cope with spaces
  4. 4371:Can't specify runtime dependency version
  5. Need to extend #Delivering the Python Runtime with your Application to give better example of Ensymble, or links to C++ packaging stuff. Depends on whether bugs in deliverables fixed.
  6. Platsec material needs to be removed to its own chapter in line with User:Stichbury comments. The way this will be done is to update Platform Security (Fundamentals of Symbian C++) with relevant material from here so it can be slotted as a chapter into any book. The section that remains in this page will be Python Specific. I may see if I can add the Python specifics to the Fundamentals chapter as well on a new section on "runtimes".

Sign in to comment…

Contents

Stichbury said...

(Hamishwillee 01:13, 10 August 2009 (UTC)) Note, I've removed a few points that have been addressed in current document


To include or not include the Python install file is a big deal. Will there be more discussion of this elsewhere? I would imagine it needs to be covered up front, rather than in chapter 16 of the book. Further information, links and background are needed somewhere.

  • (Hamishwillee 02:15, 6 August 2009 (UTC))
    • Good point. I've moved this out of the low level topic under "what the Application packager can't do" to its own top level heading "Delivering the Python Runtime with your Application"
    • The arguments have been updated to provide a clear recommendation to include the SIS file
    • I added a link to the Symbian C++ Quick Start to get the development toolchain, and there was already a link to the Ensymble Quick Start. While I agree more needs to be said/link, what this is depends on this defect 4344. I want to say as little about the C++ option as possible, but not sure what to write until I know what will happen with this defect.

While I like what you've done for platform security, I'm anxious that we don't proliferate information about it throughout the wiki. Even though we'll try to be consistent, you can guarantee some parts of one article will contradict, or make confusing, other parts of another article.

I'd rather point through to a single resource on platsec. If that means lifting out what you've done and placing it in a separate location, then working in whatever else we have, I think that's desirable.

I appreciate this is a book and at some point we have to stop abstracting and put down the content. But right now it's wiki, and even when it comes to the book, it's handy to have a single resource for platsec (most books hit on this - ask Mark, who ended up with 3 different versions of the table that shows what capabilities you need to access various areas of the filesystem to explain datacaging, spread in different chapters!).

Also, although there are links to other platsec resources, at present they are to the root of the website, and not particularly intuitive.

  • (Hamishwillee 02:15, 6 August 2009 (UTC)) Hmmmm. Ok.
    • Do you think a "Books: Platsec Chapter" topic that we can plunk into any book? If so, can I have the source for the tables/material that Mark used so I can ensure that this covers all important areas. Alternative is that I work on the existing Symbian Signed stuff and provide links to all of it. That is workable, but not much good if we then do want to print a book.
    • If I do this almost all the current sections would go - I'd keep information that is Python specific, like using dumpsis to get package for signing, the fact that Python only has 17 capabilities.
      • Stichbury 07:18, 6 August 2009 (UTC) :
        • Sure, Python specific stuff should stay.
        • I tried to convince Mark to have a platsec-specific chapter in his book, and there is one. However, it didn't stop the creep of platsec into other chapters (and the same happened in the UIQ book). Not his fault, it's clearly something people feel they have to explain *their way*. The chapter was provided by Will who wrote the platsec fundamentals wiki pages, so there's probably overlap. A longer term task would be to make sure what's in that chapter (and what got dragged into others) is put into the Fundamentals page and it's edited adequately so it becomes the last word on Platsec. Those Fundamentals pages were always supposed to be the final word - we don't want to proliferate extra pages on leaves, active objects, descriptors etc. One resource only, plus additional recipes, tutorials etc. It's why some of the migration work needs to be reviewed in case it's reinventing...
          • Hamishwillee 01:28, 7 August 2009 (UTC):
            • The fundamental problem here is that "the last word on Platsec" is not of interest to most python developers. For example, 90% of them don't need to care what a DLL or Exe is, or that and exe and DLL treat capabilities differently. 100% of them don't care that capabilities are stored as a bitfield. If you look at Platform Security (Fundamentals of Symbian C++) its useful for C++ developers, but I don't see how it could be useful for this audience (I can improve it however with some of this material). , OK, so how about I integrate/update what I have here
            • That said, the plan of record is to attempt to update the said document so that it can be used as a "slot in" chapter to this book. I probably won't get around to that until mid October. I will also need to work with Symbian Signed to ensure that there is a good document I can link to/slot in as well.

The section "Signing PyS60 Applications" seems to assume rather a lot of background understanding about signing, since it doesn't include any links.

  • (Hamishwillee 02:15, 6 August 2009 (UTC)) Agreed. Will address when I better understand what is needed in way of Platsec book chapter. TBD.

That's all I got for now. It's looking great, very comprehensive, very useful. I'd like a review from someone who knows what they're doing. What Herb be a good person to ask, or maybe Mike Jipping (user Frothep) now he's on board this project too...

Croozeus said...

I have it on my tasklist to review this chapter, add something and address something. Will get onto it asap!

--Croozeus 06:52, 6 August 2009 (BST)

Stichbury said...

Thanks for the responses. I've edited inline a couple of comments, but in summary it's all looking fine, and a review by Pankaj should be sufficient to tidy up technical loose ends. Later edit needed for the book of course, but for now it's super. Thanks all.


--Stichbury 08:39, 6 August 2009 (BST)

Croozeus said…

Hamish,

How about adding few lines on "Converting Python scripts (PY) to Python compiled scripts (PYC) using Python for PC (python.org) before packaging them in SIS files"?

It should be in this chapter. You can use the content from our quick start article, http://developer.symbian.org/wiki/index.php/PyS60_1.4.5_Quick_Start#Making_a_Standalone_Application


--Croozeus 14:43, 3 January 2010 (UTC)

Croozeus said…

Oh we have mentioned that PyS60 application packager converts them by default. Perfect then.

--Croozeus 14:50, 3 January 2010 (UTC)

Hamishwillee said…

Hi @Croozeus As you note, we already mention the byte code option as a default in the packager. I've added "compiled to byte code (Python compiled scripts - PYC) before packaging" to ensure that anyone looking for compiled scripts will see the reference.

It might also be worth adding a line/section under commercial applications to explain that this is also a step you can take to prevent piracy - if you think its worth it I'll leave that to you.

regards H

--Hamishwillee 03:43, 12 January 2010 (UTC)