PyMobileScript Documentation

v1.2.0

Build native mobile apps using Python, with high performance and a seamless developer experience.

Note: PyMobileScript is a new framework created in 2025. It still may contain some errors.

PyMobileScript is a revolutionary framework that allows Python developers to build native mobile applications for iOS and Android using pure Python code. By leveraging advanced compilation techniques, PyMobileScript translates your Python code directly to native Swift and Kotlin, resulting in high-performance applications with native look and feel.

Key Features

  • Pure Python Development: Write your entire application in Python without learning Swift, Kotlin, or JavaScript
  • Native Performance: Direct compilation to native code with no interpretation or bridges
  • Full Access to Native APIs: Use platform-specific features without writing platform-specific code
  • Rapid Development: Hot reload, intelligent debugging, and comprehensive error messages
  • Python Ecosystem Integration: Use your favorite Python libraries directly in your mobile apps

Installation

PyMobileScript requires Python 3.8 or higher and can be installed using pip.

System Requirements

  • Python 3.8+
  • macOS, Windows 10+, or Linux
  • For iOS development: macOS with Xcode 13+
  • For Android development: Android SDK 30+
  • Minimum 8GB RAM recommended

Install PyMobileScript

Install the PyMobileScript framework using pip:

pip install pymobilescript

Verify the installation:

pymobilescript --version

Setting Up Development Environment

Install the CLI tools for creating and managing projects:

pip install pymobilescript-cli

Platform-Specific Setup

For macOS, you'll need to install Xcode for iOS development:

  1. Install Xcode from the Mac App Store
  2. Install the Xcode Command Line Tools: xcode-select --install
  3. Run the PyMobileScript environment setup: pymobilescript setup ios

For Android development:

  1. Install Android Studio
  2. Install the Android SDK through Android Studio
  3. Run the PyMobileScript environment setup: pymobilescript setup android

IDE Integration

PyMobileScript works with any Python IDE, but we recommend using VSCode with our official extension for the best development experience.

  1. Install Visual Studio Code
  2. Install the Python extension
  3. Install the PyMobileScript extension from the marketplace

Quick Start

Let's create your first PyMobileScript application.

Create a New Project

Use the CLI to create a new project with a starter template:

pymobilescript create myapp

This will create a new directory called myapp with a basic project structure.

Project Structure

Your new project will have the following structure:

myapp/
├── pyproject.toml      # Project configuration
├── README.md           # Project documentation
├── app/
│   ├── __init__.py
│   ├── main.py         # Entry point
│   ├── views/          # UI views
│   │   ├── __init__.py
│   │   ├── home.py
│   │   └── settings.py
│   ├── components/     # Reusable components
│   │   ├── __init__.py
│   │   └── button.py
│   ├── resources/      # Images, fonts, etc.
│   │   ├── images/
│   │   └── fonts/
│   └── utils/          # Utility functions
│       └── __init__.py
├── tests/              # Unit tests
│   └── __init__.py
└── .pymobilescriptrc   # Framework configuration

Run Your App

Navigate to your project directory and start the development server:

cd myapp\npymobilescript dev

This will start the development server and launch your app in the simulator/emulator.

To run specifically on iOS:

pymobilescript dev --platform ios

Your First App

Let's look at the default main.py file created by the template:

app/main.py
import pymobilescript as pms
from pymobilescript.ui import *
from app.views.home import HomeView

class MyApp(pms.App):
    def __init__(self):
        super().__init__()
        self.title = "My First App"
        
    def view(self):
        return HomeView()

if __name__ == "__main__":
    app = MyApp()
    app.run()

Now, let's look at the home.py file to see the UI definition:

app/views/home.py
import pymobilescript as pms
from pymobilescript.ui import *

class HomeView(pms.View):
    def __init__(self):
        super().__init__()
        self.count = 0
        
    def increment(self):
        self.count += 1
        self.update()
        
    def render(self):
        return Container(
            style={"padding": 20, "alignItems": "center", "justifyContent": "center"},
            children=[
                Text(
                    "Welcome to PyMobileScript!",
                    style={"fontSize": 24, "fontWeight": "bold", "marginBottom": 20}
                ),
                Text(
                    f"You clicked {self.count} times",
                    style={"marginBottom": 20}
                ),
                Button(
                    text="Increment",
                    on_press=self.increment,
                    style={"backgroundColor": "#4299e1", "color": "white", "padding": 10, "borderRadius": 5}
                )
            ]
        )

