pythonnative 0.0.1__tar.gz → 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pythonnative-0.0.1 → pythonnative-0.1.0}/PKG-INFO +1 -1
- pythonnative-0.1.0/cli/pn.py +113 -0
- pythonnative-0.1.0/pythonnative/__init__.py +7 -0
- pythonnative-0.1.0/pythonnative/button.py +36 -0
- pythonnative-0.1.0/pythonnative/label.py +36 -0
- pythonnative-0.1.0/pythonnative/linear_layout.py +36 -0
- pythonnative-0.1.0/pythonnative/screen.py +50 -0
- pythonnative-0.1.0/pythonnative/view.py +13 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/pythonnative.egg-info/PKG-INFO +1 -1
- {pythonnative-0.0.1 → pythonnative-0.1.0}/pythonnative.egg-info/SOURCES.txt +8 -1
- pythonnative-0.1.0/pythonnative.egg-info/entry_points.txt +2 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/pythonnative.egg-info/top_level.txt +1 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/setup.py +6 -1
- pythonnative-0.0.1/pythonnative/pythonnative.py +0 -73
- {pythonnative-0.0.1 → pythonnative-0.1.0}/LICENSE +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/README.md +0 -0
- {pythonnative-0.0.1/pythonnative → pythonnative-0.1.0/cli}/__init__.py +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/pythonnative.egg-info/dependency_links.txt +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/pythonnative.egg-info/requires.txt +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/setup.cfg +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/tests/__init__.py +0 -0
- {pythonnative-0.0.1 → pythonnative-0.1.0}/tests/test_pythonnative.py +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def init_project(args: argparse.Namespace) -> None:
|
|
8
|
+
"""
|
|
9
|
+
Initialize a new PythonNative project.
|
|
10
|
+
"""
|
|
11
|
+
# TODO: Implementation
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_android_project(project_name: str, destination: str) -> bool:
|
|
15
|
+
"""
|
|
16
|
+
Create a new Android project using android command.
|
|
17
|
+
|
|
18
|
+
:param project_name: The name of the project.
|
|
19
|
+
:param destination: The directory where the project will be created.
|
|
20
|
+
:return: True if the project was created successfully, False otherwise.
|
|
21
|
+
"""
|
|
22
|
+
# The command to create a new Android project
|
|
23
|
+
command = f"cd {destination} && android create project --name {project_name} --path . --target android-30 --package com.example.{project_name} --activity MainActivity"
|
|
24
|
+
|
|
25
|
+
# Run the command
|
|
26
|
+
process = subprocess.run(command, shell=True, check=True, text=True)
|
|
27
|
+
|
|
28
|
+
return process.returncode == 0
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def create_ios_project(project_name: str, destination: str) -> bool:
|
|
32
|
+
"""
|
|
33
|
+
Create a new Xcode project using xcodeproj gem.
|
|
34
|
+
|
|
35
|
+
:param project_name: The name of the project.
|
|
36
|
+
:param destination: The directory where the project will be created.
|
|
37
|
+
:return: True if the project was created successfully, False otherwise.
|
|
38
|
+
"""
|
|
39
|
+
# The command to create a new Xcode project
|
|
40
|
+
command = f"cd {destination} && xcodeproj new {project_name}.xcodeproj"
|
|
41
|
+
|
|
42
|
+
# Run the command
|
|
43
|
+
process = subprocess.run(command, shell=True, check=True, text=True)
|
|
44
|
+
|
|
45
|
+
return process.returncode == 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def run_project(args: argparse.Namespace) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Run the specified project.
|
|
51
|
+
"""
|
|
52
|
+
# Determine the platform
|
|
53
|
+
platform = args.platform
|
|
54
|
+
|
|
55
|
+
# Define the build directory
|
|
56
|
+
build_dir = os.path.join(os.getcwd(), "build", platform)
|
|
57
|
+
|
|
58
|
+
# Create the build directory if it doesn't exist
|
|
59
|
+
os.makedirs(build_dir, exist_ok=True)
|
|
60
|
+
|
|
61
|
+
# Generate the required project files
|
|
62
|
+
if platform == "android":
|
|
63
|
+
create_android_project("MyApp", build_dir)
|
|
64
|
+
elif platform == "ios":
|
|
65
|
+
create_ios_project("MyApp", build_dir)
|
|
66
|
+
|
|
67
|
+
# Copy the user's Python code into the project
|
|
68
|
+
src_dir = os.path.join(os.getcwd(), "app")
|
|
69
|
+
dest_dir = os.path.join(
|
|
70
|
+
build_dir, "app"
|
|
71
|
+
) # You might need to adjust this depending on the project structure
|
|
72
|
+
shutil.copytree(src_dir, dest_dir, dirs_exist_ok=True)
|
|
73
|
+
|
|
74
|
+
# Install any necessary Python packages into the project environment
|
|
75
|
+
requirements_file = os.path.join(os.getcwd(), "requirements.txt")
|
|
76
|
+
# TODO: Fill in with actual commands for installing Python packages
|
|
77
|
+
|
|
78
|
+
# Run the project
|
|
79
|
+
# TODO: Fill in with actual commands for running the project
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def clean_project(args: argparse.Namespace) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Clean the specified project.
|
|
85
|
+
"""
|
|
86
|
+
# Define the build directory
|
|
87
|
+
build_dir = os.path.join(os.getcwd(), "build")
|
|
88
|
+
|
|
89
|
+
# Check if the build directory exists
|
|
90
|
+
if os.path.exists(build_dir):
|
|
91
|
+
# Delete the build directory
|
|
92
|
+
shutil.rmtree(build_dir)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main() -> None:
|
|
96
|
+
parser = argparse.ArgumentParser(prog="pn", description="PythonNative CLI")
|
|
97
|
+
subparsers = parser.add_subparsers()
|
|
98
|
+
|
|
99
|
+
# Create a new command 'init' that calls init_project
|
|
100
|
+
parser_init = subparsers.add_parser("init")
|
|
101
|
+
parser_init.set_defaults(func=init_project)
|
|
102
|
+
|
|
103
|
+
# Create a new command 'run' that calls run_project
|
|
104
|
+
parser_run = subparsers.add_parser("run")
|
|
105
|
+
parser_run.add_argument("platform", choices=["android", "ios"])
|
|
106
|
+
parser_run.set_defaults(func=run_project)
|
|
107
|
+
|
|
108
|
+
# Create a new command 'clean' that calls clean_project
|
|
109
|
+
parser_clean = subparsers.add_parser("clean")
|
|
110
|
+
parser_clean.set_defaults(func=clean_project)
|
|
111
|
+
|
|
112
|
+
args = parser.parse_args()
|
|
113
|
+
args.func(args)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
from .view import View
|
|
3
|
+
|
|
4
|
+
if platform.system() == "Android":
|
|
5
|
+
from java import jclass
|
|
6
|
+
|
|
7
|
+
class Button(View):
|
|
8
|
+
native_class = jclass("android.widget.Button")
|
|
9
|
+
|
|
10
|
+
def __init__(self, title: str = "") -> None:
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.native_instance = self.native_class()
|
|
13
|
+
self.set_title(title)
|
|
14
|
+
|
|
15
|
+
def set_title(self, title: str) -> None:
|
|
16
|
+
self.native_instance.setText(title)
|
|
17
|
+
|
|
18
|
+
def get_title(self) -> str:
|
|
19
|
+
return self.native_instance.getText().toString()
|
|
20
|
+
|
|
21
|
+
elif platform.system() == "iOS":
|
|
22
|
+
from rubicon.objc import ObjCClass
|
|
23
|
+
|
|
24
|
+
class Button(View):
|
|
25
|
+
native_class = ObjCClass("UIButton")
|
|
26
|
+
|
|
27
|
+
def __init__(self, title: str = "") -> None:
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.native_instance = self.native_class.alloc().init()
|
|
30
|
+
self.set_title(title)
|
|
31
|
+
|
|
32
|
+
def set_title(self, title: str) -> None:
|
|
33
|
+
self.native_instance.setTitle_forState_(title, 0)
|
|
34
|
+
|
|
35
|
+
def get_title(self) -> str:
|
|
36
|
+
return self.native_instance.titleForState_(0)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
from .view import View
|
|
3
|
+
|
|
4
|
+
if platform.system() == "Android":
|
|
5
|
+
from java import jclass
|
|
6
|
+
|
|
7
|
+
class Label(View):
|
|
8
|
+
native_class = jclass("android.widget.TextView")
|
|
9
|
+
|
|
10
|
+
def __init__(self, text: str = "") -> None:
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.native_instance = self.native_class()
|
|
13
|
+
self.set_text(text)
|
|
14
|
+
|
|
15
|
+
def set_text(self, text: str) -> None:
|
|
16
|
+
self.native_instance.setText(text)
|
|
17
|
+
|
|
18
|
+
def get_text(self) -> str:
|
|
19
|
+
return self.native_instance.getText().toString()
|
|
20
|
+
|
|
21
|
+
elif platform.system() == "iOS":
|
|
22
|
+
from rubicon.objc import ObjCClass
|
|
23
|
+
|
|
24
|
+
class Label(View):
|
|
25
|
+
native_class = ObjCClass("UILabel")
|
|
26
|
+
|
|
27
|
+
def __init__(self, text: str = "") -> None:
|
|
28
|
+
super().__init__()
|
|
29
|
+
self.native_instance = self.native_class.alloc().init()
|
|
30
|
+
self.set_text(text)
|
|
31
|
+
|
|
32
|
+
def set_text(self, text: str) -> None:
|
|
33
|
+
self.native_instance.setText_(text)
|
|
34
|
+
|
|
35
|
+
def get_text(self) -> str:
|
|
36
|
+
return self.native_instance.text()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
from .view import View
|
|
3
|
+
|
|
4
|
+
if platform.system() == "Android":
|
|
5
|
+
from java import jclass
|
|
6
|
+
|
|
7
|
+
class LinearLayout(View):
|
|
8
|
+
native_class = jclass("android.widget.LinearLayout")
|
|
9
|
+
|
|
10
|
+
def __init__(self) -> None:
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.native_instance = self.native_class()
|
|
13
|
+
self.native_instance.setOrientation(1) # Set orientation to vertical
|
|
14
|
+
self.views = []
|
|
15
|
+
|
|
16
|
+
def add_view(self, view):
|
|
17
|
+
self.views.append(view)
|
|
18
|
+
self.native_instance.addView(view.native_instance)
|
|
19
|
+
|
|
20
|
+
elif platform.system() == "iOS":
|
|
21
|
+
from rubicon.objc import ObjCClass
|
|
22
|
+
|
|
23
|
+
class LinearLayout(View):
|
|
24
|
+
native_class = ObjCClass("UIStackView")
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
super().__init__()
|
|
28
|
+
self.native_instance = self.native_class.alloc().initWithFrame_(
|
|
29
|
+
((0, 0), (0, 0))
|
|
30
|
+
)
|
|
31
|
+
self.native_instance.setAxis_(0) # Set axis to vertical
|
|
32
|
+
self.views = []
|
|
33
|
+
|
|
34
|
+
def add_view(self, view):
|
|
35
|
+
self.views.append(view)
|
|
36
|
+
self.native_instance.addArrangedSubview_(view.native_instance)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
from .view import View
|
|
3
|
+
|
|
4
|
+
if platform.system() == "Android":
|
|
5
|
+
from java import jclass
|
|
6
|
+
|
|
7
|
+
class Screen(View):
|
|
8
|
+
native_class = jclass("android.app.Activity")
|
|
9
|
+
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.native_instance = self.native_class()
|
|
13
|
+
self.layout = None
|
|
14
|
+
|
|
15
|
+
def add_view(self, view):
|
|
16
|
+
if self.layout is None:
|
|
17
|
+
raise ValueError("You must set a layout before adding views.")
|
|
18
|
+
self.layout.add_view(view)
|
|
19
|
+
|
|
20
|
+
def set_layout(self, layout):
|
|
21
|
+
self.layout = layout
|
|
22
|
+
self.native_instance.setContentView(layout.native_instance)
|
|
23
|
+
|
|
24
|
+
def show(self):
|
|
25
|
+
# This method should contain code to start the Activity
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
elif platform.system() == "iOS":
|
|
29
|
+
from rubicon.objc import ObjCClass
|
|
30
|
+
|
|
31
|
+
class Screen(View):
|
|
32
|
+
native_class = ObjCClass("UIViewController")
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
super().__init__()
|
|
36
|
+
self.native_instance = self.native_class.alloc().init()
|
|
37
|
+
self.layout = None
|
|
38
|
+
|
|
39
|
+
def add_view(self, view):
|
|
40
|
+
if self.layout is None:
|
|
41
|
+
raise ValueError("You must set a layout before adding views.")
|
|
42
|
+
self.layout.add_view(view)
|
|
43
|
+
|
|
44
|
+
def set_layout(self, layout):
|
|
45
|
+
self.layout = layout
|
|
46
|
+
self.native_instance.view().addSubview_(layout.native_instance)
|
|
47
|
+
|
|
48
|
+
def show(self):
|
|
49
|
+
# This method should contain code to present the ViewController
|
|
50
|
+
pass
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class View:
|
|
2
|
+
def __init__(self) -> None:
|
|
3
|
+
self.native_instance = None
|
|
4
|
+
self.native_class = None
|
|
5
|
+
|
|
6
|
+
def add_view(self, view):
|
|
7
|
+
raise NotImplementedError("This method should be implemented in a subclass.")
|
|
8
|
+
|
|
9
|
+
def set_layout(self, layout):
|
|
10
|
+
raise NotImplementedError("This method should be implemented in a subclass.")
|
|
11
|
+
|
|
12
|
+
def show(self):
|
|
13
|
+
raise NotImplementedError("This method should be implemented in a subclass.")
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
3
|
setup.py
|
|
4
|
+
cli/__init__.py
|
|
5
|
+
cli/pn.py
|
|
4
6
|
pythonnative/__init__.py
|
|
5
|
-
pythonnative/
|
|
7
|
+
pythonnative/button.py
|
|
8
|
+
pythonnative/label.py
|
|
9
|
+
pythonnative/linear_layout.py
|
|
10
|
+
pythonnative/screen.py
|
|
11
|
+
pythonnative/view.py
|
|
6
12
|
pythonnative.egg-info/PKG-INFO
|
|
7
13
|
pythonnative.egg-info/SOURCES.txt
|
|
8
14
|
pythonnative.egg-info/dependency_links.txt
|
|
15
|
+
pythonnative.egg-info/entry_points.txt
|
|
9
16
|
pythonnative.egg-info/requires.txt
|
|
10
17
|
pythonnative.egg-info/top_level.txt
|
|
11
18
|
tests/__init__.py
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="pythonnative",
|
|
5
|
-
version="0.0
|
|
5
|
+
version="0.1.0",
|
|
6
6
|
author="Owen Carey",
|
|
7
7
|
author_email="pythonnative@gmail.com",
|
|
8
8
|
description="A cross-platform Python tool kit for Android and iOS",
|
|
@@ -20,4 +20,9 @@ setup(
|
|
|
20
20
|
"rubicon-objc>=0.4.6,<0.5.0",
|
|
21
21
|
# Add more requirements here as necessary
|
|
22
22
|
],
|
|
23
|
+
entry_points={
|
|
24
|
+
"console_scripts": [
|
|
25
|
+
"pn=cli.pn:main",
|
|
26
|
+
],
|
|
27
|
+
},
|
|
23
28
|
)
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Detect the platform
|
|
2
|
-
import platform
|
|
3
|
-
|
|
4
|
-
system = platform.system()
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class PlatformNotDetectedError(Exception):
|
|
8
|
-
pass
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# Depending on the system, import appropriate classes
|
|
12
|
-
if system == "iOS":
|
|
13
|
-
from rubicon.objc import ObjCClass
|
|
14
|
-
|
|
15
|
-
# Map native iOS classes to PythonNative classes
|
|
16
|
-
class Button:
|
|
17
|
-
native_class = ObjCClass("UIButton")
|
|
18
|
-
|
|
19
|
-
def __init__(self, title=""):
|
|
20
|
-
self.native_instance = self.native_class.alloc().init()
|
|
21
|
-
self.set_title(title)
|
|
22
|
-
|
|
23
|
-
def set_title(self, title):
|
|
24
|
-
self.native_instance.setTitle_forState_(title, 0)
|
|
25
|
-
|
|
26
|
-
def get_title(self):
|
|
27
|
-
return self.native_instance.titleForState_(0)
|
|
28
|
-
|
|
29
|
-
class Label:
|
|
30
|
-
native_class = ObjCClass("UILabel")
|
|
31
|
-
|
|
32
|
-
def __init__(self, text=""):
|
|
33
|
-
self.native_instance = self.native_class.alloc().init()
|
|
34
|
-
self.set_text(text)
|
|
35
|
-
|
|
36
|
-
def set_text(self, text):
|
|
37
|
-
self.native_instance.setText_(text)
|
|
38
|
-
|
|
39
|
-
def get_text(self):
|
|
40
|
-
return self.native_instance.text()
|
|
41
|
-
|
|
42
|
-
elif system == "Android":
|
|
43
|
-
from java import jclass
|
|
44
|
-
|
|
45
|
-
# Map native Android classes to PythonNative classes
|
|
46
|
-
class Button:
|
|
47
|
-
native_class = jclass("android.widget.Button")
|
|
48
|
-
|
|
49
|
-
def __init__(self, title=""):
|
|
50
|
-
self.native_instance = self.native_class()
|
|
51
|
-
self.set_title(title)
|
|
52
|
-
|
|
53
|
-
def set_title(self, title):
|
|
54
|
-
self.native_instance.setText(title)
|
|
55
|
-
|
|
56
|
-
def get_title(self):
|
|
57
|
-
return self.native_instance.getText().toString()
|
|
58
|
-
|
|
59
|
-
class Label:
|
|
60
|
-
native_class = jclass("android.widget.TextView")
|
|
61
|
-
|
|
62
|
-
def __init__(self, text=""):
|
|
63
|
-
self.native_instance = self.native_class()
|
|
64
|
-
self.set_text(text)
|
|
65
|
-
|
|
66
|
-
def set_text(self, text):
|
|
67
|
-
self.native_instance.setText(text)
|
|
68
|
-
|
|
69
|
-
def get_text(self):
|
|
70
|
-
return self.native_instance.getText().toString()
|
|
71
|
-
|
|
72
|
-
else:
|
|
73
|
-
raise PlatformNotDetectedError("Platform could not be detected or is unsupported.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|