From e72864fb66cbaf19c60fad94b4f10cb9c9b39668 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Mon, 24 Apr 2017 09:08:55 +0800 Subject: [PATCH 01/31] Update recur.py --- samples/function/recur.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/function/recur.py b/samples/function/recur.py index 18ec40ae..e3f66076 100755 --- a/samples/function/recur.py +++ b/samples/function/recur.py @@ -16,9 +16,9 @@ def fact(n): def move(n, a, b, c): if n == 1: print('move', a, '-->', c) - return - move(n-1, a, c, b) - print('move', a, '-->', c) - move(n-1, b, a, c) + else: + move(n-1, a, c, b) + move(1, a, b, c) + move(n-1, b, a, c) move(4, 'A', 'B', 'C') From e62485b233e5d326af07f93944b48bf29ce8eb13 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Thu, 16 Nov 2017 09:14:58 +0800 Subject: [PATCH 02/31] update learning.py --- teach/learning.py | 256 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 199 insertions(+), 57 deletions(-) diff --git a/teach/learning.py b/teach/learning.py index 7222f3a6..038dd743 100755 --- a/teach/learning.py +++ b/teach/learning.py @@ -4,40 +4,121 @@ r''' learning.py -A Python 3 tutorial from http://www.liaoxuefeng.com +A Python 3 tutorial from https://www.liaoxuefeng.com Usage: python3 learning.py ''' +# check ####################################################################### + import sys +from datetime import datetime + +CERT_EXPIRES = '2018-07-01' def check_version(): v = sys.version_info - if v.major == 3 and v.minor >= 4: - return True - print('Your current python is %d.%d. Please use Python 3.4.' % (v.major, v.minor)) - return False - -if not check_version(): + if v.major == 3 and v.minor >= 5: + return + print('Your current python is %d.%d. Please use Python 3.6.' % (v.major, v.minor)) exit(1) -import os, io, json, subprocess, tempfile +def check_cert(): + today = datetime.now().strftime('%Y-%m-%d') + if today >= CERT_EXPIRES: + print('This learning.py is expired. Please download a newer version.') + exit(1) + +check_version() +check_cert() + +# start server ################################################################ + +import os, io, json, subprocess, tempfile, ssl from urllib import parse -from wsgiref.simple_server import make_server +from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler EXEC = sys.executable PORT = 39093 -HOST = 'local.liaoxuefeng.com:%d' % PORT TEMP = tempfile.mkdtemp(suffix='_py', prefix='learn_python_') -INDEX = 0 + +HTML_INDEX = r''' + + Learning Python + +
+ +

