forked from carlosperate/ardublockly
-
Notifications
You must be signed in to change notification settings - Fork 0
/
start.py
176 lines (152 loc) · 6.73 KB
/
start.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
# Entry point for the ArdublocklyServer application.
#
# Copyright (c) 2015 carlosperate https://github.com/carlosperate/
# Licensed under the Apache License, Version 2.0 (the "License"):
# http://www.apache.org/licenses/LICENSE-2.0
#
from __future__ import unicode_literals, absolute_import
import os
import re
import sys
import struct
import getopt
import platform
import threading
import webbrowser
import ardublocklyserver.server
import ardublocklyserver.compilersettings
def open_browser(open_file):
"""
Start a browser in a separate thread after waiting for half a second.
"""
def _open_browser():
webbrowser.get().open('http://localhost:%s/%s' %
(ardublocklyserver.server.PORT, open_file))
thread = threading.Timer(0.5, _open_browser)
thread.start()
def find_ardublockly_dir(search_path):
"""
Navigates within each node of a given path and tries to find the Ardublockly
project root directory. It assumes that the project root with have an folder
name ardublockly with an index.html file inside.
This function is required because this script can end up in executable form
in different locations of the project folder, and a literal relative path
should not be assumed.
:param search_path: Path in which to find the Ardublockly root project
folder.
:return: Path to the Ardublockly root folder.
If not found returns None.
"""
path_to_navigate = os.path.normpath(search_path)
# Navigate through each path node starting at the bottom until there are
# no folders left
while path_to_navigate:
# Check if file /ardublokly/index.html exists within current path
if os.path.isfile(
os.path.join(path_to_navigate, 'ardublockly', 'index.html')):
# Found the right folder, return it
return path_to_navigate
path_to_navigate = os.path.dirname(path_to_navigate)
# The right folder wasn't found, so return input path
return None
def parsing_cl_args():
"""
Processes the command line arguments. Arguments supported:
-h / --help
-s / --serverroot <working directory>
:return: Dictionary with available options(keys) and value(value).
"""
# Set option defaults
launch_browser = True
server_root = None
find_project_root = False
if len(sys.argv) == 1:
print("No command line arguments found.")
else:
try:
opts, args = getopt.getopt(
sys.argv[1:],
'hs:bf',
['help', 'serverroot=', 'nobrowser', 'findprojectroot'])
except getopt.GetoptError as e:
print('There was a problem parsing the command line arguments:')
print('\t%s' % e)
sys.exit(1)
for opt, arg in opts:
if opt in ('-h', '--help'):
print('Help flag parsed, these are the current options:\n')
print('\t-s <folder>\tSets the server working directory.')
print('\t-b\t\tSuppresses opening the local browser.')
sys.exit(0)
if opt in ('-s', '--serverroot'):
# Windows only issue: In BlocklyRequestHandler, if chdir is fed
# an 'incorrect' path like 'C:' instead of 'C:\' or C:/' it
# fails silently maintaining the current working directory.
# Use regular expressions to catch this corner case.
if re.match("^[a-zA-Z]:$", arg):
print('The windows drive letter needs to end in a slash, ' +
'eg. %s\\' % arg)
sys.exit(1)
# Check if the value is a valid directory
arg = os.path.normpath(arg)
if os.path.isdir(arg):
server_root = arg
print ('Parsed "%s" flag with "%s" value.' % (opt, arg))
else:
print('Invalid directory "' + arg + '".')
sys.exit(1)
elif opt in ('-b', '--nobrowser'):
launch_browser = False
print ('Parsed "%s" flag. No browser will be opened.' % opt)
elif opt in ('-f', '--findprojectroot'):
find_project_root = True
print ('Parsed "%s" flag. The ardublockly project root will be '
'set as the server root directory.' % opt)
else:
print('Flag ' + opt + ' not recognised.')
return find_project_root, launch_browser, server_root
def main():
"""
Initialises the Settings singleton, resolves paths, and starts the server.
"""
print('Running Python %s (%s bit) on %s' % (platform.python_version(),
(struct.calcsize('P') * 8), platform.platform()))
print('\n\n======= Parsing Command line arguments =======\n')
find_project_root, launch_browser, server_root = parsing_cl_args()
print('\n\n======= Resolving server and project paths =======\n')
# Based on command line options, set the server root to the ardublockly
# project root directory, a directory specified in the arguments, or by
# default to the project root directory.
this_file_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
ardublockly_root_dir = find_ardublockly_dir(this_file_dir)
if ardublockly_root_dir is None:
print('The Ardublockly project root folder could not be found within '
'the %s directory !' % this_file_dir)
sys.exit(1)
print("Ardublockly root directory: %s" % ardublockly_root_dir)
if find_project_root is True or server_root is None:
server_root = ardublockly_root_dir
else:
# Arguments have set a server root, and to not find ardublockly dir
if not os.path.commonprefix([server_root, ardublockly_root_dir]):
print('The Ardublockly project folder needs to be accessible from '
'the server root directory !')
print("Selected server root: %s" % server_root)
print('\n\n======= Loading Settings =======')
# ServerCompilerSettings is a singleton, no need to save instance
ardublocklyserver.compilersettings.ServerCompilerSettings(
ardublockly_root_dir)
print('\n\n======= Starting Server =======\n')
if launch_browser:
# Find the relative path from server root to ardublockly html
ardublockly_html_dir = os.path.join(ardublockly_root_dir, 'ardublockly')
relative_path = os.path.relpath(ardublockly_html_dir, server_root)
print("Ardublockly page relative path from server root: %s" %
relative_path)
open_browser(relative_path)
ardublocklyserver.server.start_server(server_root)
if __name__ == '__main__':
main()