Passed
Pull Request — master (#6)
by Erik
52s
created

pypen.__main__.cli()   B

Complexity

Conditions 7

Size

Total Lines 30
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 30
rs 7.904
c 0
b 0
f 0
cc 7
nop 0
1
import sys
2
import argparse
3
import time
4
from os import path, getcwd
5
6
from importlib import util as import_util
7
8
from pypen.settings import settings
9
import pygame
10
11
_argument_parser = argparse.ArgumentParser()
12
13
def space_print(msg=""):
14
    print()
15
    print(msg)
16
    print()
17
18
def print_help(msg=""):
19
    if msg:
20
        space_print(msg)
21
22
    _argument_parser.print_help(sys.stderr)
23
    sys.exit(0)
24
25
def cli():
26
    global _argument_parser
27
    try:
28
        _argument_parser = argparse.ArgumentParser(description="The PyPen CLI for managing PyPen Sketches", prog="pypen")
29
        _argument_parser.add_argument(
30
            "-i",
31
            "--init",
32
            action="store_true",
33
            help="Flag to create a new PyPen sketch which imports pypen and contains default functions.")
34
35
        _argument_parser.add_argument("filename", nargs="?", help="The name/path of your PyPen Sketch.", default="")
36
        _argument_parser.add_argument("-f", "--fullscreen", action="store_true")
37
        _argument_parser.add_argument("--timeout", help="Timeout in seconds. Window will close once done.", type=float, required=False, default=0.0)
38
39
        arguments = _argument_parser.parse_args()
40
41
        if len(sys.argv) == 1:
42
            print_help("It seems like you are running the pypen command without any arguments.\nHere is some help:")
43
44
        if not arguments.init and not arguments.filename:
45
            print_help("PyPen needs a path to a sketch in order to run it!\nPlease provide a path with 'pypen <path_to_sketch>'\nor run 'pypen --init <path_to_new_sketch>' to create a new one!")
46
47
        if arguments.init:
48
            path_to_new_sketch = arguments.filename if arguments.filename else settings.default_pypen_name
49
            init(path_to_new_sketch)
50
51
        main(arguments)
52
    except argparse.ArgumentError as error:
53
        print(str(error))
54
        sys.exit(1)
55
56
57
def init(path_to_new_file):
58
    if path.splitext(path_to_new_file)[1] != ".py":
59
        path_to_new_file += ".py"
60
61
    pypen_path = path.join(getcwd(), path_to_new_file)
62
    template = ""
63
64
    try:
65
        with open(path.join(path.realpath(__file__), "..", "pypen_template.py"), "r") as template_file:
66
            template = template_file.read()
67
    except EnvironmentError:
68
        # In case PyPen is installed in a directory that doesn't have read access,
69
        # it uses the below template instead of reading the template file
70
        template = """from pypen import *
71
72
73
def start():
74
    settings.fps = 60
75
76
77
def update():
78
    clear()
79
    rectangle(20, 20, 300, 400, "red")
80
"""
81
82
    try:
83
        with open(pypen_path, "w") as new_file:
84
            new_file.writelines(template)
85
    except EnvironmentError:
86
        space_print("Could not create file {}\nDo you have the right permissions?".format(pypen_path))
87
        sys.exit(1)
88
89
    space_print("'{0}' has been created!\nRun it using 'pypen {0}'".format(path_to_new_file))
90
    sys.exit(0)
91
92
93
def main(arguments):
94
    if not arguments.init:
95
        try:
96
            file_path = path.join(getcwd(), arguments.filename)
97
            spec = import_util.spec_from_file_location("", file_path)
98
            user_sketch = import_util.module_from_spec(spec)
99
            spec.loader.exec_module(user_sketch)
100
        except FileNotFoundError:
101
            print()
102
            print(f"Hmm, PyPen can't find '{arguments.filename}'.")
103
            print("Are you sure that's the right path?")
104
            print()
105
            sys.exit(1)
106
107
    try:
108
        user_sketch.TIME
0 ignored issues
show
introduced by
The variable user_sketch does not seem to be defined in case BooleanNotNode on line 94 is False. Are you sure this can never be the case?
Loading history...
109
        user_sketch.T
110
        user_sketch.rectangle
111
        user_sketch.PI
112
    except AttributeError:
113
        print()
114
        print(f"It seems like you're not importing PyPen to your sketch '{arguments.filename}'")
115
        print("Import it by writing 'from pypen import *' at the very top!")
116
        print()
117
        sys.exit(1)
118
119
    try:
120
        user_sketch.start
121
    except AttributeError:
122
        settings._user_has_start = False
123
124
    try:
125
        user_sketch.update
126
    except AttributeError:
127
        settings._user_has_update = False
128
129
    if not settings._user_has_start and not settings._user_has_update:
130
        print()
131
        print(
132
            f"Your PyPen sketch '{arguments.filename}' appears to have neither a start() nor an update() function.")
133
        print("Try to add at least one of those and run again!")
134
        print()
135
        sys.exit(1)
136
137
    def start():
138
        user_sketch.start()
0 ignored issues
show
introduced by
The variable user_sketch does not seem to be defined in case BooleanNotNode on line 94 is False. Are you sure this can never be the case?
Loading history...
139
        if settings._user_has_update:
140
            update()
141
142
    def update(passed_time=0, delta_time=0, frame_count=0):
143
        if not settings._user_has_update:
144
            return
145
        user_sketch.TIME = user_sketch.T = passed_time
0 ignored issues
show
introduced by
The variable user_sketch does not seem to be defined in case BooleanNotNode on line 94 is False. Are you sure this can never be the case?
Loading history...
146
        user_sketch.DELTA_TIME = user_sketch.DT = delta_time
147
        user_sketch.FRAME = user_sketch.F = frame_count
148
149
        user_sketch.update()
150
151
    pygame.init()
152
    pygame.display.set_caption(f"PyPen | {arguments.filename}")
153
154
    pygame.display.set_mode((settings.width, settings.height), pygame.SRCALPHA)
155
156
    if settings._user_has_start:
157
        initial_settings = settings
158
        start()
159
160
        if settings.width != initial_settings.width or settings.height != initial_settings.height:
161
            pygame.display.set_mode((settings.width, settings.height), pygame.SRCALPHA)
162
163
    pygame.display.flip()
164
    clock = pygame.time.Clock()
165
166
    is_running = True
167
    passed_time = frame_count = 0
168
169
    while is_running:
170
        # Handle events
171
        for event in pygame.event.get():
172
            if event.type == pygame.QUIT:
173
                is_running = False
174
175
            if event.type == pygame.KEYDOWN:
176
                if event.key == pygame.K_ESCAPE:
177
                    is_running = False
178
179
        delta_time = clock.tick(settings.fps if settings.fps > 0 else 1)/1000
180
        passed_time += delta_time
181
        frame_count += 1
182
183
        if arguments.timeout > 0:
184
            if passed_time > arguments.timeout:
185
                is_running = False
186
187
        if settings._user_has_update:
188
            update(passed_time, delta_time, frame_count)
189
190
        pygame.display.flip()
191
192
193
if __name__ == "__main__":
194
    cli()
195