This creates a simple counter app with a button that increments the count when pressed.

Making Changes

Let's modify the home view to add some more UI elements:

app/views/home.py
import pymobilescript as pms
from pymobilescript.ui import *

class HomeView(pms.View):
    def __init__(self):
        super().__init__()
        self.count = 0
        self.name = ""
        
    def increment(self):
        self.count += 1
        self.update()
        
    def on_name_change(self, text):
        self.name = text
        self.update()
        
    def render(self):
        return Container(
            style={"padding": 20, "alignItems": "center", "justifyContent": "center"},
            children=[
                Text(
                    "Welcome to PyMobileScript!",
                    style={"fontSize": 24, "fontWeight": "bold", "marginBottom": 20}
                ),
                Input(
                    placeholder="Enter your name",
                    value=self.name,
                    on_change=self.on_name_change,
                    style={"width": "100%", "marginBottom": 20, "padding": 10, "borderWidth": 1, "borderColor": "#e2e8f0", "borderRadius": 5}
                ),
                Text(
                    f"Hello, {self.name or 'Friend'}!" if self.name else "Please enter your name above",
                    style={"marginBottom": 20}
                ),
                Text(
                    f"You clicked {self.count} times",
                    style={"marginBottom": 20}
                ),
                Button(
                    text="Increment",
                    on_press=self.increment,
                    style={"backgroundColor": "#4299e1", "color": "white", "padding": 10, "borderRadius": 5}
                )
            ]
        )

With these changes, the app now includes a text input field where the user can enter their name, and the UI will update to display a greeting.

Hot Reload: PyMobileScript supports hot reloading, which means you can see your changes immediately without restarting the app. Just save your files, and the UI will update automatically.

Project Structure

Understanding the PyMobileScript project structure is essential for organizing your code effectively.

Core Components

  • pyproject.toml: The main configuration file for your project. It contains metadata, dependencies, and build settings.
  • app/main.py: The entry point of your application. It defines the main App class and initializes the application.
  • app/views/: Contains your application's screens or pages. Each view represents a different screen in your app.
  • app/components/: Contains reusable UI components that can be shared across multiple views.
  • app/resources/: Contains static resources like images, fonts, and other assets.
  • app/utils/: Contains utility functions and helper classes that can be used throughout your application.
  • .pymobilescriptrc: Framework-specific configuration file. It contains settings for the build process, plugins, and other framework-specific options.

Configuration Files

The pyproject.toml file is the main configuration file for your project. Here's an example of a basic configuration:

pyproject.toml
[project]
name = "my-mobile-app"
version = "0.1.0"
description = "My first PyMobileScript app"
authors = [
    {name = "Your Name", email = "your.email@example.com"}
]
requires-python = ">=3.8"

[build-system]
requires = ["pymobilescript-build>=1.0.0"]
build-backend = "pymobilescript.build"

[tool.pymobilescript]
app_name = "My Mobile App"
bundle_id = "com.example.mymobileapp"
version_code = 1
min_sdk_version = 21
target_sdk_version = 31

[tool.pymobilescript.ios]
deployment_target = "14.0"
team_id = "XXXXXXXXXX"  # Your Apple Developer Team ID

[tool.pymobilescript.android]
compile_sdk_version = 31

The .pymobilescriptrc file contains framework-specific configuration options:

.pymobilescriptrc
{
  "plugins": [
    "pymobilescript-camera",
    "pymobilescript-location"
  ],
  "fonts": [
    {
      "name": "Roboto",
      "assets": [
        "app/resources/fonts/Roboto-Regular.ttf",
        "app/resources/fonts/Roboto-Bold.ttf",
        "app/resources/fonts/Roboto-Italic.ttf"
      ]
    }
  ],
  "environment": {
    "development": {
      "api_url": "https://api.example.com/dev"
    },
    "production": {
      "api_url": "https://api.example.com/prod"
    }
  }
}

Recommended Project Organization

As your project grows, we recommend organizing your code according to the following structure:

