exebuilder 0.3.2__tar.gz → 0.5.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exebuilder
3
- Version: 0.3.2
3
+ Version: 0.5.0
4
4
  Summary: A simple EXE builder for Python files.
5
5
  Author: Victor Zou
6
6
  Project-URL: Homepage, https://github.com/qzou1222-alt/exebuilder
@@ -11,7 +11,7 @@ Requires-Dist: pyinstaller
11
11
 
12
12
  # exebuilder
13
13
 
14
- Simple EXE builder for Python files.
14
+ Simple EXE and project builder for Python files.
15
15
 
16
16
  ## Install
17
17
 
@@ -51,16 +51,37 @@ Runs the Python file as a temporary EXE.
51
51
 
52
52
  ---
53
53
 
54
+ ### Make project
55
+
56
+ ```python
57
+
58
+ from exebuilder import Project
59
+
60
+ pjct=Project("my_entry.py")
61
+
62
+ pjct.buildver()
63
+
64
+ ```
65
+
66
+ or
67
+
68
+ ```python
69
+
70
+ project=make_project("my_entry.py")
71
+
72
+ project.buildver()
73
+
74
+ ```
54
75
  ## CLI
55
76
 
56
77
  ```bash
57
- exebuilder my_file.py
78
+ exebuilder my_file.py --logo my_pic.gif
58
79
  ```
59
80
 
60
81
  or
61
82
 
62
83
  ```bash
63
- python exebuilder.py my_file.py
84
+ python exebuilder.py my_file.py --logo my_pic.gif
64
85
  ```
65
86
 
66
87
  creates:
@@ -79,4 +100,6 @@ from exebuilder import build, runasexe
79
100
  build("game.py")
80
101
 
81
102
  runasexe("tool.py")
103
+
104
+ myproject=Project()
82
105
  ```
@@ -1,6 +1,6 @@
1
1
  # exebuilder
2
2
 
3
- Simple EXE builder for Python files.
3
+ Simple EXE and project builder for Python files.
4
4
 
5
5
  ## Install
6
6
 
@@ -40,16 +40,37 @@ Runs the Python file as a temporary EXE.
40
40
 
41
41
  ---
42
42
 
43
+ ### Make project
44
+
45
+ ```python
46
+
47
+ from exebuilder import Project
48
+
49
+ pjct=Project("my_entry.py")
50
+
51
+ pjct.buildver()
52
+
53
+ ```
54
+
55
+ or
56
+
57
+ ```python
58
+
59
+ project=make_project("my_entry.py")
60
+
61
+ project.buildver()
62
+
63
+ ```
43
64
  ## CLI
44
65
 
45
66
  ```bash
46
- exebuilder my_file.py
67
+ exebuilder my_file.py --logo my_pic.gif
47
68
  ```
48
69
 
49
70
  or
50
71
 
51
72
  ```bash
52
- python exebuilder.py my_file.py
73
+ python exebuilder.py my_file.py --logo my_pic.gif
53
74
  ```
54
75
 
55
76
  creates:
@@ -68,4 +89,6 @@ from exebuilder import build, runasexe
68
89
  build("game.py")
69
90
 
70
91
  runasexe("tool.py")
92
+
93
+ myproject=Project()
71
94
  ```