+
+ + +''' + +class LearningHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_GET(self): + if self.path != '/': + return self.send_error(404) + self._sendHttpHeader('text/html') + self._sendHttpBody(HTML_INDEX) + + def do_POST(self): + if self.path != '/run': + return self.send_error(400) + print('Prepare code...') + body = self.rfile.read(int(self.headers['Content-length'])) + qs = parse.parse_qs(body.decode('utf-8')) + if not 'code' in qs: + return self.send_error(400) + code = qs['code'][0] + r = dict() + try: + fpath = write_py(get_name(), code) + print('Execute: %s %s' % (EXEC, fpath)) + r['output'] = decode(subprocess.check_output([EXEC, fpath], stderr=subprocess.STDOUT, timeout=5)) + except subprocess.CalledProcessError as e: + r = dict(error='Exception', output=decode(e.output)) + except subprocess.TimeoutExpired as e: + r = dict(error='Timeout', output='执行超时') + except subprocess.CalledProcessError as e: + r = dict(error='Error', output='执行错误') + print('Execute done.') + self._sendHttpHeader() + self._sendHttpBody(r) + + def _sendHttpHeader(self, contentType='application/json'): + origin = self.headers['Origin'] or 'https://www.liaoxuefeng.com' + self.send_response(200) + self.send_header('Content-Type', contentType) + self.send_header('Access-Control-Allow-Origin', origin) + self.send_header('Access-Control-Allow-Methods', 'GET,POST') + self.send_header('Access-Control-Max-Age', '86400') + self.end_headers() + + def _sendHttpBody(self, data): + body = b'' + if isinstance(data, bytes): + body = data + elif isinstance(data, str): + body = data.encode('utf-8', errors='ignore') + else: + body = json.dumps(data).encode('utf-8', errors='ignore') + self.wfile.write(body) def main(): - httpd = make_server('127.0.0.1', PORT, application) + certfile = write_cert() + httpd = HTTPServer(('127.0.0.1', PORT), LearningHTTPRequestHandler) + httpd.socket = ssl.wrap_socket(httpd.socket, certfile=certfile, server_side=True) print('Ready for Python code on port %d...' % PORT) + print('Press Ctrl + C to exit...') httpd.serve_forever() +# functions ################################################################### + +INDEX = 0 + def get_name(): global INDEX INDEX = INDEX + 1 @@ -56,51 +137,112 @@ def decode(s): except UnicodeDecodeError: return s.decode('gbk') -def application(environ, start_response): - host = environ.get('HTTP_HOST') - method = environ.get('REQUEST_METHOD') - path = environ.get('PATH_INFO') - if method == 'GET' and path == '/': - start_response('200 OK', [('Content-Type', 'text/html')]) - return [b'Learning Python

'] - if method == 'GET' and path == '/env': - start_response('200 OK', [('Content-Type', 'text/html')]) - L = [b'ENV'] - for k, v in environ.items(): - p = '

%s = %s' % (k, str(v)) - L.append(p.encode('utf-8')) - L.append(b'') - return L - if host != HOST or method != 'POST' or path != '/run' or not environ.get('CONTENT_TYPE', '').lower().startswith('application/x-www-form-urlencoded'): - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"bad_request"}'] - s = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) - qs = parse.parse_qs(s.decode('utf-8')) - if not 'code' in qs: - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"invalid_params"}'] - name = qs['name'][0] if 'name' in qs else get_name() - code = qs['code'][0] - headers = [('Content-Type', 'application/json')] - origin = environ.get('HTTP_ORIGIN', '') - if origin.find('.liaoxuefeng.com') == -1: - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"invalid_origin"}'] - headers.append(('Access-Control-Allow-Origin', origin)) - start_response('200 OK', headers) - r = dict() - try: - fpath = write_py(name, code) - print('Execute: %s %s' % (EXEC, fpath)) - r['output'] = decode(subprocess.check_output([EXEC, fpath], stderr=subprocess.STDOUT, timeout=5)) - except subprocess.CalledProcessError as e: - r = dict(error='Exception', output=decode(e.output)) - except subprocess.TimeoutExpired as e: - r = dict(error='Timeout', output='执行超时') - except subprocess.CalledProcessError as e: - r = dict(error='Error', output='执行错误') - print('Execute done.') - return [json.dumps(r).encode('utf-8')] +# certificate ################################################################# + +def write_cert(): + fpath = os.path.join(TEMP, 'local.liaoxuefeng.com.pem') + with open(fpath, 'w', encoding='utf-8') as f: + f.write(CERT_DATA) + return fpath + +CERT_DATA = r''' +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA5b3zv77bzN8JShoXkVjXFG9NK342wnfgye+NmuSoRfCMPrwL +GToJZiwxokXGyVY8obmQA69WUgonpuotp0AhDK8bOvykKuX+7MyE36sh9TUVOiIw +6D3ODG2E1K5IIEytfGhuPmeJe3OapnL/lJytlLhonu63VEf+jpYh6I/gXD4hZu1N +tx4rOeJLl3qSFgRgX4oBZtO0d4aHop/XW5XcdaeuJxIW5qw7PxXqlch4h9TUs0Og +udko380DrO9pmTuVXr2rtk6Jy96wDAVwsAiSX85FF59Q3QmjDzM+fx8a/vyWkxOw +9dT0DzfZBJ9g/tPk13ir14U1vPpDMO1lIXjKZQIDAQABAoIBAEp+FwT7W8XII/j1 +EOM+DS9BD6KkoBjaSfbwR9gLgEx9PNwymN6rJNUOS2G0gkpSPgKqannnZnPfew/y +Kq9qacz1Ej1EIe8O+GPLxOHJWY9qkOFyqK0FLUR2VnWntRdUBYSrT+PIKpnu2BxU +eW60hswMJ1AxUxxu46lUINaJoFQH7ANHzpCxXFiWDiVK8VCCFS3MaJfqz945zLdg +orHMty+gCcaWRX9wanZ5k9RmX2qzqLAAhlnKIfmItpel8HTppOk1taVDopUgPGd+ +8IG7IANbRlykkeBvlA5soSk7RNM2+crHcdCz5ehoSjMHsY3e99EPoPjKQmb3Ak0p +zgtjPpkCgYEA8p+eULq0OM2anLQeOqQe2QNxkTuriOI2qyobOnCYAJRFlxCLJ8K8 +OIf+srIJUYzJsGmPSqo8iizM5V9bmBRihYnPwePUJS0af8G2vdeJARoAFBo4LZNi +YBN3Gi6hKo8hDgOPQ6D2a25NXYua4z5HlOb8PU6JhX1/6O6yv4ScZh8CgYEA8miG +QxHbx3a7Zfy3/QCQrEwmbp9k49ex/DZvh50N5MqG9h6lb6+ct+qUT7HkvcXUrBxL +6HP7aLVUTTvo9z10sBh1Kt1UQP/57JbKQNMCYKUbMxZH59XdFPzVwkbyDE7Z29tf +8QEMnk9CM6HbvbQDSvOZ04IsfSEstMEPKqVmFvsCgYEAsOSborRdTcTp4zKXj521 +N/gAxyjAKe70eNscOwF4cYOpMTjInFaosHbGxjZ0ANcq/coYxRFVTlDXmqxptXm3 +UzFlHjIjrG80EM2FlOgeZYU1ZXKwXtpEMVQ/1AEHVGZCbVs/CsnCoBUtpvRwGxp/ +ShsW8QPf1EnqBkRyYpwnA3UCgYA5nrLbWnFddlGRKoMpdmrtKaSxAt5ecjTyeJYG +LETTL3jpI9u7MokUBoR+dRCkM1QcHRXGCVunRgLl4Om9azRDb2zaZYXTdYUYwbcN +tZqJEnXmrNMmvmUwyfCdn3OFjXCnm/uwM8mmD7zyvPSYoSNvO3xDFFwy2iHgTUun +nW0o5QKBgQCF/mCu/z1+CsddcHu1RYjnG08uVk0ErjTLB5Qy0YI2NWVE2zdV9fi9 +MWn7S+oEcmjaMdXdF0W/MDyB8TLUSdsXGHPl/vRizK3vhDQGxQ+y3ru8GEVq8BjX +YePMDifbgHDXrCeBeb7TypefD/ScxdVJdI9sPSno20AehzDkXcAssQ== +-----END RSA PRIVATE KEY----- + +-----BEGIN CERTIFICATE----- +MIIFzTCCBLWgAwIBAgIQB594sjWBo6qup5zlKa2F7zANBgkqhkiG9w0BAQsFADCB +lzELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsT +FERvbWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NM +IENBIC0gRzUwHhcNMTcwNzA1MDAwMDAwWhcNMTgwNzA1MjM1OTU5WjAgMR4wHAYD +VQQDDBVsb2NhbC5saWFveHVlZmVuZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDlvfO/vtvM3wlKGheRWNcUb00rfjbCd+DJ742a5KhF8Iw+vAsZ +OglmLDGiRcbJVjyhuZADr1ZSCiem6i2nQCEMrxs6/KQq5f7szITfqyH1NRU6IjDo +Pc4MbYTUrkggTK18aG4+Z4l7c5qmcv+UnK2UuGie7rdUR/6OliHoj+BcPiFm7U23 +His54kuXepIWBGBfigFm07R3hoein9dbldx1p64nEhbmrDs/FeqVyHiH1NSzQ6C5 +2SjfzQOs72mZO5Vevau2TonL3rAMBXCwCJJfzkUXn1DdCaMPMz5/Hxr+/JaTE7D1 +1PQPN9kEn2D+0+TXeKvXhTW8+kMw7WUheMplAgMBAAGjggKJMIIChTAgBgNVHREE +GTAXghVsb2NhbC5saWFveHVlZmVuZy5jb20wCQYDVR0TBAIwADBhBgNVHSAEWjBY +MFYGBmeBDAECATBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2Nw +czAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAfBgNVHSME +GDAWgBRtWMd/GufhPy6mjJc1Qrv00zisPzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l +BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGbBggrBgEFBQcBAQSBjjCBizA8Bggr +BgEFBQcwAYYwaHR0cDovL3RydXN0YXNpYTItb2NzcC5kaWdpdGFsY2VydHZhbGlk +YXRpb24uY29tMEsGCCsGAQUFBzAChj9odHRwOi8vdHJ1c3Rhc2lhMi1haWEuZGln +aXRhbGNlcnR2YWxpZGF0aW9uLmNvbS90cnVzdGFzaWFnNS5jcnQwggEDBgorBgEE +AdZ5AgQCBIH0BIHxAO8AdQDd6x0reg1PpiCLga2BaHB+Lo6dAdVciI09EcTNtuy+ +zAAAAV0QuhtTAAAEAwBGMEQCIERpJLcXX4eFEW02eZMh6EYFW236foQrCsakOgQQ +NW96AiBCE6/7vrUxWKf964i4D9z2NA0TCuXm9giVgQaFju0XXQB2AKS5CZC0GFgU +h7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABXRC6G5MAAAQDAEcwRQIhAK4GeiTU +OQcjGFvLAugOMIEKCEuiJsEu0t+f1ql5Edn2AiAUqqLMw87IkjMnJsbEUGsHkng0 +KL6MLDC3BaHVcH6HsjANBgkqhkiG9w0BAQsFAAOCAQEAYDU2DSBh/63brAW/VWlQ +PQIZzWhji6209MG5hg/RN3Zo9uoz2GodNWwOSkvcFVUz9oBExLfcfhZAsBz26dgs +abWstAje63oduhXU9MR1LDFfG6GLit0Pou0yiS0hfg3jpxpYCIo97QAe8bkuMdRQ +7V09yKKo44M+iXbkIUivnM1ckYJHU9xQ3y8/q/DQajUmVIEPRzmyz6B3tP4WA11T +X5T89OK6osvLcYSJXvxOeR3J8Ohxdwi+PRX4BCgXgTseOj+biwJuCo9z7uwvCoXG +fdilj1tXNa5eDtSRplqbFB+kPGkP/NZ5b1+huarDqE/aeNpmREqONhxi49KB1/9u +1w== +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFZTCCBE2gAwIBAgIQOhAOfxCeGsWcxf/2QNXkQjANBgkqhkiG9w0BAQsFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMTYwODExMDAwMDAwWhcNMjYwODEwMjM1OTU5WjCBlzEL +MAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIElu +Yy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsTFERv +bWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NMIENB +IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39aSJZG/97x3a +6Qmuc9+MubagegRAVUmFYHTYTs8IKB2pM7wXN7W8mekdZaEgUjDFxvRBK/DhTb7U +8ONLsKKdT86aOhzbz2noCTn9wPWnGwkg+/4YKg/dPQQdV9tMsSu0cwqInWHxSAkm +AI1hYFC9D7Sf7Hp/5cRcD+dK454YMRzNOGLQnCVI8JEqrz6o9SOvQNTqTcfqt6DC +0UlXG+MPD1eNPjlzf1Vwaab+VSTgySoC+Ikbq2VsdykeOiGXW/OIiASH7+2LcR05 +PmQ7GEOlM8yzoVojFpM8sHz+WxI05ZOPri5+vX3HhHHjWr5432G0dVmgohnZvlVZ +oy8XrlbpAgMBAAGjggF2MIIBcjASBgNVHRMBAf8ECDAGAQH/AgEAMC8GA1UdHwQo +MCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9wY2EzLWc1LmNybDAOBgNVHQ8B +Af8EBAMCAQYwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJodHRwOi8vcy5z +eW1jZC5jb20wYQYDVR0gBFowWDBWBgZngQwBAgEwTDAjBggrBgEFBQcCARYXaHR0 +cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5 +bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCkGA1Ud +EQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0yLTYwMTAdBgNVHQ4EFgQU +bVjHfxrn4T8upoyXNUK79NM4rD8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6 +Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBABUphhBbeG7scE3EveIN0dOjXPgwgQi8 +I2ZAKYm6DawoGz1lEJVdvFmkyMbP973X80b7mKmn0nNbe1kjA4M0O0hHaMM1ZaEv +7e9vHEAoGyysMO6HzPWYMkyNxcCV7Nos2Uv4RvLDpQHh7P4Kt6fUU13ipcynrtQD +1lFUM0yoTzwwFsPu3Pk+94hL58ErqwqJQwxoHMgLIQeMVHeNKcWFy1bddSbIbCWU +Zs6cMxhrra062ZCpDCbxyEaFNGAtYQMqNz55Z/14XgSUONZ/cJTns6QKhpcgTOwB +fnNzRnk+aWreP7osKhXlz4zs+llP7goBDKFOMMtoEXx3YjJCKgpqmBU= +-----END CERTIFICATE----- +''' + +# start main at last ########################################################## if __name__ == '__main__': main() From 3b42503e5b2288fd9c4cfbf67b3b275a8bd0ea7b Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Fri, 17 Nov 2017 08:36:49 +0800 Subject: [PATCH 03/31] add close_connection=True --- teach/learning.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/teach/learning.py b/teach/learning.py index 038dd743..4335c9e3 100755 --- a/teach/learning.py +++ b/teach/learning.py @@ -59,12 +59,14 @@ def check_cert(): class LearningHTTPRequestHandler(BaseHTTPRequestHandler): def do_GET(self): + self.close_connection = True if self.path != '/': return self.send_error(404) self._sendHttpHeader('text/html') self._sendHttpBody(HTML_INDEX) def do_POST(self): + self.close_connection = True if self.path != '/run': return self.send_error(400) print('Prepare code...') From cf8ca5a27a292d7ae7fecef8e807453f4d6d372b Mon Sep 17 00:00:00 2001 From: Marquez Date: Mon, 28 May 2018 14:49:58 +0800 Subject: [PATCH 04/31] Remove unnecessary module import Remove the import of queue, which is not used --- samples/multitask/task_worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/multitask/task_worker.py b/samples/multitask/task_worker.py index a5d0097e..8155a2b6 100755 --- a/samples/multitask/task_worker.py +++ b/samples/multitask/task_worker.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import time, sys, queue +import time, sys from multiprocessing.managers import BaseManager # 创建类似的QueueManager: From 99a3e8edea105062931da1c65b84662442d23f3f Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sun, 8 Jul 2018 14:29:59 +0800 Subject: [PATCH 05/31] update cert --- teach/learning.py | 169 ++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 87 deletions(-) diff --git a/teach/learning.py b/teach/learning.py index 4335c9e3..77f48dbb 100755 --- a/teach/learning.py +++ b/teach/learning.py @@ -16,7 +16,7 @@ import sys from datetime import datetime -CERT_EXPIRES = '2018-07-01' +CERT_EXPIRES = '2019-07-07' def check_version(): v = sys.version_info @@ -149,98 +149,93 @@ def write_cert(): CERT_DATA = r''' -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIFzTCCBLWgAwIBAgIQB594sjWBo6qup5zlKa2F7zANBgkqhkiG9w0BAQsFADCB -lzELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsT -FERvbWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NM -IENBIC0gRzUwHhcNMTcwNzA1MDAwMDAwWhcNMTgwNzA1MjM1OTU5WjAgMR4wHAYD -VQQDDBVsb2NhbC5saWFveHVlZmVuZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDlvfO/vtvM3wlKGheRWNcUb00rfjbCd+DJ742a5KhF8Iw+vAsZ -OglmLDGiRcbJVjyhuZADr1ZSCiem6i2nQCEMrxs6/KQq5f7szITfqyH1NRU6IjDo -Pc4MbYTUrkggTK18aG4+Z4l7c5qmcv+UnK2UuGie7rdUR/6OliHoj+BcPiFm7U23 -His54kuXepIWBGBfigFm07R3hoein9dbldx1p64nEhbmrDs/FeqVyHiH1NSzQ6C5 -2SjfzQOs72mZO5Vevau2TonL3rAMBXCwCJJfzkUXn1DdCaMPMz5/Hxr+/JaTE7D1 -1PQPN9kEn2D+0+TXeKvXhTW8+kMw7WUheMplAgMBAAGjggKJMIIChTAgBgNVHREE -GTAXghVsb2NhbC5saWFveHVlZmVuZy5jb20wCQYDVR0TBAIwADBhBgNVHSAEWjBY -MFYGBmeBDAECATBMMCMGCCsGAQUFBwIBFhdodHRwczovL2Quc3ltY2IuY29tL2Nw -czAlBggrBgEFBQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAfBgNVHSME -GDAWgBRtWMd/GufhPy6mjJc1Qrv00zisPzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l -BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGbBggrBgEFBQcBAQSBjjCBizA8Bggr -BgEFBQcwAYYwaHR0cDovL3RydXN0YXNpYTItb2NzcC5kaWdpdGFsY2VydHZhbGlk -YXRpb24uY29tMEsGCCsGAQUFBzAChj9odHRwOi8vdHJ1c3Rhc2lhMi1haWEuZGln -aXRhbGNlcnR2YWxpZGF0aW9uLmNvbS90cnVzdGFzaWFnNS5jcnQwggEDBgorBgEE -AdZ5AgQCBIH0BIHxAO8AdQDd6x0reg1PpiCLga2BaHB+Lo6dAdVciI09EcTNtuy+ -zAAAAV0QuhtTAAAEAwBGMEQCIERpJLcXX4eFEW02eZMh6EYFW236foQrCsakOgQQ -NW96AiBCE6/7vrUxWKf964i4D9z2NA0TCuXm9giVgQaFju0XXQB2AKS5CZC0GFgU -h7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABXRC6G5MAAAQDAEcwRQIhAK4GeiTU -OQcjGFvLAugOMIEKCEuiJsEu0t+f1ql5Edn2AiAUqqLMw87IkjMnJsbEUGsHkng0 -KL6MLDC3BaHVcH6HsjANBgkqhkiG9w0BAQsFAAOCAQEAYDU2DSBh/63brAW/VWlQ -PQIZzWhji6209MG5hg/RN3Zo9uoz2GodNWwOSkvcFVUz9oBExLfcfhZAsBz26dgs -abWstAje63oduhXU9MR1LDFfG6GLit0Pou0yiS0hfg3jpxpYCIo97QAe8bkuMdRQ -7V09yKKo44M+iXbkIUivnM1ckYJHU9xQ3y8/q/DQajUmVIEPRzmyz6B3tP4WA11T -X5T89OK6osvLcYSJXvxOeR3J8Ohxdwi+PRX4BCgXgTseOj+biwJuCo9z7uwvCoXG -fdilj1tXNa5eDtSRplqbFB+kPGkP/NZ5b1+huarDqE/aeNpmREqONhxi49KB1/9u -1w== +MIIFlzCCBH+gAwIBAgIQDnY5H0NC4bAIvIdkO1PbfDANBgkqhkiG9w0BAQsFADBy +MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg +SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy +dXN0QXNpYSBUTFMgUlNBIENBMB4XDTE4MDcwODAwMDAwMFoXDTE5MDcwODEyMDAw +MFowIDEeMBwGA1UEAxMVbG9jYWwubGlhb3h1ZWZlbmcuY29tMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEArNs0nkOrt8Bq5latEhaUU9GB6cHwTcuzWaNP +tIBEnREJPyp2S2YqceCH2r6jjdoO+WUH44jteY4G1gz5qnOGrMDum7d5yZxr0XnA +MzKNNvmQ5R+ziOvHSYdk9BVBpx0V3zOW/a97zsJCA/1B+qyyQfWSy6LtbWTgoQ3L +WYdQJ4AjL4jdKcBmsGhs/K+xM8E9xssV6E4Swn6IoUVfLBQzqgRz10ST9cLxhOR7 +k/0QJcESeCMuq7NMJgdR6A74/AOys0jzCugDf8RxJns0M+CJ+91krTdn1l0T2Wy4 +vRjQvAw6Xtdg0mKEvbpxl8LhgcQQwEl3FkjqNqfW0EM2Eb8lHQIDAQABo4ICeTCC +AnUwHwYDVR0jBBgwFoAUf9OZ86BHDjEAVlYijrfMnt3KAYowHQYDVR0OBBYEFD0U +bMsvpjwYAld0A+0MK3wA9cynMCAGA1UdEQQZMBeCFWxvY2FsLmxpYW94dWVmZW5n +LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF +BwMCMEwGA1UdIARFMEMwNwYJYIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0dHBz +Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIBMIGBBggrBgEFBQcBAQR1 +MHMwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwMi5kaWdpY2VydC5jb20wSgYIKwYB +BQUHMAKGPmh0dHA6Ly9jYWNlcnRzLmRpZ2l0YWxjZXJ0dmFsaWRhdGlvbi5jb20v +VHJ1c3RBc2lhVExTUlNBQ0EuY3J0MAkGA1UdEwQCMAAwggEDBgorBgEEAdZ5AgQC +BIH0BIHxAO8AdQC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWR4 +Q3wGAAAEAwBGMEQCICpbOL7rKNzMYP8a+HwjVFhQKROAnlQ3Ig2l5RCJz4zMAiA1 +Lgzf7TUfpvEyU/yqsHNDfzuTrtVA56pPJa4xa9/Q6gB2AId1v+dZfPiMQ5lfvfNu +/1aNR1Y2/0q1YMG06v9eoIMPAAABZHhDe8YAAAQDAEcwRQIgYuPTsE8JwnVMmN0Q +Feq4u5tyO5/nMoGstlouXLwbvbECIQC9zVOzfr+7SmWEES1NMRel++nZhFFQ0pmT +LjhCQPBd2jANBgkqhkiG9w0BAQsFAAOCAQEAIkbLq1OsPZlkBmVNvFWQ6lD9SMc2 ++tuaqPHF2rECQfL8EprUF9KZLP1ye2dUvZodbbB1JcgBPNcz3NX5yTi3CIiNcf/B +qPk5o726hS2Vdyk3rhkNiezNI03UHohHkQ2U4PK4iOSZUgXABjlqyuq6KgoQ00JM +LZXvOnpMPjK3jeiZK46TvPP4FlOfnyx5C1gJBUzbIEMGb9f2jwGklRKyrREJ9Dqq +9C/8q7mEL2+q8COLrX6QQb268+FRm5l0YpRwVF+ciq2jsUO3UX3cJf5SRjq3gvcn +cRROlQJP6aKj8AWyU44RStiJzqzPkFbVQGhrmZ9dtiupZLeNZQLlWAVYlA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFZTCCBE2gAwIBAgIQOhAOfxCeGsWcxf/2QNXkQjANBgkqhkiG9w0BAQsFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMTYwODExMDAwMDAwWhcNMjYwODEwMjM1OTU5WjCBlzEL -MAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIElu -Yy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsTFERv -bWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NMIENB -IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39aSJZG/97x3a -6Qmuc9+MubagegRAVUmFYHTYTs8IKB2pM7wXN7W8mekdZaEgUjDFxvRBK/DhTb7U -8ONLsKKdT86aOhzbz2noCTn9wPWnGwkg+/4YKg/dPQQdV9tMsSu0cwqInWHxSAkm -AI1hYFC9D7Sf7Hp/5cRcD+dK454YMRzNOGLQnCVI8JEqrz6o9SOvQNTqTcfqt6DC -0UlXG+MPD1eNPjlzf1Vwaab+VSTgySoC+Ikbq2VsdykeOiGXW/OIiASH7+2LcR05 -PmQ7GEOlM8yzoVojFpM8sHz+WxI05ZOPri5+vX3HhHHjWr5432G0dVmgohnZvlVZ -oy8XrlbpAgMBAAGjggF2MIIBcjASBgNVHRMBAf8ECDAGAQH/AgEAMC8GA1UdHwQo -MCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9wY2EzLWc1LmNybDAOBgNVHQ8B -Af8EBAMCAQYwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJodHRwOi8vcy5z -eW1jZC5jb20wYQYDVR0gBFowWDBWBgZngQwBAgEwTDAjBggrBgEFBQcCARYXaHR0 -cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5 -bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCkGA1Ud -EQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0yLTYwMTAdBgNVHQ4EFgQU -bVjHfxrn4T8upoyXNUK79NM4rD8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6 -Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBABUphhBbeG7scE3EveIN0dOjXPgwgQi8 -I2ZAKYm6DawoGz1lEJVdvFmkyMbP973X80b7mKmn0nNbe1kjA4M0O0hHaMM1ZaEv -7e9vHEAoGyysMO6HzPWYMkyNxcCV7Nos2Uv4RvLDpQHh7P4Kt6fUU13ipcynrtQD -1lFUM0yoTzwwFsPu3Pk+94hL58ErqwqJQwxoHMgLIQeMVHeNKcWFy1bddSbIbCWU -Zs6cMxhrra062ZCpDCbxyEaFNGAtYQMqNz55Z/14XgSUONZ/cJTns6QKhpcgTOwB -fnNzRnk+aWreP7osKhXlz4zs+llP7goBDKFOMMtoEXx3YjJCKgpqmBU= +MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO +MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL +ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS +U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8 +Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa +e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO +JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA +zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK +ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe +3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K +AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD +AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG +AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au +ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj +ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg +hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t +L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233 +lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ +DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP +ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F +UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C +qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY +RmE= -----END CERTIFICATE----- ''' From b2d7068605353a225524ea04341ae6885c31be22 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Fri, 12 Oct 2018 11:23:37 +0800 Subject: [PATCH 06/31] add ChainMap sample --- samples/commonlib/use_chainmap.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 samples/commonlib/use_chainmap.py diff --git a/samples/commonlib/use_chainmap.py b/samples/commonlib/use_chainmap.py new file mode 100755 index 00000000..406e29e0 --- /dev/null +++ b/samples/commonlib/use_chainmap.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from collections import ChainMap +import os, argparse + +defaults = { + 'color': 'red', + 'user': 'guest' +} + +parser = argparse.ArgumentParser() +parser.add_argument('-u', '--user') +parser.add_argument('-c', '--color') +namespace = parser.parse_args() +command_line_args = { k: v for k, v in vars(namespace).items() if v } + +combined = ChainMap(command_line_args, os.environ, defaults) +print('color=%s' % combined['color']) +print('user=%s' % combined['user']) From dcfcf7bc259f2136885cbd0fd7cbd548af8941e5 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sun, 18 Nov 2018 19:24:37 +0800 Subject: [PATCH 07/31] add turtle sample --- samples/gui/turtle/rect.py | 26 ++++++++++++++++ samples/gui/turtle/stars.py | 16 ++++++++++ samples/gui/turtle/tree.py | 59 +++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 samples/gui/turtle/rect.py create mode 100644 samples/gui/turtle/stars.py create mode 100644 samples/gui/turtle/tree.py diff --git a/samples/gui/turtle/rect.py b/samples/gui/turtle/rect.py new file mode 100644 index 00000000..9bd0e801 --- /dev/null +++ b/samples/gui/turtle/rect.py @@ -0,0 +1,26 @@ +# 导入turtle包的所有内容: +from turtle import * + +# 设置笔刷宽度: +width(4) + +# 前进: +forward(200) +# 右转90度: +right(90) + +# 笔刷颜色: +pencolor('red') +forward(100) +right(90) + +pencolor('green') +forward(200) +right(90) + +pencolor('blue') +forward(100) +right(90) + +# 调用done()使得窗口等待被关闭,否则将立刻关闭窗口: +done() diff --git a/samples/gui/turtle/stars.py b/samples/gui/turtle/stars.py new file mode 100644 index 00000000..3a7db272 --- /dev/null +++ b/samples/gui/turtle/stars.py @@ -0,0 +1,16 @@ +from turtle import * + +def drawStar(x, y): + pu() + goto(x, y) + pd() + # set heading: 0 + seth(0) + for i in range(5): + fd(40) + rt(144) + +for x in range(0, 250, 50): + drawStar(x, 0) + +done() diff --git a/samples/gui/turtle/tree.py b/samples/gui/turtle/tree.py new file mode 100644 index 00000000..43670e39 --- /dev/null +++ b/samples/gui/turtle/tree.py @@ -0,0 +1,59 @@ +from turtle import * + +colormode(255) + +lt(90) + +lv = 14 +l = 120 +s = 45 + +width(lv) + +r = 0 +g = 0 +b = 0 +pencolor(r, g, b) + +penup() +bk(l) +pendown() +fd(l) + +def draw_tree(l, level): + global r, g, b + # save the current pen width + w = width() + + # narrow the pen width + width(w * 3.0 / 4.0) + # set color: + r = r + 1 + g = g + 2 + b = b + 3 + pencolor(r % 200, g % 200, b % 200) + + l = 3.0 / 4.0 * l + + lt(s) + fd(l) + + if level < lv: + draw_tree(l, level + 1) + bk(l) + rt(2 * s) + fd(l) + + if level < lv: + draw_tree(l, level + 1) + bk(l) + lt(s) + + # restore the previous pen width + width(w) + +speed("fastest") + +draw_tree(l, 4) + +done() From 4938a393bbf64bfb431530b48a79888ed585a457 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sun, 7 Jul 2019 10:45:59 +0800 Subject: [PATCH 08/31] update cert --- teach/learning.py | 106 +++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/teach/learning.py b/teach/learning.py index 77f48dbb..edaeb2da 100755 --- a/teach/learning.py +++ b/teach/learning.py @@ -16,11 +16,11 @@ import sys from datetime import datetime -CERT_EXPIRES = '2019-07-07' +CERT_EXPIRES = '2020-08-07' def check_version(): v = sys.version_info - if v.major == 3 and v.minor >= 5: + if v.major == 3 and v.minor >= 6: return print('Your current python is %d.%d. Please use Python 3.6.' % (v.major, v.minor)) exit(1) @@ -149,66 +149,64 @@ def write_cert(): CERT_DATA = r''' -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- - -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- - -----BEGIN CERTIFICATE----- MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 From 516c804f6aab4a8b661bbf70e56e5b5dd2a2ccf9 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sun, 7 Jul 2019 10:50:32 +0800 Subject: [PATCH 09/31] Update learning.py --- teach/learning.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/teach/learning.py b/teach/learning.py index edaeb2da..dbf6cf27 100755 --- a/teach/learning.py +++ b/teach/learning.py @@ -8,7 +8,7 @@ Usage: -python3 learning.py +$ python3 learning.py ''' # check ####################################################################### From b1d67cd7295999810917ce98722c7feb69a792ae Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 17 Mar 2020 15:48:42 +0800 Subject: [PATCH 10/31] Update do_iter.py --- samples/advance/do_iter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/advance/do_iter.py b/samples/advance/do_iter.py index 99ba3702..0ded6af4 100755 --- a/samples/advance/do_iter.py +++ b/samples/advance/do_iter.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from collections import Iterable, Iterator +from collections.abc import Iterable, Iterator def g(): yield 1 From c28549df9bcc2041ef97815d3bf84cf67ec3a4b4 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 5 May 2020 07:43:44 +0800 Subject: [PATCH 11/31] remove teach --- teach/README.md | 25 ---- teach/learning.py | 243 -------------------------------------- teach/run-learning.py.png | Bin 7267 -> 0 bytes 3 files changed, 268 deletions(-) delete mode 100644 teach/README.md delete mode 100755 teach/learning.py delete mode 100644 teach/run-learning.py.png diff --git a/teach/README.md b/teach/README.md deleted file mode 100644 index d5cb2ae8..00000000 --- a/teach/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 安装Python学习助手 - -首先确认Python 3.4已安装。 - -# 下载learning.py - -下载地址: - -[https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/learning.py](https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/learning.py) - -(右键 - 另存为) - -放到某个目录,例如`C:\Work`下。 - -# 运行命令: - -切换到`learning.py`所在目录,运行: - -``` -C:\Work> python learning.py -``` - -如果看到`Ready for Python code on port 39093...`表示运行成功,不要关闭命令行窗口,最小化放到后台运行即可。 - -![run-learning.py.png](https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/run-learning.py.png) diff --git a/teach/learning.py b/teach/learning.py deleted file mode 100755 index dbf6cf27..00000000 --- a/teach/learning.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -r''' -learning.py - -A Python 3 tutorial from https://www.liaoxuefeng.com - -Usage: - -$ python3 learning.py -''' - -# check ####################################################################### - -import sys -from datetime import datetime - -CERT_EXPIRES = '2020-08-07' - -def check_version(): - v = sys.version_info - if v.major == 3 and v.minor >= 6: - return - print('Your current python is %d.%d. Please use Python 3.6.' % (v.major, v.minor)) - exit(1) - -def check_cert(): - today = datetime.now().strftime('%Y-%m-%d') - if today >= CERT_EXPIRES: - print('This learning.py is expired. Please download a newer version.') - exit(1) - -check_version() -check_cert() - -# start server ################################################################ - -import os, io, json, subprocess, tempfile, ssl -from urllib import parse -from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler - -EXEC = sys.executable -PORT = 39093 -TEMP = tempfile.mkdtemp(suffix='_py', prefix='learn_python_') - -HTML_INDEX = r''' - - Learning Python - -