myapp/
├── pyproject.toml
├── README.md
├── app/
│   ├── main.py
│   ├── views/
│   │   ├── __init__.py
│   │   ├── auth/          # Authentication-related views
│   │   │   ├── __init__.py
│   │   │   ├── login.py
│   │   │   └── register.py
│   │   ├── main/          # Main app views
│   │   │   ├── __init__.py
│   │   │   ├── home.py
│   │   │   ├── profile.py
│   │   │   └── settings.py
│   │   └── common/        # Shared views
│   │       ├── __init__.py
│   │       ├── about.py
│   │       └── error.py
│   ├── components/
│   │   ├── __init__.py
│   │   ├── buttons.py
│   │   ├── cards.py
│   │   ├── forms.py
│   │   └── navigation.py
│   ├── models/            # Data models
│   │   ├── __init__.py
│   │   ├── user.py
│   │   └── item.py
│   ├── services/          # API and other services
│   │   ├── __init__.py
│   │   ├── api.py
│   │   └── auth.py
│   ├── resources/
│   │   ├── images/
│   │   └── fonts/
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── validation.py
│   │   └── formatting.py
│   ├── config.py          # App configuration
│   └── themes.py          # UI themes
├── tests/
│   ├── __init__.py
│   ├── test_views.py
│   └── test_models.py
└── .pymobilescriptrc
This structure is just a recommendation. Feel free to adapt it to your specific needs and preferences.

Components

Components are the building blocks of PyMobileScript applications. They encapsulate UI elements and logic that can be reused throughout your application.

Built-in Components

PyMobileScript provides a rich set of built-in components that map to native UI elements on iOS and Android.

Text

Displays text with customizable styling

Button

A pressable button with customizable appearance

Input

Text input field for user data entry

Image

Displays local or remote images

Container

Basic layout component for grouping other components

ScrollView

Container that allows scrolling its contents

ListView

Efficiently displays scrollable lists of items

Stack

Layout component that stacks children vertically or horizontally

Grid

Arranges items in a grid layout

Switch

Toggle switch for boolean values

Checkbox

Checkbox for selecting multiple options

RadioButton

Radio button for selecting a single option from many

Slider

Slider for selecting a value from a range

Progress

Displays progress of an operation

Modal

Displays content in a modal window

Tabs

Tabbed navigation component

Creating Custom Components

You can create your own custom components by extending the pms.Component class.

app/components/custom_button.py
import pymobilescript as pms
from pymobilescript.ui import *

class CustomButton(pms.Component):
    def __init__(self, text, on_press=None, variant="primary"):
        super().__init__()
        self.text = text
        self.on_press = on_press
        self.variant = variant
        
    def render(self):
        # Define styles based on variant
        if self.variant == "primary":
            style = {
                "backgroundColor": "#4299e1",
                "color": "white",
                "padding": 12,
                "borderRadius": 8,
                "fontWeight": "bold"
            }
        elif self.variant == "secondary":
            style = {
                "backgroundColor": "#a0aec0",
                "color": "white",
                "padding": 12,
                "borderRadius": 8,
                "fontWeight": "bold"
            }
        else:  # outline
            style = {
                "backgroundColor": "transparent",
                "color": "#4299e1",
                "padding": 12,
                "borderRadius": 8,
                "fontWeight": "bold",
                "borderWidth": 2,
                "borderColor": "#4299e1"
            }
            
        return Button(
            text=self.text,
            on_press=self.on_press,
            style=style
        )

Using the custom component:

from app.components.custom_button import CustomButton

def render(self):
    return Container(
        children=[
            CustomButton(
                text="Primary Button",
                on_press=self.handle_press,
                variant="primary"
            ),
            CustomButton(
                text="Secondary Button",
                on_press=self.handle_press,
                variant="secondary"
            ),
            CustomButton(
                text="Outline Button",
                on_press=self.handle_press,
                variant="outline"
            )
        ]
    )

Component Lifecycle

PyMobileScript components have a lifecycle that you can hook into to perform actions at different stages.

import pymobilescript as pms
from pymobilescript.ui import *