@@ -0,0 +1,226 @@
1
+ """
2
+ Build EXE files from Python files. (v0.4.0)
3
+
4
+ Contents Updated!
5
+ =================
6
+
7
+ Add a make-project tool.
8
+
9
+ Exebuilder
10
+ ==========
11
+
12
+ CLI
13
+ ---
14
+
15
+ exebuilder <file> [--quiet]
16
+ Build a Python file into an EXE using PyInstaller.
17
+
18
+ API
19
+ ---
20
+
21
+ - build(file, logo=None, prt=True)
22
+ Build an EXE from a Python file.
23
+
24
+ - runasexe(file, warnprt=True, buildprt=False)
25
+ Build a temporary EXE and execute it immediately.
26
+
27
+ - Project(entry, name="MyProject", start_version="0.0.0")
28
+ Build a app project.
29
+
30
+ - make_project(entry, name="MyProject")
31
+ Generate a project.
32
+
33
+ Utilities
34
+ ---------
35
+
36
+ - is_pyfile(file)
37
+ Check whether a file is a Python file.
38
+
39
+ - Warnings
40
+ Built-in warning messages.
41
+ """
42
+ from pathlib import Path as _P
43
+ from PIL.Image import Image as _Image
44
+ PILImage=_Image
45
+ __version__ = "0.5.0"
46
+ def is_pyfile(file:str|_P) -> bool:
47
+ '''Return whether a file is a Python file.'''
48
+ if isinstance(file,_P):
49
+ file=file.name
50
+ return file.lower().endswith('.py')
51
+ class _Warnings:
52
+ def __init__(self):
53
+ self.warns:dict[int,str]=dict()
54
+ self._private=False
55
+ def __init_subclass__(cls):
56
+ raise TypeError("[exebuilder._Warnings] cannot be subclass")
57
+ def __setitem__(self, warnindex:int, warn:str):
58
+ if not self._private:
59
+ self.warns[warnindex]=warn
60
+ def __getitem__(self, warnindex:int):
61
+ return self.warns[warnindex]
62
+ Warnings=_Warnings()
63
+ '''Exebuilder's warnings. Use Warnings[index] to get it.'''
64
+ Warnings[1]="[exebuilder] only supports python file"
65
+ Warnings[2]="something wrong when [exebuilder] building"
66
+ Warnings[3]="EXE not found"
67
+ Warnings[4]="something wrong when EXE running"
68
+ Warnings[5]="python file not found"
69
+ def runasexe(pyfile: str | _P, warnprt:bool=True, buildprt:bool=False):
70
+ """Build and run a temporary EXE from a Python file."""
71
+ from tempfile import TemporaryDirectory
72
+ import subprocess
73
+ if not is_pyfile(pyfile):
74
+ if warnprt:
75
+ print(f"Building failed: {Warnings[1]}")
76
+ return False
77
+ if not _P(pyfile).exists():
78
+ if warnprt:
79
+ print(f"Building failed: {Warnings[5]}")
80
+ return False
81
+ with TemporaryDirectory() as temp:
82
+ temp = _P(temp)
83
+ try:
84
+ subprocess.run([
85
+ "pyinstaller",
86
+ "--onefile",
87
+ "--distpath", str(temp),
88
+ "--workpath", str(temp),
89
+ "--specpath", str(temp),
90
+ str(pyfile)
91
+ ],
92
+ stdout=subprocess.DEVNULL if not buildprt else None,
93
+ stderr=subprocess.DEVNULL if not buildprt else None,
94
+ check=True
95
+ )
96
+ except subprocess.CalledProcessError:
97
+ if warnprt:
98
+ print(f"Building failed: {Warnings[2]}")
99
+ return False
100
+ exe = temp / f"{_P(pyfile).stem}.exe"
101
+ if not exe.exists():
102
+ if warnprt:
103
+ print(f"Building failed: {Warnings[3]}")
104
+ return False
105
+ try:
106
+ subprocess.run([str(exe)],check=True)
107
+ except subprocess.CalledProcessError:
108
+ if warnprt:
109
+ print(f"Running failed: {Warnings[4]}")
110
+ return False
111
+ return True
112
+ def build(pyfile:str|_P, name:str|None=None,logo:str|_P|PILImage|None=None,prt:bool=True) -> bool:
113
+ '''Build an EXE from a python file. Prt controls whether messages are printed in the terminal.'''
114
+ import subprocess
115
+ import sys
116
+ import tempfile
117
+ from PIL import Image
118
+ with tempfile.TemporaryDirectory() as temp:
119
+ temp=_P(temp)
120
+ def logo_prep():
121
+ nonlocal logo
122
+ if logo is None:
123
+ return
124
+ elif isinstance(logo,(str,_P)):
125
+ logo=Image.open(logo)
126
+ logo.seek(0)
127
+ logo.save(temp/"logo.ico")
128
+ logo_prep()
129
+ if isinstance(pyfile, _P):
130
+ pyfile=str(pyfile)
131
+ if not _P(pyfile).exists():
132
+ if prt:
133
+ print(f"Building failed: {Warnings[5]}")
134
+ return False
135
+ if not is_pyfile(pyfile):
136
+ if prt:
137
+ print(f"Building failed: {Warnings[1]}")
138
+ return False
139
+ try:
140
+ subprocess.run([
141
+ sys.executable, "-m", "PyInstaller",
142
+ "--onefile",
143
+ *(("--icon",
144
+ str(temp/"logo.ico")) if logo else ()),
145
+ *(("--name",
146
+ name) if name else ()),
147
+ pyfile,
148
+ ],check=True,
149
+ stdout=subprocess.DEVNULL if not prt else None,
150
+ stderr=subprocess.DEVNULL if not prt else None)
151
+ except subprocess.CalledProcessError:
152
+ if prt:
153
+ print(f"Building failed: {Warnings[2]}")
154
+ return False
155
+ if prt:
156
+ print("Building success")
157
+ return True
158
+ LAST_VERSION=object()
159
+ FIRST_VERSION=object()
160
+ class Project:
161
+ '''Simple project. You can use Project(...) to build a project, but make_project(...) is easier.'''
162
+
163
+ def __init__(self, entry:str|_P, name:str="MyProject", start_version:str="0.0.0"):
164
+ if not _P(entry).exists():
165
+ raise FileNotFoundError(entry)
166
+ self.name=name
167
+ self.latest_version=start_version
168
+ self.versions = {
169
+ start_version: {"entry": entry}
170
+ }
171
+ def update(self, new_entry, new_version):
172
+ if not _P(new_entry).exists():
173
+ raise FileNotFoundError(new_entry)
174
+ self._version_check(new_version)
175
+ self.versions[new_version] = {"entry": new_entry}
176
+ self.latest_version = new_version
177
+ def _version_check(self, v: str):
178
+ new_v = self._parse(v)
179
+ last_v = self._parse(self.latest_version)
180
+ if new_v < last_v:
181
+ raise ValueError("v is not the latest version")
182
+ @staticmethod
183
+ def _parse(v:str):
184
+ parts = v.split(".")
185
+ if not all(p.isdigit() for p in parts):
186
+ raise ValueError("Invalid version format")
187
+ return tuple(int(p) for p in parts)
188
+ def buildver(self, version:object|str=LAST_VERSION,showversion:bool=True):
189
+ if version is LAST_VERSION:
190
+ version=self.latest_version
191
+ elif version is FIRST_VERSION:
192
+ version=list(self.versions.keys())[0]
193
+ if version not in self.versions:
194
+ raise ValueError("Version not found")
195
+ if showversion:
196
+ name=f"{self.name}-v{version}"
197
+ else:
198
+ name=self.name
199
+ build(self.versions[version]["entry"],name=name,prt=False)
200
+ def upload(self, dist: str | _P, project: str, channel: str, prt:bool=True):
201
+ '''Upload your app project to itch.io'''
202
+ import subprocess
203
+
204
+ try:
205
+ subprocess.run([
206
+ "butler",
207
+ "push",
208
+ str(dist),
209
+ f"{project}:{channel}"
210
+ ], check=True)
211
+ if prt:
212
+ print("Upload success")
213
+ return True
214
+ except subprocess.CalledProcessError:
215
+ if prt:
216
+ print(f"Upload failed")
217
+ return False
218
+ except FileNotFoundError:
219
+ if prt:
220
+ print("Butler not found")
221
+ return False
222
+ def make_project(entry:str|_P, name:str="MyProject"):
223
+ '''Build a project.'''
224
+ pjct=Project(entry,name)
225
+ return pjct
226
+ Warnings._private=True
@@ -8,6 +8,9 @@ def main():
8
8
  file = args[0]