- -

-
- - -''' - -class LearningHTTPRequestHandler(BaseHTTPRequestHandler): - - def do_GET(self): - self.close_connection = True - if self.path != '/': - return self.send_error(404) - self._sendHttpHeader('text/html') - self._sendHttpBody(HTML_INDEX) - - def do_POST(self): - self.close_connection = True - if self.path != '/run': - return self.send_error(400) - print('Prepare code...') - body = self.rfile.read(int(self.headers['Content-length'])) - qs = parse.parse_qs(body.decode('utf-8')) - if not 'code' in qs: - return self.send_error(400) - code = qs['code'][0] - r = dict() - try: - fpath = write_py(get_name(), code) - print('Execute: %s %s' % (EXEC, fpath)) - r['output'] = decode(subprocess.check_output([EXEC, fpath], stderr=subprocess.STDOUT, timeout=5)) - except subprocess.CalledProcessError as e: - r = dict(error='Exception', output=decode(e.output)) - except subprocess.TimeoutExpired as e: - r = dict(error='Timeout', output='执行超时') - except subprocess.CalledProcessError as e: - r = dict(error='Error', output='执行错误') - print('Execute done.') - self._sendHttpHeader() - self._sendHttpBody(r) - - def _sendHttpHeader(self, contentType='application/json'): - origin = self.headers['Origin'] or 'https://www.liaoxuefeng.com' - self.send_response(200) - self.send_header('Content-Type', contentType) - self.send_header('Access-Control-Allow-Origin', origin) - self.send_header('Access-Control-Allow-Methods', 'GET,POST') - self.send_header('Access-Control-Max-Age', '86400') - self.end_headers() - - def _sendHttpBody(self, data): - body = b'' - if isinstance(data, bytes): - body = data - elif isinstance(data, str): - body = data.encode('utf-8', errors='ignore') - else: - body = json.dumps(data).encode('utf-8', errors='ignore') - self.wfile.write(body) - -def main(): - certfile = write_cert() - httpd = HTTPServer(('127.0.0.1', PORT), LearningHTTPRequestHandler) - httpd.socket = ssl.wrap_socket(httpd.socket, certfile=certfile, server_side=True) - print('Ready for Python code on port %d...' % PORT) - print('Press Ctrl + C to exit...') - httpd.serve_forever() - -# functions ################################################################### - -INDEX = 0 - -def get_name(): - global INDEX - INDEX = INDEX + 1 - return 'test_%d' % INDEX - -def write_py(name, code): - fpath = os.path.join(TEMP, '%s.py' % name) - with open(fpath, 'w', encoding='utf-8') as f: - f.write(code) - print('Code wrote to: %s' % fpath) - return fpath - -def decode(s): - try: - return s.decode('utf-8') - except UnicodeDecodeError: - return s.decode('gbk') - -# certificate ################################################################# - -def write_cert(): - fpath = os.path.join(TEMP, 'local.liaoxuefeng.com.pem') - with open(fpath, 'w', encoding='utf-8') as f: - f.write(CERT_DATA) - return fpath - -CERT_DATA = r''' ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEArUtX5vRI7RsCBEN8sIPskQyLJhsXzxQ947dcH2so0uuCYodm -wkuKwMtjCvP5nnM2PRaJMSD3ke4OA2BdD+CWGFmoXdD8yJbAOh6da4boOi2Rh174 -YlZLcpGBhbqprXlRC1Ip0jzW38y4dOW9m9L1QEALoHZ6vJG1sYouLEfPLubI9+bg -VO1WipHBebuT4OosivsJxBhNqe1dR7rCkCjV1v/iBmbJCujrH9rri12LmksL0HhW -7V5mccae07mao0tfu1esFeLqYWM7+heQ82qXwg1WfbztXWJkP088fPjFGWSAVcZS -9RzPEt/lC34If15AqSEr60zKDkQ1olU36YHO+wIDAQABAoIBAAGuaJ4VLPyelaCX -S7HmDcOt1KRxgIPMpU8SG9gy23S0aTxDJl7oibeWIZIHzO+vHCMalrPTJzkTZK++ -sxhw1t6fRrq7nirktN0Q0qPU7WgxwfwyEoSDDtH/5xBLlSgu3veWUVE4sDhVTaLW -Cca7FLsOBAQyB2h7R2vUtImkcWD57c4kDH90hN8htl+KFhMrBctiRbzvcB2tk/xO -e46YJ1GSRQg3OQQGQJeDczAoGzsv20pYuvDmqlhrQC64Zxxz7nZfftbCztvuVoPj -RGLRm/wRXPjujqBXivePanxYLP4dUOa6/NK7J5uea41e3CHIPTk1id4G15Knkypv -vQcJ2/kCgYEA3LAwxc/+DR3uwbcM5ZWeFK+16LfR+fF/ZNtm2vHuN458ZpcbBELO -rhUmye30LE0wwSPgPtjkXQ2r2BZD9fzji2jIGaWtsSvigjhMGRWOhVtlfB5kBNx+ -Kk3PjunOId+HodVvOQxxXWbljiLQCNG3di7r+7ojcsj+ruos7iBSZ5kCgYEAyQXO -rLx9WP+xoCu3OV1PD5LFcvb/x9R3xMzEsZGYh/s969bNHkPvT/4BFcMBVv8X0WdE -kY04YJd3m1XzmOXeTR7XSZhG0sekYRbnEl8aWyMTmuhtjXwPHYReTx9ZEl3oRTfY -lubd51QPnArwGD+E9+1i2uCNjbFiDOv/+Tedt7MCgYEAjfLeTD5OoM1CB2PgbcPg -3Flw3nFuJCCL2qms7ON0YFPL/IjxHbqDCkIcowHlbqFv3Ktgz8veh2QFxoX7zLuO -+Nq66pRAtpcNqMjhWbkd5PU2v7EkkGPq2vcVrE0DA5KtwRBx6/Xu7S8ENHp76VBL -ez8PFulRZ8GU35lMsRYlKvECgYEAl1tRBwyREK7NTj08IuwXuDEZi/tgEVTvrPVE -8DIg99n7AJTmMnCSQteMd5cxbhB6HYg0v6bmGQxS2Vm5JZmGbOjYzqfiQ5hgM14s -M8/5pz9c5pk0y3/qXZ4p6EdBKKweU+e9o7lGwYOwkRxHNOq2snpBoW3MBzDVE8eq -Hzp5/TMCgYAomXNpRtHcXt2VhJR0FefYOfj4n4cGAtg8/dNlJSzkhR6ad2KniCz1 -KgedQRAsqRSh0UZgTTxPA5Y/zpAvmAHFB7fr9syWb1QSBBvgLWkzpUgaEEJBRjwu -s2urAziMIcPf+mZf9rFscD/JKYQo3fHSd/UWTSM0SkQNu7uHqcgN8g== ------END RSA PRIVATE KEY----- ------BEGIN CERTIFICATE----- -MIIFkjCCBHqgAwIBAgIQAt7xtFqJsgRZGvKRMyO9njANBgkqhkiG9w0BAQsFADBy -MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg -SW5jLjEdMBsGA1UECxMURG9tYWluIFZhbGlkYXRlZCBTU0wxHTAbBgNVBAMTFFRy -dXN0QXNpYSBUTFMgUlNBIENBMB4XDTE5MDYwOTAwMDAwMFoXDTIwMDgwNzEyMDAw -MFowIDEeMBwGA1UEAxMVbG9jYWwubGlhb3h1ZWZlbmcuY29tMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEArUtX5vRI7RsCBEN8sIPskQyLJhsXzxQ947dc -H2so0uuCYodmwkuKwMtjCvP5nnM2PRaJMSD3ke4OA2BdD+CWGFmoXdD8yJbAOh6d -a4boOi2Rh174YlZLcpGBhbqprXlRC1Ip0jzW38y4dOW9m9L1QEALoHZ6vJG1sYou -LEfPLubI9+bgVO1WipHBebuT4OosivsJxBhNqe1dR7rCkCjV1v/iBmbJCujrH9rr -i12LmksL0HhW7V5mccae07mao0tfu1esFeLqYWM7+heQ82qXwg1WfbztXWJkP088 -fPjFGWSAVcZS9RzPEt/lC34If15AqSEr60zKDkQ1olU36YHO+wIDAQABo4ICdDCC -AnAwHwYDVR0jBBgwFoAUf9OZ86BHDjEAVlYijrfMnt3KAYowHQYDVR0OBBYEFOe3 -Dec5wHbk5Hf8h6l2DDHgHxHhMCAGA1UdEQQZMBeCFWxvY2FsLmxpYW94dWVmZW5n -LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF -BwMCMEwGA1UdIARFMEMwNwYJYIZIAYb9bAECMCowKAYIKwYBBQUHAgEWHGh0dHBz -Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQIBMH0GCCsGAQUFBwEBBHEw -bzAhBggrBgEFBQcwAYYVaHR0cDovL29jc3AuZGNvY3NwLmNuMEoGCCsGAQUFBzAC -hj5odHRwOi8vY2FjZXJ0cy5kaWdpdGFsY2VydHZhbGlkYXRpb24uY29tL1RydXN0 -QXNpYVRMU1JTQUNBLmNydDAJBgNVHRMEAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB -8QDvAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFrOiI+ygAA -BAMARjBEAiAGlx0z2YTgQMyVva5eRZTnry0rUjPGCXWP1Y4/XgpO9wIgSBtIfCjH -GC+xLuvUOEQZAfnh6xoDFJ6urTk/tdkJ/BYAdgCHdb/nWXz4jEOZX73zbv9WjUdW -Nv9KtWDBtOr/XqCDDwAAAWs6Ij+WAAAEAwBHMEUCIQDNqJG+8r5IwXDOLHyfUkg8 -XpkaMYjncE5mSMLwyprt1gIgLAilaTtP0zlar11n3LTVhz/XG8o5kUoFIgps/cDS -PN0wDQYJKoZIhvcNAQELBQADggEBAEPFPqZE03u06PZ9jMpoke4CXHF3iTBABuTA -//g6w7Pn/DlMuHs5OS2S4RXQs5QJfdLpS7TsYatYmfhDO+b13QuBM/09BFh+KXsJ -ITbS9omy8eB/IK+OGCIJwoj1psoU4tw/MO2sly5N8rgJgYytD1U0+BbDIhWY1jlK -lP3rTkV1OkoGfPFzjjqk5VIiNdGXqn/aeXMbycbyyyDGwhLmqMARWLiDvQLywwzu -cGxJS4s+oP4SIYVH+sfyG51fRSTIyqzI8tP1MNuPi1R6r88NijyQ+f/tQs8R3OB+ -AHcthgqp6TI5qsN89vJzqD4NTBBrCcyU1PshW5rAjJelnJlmfIU= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIErjCCA5agAwIBAgIQBYAmfwbylVM0jhwYWl7uLjANBgkqhkiG9w0BAQsFADBh -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -QTAeFw0xNzEyMDgxMjI4MjZaFw0yNzEyMDgxMjI4MjZaMHIxCzAJBgNVBAYTAkNO -MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMR0wGwYDVQQL -ExREb21haW4gVmFsaWRhdGVkIFNTTDEdMBsGA1UEAxMUVHJ1c3RBc2lhIFRMUyBS -U0EgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgWa9X+ph+wAm8 -Yh1Fk1MjKbQ5QwBOOKVaZR/OfCh+F6f93u7vZHGcUU/lvVGgUQnbzJhR1UV2epJa -e+m7cxnXIKdD0/VS9btAgwJszGFvwoqXeaCqFoP71wPmXjjUwLT70+qvX4hdyYfO -JcjeTz5QKtg8zQwxaK9x4JT9CoOmoVdVhEBAiD3DwR5fFgOHDwwGxdJWVBvktnoA -zjdTLXDdbSVC5jZ0u8oq9BiTDv7jAlsB5F8aZgvSZDOQeFrwaOTbKWSEInEhnchK -ZTD1dz6aBlk1xGEI5PZWAnVAba/ofH33ktymaTDsE6xRDnW97pDkimCRak6CEbfe -3dXw6OV5AgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUf9OZ86BHDjEAVlYijrfMnt3K -AYowHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQD -AgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAG -AQH/AgEAMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au -ZGlnaWNlcnQuY29tMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2lj -ZXJ0LmNvbS9EaWdpQ2VydEdsb2JhbFJvb3RDQS5jcmwwTAYDVR0gBEUwQzA3Bglg -hkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29t -L0NQUzAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAK3dVOj5dlv4MzK2i233 -lDYvyJ3slFY2X2HKTYGte8nbK6i5/fsDImMYihAkp6VaNY/en8WZ5qcrQPVLuJrJ -DSXT04NnMeZOQDUoj/NHAmdfCBB/h1bZ5OGK6Sf1h5Yx/5wR4f3TUoPgGlnU7EuP -ISLNdMRiDrXntcImDAiRvkh5GJuH4YCVE6XEntqaNIgGkRwxKSgnU3Id3iuFbW9F -UQ9Qqtb1GX91AJ7i4153TikGgYCdwYkBURD8gSVe8OAco6IfZOYt/TEwii1Ivi1C -qnuUlWpsF1LdQNIdfbW3TSe0BhQa7ifbVIfvPWHYOu3rkg1ZeMo6XRU9B4n5VyJY -RmE= ------END CERTIFICATE----- -''' - -# start main at last ########################################################## - -if __name__ == '__main__': - main() diff --git a/teach/run-learning.py.png b/teach/run-learning.py.png deleted file mode 100644 index d9491a959eb2ed5da4a012904951a30c3b23df49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7267 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 From 6141e7d0b1a1027caa27be5972a1f8765727aa5e Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 5 May 2020 07:46:13 +0800 Subject: [PATCH 12/31] add hellorobot --- .../hellorobot/hellorobot/.vscode/extensions.json | 13 +++++++++++++ .../hellorobot/hellorobot/.vscode/launch.json | 14 ++++++++++++++ .../hellorobot/hellorobot/.vscode/settings.json | 6 ++++++ samples/micropython/hellorobot/hellorobot/main.py | 14 ++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 samples/micropython/hellorobot/hellorobot/.vscode/extensions.json create mode 100644 samples/micropython/hellorobot/hellorobot/.vscode/launch.json create mode 100644 samples/micropython/hellorobot/hellorobot/.vscode/settings.json create mode 100644 samples/micropython/hellorobot/hellorobot/main.py diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/extensions.json b/samples/micropython/hellorobot/hellorobot/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/hellorobot/hellorobot/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "lego-education.ev3-micropython" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "ms-python.python" + ] +} \ No newline at end of file diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/launch.json b/samples/micropython/hellorobot/hellorobot/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/hellorobot/hellorobot/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Download and Run", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py" + } + ] +} diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/settings.json b/samples/micropython/hellorobot/hellorobot/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/hellorobot/hellorobot/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/samples/micropython/hellorobot/hellorobot/main.py b/samples/micropython/hellorobot/hellorobot/main.py new file mode 100644 index 00000000..d51e43bd --- /dev/null +++ b/samples/micropython/hellorobot/hellorobot/main.py @@ -0,0 +1,14 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks import ev3brick as brick +from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) +from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) +from pybricks.tools import print, wait, StopWatch +from pybricks.robotics import DriveBase + +# Write your program here +brick.sound.beep() +# 输出到控制台: +print('Hello, robot!') +# 输出到EV3屏幕: +brick.display.text('Hello, robot!') From 2c9b880d5b242f37a9acba92af2bf39403ab123d Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 5 May 2020 07:47:54 +0800 Subject: [PATCH 13/31] move --- .../hellorobot/{hellorobot => }/.vscode/extensions.json | 0 .../micropython/hellorobot/{hellorobot => }/.vscode/launch.json | 0 .../micropython/hellorobot/{hellorobot => }/.vscode/settings.json | 0 samples/micropython/hellorobot/{hellorobot => }/main.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename samples/micropython/hellorobot/{hellorobot => }/.vscode/extensions.json (100%) rename samples/micropython/hellorobot/{hellorobot => }/.vscode/launch.json (100%) rename samples/micropython/hellorobot/{hellorobot => }/.vscode/settings.json (100%) rename samples/micropython/hellorobot/{hellorobot => }/main.py (100%) diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/extensions.json b/samples/micropython/hellorobot/.vscode/extensions.json similarity index 100% rename from samples/micropython/hellorobot/hellorobot/.vscode/extensions.json rename to samples/micropython/hellorobot/.vscode/extensions.json diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/launch.json b/samples/micropython/hellorobot/.vscode/launch.json similarity index 100% rename from samples/micropython/hellorobot/hellorobot/.vscode/launch.json rename to samples/micropython/hellorobot/.vscode/launch.json diff --git a/samples/micropython/hellorobot/hellorobot/.vscode/settings.json b/samples/micropython/hellorobot/.vscode/settings.json similarity index 100% rename from samples/micropython/hellorobot/hellorobot/.vscode/settings.json rename to samples/micropython/hellorobot/.vscode/settings.json diff --git a/samples/micropython/hellorobot/hellorobot/main.py b/samples/micropython/hellorobot/main.py similarity index 100% rename from samples/micropython/hellorobot/hellorobot/main.py rename to samples/micropython/hellorobot/main.py From 0b88c208918d51fef9025d4144c70c90db7671a6 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 5 May 2020 10:34:57 +0800 Subject: [PATCH 14/31] add smallcar --- .../smallcar/.vscode/extensions.json | 13 +++++ .../micropython/smallcar/.vscode/launch.json | 14 +++++ .../smallcar/.vscode/settings.json | 7 +++ samples/micropython/smallcar/main.py | 51 +++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 samples/micropython/smallcar/.vscode/extensions.json create mode 100644 samples/micropython/smallcar/.vscode/launch.json create mode 100644 samples/micropython/smallcar/.vscode/settings.json create mode 100644 samples/micropython/smallcar/main.py diff --git a/samples/micropython/smallcar/.vscode/extensions.json b/samples/micropython/smallcar/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/smallcar/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "lego-education.ev3-micropython" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "ms-python.python" + ] +} \ No newline at end of file diff --git a/samples/micropython/smallcar/.vscode/launch.json b/samples/micropython/smallcar/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/smallcar/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Download and Run", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py" + } + ] +} diff --git a/samples/micropython/smallcar/.vscode/settings.json b/samples/micropython/smallcar/.vscode/settings.json new file mode 100644 index 00000000..a9e3a557 --- /dev/null +++ b/samples/micropython/smallcar/.vscode/settings.json @@ -0,0 +1,7 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false, + "python.formatting.provider": "autopep8" +} diff --git a/samples/micropython/smallcar/main.py b/samples/micropython/smallcar/main.py new file mode 100644 index 00000000..9ddd7aec --- /dev/null +++ b/samples/micropython/smallcar/main.py @@ -0,0 +1,51 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks import ev3brick as brick +from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) +from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) +from pybricks.tools import print, wait, StopWatch +from pybricks.robotics import DriveBase + +# Write your program here + +motor = Motor(Port.B) +ultrasonic = UltrasonicSensor(Port.S4) + +brick.sound.beep() +brick.light(None) + +speed = 0 +colors = [None, Color.GREEN, Color.YELLOW, Color.RED] + +def setSpeed(acc): + global speed + if acc < 0: + speed = max(0, speed - 1) + elif acc > 0: + speed = min(3, speed + 1) + else: + speed = 0 + if speed > 0: + motor.run(speed * 90) + else: + motor.stop() + brick.light(colors[speed]) + +while True: + if not any(brick.buttons()): + wait(10) + else: + if Button.LEFT in brick.buttons(): + setSpeed(-1) + elif Button.RIGHT in brick.buttons(): + setSpeed(1) + elif Button.CENTER in brick.buttons(): + setSpeed(0) + elif Button.UP in brick.buttons(): + setSpeed(0) + break + wait(500) + if ultrasonic.distance() < 200: + setSpeed(0) + +brick.sound.beep() From 7827c77fb4ee5e6a6720248d98f042cf7e46a6dc Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 6 May 2020 08:23:54 +0800 Subject: [PATCH 15/31] add rccar --- .../micropython/rccar/.vscode/extensions.json | 13 +++ samples/micropython/rccar/.vscode/launch.json | 14 +++ .../micropython/rccar/.vscode/settings.json | 6 ++ samples/micropython/rccar/devices.py | 47 ++++++++ samples/micropython/rccar/main.py | 100 ++++++++++++++++++ 5 files changed, 180 insertions(+) create mode 100644 samples/micropython/rccar/.vscode/extensions.json create mode 100644 samples/micropython/rccar/.vscode/launch.json create mode 100644 samples/micropython/rccar/.vscode/settings.json create mode 100644 samples/micropython/rccar/devices.py create mode 100644 samples/micropython/rccar/main.py diff --git a/samples/micropython/rccar/.vscode/extensions.json b/samples/micropython/rccar/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/rccar/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "lego-education.ev3-micropython" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "ms-python.python" + ] +} \ No newline at end of file diff --git a/samples/micropython/rccar/.vscode/launch.json b/samples/micropython/rccar/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/rccar/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Download and Run", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py" + } + ] +} diff --git a/samples/micropython/rccar/.vscode/settings.json b/samples/micropython/rccar/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/rccar/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/samples/micropython/rccar/devices.py b/samples/micropython/rccar/devices.py new file mode 100644 index 00000000..0c6c133c --- /dev/null +++ b/samples/micropython/rccar/devices.py @@ -0,0 +1,47 @@ +# list input devices + +class InputDevice(): + def __init__(self): + self.name = '' + self.handler = '' + + def __str__(self): + return '' % (self.name, self.handler) + + def setName(self, name): + if len(name) >= 2 and name.startswith('"') and name.endswith('"'): + name = name[1:len(name)-1] + self.name = name + + def setHandler(self, handlers): + for handler in handlers.split(' '): + if handler.startswith('event'): + self.handler = handler + +def listDevices(): + devices = [] + with open('/proc/bus/input/devices', 'r') as f: + device = None + while True: + s = f.readline() + if s == '': + break + s = s.strip() + if s == '': + devices.append(device) + device = None + else: + if device is None: + device = InputDevice() + if s.startswith('N: Name='): + device.setName(s[8:]) + elif s.startswith('H: Handlers='): + device.setHandler(s[12:]) + return devices + +def detectJoystick(joystickNames): + for device in listDevices(): + for joystickName in joystickNames: + if joystickName in device.name: + return '/dev/input/%s' % device.handler + return None diff --git a/samples/micropython/rccar/main.py b/samples/micropython/rccar/main.py new file mode 100644 index 00000000..595133d5 --- /dev/null +++ b/samples/micropython/rccar/main.py @@ -0,0 +1,100 @@ +#!/usr/bin/env pybricks-micropython + +import struct, threading + +from pybricks import ev3brick as brick +from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) +from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) +from pybricks.tools import print, wait, StopWatch +from pybricks.robotics import DriveBase +from devices import detectJoystick + +class Robot(): + def __init__(self): + self.motor = Motor(Port.B) + self.ultrasonic = UltrasonicSensor(Port.S4) + self.active = True + self.speed = 0 + self.colors = [None, Color.GREEN, Color.YELLOW, Color.RED] + + def setSpeed(self, acc): + if acc < 0: + self.speed = max(-3, self.speed - 1) + elif acc > 0: + self.speed = min(3, self.speed + 1) + else: + self.speed = 0 + if self.speed != 0: + self.motor.run(self.speed * 90) + else: + self.motor.stop() + brick.light(self.colors[abs(self.speed)]) + + def inactive(self): + self.active = False + self.setSpeed(0) + brick.sound.beep() + +def autoStopLoop(robot): + while robot.active: + if robot.speed > 0 and robot.ultrasonic.distance() < 200: + robot.setSpeed(0) + wait(100) + +def joystickLoop(robot, eventFile): + FORMAT = 'llHHI' + EVENT_SIZE = struct.calcsize(FORMAT) + with open(eventFile, 'rb') as infile: + while True: + event = infile.read(EVENT_SIZE) + _, _, t, c, v = struct.unpack(FORMAT, event) + # button A, B: + if t == 1 and v == 1: + if c == 305: + # press A: + robot.setSpeed(1) + elif c == 304: + # press B: + robot.setSpeed(-1) + elif c == 307: + # press X: + return robot.inactive() + elif t == 3: + if c == 1: + # Left stick & verticle: + speed = 0 + if v < 32768: + # up: + speed = 1 + elif v > 32768: + # down: + speed = -1 + robot.setSpeed(speed) + +def buttonLoop(robot): + while True: + if not any(brick.buttons()): + wait(10) + else: + if Button.LEFT in brick.buttons(): + robot.setSpeed(-1) + elif Button.RIGHT in brick.buttons(): + robot.setSpeed(1) + elif Button.CENTER in brick.buttons(): + robot.setSpeed(0) + elif Button.UP in brick.buttons(): + return robot.inactive() + wait(500) + +def main(): + brick.sound.beep() + joystickEvent = detectJoystick(['Controller']) + robot = Robot() + t = threading.Thread(target=autoStopLoop, args=(robot,)) + t.start() + if joystickEvent: + joystickLoop(robot, joystickEvent) + else: + buttonLoop(robot) + +main() From 9abe1777fba8a3d1af4f9f6143c7ef0695335971 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Thu, 7 May 2020 15:15:34 +0800 Subject: [PATCH 16/31] add tank --- .../micropython/tank/.vscode/extensions.json | 13 +++ samples/micropython/tank/.vscode/launch.json | 14 +++ .../micropython/tank/.vscode/settings.json | 6 + samples/micropython/tank/cannon.wav | Bin 0 -> 141378 bytes samples/micropython/tank/devices.py | 47 ++++++++ samples/micropython/tank/joystick.py | 61 +++++++++++ samples/micropython/tank/main.py | 103 ++++++++++++++++++ 7 files changed, 244 insertions(+) create mode 100644 samples/micropython/tank/.vscode/extensions.json create mode 100644 samples/micropython/tank/.vscode/launch.json create mode 100644 samples/micropython/tank/.vscode/settings.json create mode 100644 samples/micropython/tank/cannon.wav create mode 100644 samples/micropython/tank/devices.py create mode 100644 samples/micropython/tank/joystick.py create mode 100644 samples/micropython/tank/main.py diff --git a/samples/micropython/tank/.vscode/extensions.json b/samples/micropython/tank/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/tank/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "lego-education.ev3-micropython" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "ms-python.python" + ] +} \ No newline at end of file diff --git a/samples/micropython/tank/.vscode/launch.json b/samples/micropython/tank/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/tank/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Download and Run", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py" + } + ] +} diff --git a/samples/micropython/tank/.vscode/settings.json b/samples/micropython/tank/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/tank/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/samples/micropython/tank/cannon.wav b/samples/micropython/tank/cannon.wav new file mode 100644 index 0000000000000000000000000000000000000000..ee0d010272b91dc47a95f79ec4ef58541d6f7301 GIT binary patch literal 141378 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�evWZ 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%0DF7}ADV|ZU>mS&`D^*>kaZX0hxmUY_pTS$ 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 F_!kg_-TnXo literal 0 HcmV?d00001 diff --git a/samples/micropython/tank/devices.py b/samples/micropython/tank/devices.py new file mode 100644 index 00000000..0c6c133c --- /dev/null +++ b/samples/micropython/tank/devices.py @@ -0,0 +1,47 @@ +# list input devices + +class InputDevice(): + def __init__(self): + self.name = '' + self.handler = '' + + def __str__(self): + return '' % (self.name, self.handler) + + def setName(self, name): + if len(name) >= 2 and name.startswith('"') and name.endswith('"'): + name = name[1:len(name)-1] + self.name = name + + def setHandler(self, handlers): + for handler in handlers.split(' '): + if handler.startswith('event'): + self.handler = handler + +def listDevices(): + devices = [] + with open('/proc/bus/input/devices', 'r') as f: + device = None + while True: + s = f.readline() + if s == '': + break + s = s.strip() + if s == '': + devices.append(device) + device = None + else: + if device is None: + device = InputDevice() + if s.startswith('N: Name='): + device.setName(s[8:]) + elif s.startswith('H: Handlers='): + device.setHandler(s[12:]) + return devices + +def detectJoystick(joystickNames): + for device in listDevices(): + for joystickName in joystickNames: + if joystickName in device.name: + return '/dev/input/%s' % device.handler + return None diff --git a/samples/micropython/tank/joystick.py b/samples/micropython/tank/joystick.py new file mode 100644 index 00000000..0379051c --- /dev/null +++ b/samples/micropython/tank/joystick.py @@ -0,0 +1,61 @@ +# joystick control: + +import struct + +# define button code: + +BUTTON_A = 305 +BUTTON_B = 304 +BUTTON_X = 307 +BUTTON_Y = 306 +BUTTON_PLUS = 313 +BUTTON_MINUS = 312 +BUTTON_START = 317 +BUTTON_HOME = 316 + +class JoyStick(): + def __init__(self, eventFile): + self.eventFile = eventFile + self.buttonHandler = None + self.joyLeftHandler = None + self.joyRightHandler = None + + def setButtonHandler(self, buttonHandler): + self.buttonHandler = buttonHandler + + def setJoyLeftHandler(self, joyLeftHandler): + self.joyLeftHandler = joyLeftHandler + + def setJoyRightHandler(self, joyRightHandler): + self.joyRightHandler = joyRightHandler + + def startLoop(self): + FORMAT = 'llHHI' + EVENT_SIZE = struct.calcsize(FORMAT) + with open(self.eventFile, 'rb') as infile: + lx, ly, rx, ry = 0, 0, 0, 0 + while True: + event = infile.read(EVENT_SIZE) + _, _, t, c, v = struct.unpack(FORMAT, event) + if t == 1 and v == 1: + # button pressed: + if self.buttonHandler: + if not self.buttonHandler(c): + return + if t == 3: + if c == 0 and self.joyLeftHandler: + # left stick & horizontal: + lx = v - 32768 + self.joyLeftHandler(lx, ly) + elif c == 1 and self.joyLeftHandler: + # left stick & vertical: + ly = v - 32768 + self.joyLeftHandler(lx, ly) + elif c == 3 and self.joyRightHandler: + # right stick & horizontal: + rx = v - 32768 + self.joyRightHandler(rx, ry) + elif c == 4 and self.joyRightHandler: + # right stick & vertical: + ry = v - 32768 + self.joyRightHandler(rx, ry) diff --git a/samples/micropython/tank/main.py b/samples/micropython/tank/main.py new file mode 100644 index 00000000..efb082da --- /dev/null +++ b/samples/micropython/tank/main.py @@ -0,0 +1,103 @@ +#!/usr/bin/env pybricks-micropython + +import struct, threading + +from pybricks import ev3brick as brick +from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor) +from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align) +from pybricks.tools import print, wait, StopWatch +from pybricks.robotics import DriveBase + +from devices import detectJoystick +from joystick import JoyStick, BUTTON_A, BUTTON_X + +SPEED = 100 +STEERING = 90 + +STATUS_STOPPED = 0 +STATUS_FORWARD = 1 +STATUS_BACKWARD = 2 +STATUS_STEERING = 3 + +COLORS = (None, Color.GREEN, Color.RED, Color.YELLOW) + +class Driver(): + def __init__(self, leftMotor, rightMotor, diameter, axle): + self.driver = DriveBase(leftMotor, rightMotor, diameter, axle) + self.x = 0 + self.y = 0 + self.speed = 0 + self.steering = 0 + + def drive(self, speed, steering): + self.speed = speed + self.steering = steering + if self.speed == 0: + self.driver.stop() + else: + self.driver.drive(self.speed, self.steering) + +class Robot(): + def __init__(self, leftMotor, rightMotor, topMotor, diameter, axle, maxSpeed=300, maxSteering=180, port=Port.S4): + self.driver = Driver(leftMotor, rightMotor, diameter, axle) + self.cannon = topMotor + self.ultrasonic = UltrasonicSensor(port) + self.speedStep = 32767 // maxSpeed + self.steeringStep = 32767 // maxSteering + self.active = True + + def drive(self, x, y): + # map y (-32768 ~ +32767) to speed (+maxSpeed ~ -maxSpeed): + speed = -y // self.speedStep + # map x (-32768 ~ +32767) to steering (-maxSteering ~ +maxSteering): + steering = x // self.steeringStep + self.driver.drive(speed, steering) + + def target(self, x): + self.cannon.run(-x // 327) + + def fire(self): + brick.sound.file('cannon.wav') + + def inactive(self): + self.active = False + self.drive(0, 0) + brick.sound.beep() + +def autoStopLoop(robot): + while robot.active: + if robot.ultrasonic.distance() < 200: + robot.drive(0, 0) + wait(100) + +def main(): + brick.sound.beep() + joystickEvent = detectJoystick(['Controller']) + if joystickEvent: + robot = Robot(Motor(Port.D), Motor(Port.A), Motor(Port.B), 55, 200) + t = threading.Thread(target=autoStopLoop, args=(robot,)) + t.start() + + def onButtonPressed(code): + if code == BUTTON_X: + robot.inactive() + return False + if code == BUTTON_A: + robot.fire() + return True + + def onLeftJoyChanged(x, y): + robot.drive(x, y) + + def onRightJoyChanged(x, y): + robot.target(x) + + joystick = JoyStick(joystickEvent) + joystick.setButtonHandler(onButtonPressed) + joystick.setJoyLeftHandler(onLeftJoyChanged) + joystick.setJoyRightHandler(onRightJoyChanged) + joystick.startLoop() + else: + brick.sound.beep() + +main() From 71f47bb22368b6a47d899fc65271e92efec61bf1 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Thu, 1 Oct 2020 20:51:23 +0800 Subject: [PATCH 17/31] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 12a9352c..0e149d09 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ Python 3 教程 ============ + +[Python 3 教程](https://www.liaoxuefeng.com/wiki/1016959663602400) From b8a97b6145deabf344e2e0be7a592693913583cd Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Wed, 23 Dec 2020 23:15:00 +1100 Subject: [PATCH 18/31] docs: fix simple typo, verticle -> vertical There is a small typo in samples/micropython/rccar/main.py. Should read `vertical` rather than `verticle`. --- samples/micropython/rccar/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/micropython/rccar/main.py b/samples/micropython/rccar/main.py index 595133d5..cf18c927 100644 --- a/samples/micropython/rccar/main.py +++ b/samples/micropython/rccar/main.py @@ -61,7 +61,7 @@ def joystickLoop(robot, eventFile): return robot.inactive() elif t == 3: if c == 1: - # Left stick & verticle: + # Left stick & vertical: speed = 0 if v < 32768: # up: From 756b1f73a9eade7bc10cfa36b471bf25c0d625b3 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 09:11:33 +0800 Subject: [PATCH 19/31] refactor --- samples/basic/{ => hello}/hello.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/basic/{ => hello}/hello.py (100%) diff --git a/samples/basic/hello.py b/samples/basic/hello/hello.py similarity index 100% rename from samples/basic/hello.py rename to samples/basic/hello/hello.py From 841c1e74ddedea07cd90ad121c51c95d82ed8ac5 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 11:30:17 +0800 Subject: [PATCH 20/31] Create CNAME --- docs/CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/CNAME diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..fac3311c --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +learn-python3.itranswarp.com \ No newline at end of file From 7c317c39a69921d3ee5e965f3c5dfd512515ebe3 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 11:32:22 +0800 Subject: [PATCH 21/31] Create pyscript_plugin.js --- docs/pyscript_plugin.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/pyscript_plugin.js diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js new file mode 100644 index 00000000..89e1ad83 --- /dev/null +++ b/docs/pyscript_plugin.js @@ -0,0 +1,6 @@ +export default class LearnPython3Plugin { + afterStartup(runtime) { + console.log('[plugin] pyscript startup.'); + window.__pyscript_ready__ = true; + } +} From f983b17f6b8c6848c76158c892e3b77e47b5e7c8 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 20:23:20 +0800 Subject: [PATCH 22/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 89e1ad83..d3d6af84 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -3,4 +3,12 @@ export default class LearnPython3Plugin { console.log('[plugin] pyscript startup.'); window.__pyscript_ready__ = true; } + + afterPyScriptExec(opt) { + let + tag = opt.pyScriptTag, + outputId = tag.getAttribute('output'), + $btn = $('button[outputId=' + outputId + ']); + $button.removeAttr('disabled'); + } } From 480131640736b93d9ea782af33aeb4d567ae83a8 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 20:26:26 +0800 Subject: [PATCH 23/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index d3d6af84..48b74e6a 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -8,7 +8,7 @@ export default class LearnPython3Plugin { let tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), - $btn = $('button[outputId=' + outputId + ']); + $btn = $('button[outputId=' + outputId + ']'); $button.removeAttr('disabled'); } } From 5f0f6cb5c18403928403242c9fa7510a3cb8baa5 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 20:30:29 +0800 Subject: [PATCH 24/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 48b74e6a..bd30a4c2 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -9,6 +9,6 @@ export default class LearnPython3Plugin { tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), $btn = $('button[outputId=' + outputId + ']'); - $button.removeAttr('disabled'); + $btn.removeAttr('disabled'); } } From 9dfc8a1425c1ce93f9fc7a70ee033f4d95c8dba5 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 20:32:05 +0800 Subject: [PATCH 25/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index bd30a4c2..1fac7731 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -8,7 +8,10 @@ export default class LearnPython3Plugin { let tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), - $btn = $('button[outputId=' + outputId + ']'); + $btn = $('button[outputId=' + outputId + ']'), + $i = $btn.find('i'); + $i.removeClass('uk-icon-spinner'); + $i.removeClass('uk-icon-spin'); $btn.removeAttr('disabled'); } } From 147c587f20026bede42224948a1e7d6c28c3bd48 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 21:16:26 +0800 Subject: [PATCH 26/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 1fac7731..5ed45f9b 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -5,6 +5,8 @@ export default class LearnPython3Plugin { } afterPyScriptExec(opt) { + console.log('Result >>>'); + console.log(opt.result); let tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), From 5189b15c88c98d32e5dd5822e57a13d602df0866 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 21:21:09 +0800 Subject: [PATCH 27/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 5ed45f9b..835b1f64 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -5,8 +5,7 @@ export default class LearnPython3Plugin { } afterPyScriptExec(opt) { - console.log('Result >>>'); - console.log(opt.result); + console.log(opt); let tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), @@ -16,4 +15,9 @@ export default class LearnPython3Plugin { $i.removeClass('uk-icon-spin'); $btn.removeAttr('disabled'); } + + onUserError(err) { + console.log('Error >>>'); + console.error(err); + } } From 4164c5cd8627b91b33c7a7b4500cb923d5fc56ec Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 21:54:44 +0800 Subject: [PATCH 28/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 835b1f64..ef28f964 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -5,19 +5,31 @@ export default class LearnPython3Plugin { } afterPyScriptExec(opt) { - console.log(opt); let tag = opt.pyScriptTag, outputId = tag.getAttribute('output'), $btn = $('button[outputId=' + outputId + ']'), $i = $btn.find('i'); - $i.removeClass('uk-icon-spinner'); - $i.removeClass('uk-icon-spin'); + $i.removeClass('uk-icon-spinner'); + $i.removeClass('uk-icon-spin'); $btn.removeAttr('disabled'); + let err = $(tag).find('pre.py-error').text(); + if (err) { + let + $out = $('#' + outputId), + s = $out.text(); + if (s) { + s = s + '\n' + err; + } else { + s = err; + } + $out.text(s); + $out.addClass('uk-alert-danger'); + } } onUserError(err) { - console.log('Error >>>'); + console.log('Error >>>'); console.error(err); } } From 90ec8263cf6211470399bf62ac21d8c86a4fa769 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 21:59:47 +0800 Subject: [PATCH 29/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index ef28f964..2b1cf6fe 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -13,17 +13,17 @@ export default class LearnPython3Plugin { $i.removeClass('uk-icon-spinner'); $i.removeClass('uk-icon-spin'); $btn.removeAttr('disabled'); - let err = $(tag).find('pre.py-error').text(); + let err = $(tag).find('pre.py-error').html(); if (err) { let $out = $('#' + outputId), - s = $out.text(); + s = $out.html(); if (s) { - s = s + '\n' + err; + s = s + '
' + err; } else { s = err; } - $out.text(s); + $out.html(s); $out.addClass('uk-alert-danger'); } } From b35486349f60ea47edf11fc45da5157767e3cb07 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 26 Apr 2023 22:14:33 +0800 Subject: [PATCH 30/31] Update pyscript_plugin.js --- docs/pyscript_plugin.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js index 2b1cf6fe..39e7bae7 100644 --- a/docs/pyscript_plugin.js +++ b/docs/pyscript_plugin.js @@ -18,11 +18,7 @@ export default class LearnPython3Plugin { let $out = $('#' + outputId), s = $out.html(); - if (s) { - s = s + '
' + err; - } else { - s = err; - } + s = s + err.replaceAll(' ', ' '); $out.html(s); $out.addClass('uk-alert-danger'); } From 27f49401960be8233d2c52b9e214ac9da7be22d3 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Tue, 3 Oct 2023 13:05:24 +0800 Subject: [PATCH 31/31] Create do_match.py --- samples/basic/do_match.py | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 samples/basic/do_match.py diff --git a/samples/basic/do_match.py b/samples/basic/do_match.py new file mode 100644 index 00000000..b14fe51f --- /dev/null +++ b/samples/basic/do_match.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# 简单匹配: +print('-- simple match --') + +score = 'A' + +match score: + case 'A': + print('score is A.') + case 'B': + print('score is B.') + case 'C': + print('score is C.') + case _: + print('score is ???.') + +# 复杂匹配: +print('-- complex match --') + +age = 15 + +match age: + case x if x < 10: + print('< 10 years old.') + case 10: + print('10 years old.') + case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18: + print('11~18 years old.') + case 19: + print('19 years old.') + case _: + print('not sure.') + +# 列表匹配: +print('-- match list --') + +args = ['gcc', 'hello.c', 'world.c'] +# args = ['clean'] +# args = ['gcc'] + +match args: + # 如果仅出现gcc,报错: + case ['gcc']: + print('gcc: missing source file(s).') + # 出现gcc,且至少指定了一个文件: + case ['gcc', file1, *files]: + print('gcc compile: ' + file1 + ', ' + ', '.join(files)) + # 仅出现clean: + case ['clean']: + print('clean') + case _: + print('invalid command.')