class LifecycleComponent(pms.Component):
    def __init__(self):
        super().__init__()
        self.data = None
        
    def mount(self):
        # Called when the component is first mounted
        print("Component mounted")
        # Perform initialization, API calls, etc.
        self.load_data()
        
    def unmount(self):
        # Called when the component is removed from the UI
        print("Component unmounted")
        # Perform cleanup, unsubscribe from events, etc.
        
    def update(self):
        # Called when the component's state changes
        print("Component updated")
        super().update()  # Don't forget to call the parent method
        
    def should_update(self, next_props, next_state):
        # Return True if the component should re-render
        # This is an optimization to prevent unnecessary renders
        return True
        
    async def load_data(self):
        # Async method to fetch data
        self.data = await api.fetch_data()
        self.update()
        
    def render(self):
        if self.data is None:
            return Text("Loading...")
            
        return Container(
            children=[
                Text(f"Data: {self.data}")
            ]
        )

Component Composition

Component composition is a powerful pattern in PyMobileScript. You can combine smaller components to build more complex UIs.

import pymobilescript as pms
from pymobilescript.ui import *
from app.components.custom_button import CustomButton
from app.components.header import Header
from app.components.card import Card

class ProfileView(pms.View):
    def __init__(self, user_id):
        super().__init__()
        self.user_id = user_id
        self.user = None
        
    def mount(self):
        self.load_user()
        
    async def load_user(self):
        self.user = await api.get_user(self.user_id)
        self.update()
        
    def render(self):
        if self.user is None:
            return Container(
                style={"alignItems": "center", "justifyContent": "center", "flex": 1},
                children=[
                    Text("Loading user profile...")
                ]
            )
            
        return Container(
            children=[
                Header(title="User Profile"),
                Card(
                    children=[
                        Image(
                            source=self.user.avatar_url,
                            style={"width": 100, "height": 100, "borderRadius": 50, "alignSelf": "center"}
                        ),
                        Text(
                            self.user.name,
                            style={"fontSize": 24, "fontWeight": "bold", "textAlign": "center", "marginTop": 10}
                        ),
                        Text(
                            self.user.email,
                            style={"textAlign": "center", "color": "#666"}
                        )
                    ]
                ),
                CustomButton(
                    text="Edit Profile",
                    on_press=self.edit_profile,
                    variant="primary"
                ),
                CustomButton(
                    text="Logout",
                    on_press=self.logout,
                    variant="outline"
                )
            ]
        )
        
    def edit_profile(self):
        # Navigate to edit profile screen
        self.navigate("edit_profile", {"user_id": self.user_id})
        
    def logout(self):
        # Handle logout
        api.logout()
        self.navigate("login")

Building Your App

When you're ready to distribute your app, you'll need to build it for your target platforms. PyMobileScript simplifies this process with a unified build system.

Building for Development

During development, PyMobileScript uses a development build that includes debug information and tools to help you identify and fix issues.

pymobilescript build --dev

This will create a development build for both iOS and Android.

Building for Production

When you're ready to release your app, you'll need to create a production build. This build is optimized for performance and size.

pymobilescript build --production

This will create a production build for both iOS and Android. The output will be located in the build/ directory.

Platform-Specific Builds

You can also build for a specific platform:

pymobilescript build --platform ios --production

This will create an iOS app bundle (.ipa file) in the build/ios/ directory.

Build Configuration

You can customize the build process by modifying the build configuration in your pyproject.toml file:

pyproject.toml
[tool.pymobilescript.build]
optimization_level = "high"  # Can be "none", "low", "medium", or "high"
include_source_maps = false  # Whether to include source maps for debugging
asset_compression = true     # Whether to compress assets
bundle_identifier = "com.example.myapp"
version = "1.0.0"
build_number = "1"

[tool.pymobilescript.build.ios]
team_id = "XXXXXXXXXX"
provisioning_profile = "path/to/profile.mobileprovision"
code_sign_identity = "iPhone Distribution"
export_method = "app-store"  # Can be "app-store", "ad-hoc", "enterprise", or "development"

[tool.pymobilescript.build.android]
keystore = "path/to/keystore.jks"
keystore_password = "your-keystore-password"
key_alias = "your-key-alias"
key_password = "your-key-password"
build_type = "aab"  # Can be "apk" or "aab" (Android App Bundle)
Security Warning: Never commit sensitive information like keystore passwords to version control. Consider using environment variables or a secure CI/CD pipeline to provide these values during the build process.

Environment-Specific Builds

You can create builds for different environments (e.g., staging, production) by specifying the environment name:

pymobilescript build --env staging

This will use the configuration specified in the environment.staging section of your .pymobilescriptrc file.