9
9
  flags = args[1:]
10
10
  prt = "--quiet" not in flags
11
- build(file,prt)
11
+ logo=None
12
+ if "--logo" in flags:
13
+ logo=flags[flags.index("--logo")+1]
14
+ build(file,logo,prt)
12
15
  if __name__ == "__main__":
13
16
  main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exebuilder
3
- Version: 0.3.2
3
+ Version: 0.5.0
4
4
  Summary: A simple EXE builder for Python files.
5
5
  Author: Victor Zou
6
6
  Project-URL: Homepage, https://github.com/qzou1222-alt/exebuilder
@@ -11,7 +11,7 @@ Requires-Dist: pyinstaller
11
11
 
12
12
  # exebuilder
13
13
 
14
- Simple EXE builder for Python files.
14
+ Simple EXE and project builder for Python files.
15
15
 
16
16
  ## Install
17
17
 
@@ -51,16 +51,37 @@ Runs the Python file as a temporary EXE.
51
51
 
52
52
  ---
53
53
 
54
+ ### Make project
55
+
56
+ ```python
57
+
58
+ from exebuilder import Project
59
+
60
+ pjct=Project("my_entry.py")
61
+
62
+ pjct.buildver()
63
+
64
+ ```
65
+
66
+ or
67
+
68
+ ```python
69
+
70
+ project=make_project("my_entry.py")
71
+
72
+ project.buildver()
73
+
74
+ ```
54
75
  ## CLI
55
76
 
56
77
  ```bash
57
- exebuilder my_file.py
78
+ exebuilder my_file.py --logo my_pic.gif
58
79
  ```
59
80
 
60
81
  or
61
82
 
62
83
  ```bash
63
- python exebuilder.py my_file.py
84
+ python exebuilder.py my_file.py --logo my_pic.gif
64
85
  ```
65
86
 
66
87
  creates:
@@ -79,4 +100,6 @@ from exebuilder import build, runasexe
79
100
  build("game.py")
80
101
 
81
102
  runasexe("tool.py")
103
+
104
+ myproject=Project()
82
105
  ```
@@ -8,7 +8,7 @@ Issues = "https://github.com/qzou1222-alt/exebuilder/issues"
8
8
  exebuilder = "exebuilder.__main__:main"
9
9
  [project]
10
10
  name = "exebuilder"
11
- version = "0.3.2"
11
+ version = "0.5.0"
12
12
  authors = [
13
13
  { name="Victor Zou" }
14
14
  ]
@@ -1,151 +0,0 @@
1
- """
2
- Build EXE files from Python files. (v0.3.2)
3
-
4
- Contents Updated!
5
- =================
6
-
7
- 1. Fixed some building and checking bug:
8
-
9
- - runasexe can't catch some error;
10
-
11
- - runasexe doesn't check exe is exists;
12
-
13
- - runasexe building messege is always hidden;
14
-
15
- - runasexe can't check a file is python file.
16
-
17
- 2. Optimized some checking codes:
18
-
19
- - Added more warnings;
20
-
21
- - runasexe parameter "prt" disassemble to two parameters: "warnprt" and "buildprt";
22
-
23
- - All methods support .PY file now;
24
-
25
- - Unified warning messages.
26
-
27
- Exebuilder
28
- ==========
29
-
30
- CLI
31
- ---
32
-
33
- exebuilder <file> [--quiet]
34
- Build a Python file into an EXE using PyInstaller.
35
-
36
- API
37
- ---
38
-
39
- - build(file, prt=True)
40
- Build an EXE from a Python file.
41
-
42
- - runasexe(file, warnprt=True, buildprt=False)
43
- Build a temporary EXE and execute it immediately.
44
-
45
- Utilities
46
- ---------
47
-
48
- - is_pyfile(file)
49
- Check whether a file is a Python file.
50
-
51
- - Warnings
52
- Built-in warning messages.
53
- """
54
- from pathlib import Path as _P
55
- __version__ = "0.3.2"
56
- def is_pyfile(file:str|_P) -> bool:
57
- '''Return whether a file is a Python file.'''
58
- if isinstance(file,_P):
59
- file=file.name
60
- return file.lower().endswith('.py')
61
- class _Warnings:
62
- def __init__(self):
63
- self.warns:dict[int,str]=dict()
64
- self._private=False
65
- def __init_subclass__(cls):
66
- raise TypeError("[exebuilder._Warnings] cannot be subclass")
67
- def __setitem__(self, warnindex:int, warn:str):
68
- if not self._private:
69
- self.warns[warnindex]=warn
70
- def __getitem__(self, warnindex:int):
71
- return self.warns[warnindex]
72
- Warnings=_Warnings()
73
- '''Exebuilder's warnings. Use Warnings[index] to get it.'''
74
- Warnings[1]="[exebuilder] only supports python file"
75
- Warnings[2]="something wrong when [exebuilder] building"
76
- Warnings[3]="EXE not found"
77
- Warnings[4]="something wrong when EXE running"
78
- Warnings[5]="python file not found"
79
- def runasexe(pyfile: str | _P, warnprt:bool=True, buildprt:bool=False):
80
- """Build and run a temporary EXE from a Python file."""
81
- from tempfile import TemporaryDirectory
82
- import subprocess
83
- if not is_pyfile(pyfile):
84
- if warnprt:
85
- print(f"Building failed: {Warnings[1]}")
86
- return False
87
- if not _P(pyfile).exists():
88
- if warnprt:
89
- print(f"Building failed: {Warnings[5]}")
90
- return False
91
- with TemporaryDirectory() as temp:
92
- temp = _P(temp)
93
- try:
94
- subprocess.run([
95
- "pyinstaller",
96
- "--onefile",
97
- "--distpath", str(temp),
98
- "--workpath", str(temp),
99
- "--specpath", str(temp),
100
- str(pyfile)
101
- ],
102
- stdout=subprocess.DEVNULL if not buildprt else None,
103
- stderr=subprocess.DEVNULL if not buildprt else None,
104
- check=True
105
- )
106
- except subprocess.CalledProcessError:
107
- if warnprt:
108
- print(f"Building failed: {Warnings[2]}")
109
- return False
110
- exe = temp / f"{_P(pyfile).stem}.exe"
111
- if not exe.exists():
112
- if warnprt:
113
- print(f"Building failed: {Warnings[3]}")
114
- return False
115
- try:
116
- subprocess.run([str(exe)],check=True)
117
- except subprocess.CalledProcessError:
118
- if warnprt:
119
- print(f"Running failed: {Warnings[4]}")
120
- return False
121
- return True
122
- def build(pyfile:str|_P, prt:bool=True) -> bool:
123
- '''Build an EXE from a python file. Prt controls whether messages are printed in the terminal.'''
124
- import subprocess
125
- import sys
126
- if isinstance(pyfile, _P):
127
- pyfile=str(pyfile)
128
- if not _P(pyfile).exists():
129
- if prt:
130
- print(f"Building failed: {Warnings[5]}")
131
- return False
132
- if not is_pyfile(pyfile):
133
- if prt:
134
- print(f"Building failed: {Warnings[1]}")
135
- return False
136
- try:
137
- subprocess.run([
138
- sys.executable, "-m", "PyInstaller",
139
- "--onefile",
140
- pyfile,
141
- ],check=True,
142
- stdout=subprocess.DEVNULL if not prt else None,
143
- stderr=subprocess.DEVNULL if not prt else None)
144
- except subprocess.CalledProcessError:
145
- if prt:
146
- print(f"Building failed: {Warnings[2]}")
147
- return False
148
- if prt:
149
- print("Building success")
150
- return True
151
- Warnings._private=True
File without changes