.pymobilescriptrc
{
  "environment": {
    "development": {
      "api_url": "https://api.example.com/dev",
      "logging_level": "debug"
    },
    "staging": {
      "api_url": "https://api.example.com/staging",
      "logging_level": "info"
    },
    "production": {
      "api_url": "https://api.example.com/prod",
      "logging_level": "error"
    }
  }
}

You can access these environment variables in your code:

import pymobilescript as pms

# Access environment variables
api_url = pms.env.get("api_url")
logging_level = pms.env.get("logging_level")

Custom Build Scripts

For more complex build requirements, you can create custom build scripts that run before or after the main build process:

build_scripts.py
# build_scripts.py
import subprocess
import os
import json

def pre_build(context):
    """Runs before the build process starts."""
    print("Running pre-build script...")
    # Generate build-specific files
    with open("app/build_config.py", "w") as f:
        f.write(f"BUILD_NUMBER = '{context['build_number']}'
")
        f.write(f"BUILD_ENV = '{context['environment']}'
")
        f.write(f"BUILD_DATE = '{context['date']}'
")

def post_build(context):
    """Runs after the build process completes."""
    print("Running post-build script...")
    # Notify team about new build
    build_info = {
        "version": context["version"],
        "build_number": context["build_number"],
        "environment": context["environment"],
        "date": context["date"],
        "platforms": context["platforms"]
    }
    with open("build/build_info.json", "w") as f:
        json.dump(build_info, f, indent=2)
        
    # Run additional optimization or verification
    if "android" in context["platforms"]:
        apk_path = os.path.join("build", "android", f"{context['name']}.apk")
        subprocess.run(["zipalign", "-v", "4", apk_path, f"{apk_path}.aligned"])
        os.rename(f"{apk_path}.aligned", apk_path)

Reference these scripts in your pyproject.toml:

pyproject.toml
[tool.pymobilescript.build]
pre_build_script = "build_scripts.pre_build"
post_build_script = "build_scripts.post_build"

iOS Deployment

Deploying your PyMobileScript app to iOS devices and the App Store involves several steps.

Prerequisites

  • An Apple Developer account ($99/year)
  • Xcode installed on your Mac
  • App Store Connect setup for your app
  • Certificates and provisioning profiles

Setup for iOS Deployment

Before you can deploy your app, you need to set up your Apple Developer account and create the necessary certificates and provisioning profiles.

The PyMobileScript CLI can help automate this process:

pymobilescript setup ios-deployment

This interactive command will guide you through the process of setting up your iOS deployment credentials.

Deploying to TestFlight

TestFlight allows you to distribute beta versions of your app to testers before releasing it to the App Store.

pymobilescript deploy ios --beta

This will build your app, create an iOS app bundle, and upload it to TestFlight. You can then invite testers through App Store Connect.

App Store Submission

When you're ready to submit your app to the App Store, you can use the deployment command:

pymobilescript deploy ios --release

This will build your app, create an iOS app bundle, and upload it to App Store Connect. You'll need to complete the submission process through the App Store Connect website, including:

  • App information and metadata
  • Screenshots and app preview videos
  • Privacy policy
  • App Review information
  • Version release information

Advanced iOS Deployment

For more advanced deployment scenarios, you can customize the deployment process with additional options:

pymobilescript deploy ios --release --skip-build --ipa-path ./build/ios/MyApp.ipa --wait-for-processing

This command will:

  • Skip the build process (useful if you've already built the app)
  • Use a specific .ipa file instead of building a new one
  • Wait for App Store Connect to finish processing the build before exiting

iOS Deployment Configuration

You can configure iOS deployment settings in your pyproject.toml file:

pyproject.toml
[tool.pymobilescript.deploy.ios]
team_id = "XXXXXXXXXX"
app_store_connect_api_key_id = "XXXXXXXXXX"
app_store_connect_api_issuer_id = "XXXXXXXXXX"
app_store_connect_api_key_path = "path/to/api_key.p8"
app_specific_password = "xxxx-xxxx-xxxx-xxxx"  # For Apple ID authentication
skip_build_validation = false
skip_app_store_validation = false
submit_for_review = false  # Whether to automatically submit for review
App Store Connect API: Using the App Store Connect API is recommended over Apple ID authentication. It provides more reliable and secure automated deployments.

Frequently Asked Questions

Help Us Improve