231 Commits

Author SHA1 Message Date
Kristjan Komlosi
89ea9564c8 fixed onclick binding 2020-06-02 10:45:16 +02:00
Kristjan Komlosi
00c619ce34 fixed typo 2020-06-02 09:53:09 +02:00
Kristjan Komlosi
8f22a6baee removed lighttpd configuration as the defaults work fine 2020-06-02 09:52:40 +02:00
Kristjan Komlosi
fa2c1cccb1 removed old pipfiles 2020-06-02 09:52:08 +02:00
Kristjan Komlosi
7058512ee0 tidied comments, condensed UV calculation, removed redundant getA/B/I() 2020-04-24 16:49:09 +02:00
Kristjan Komlosi
325f1176c3 tidied translation tables 2020-04-24 16:47:43 +02:00
Kristjan Komlosi
0a9e610dd7 pruned import 2020-04-24 16:46:53 +02:00
Kristjan Komlosi
43b5277923 pipenv update 2020-04-24 16:46:27 +02:00
Kristjan Komlosi
5265ba9ae9 hotfix #2 2020-02-15 22:02:36 +01:00
Kristjan Komlosi
16e9c52194 rc.local hotfix 2020-02-15 21:59:41 +01:00
Kristjan Komlosi
c5db357cc0 fixed lighttpd root directory 2020-02-15 21:50:03 +01:00
Kristjan Komlosi
b7eb29f78b made rc.local executable 2020-02-15 21:46:12 +01:00
Kristjan Komlosi
1457655f16 GUI redesign 2020-02-15 15:56:28 +01:00
Kristjan Komlosi
a3f3558f7c fixed wavelength order in spectrogram 2020-02-14 14:18:38 +01:00
Kristjan Komlosi
bc72207187 fixed broken git headers 2019-11-18 17:19:18 +01:00
Kristjan Komlosi
7837f605cf Merge branch 'master' of github.com:cls-02/TeraHz 2019-11-17 22:23:28 +01:00
Kristjan Komlosi
3d1a925ba6 added school logo 2019-11-17 22:23:09 +01:00
Kristjan Komlosi
682fe20db2 added school logo 2019-11-17 22:21:54 +01:00
Kristjan Komlosi
949dd0bef2 Updated the main readme 2019-11-17 22:04:57 +01:00
Kristjan Komlosi
58cb777935 Documentation updates 2019-11-17 19:07:47 +01:00
Kristjan Komlosi
6ffc4f8aa2 Updated documentation pages titles 2019-11-12 21:30:48 +01:00
Kristjan Komlosi
87bd420d31 fixed a broken markdown list 2019-11-12 21:30:00 +01:00
Kristjan Komlosi
3e1a43c10f updated documentation 2019-11-12 21:28:27 +01:00
Kristjan Komlosi
ed0b21a496 Shortened the build guide significantly 2019-11-12 21:20:28 +01:00
Kristjan Komlosi
b93358dc32 made install.sh directory independent 2019-11-12 20:29:34 +01:00
Kristjan Komlosi
7f8e69fcf3 fixed gitignore to reinclude wrongly ignored frontend libraries 2019-11-12 20:23:24 +01:00
Kristjan Komlosi
751095a5a1 removed old sensor documentation 2019-11-12 20:03:03 +01:00
Kristjan Komlosi
665cf6050b removed old utils virtualenv 2019-11-12 19:56:22 +01:00
Kristjan Komlosi
8e7435ff8f cleared previously tracked gitignored files 2019-11-12 19:43:50 +01:00
Kristjan Komlosi
08310e074d .gitignore update 2019-11-12 19:40:02 +01:00
Kristjan Komlosi
598352f526 fixed install.sh to make edit_ssid executable 2019-11-12 19:29:32 +01:00
Kristjan Komlosi
e88171b31c fixed configuration files 2019-11-12 19:23:57 +01:00
Kristjan Komlosi
a5b393a879 made edit_ssid.sh executable 2019-11-12 19:13:07 +01:00
Kristjan Komlosi
9b4e733209 added interfaces file 2019-11-11 19:06:46 +01:00
Kristjan Komlosi
4cf102946e update ssid at each boot 2019-11-11 17:54:41 +01:00
Kristjan Komlosi
c72c0800fc made edit_ssid.sh path-independent 2019-11-11 17:41:55 +01:00
Kristjan Komlosi
095a95c1eb fixed relative path problems in run.sh 2019-11-11 17:34:18 +01:00
Kristjan Komlosi
fd5e482de9 made backend startup script executable 2019-11-11 17:14:16 +01:00
Kristjan Komlosi
ccbeb20f70 Merge branch 'buster' of github.com:cls-02/TeraHz into buster 2019-11-11 16:59:06 +01:00
Kristjan Komlosi
a4dca60892 removed lighttpd config files, as the frontend now uses defaults 2019-11-11 16:58:58 +01:00
Kristjan Komlosi
93cc25e7ef made the install script executable 2019-11-11 12:33:38 +01:00
Kristjan Komlosi
95e22b5d1f added gunicorn to pip3 dependencies 2019-11-10 18:37:55 +01:00
Kristjan Komlosi
f3a22fa511 fixed errors in edit_ssid script 2019-11-10 18:31:00 +01:00
Kristjan Komlosi
6981c821cc fixed install script issues #2 2019-11-10 18:01:11 +01:00
Kristjan Komlosi
837906f6a5 fixed install script issues 2019-11-10 17:58:54 +01:00
Kristjan Komlosi
f0d1fe2301 install and setup scripts 2019-11-09 19:51:26 +01:00
Kristjan Komlosi
28d0484db1 added a rudimentary install script 2019-11-09 15:44:05 +01:00
Kristjan Komlosi
2d3b747d42 removed dhcpcd config file 2019-11-09 15:43:48 +01:00
Kristjan Komlosi
c5d6c31d5f removed old documentation files 2019-11-09 15:00:09 +01:00
Kristjan Komlosi
0a9b73417b removed the backend venv because of disuse 2019-11-09 14:56:21 +01:00
Kristjan Komlosi
62b5080d43 added a Gunicorn start script 2019-11-09 14:55:46 +01:00
Kristjan Komlosi
4e7f7344f2 removed unnecessary config files 2019-11-09 13:54:47 +01:00
Kristjan Komlosi
5a3dccfa68 renamed gen_ssid to edit_ssid 2019-11-09 13:52:49 +01:00
Kristjan Komlosi
c0a8e72e34 added a hostapd config generator 2019-11-09 13:47:49 +01:00
Kristjan Komlosi
fd2cf5b282 changed lighttpd.conf back to defaults 2019-11-09 12:05:20 +01:00
Kristjan Komlosi
3523316c70 added FastCGI config 2019-11-09 11:52:26 +01:00
Kristjan Komlosi
bb9613ea41 moved driver objects into function scope 2019-11-03 12:51:14 +01:00
Kristjan Komlosi
79d107595c removed unnecessary etc files 2019-11-03 12:50:47 +01:00
Kristjan Komlosi
ffdb162ad4 fixed a bug with negative uv values 2019-11-02 12:38:18 +01:00
Kristjan Komlosi
9d9a192d8b named ticks 2019-11-02 12:12:36 +01:00
Kristjan Komlosi
45711e18e7 table fill rewrite, no globalObject necessary 2019-11-02 11:59:06 +01:00
Kristjan Komlosi
e57370588c fixed text color fill 2019-11-01 22:02:10 +01:00
Kristjan Komlosi
5384cc82a1 color tests 2019-11-01 21:53:42 +01:00
Kristjan Komlosi
e770fdf78e in pursuit of white 2019-11-01 21:51:21 +01:00
Kristjan Komlosi
d318c3661a fixed missing commas 2019-11-01 21:43:50 +01:00
Kristjan Komlosi
b960473aed Merge branch 'buster' of github.com:cls-02/TeraHz into buster 2019-11-01 21:42:40 +01:00
Kristjan Komlosi
c98b42a6cd set tick labels to white 2019-11-01 21:42:37 +01:00
Kristjan Komlosi
b7c2409655 set tick labels to white 2019-11-01 21:40:00 +01:00
Kristjan Komlosi
3a98bf0907 imported options 2019-11-01 21:37:23 +01:00
Kristjan Komlosi
d42316d706 set grid color 2019-11-01 21:36:34 +01:00
Kristjan Komlosi
de47450381 fixed passing arguments to flot, see comment 2019-11-01 21:32:55 +01:00
Kristjan Komlosi
8bd17e6582 forgot colorhelpers 2019-11-01 21:21:14 +01:00
Kristjan Komlosi
bd08aa2641 lib imports 2019-11-01 21:20:03 +01:00
Kristjan Komlosi
5d79d509f8 trying to make flot work 2019-11-01 21:11:56 +01:00
Kristjan Komlosi
7315381410 added a test graph 2019-11-01 21:03:22 +01:00
Kristjan Komlosi
005382b3d4 changed the canvas placeholder to fit flot 2019-11-01 21:03:04 +01:00
Kristjan Komlosi
a68c72f99b changed the x axis data to numbers 2019-11-01 20:48:54 +01:00
Kristjan Komlosi
f5f9e53f48 append != push 2019-11-01 20:40:55 +01:00
Kristjan Komlosi
27b508ba18 Object.keys bullshit 2019-11-01 20:40:16 +01:00
Kristjan Komlosi
725c58f709 Object.keys is not a function 2019-11-01 20:37:53 +01:00
Kristjan Komlosi
e8ed8f780f testing a less neurotic JSON parse 2019-11-01 20:36:53 +01:00
Kristjan Komlosi
008ff9df93 added flot as the new plot library 2019-11-01 20:36:32 +01:00
Kristjan Komlosi
759fc6affe fixed race condition in updateData 2019-11-01 20:03:56 +01:00
Kristjan Komlosi
ca88cd7d71 console logging 2019-11-01 20:01:49 +01:00
Kristjan Komlosi
ff796b17fc git merge is a pain 2019-11-01 19:57:23 +01:00
Kristjan Komlosi
63ee66fb6d Merge branch 'buster' of github.com:cls-02/TeraHz into buster 2019-11-01 19:56:40 +01:00
Kristjan Komlosi
c2b0722d3a semicolons 2019-11-01 19:55:49 +01:00
Kristjan Komlosi
50a1cb83db removed chart.js and glue code. updateData prints debug info 2019-11-01 19:54:38 +01:00
Kristjan Komlosi
e4522f11b7 removed chart.js and glue code. updateData prints debug info 2019-11-01 19:47:33 +01:00
Kristjan Komlosi
8f8ef9753f adding timeout to backend ajax 2019-11-01 19:31:21 +01:00
Kristjan Komlosi
537183078f styling 6 2019-10-06 17:06:34 +02:00
Kristjan Komlosi
766d9b09e6 styling 5 2019-10-06 17:03:45 +02:00
Kristjan Komlosi
c049d5e8df Merge branch 'master' of github.com:cls-02/TeraHz 2019-10-06 17:02:30 +02:00
Kristjan Komlosi
47937d8bb8 stlying4 2019-10-06 17:02:13 +02:00
Kristjan Komlosi
e21efc1b4a stlying4 2019-10-06 17:00:46 +02:00
Kristjan Komlosi
8edc170b75 styling3 2019-10-06 16:56:39 +02:00
Kristjan Komlosi
4044c43292 styling 2 2019-10-06 16:52:11 +02:00
Kristjan Komlosi
a19b17e19d styling 2019-10-06 16:46:53 +02:00
Kristjan Komlosi
dbefb381df muh gradients 2019-09-23 18:22:00 +02:00
Kristjan Komlosi
21bfae9fbc Static code analysis and corrections 2019-07-17 16:06:09 +02:00
Kristjan Komlosi
674692c2fc added datasheet and store links 2019-07-08 10:14:11 +02:00
Kristjan Komlosi
311137fd0a Updates on sensors. 2019-07-01 09:45:35 +02:00
Kristjan Komlosi
8d5503832a moved sensor-docs 2019-07-01 09:45:22 +02:00
Kristjan Komlosi
be0da7e74d Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-26 01:30:47 +02:00
Kristjan Komlosi
3ef2e80675 Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-26 01:30:44 +02:00
Kristjan Komlosi
191feb7077 Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-26 01:30:27 +02:00
Kristjan Komlosi
0a856e69c7 Added the developer's guide 2019-06-26 01:29:50 +02:00
Kristjan Komlosi
92364a86c2 Electrical guide, manual structure. 2019-06-25 09:54:04 +02:00
Kristjan Komlosi
fd1f07d40d Electrical guide, manual structure. 2019-06-25 00:45:53 +02:00
Kristjan Komlosi
102b333ea0 Fixed titles for the kjillionth time 2019-06-24 20:26:30 +02:00
Kristjan Komlosi
6574a724b4 Added some pictures to the build guide 2019-06-23 14:25:21 +02:00
Kristjan Komlosi
bc0abbb985 removed residual .orig files 2019-06-23 11:06:13 +02:00
Kristjan Komlosi
f4d95e2441 removed package lock to calm GitHub security down 2019-06-23 10:43:02 +02:00
Kristjan Komlosi
efcba4cfb0 Updated jQuery for security reasons 2019-06-23 00:46:14 +02:00
Kristjan Komlosi
69e145aac6 Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-23 00:44:19 +02:00
Kristjan Komlosi
a6e44e6c56 Fixed dependency list 2019-06-23 00:37:25 +02:00
Kristjan Komlosi
a6fa60a40a Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-23 00:35:47 +02:00
Kristjan Komlosi
3c792cf286 Fixed dependency list 2019-06-23 00:35:18 +02:00
Kristjan Komlosi
babd6d88dc Fixed dependency list 2019-06-23 00:34:27 +02:00
Kristjan Komlosi
21290682b6 Added the development team to license 2019-06-23 00:32:43 +02:00
Kristjan Komlosi
bd45b88477 Switched site order 2019-06-23 00:31:31 +02:00
Kristjan Komlosi
6f5c01fccc moved titles to mkdocs config file 2019-06-23 00:30:27 +02:00
Kristjan Komlosi
6af5d94b8a Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-23 00:24:20 +02:00
Kristjan Komlosi
2cd3ff1e78 Documentiation titles 2019-06-23 00:23:52 +02:00
Kristjan Komlosi
2afc8c8708 Documentiation titles 2019-06-23 00:22:46 +02:00
Kristjan Komlosi
e8a6021e3f Set MkDocs theme to ReadTheDocs 2019-06-23 00:20:30 +02:00
Kristjan Komlosi
da641cad7f mkdocs site_dir change 2019-06-23 00:18:02 +02:00
Kristjan Komlosi
75f3a6d1c0 MkDocs hopefully fixed. 2019-06-23 00:11:47 +02:00
Kristjan Komlosi
06f1f9c10c Added a Docs shield to the readme 2019-06-23 00:03:10 +02:00
Kristjan Komlosi
ef0fb8b990 Removed residal MkDocs Garbo. 2019-06-22 23:56:03 +02:00
Kristjan Komlosi
d81884eebd Moved frm MkDocs to Sphinx. Looks nicer. 2019-06-22 23:48:10 +02:00
Kristjan Komlosi
6dc3db1648 Merge branch 'master' of https://github.com/cls-02/TeraHz 2019-06-22 23:42:52 +02:00
Kristjan Komlosi
fbca31d88a MkDocs hopefully fixed. 2019-06-22 23:41:05 +02:00
Kristjan Komlosi
852e05d2c2 MkDocs hopefully fixed. 2019-06-22 23:40:41 +02:00
Kristjan Komlosi
ef90f0e4dc MkDocs site_dir 2019-06-22 23:34:48 +02:00
Kristjan Komlosi
5dfbe6f951 MkDocs site_name 2019-06-22 23:32:42 +02:00
Kristjan Komlosi
54618be769 Documentation 2019-06-22 23:30:27 +02:00
Kristjan Komlosi
721c6ac0a7 ReadTheDocs YAML file 2019-06-22 23:24:40 +02:00
Kristjan Komlosi
7e3a4855d8 MkDocs initialization and RTFD.io integration 2019-06-22 23:18:07 +02:00
Kristjan Komlosi
41ae988562 Merge branch 'master' of https://github.com/d3m1g0d/TeraHz 2019-06-22 22:59:16 +02:00
Kristjan Komlosi
8f38cf62ac Documentation 2019-06-22 22:58:21 +02:00
Kristjan Komlosi
26890a8bbf Documented Python and module installation process. 2019-06-22 11:29:13 +02:00
Kristjan Komlosi
879cb28b9e Documented Python and module installation process. 2019-06-22 00:05:35 +02:00
Kristjan Komlosi
6c37a7b1a9 Build docs and config fixes 2019-06-21 15:27:44 +02:00
Kristjan Komlosi
919dd41321 typos 2019-06-21 10:14:20 +02:00
Kristjan Komlosi
017721f659 Started work on build guide 2019-06-21 10:13:03 +02:00
d3m1g0d
ee0d1184ed etc edits 2019-06-15 16:33:34 +02:00
d3m1g0d
b4352eb844 etc edits 2019-06-15 16:30:43 +02:00
d3m1g0d
dddd6e8632 etc edits 2019-06-15 16:00:46 +02:00
d3m1g0d
548ae2be2c etc edits 2019-06-15 14:09:14 +02:00
d3m1g0d
209f557a9b Merge remote-tracking branch 'origin/master'
merge to include updated data
2019-06-15 13:53:05 +02:00
d3m1g0d
307972b9ec etc files 2019-06-15 13:52:21 +02:00
Kristjan Komlosi
9bd22c5fff Merge branch 'master' of https://github.com/d3m1g0d/TeraHz 2019-06-14 10:09:44 +02:00
d3m1g0d
3f2e729d85 licensing 2019-05-30 20:36:37 +02:00
d3m1g0d
c48da832e0 removed old main app 2019-05-30 17:52:27 +02:00
d3m1g0d
659fb74071 licensing 2019-05-30 17:48:01 +02:00
d3m1g0d
0035b2e6f3 changed the readme to match my less 1337 username 2019-05-30 17:37:50 +02:00
d3m1g0d
0f58892d85 added a license (ISC) 2019-05-30 17:37:25 +02:00
d3m1g0d
cf8af255c6 updated readme 2019-05-12 11:19:27 +02:00
d3m1g0d
5391985618 missing index 2019-04-28 11:37:57 +02:00
d3m1g0d
a23ecd095c typo fix 2019-04-28 11:37:08 +02:00
d3m1g0d
ca819b84e7 arrays 2019-04-28 11:36:19 +02:00
d3m1g0d
4691b30bf3 arrays 2019-04-28 11:24:53 +02:00
d3m1g0d
b37849ddef graph reordering 2019-04-28 11:05:38 +02:00
d3m1g0d
58c79ecbd4 added a heading 2019-04-17 17:12:30 +02:00
d3m1g0d
888296e3e1 array index fix 2019-04-17 17:08:35 +02:00
d3m1g0d
863b998eae added table fillers 2019-04-17 17:07:44 +02:00
d3m1g0d
c78ed7323a html fixes 2019-04-17 17:05:06 +02:00
d3m1g0d
9e69651f0c lux and uvabi added 2019-04-17 16:50:59 +02:00
d3m1g0d
2211f7ca95 being irresponsive 2019-04-16 18:35:42 +02:00
d3m1g0d
dc12b92d5b margins 2019-04-16 18:32:08 +02:00
d3m1g0d
559b1f2a7c margins 2019-04-16 18:30:40 +02:00
d3m1g0d
7abc0ec624 cropped down the canvas 2019-04-16 18:24:12 +02:00
d3m1g0d
91ef012688 async? async! 2019-04-16 17:54:50 +02:00
d3m1g0d
0f5bd9fef4 fix 2019-04-16 17:19:33 +02:00
d3m1g0d
45594aeac0 stopped coding JS in C 2019-04-16 17:12:43 +02:00
d3m1g0d
c8b3ab2413 chart.js import 2019-04-15 17:43:49 +02:00
d3m1g0d
52464ec5a8 added inital chart.js support 2019-04-15 17:43:34 +02:00
d3m1g0d
37db23a0e8 Divide and conquer on updateData... 2019-04-14 20:38:43 +02:00
d3m1g0d
c4fe5fbf37 added missing ID selector 2019-04-06 15:56:07 +02:00
d3m1g0d
8072fe9c36 merge 2019-04-06 15:53:02 +02:00
d3m1g0d
2e263f1b14 table parsing test no 1 2019-04-06 15:51:38 +02:00
d3m1g0d
fe07f41425 table parsing test no 1 2019-04-06 15:51:02 +02:00
d3m1g0d
4b7f96a378 typo fix 2019-04-06 15:47:29 +02:00
d3m1g0d
02ebfd7ce2 fixed CORS constraints 2019-04-06 15:35:43 +02:00
d3m1g0d
2e53784002 fixed wrong url in frontend 2019-04-06 15:24:07 +02:00
d3m1g0d
4c35d0f179 renamed website.html to index.html to ease development 2019-04-06 15:22:04 +02:00
d3m1g0d
fc112d997b First try AJAX 2019-04-06 15:18:43 +02:00
TeraHz User
2e4c7e2683 changed filename to ease development with flask 2019-04-06 13:43:22 +01:00
d3m1g0d
fa6675cb04 Website design 2019-04-06 14:11:38 +02:00
d3m1g0d
212ea9ec65 fixed wrong equation at line 201 2019-03-31 11:53:23 +02:00
d3m1g0d
c92fd63160 Merge branch 'master' of https://github.com/d3m1g0d/TeraHz 2019-03-31 11:52:28 +02:00
d3m1g0d
f8b7306dd0 fixed addr to self.addr in UV functions 2019-03-31 11:52:19 +02:00
d3m1g0d
b6f2379a38 fixed addr to self.addr in UV functions 2019-03-31 11:50:42 +02:00
d3m1g0d
fc7a1bf167 fix #2 2019-03-31 11:47:40 +02:00
d3m1g0d
3c55e96341 fix 2019-03-31 11:44:38 +02:00
d3m1g0d
44a636010e prototyping 2019-03-31 11:09:44 +02:00
d3m1g0d
36d77591f4 sucessful backend implementation for spectrometer 2019-03-31 10:48:55 +02:00
d3m1g0d
c4fba54407 Work on website 2019-03-26 20:54:33 +01:00
ANormalPerson1
6c63adcdfb Merge branch 'master' of https://github.com/d3m1g0d/TeraHz 2019-03-20 16:21:43 +01:00
ANormalPerson1
46d788aae3 Started main backend development.
Yeet
2019-03-20 16:20:14 +01:00
d3m1g0d
8f7f170d6a cache 2019-03-20 15:46:52 +01:00
d3m1g0d
ea28ff7bef Added a witty marketing pitch to the readme 2019-03-13 19:21:42 +01:00
d3m1g0d
d1435047e4 python cache commit 2019-03-13 19:02:12 +01:00
d3m1g0d
253ec3a28e added storage module 2019-03-13 19:01:21 +01:00
d3m1g0d
e3bbab819b created a sample database for testing storage module 2019-03-13 19:00:55 +01:00
d3m1g0d
1ba8f72e09 made Spectrometer operation more sane 2019-03-13 19:00:35 +01:00
d3m1g0d
3377554e0d Added to readme 2019-03-13 19:00:01 +01:00
d3m1g0d
e441f4f7f7 pruned venvs 2019-03-12 21:57:16 +01:00
d3m1g0d
33f0511081 pruned venvs 2019-03-12 21:56:25 +01:00
d3m1g0d
8ee094481c commit 2019-03-11 14:33:26 +01:00
d3m1g0d
d5815fe849 storeTemp() and loadTemp() 2019-03-06 20:44:26 +01:00
d3m1g0d
f8a05efc31 Started work on storage backend 2019-03-04 16:57:19 +01:00
d3m1g0d
6b2e7f3129 Added UV sensor code. Calculations may be inaccurate. 2019-03-03 20:21:08 +01:00
TeraHz User
65733488f7 hotfixed getIntTime() 2019-03-02 14:09:27 +00:00
d3m1g0d
7e538ad284 Lux meter support finished 2019-03-02 14:51:31 +01:00
d3m1g0d
99404c8f15 fix 2019-03-02 14:37:58 +01:00
d3m1g0d
3fafe3f896 fix 2019-03-02 14:35:41 +01:00
d3m1g0d
fe883048e6 fix 2019-03-02 14:33:16 +01:00
d3m1g0d
e54a31e56f added SMBus Lux meter support 2019-03-02 14:24:50 +01:00
d3m1g0d
b4b301d6db i2c development 2019-03-02 10:58:24 +01:00
d3m1g0d
aa93b0a61f made filenames less autistic 2019-03-02 10:30:33 +01:00
D3m1J4ck
dfca408af3 osnovna spletna stran 2019-02-24 15:38:38 +01:00
TeraHz User
befbf04cd2 SMBus access working! 2019-02-20 18:11:59 +00:00
d3m1g0d
fa45326052 hotfix 2019-02-20 18:46:39 +01:00
d3m1g0d
83b175f0ad Merge remote-tracking branch 'origin/master' 2019-02-20 18:40:49 +01:00
d3m1g0d
59af6587e7 started development on SMBus sensors 2019-02-20 18:39:34 +01:00
Kristjan Komlosi
ef11b0e3b7 Add files via upload 2019-02-03 17:13:24 +01:00
d3m1g0d
cfa9c8ea23 demo + utils venv 2019-02-03 13:40:10 +01:00
Kristjan Komlosi
512f877039 gain adjustments 2019-02-01 08:50:15 +01:00
d3m1g0d
5fa112490b made setParameters usable 2019-01-24 18:41:35 +01:00
4181 changed files with 21720 additions and 748278 deletions

BIN
..gitignore.swp Normal file

Binary file not shown.

132
.gitignore vendored Normal file
View File

@@ -0,0 +1,132 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Include frontend libraries though
!/frontend/lib

2
.pylintrc Normal file
View File

@@ -0,0 +1,2 @@
[MASTER]
disable = c0103

14
LICENSE.txt Normal file
View File

@@ -0,0 +1,14 @@
Copyright (c) 2018, 2019, Kristjan Komloši, Jakob Kosec, Juš Dolžan,
TeraHz development team
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -1,9 +1,37 @@
# TeraHz
TeraHz is a low-cost spectrometer.
[![Documentation Status](https://readthedocs.org/projects/terahz/badge/?version=latest)](https://terahz.readthedocs.io/en/latest/?badge=latest)
# <img alt="TeraHz logo" src="docs/imgs/logo-sq.png" width="200px"> TeraHz
*Za slovensko različico se odpravite na <http://git.sckr-lab.tk/kristjank/TeraHz>*
TeraHz is a low-cost portable spectrometer based on Raspberry Pi and a few
commonly available sensor breakout boards. It's designed to bring low-cost
scientific exploration of the light spectrum to educational institutions that
cannot afford the options available on the current market. It costs less than
200€ with money to spare and uses only free, libre and open-source software
(FLOSS). It is free to use under the ISC license, a spiritual successor to the
classic 3-clause BSD license.
## How to install
Stable releases are available under the releases tab and can be installed either
by flashing a **preinstalled** ready to boot image with a stable version of
TeraHz preinstalled or by flashing a **preconfigured** image of DietPi and
installing TeraHz manually, which is useful if you want to test bleeding edge
releases. For more information, check out the [Build
guide](https://terahz.readthedocs.io/en/latest/build/).
## Docs
TeraHz usually works out of the box. A wireless network named `TeraHz_XXXXXX`
(XXXXXX = the last half of the MAC address) will appear. Password is
`terahertz`. After connection, open a web browser and visit `terahz.site`.
The UI will appear. To fetch data from the sensors, press the 'Get Data' button.
The readings are then plotted and written into the tables below the graph.
More documentation is available at <https://terahz.readthedocs.io>
## Development team
Copyright 2018, 2019
- Kristjan Komloši (cls-02) - Project leader and main programmer
- Jakob Kosec (D3m1j4ck) - Frontend designer
- Juš Dolžan (ANormalPerson) - Math double-checker
- Kristjan "d3m1g0d" Komloši (electronics engineer, middleware)
- Juš "ANormalPerson" Dolžan (backend developer)
- Jakob "D3m1j4ck" Kosec (frontend developer)
<img alt="TeraHz logo" src="http://www.sckr.si/documents/upload/konektor/logo/_SC.gif" width="200px">
TeraHz has been developed under guidance and financial support of Šolski Center Kranj (Kranj School Centre). Without their support, this project might have never been possible.

16
backend/app.py Normal file
View File

@@ -0,0 +1,16 @@
# app.py - main backend program
'''Main TeraHz backend program'''
# All code in this file is licensed under the ISC license, provided in LICENSE.txt
from flask import Flask, jsonify
import sensors
app = Flask(__name__)
@app.route('/data')
def sendData():
'''Responder function for /data route'''
s = sensors.Spectrometer(path='/dev/serial0', baudrate=115200, tout=1)
u = sensors.UVSensor()
l = sensors.LxMeter()
response = jsonify([s.getData(), l.getData(), u.getABI()])
response.headers.add('Access-Control-Allow-Origin', '*')
return response

4
backend/run.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
# run.sh - run the backend server
cd `dirname $0`
sudo gunicorn app:app -b 0.0.0.0:5000 &

BIN
backend/sample.db Normal file

Binary file not shown.

View File

@@ -1,39 +1,40 @@
# sensors.py - a module for interfacing to the sensors
'''Module for interfacing with TeraHz sensors'''
# Copyright 2019 Kristjan Komloši
# The code in this file is licensed under the 3-clause BSD License
# All code in this file is licensed under the ISC license, provided in LICENSE.txt
import serial as ser
import pandas as pd
from threading import Timer
from sys import exit as ex
import time
import smbus2
class Spectrometer:
'''Class representing the AS7265X specrometer'''
def initializeSensor(self):
'''confirm the sensor is responding and proceed with spectrometer initialization'''
'''confirm the sensor is responding and proceed\
with spectrometer initialization'''
try:
rstring='undefined' # just need it set to a value
rstring = 'undefined' # just need it set to a value
self.setParameters({'gain': 0})
self.serialObject.write(b'AT\n')
rstring=self.serialObject.readline().decode()
rstring = self.serialObject.readline().decode()
if rstring == 'undefined':
raise Exception #sensor didn't respond
raise Exception # sensor didn't respond
if rstring == 'OK':
pass #handshake passed
pass # handshake passed
if rstring == 'ERROR':
raise Exception #sensor is in error state
raise Exception # sensor is in error state
except:
print('An exception ocurred when performing spectrometer handshake')
ex(1)
self.setParameters()
raise Exception(
'An exception ocurred when performing spectrometer handshake')
def setParameters(self, parameters={}):
def setParameters(self, parameters):
'''applies the parameters like LED light and gain to the spectrometer'''
try:
if 'it_time' in parameters:
it_time = int(parameters['it_time'])
if it_time <=0 :
if it_time <= 0:
it_time = 1
self.serialObject.write('ATINTTIME={}\n'.format(string(it_time)).encode())
self.serialObject.write(
'ATINTTIME={}\n'.format(str(it_time)).encode())
self.serialObject.readline()
if 'gain' in parameters:
@@ -46,44 +47,193 @@ class Spectrometer:
if 'led' in parameters:
led = bool(parameters['led'])
if led:
led=1
led = 1
else:
led=0
led = 0
self.serialObject.write('ATLED3={}\n'.format(led).encode())
self.serialObject.readline()
except:
print('An exception occured during spectrometer initialization')
ex(1)
raise Exception(
'An exception occured during spectrometer initialization')
def startDataCollection(self):
def getData(self):
'''Returns spectral data in a pandas DataFrame.'''
try:
self.serialObject.write(b'ATCDATA\n')
rawresp = self.serialObject.readline().decode()
except:
print('An exception occurred when polling for spectrometer data')
ex(1)
raise Exception(
'An exception occurred when polling for spectrometer data')
else:
responseorder = [i for i in 'RSTUVWGHIJKLABCDEF']
realorder = [i for i in 'ABCDEFGHRISJTUVWKL']
response = pd.Series([float(i)/35.0 for i in rawresp[:-3].split(',')], index=responseorder)
self.data = pd.DataFrame(response, index=realorder, columns = ['uW/cm^2'])
self.schedule(self.rrate)
responseorder = list('RSTUVWGHIJKLABCDEF')
realorder = list('ABCDEFGHRISJTUVWKL')
response = pd.Series(
[float(i) / 35.0 for i in rawresp[:-3].split(',')], index=responseorder)
return pd.DataFrame(response, index=realorder, columns=['uW/cm^2']).to_dict()['uW/cm^2']
def schedule(self, refresh):
self.timerObject = Timer(refresh, self.startDataCollection)
self.timerObject.start()
def __init__(self, path='/dev/ttyUSB0', baudrate=115200, tout=1, rrate=1, params={}):
self.path=path
self.baudrate=baudrate
self.timeout=1
self.rrate=rrate
def __init__(self, path='/dev/ttyUSB0', baudrate=115200, tout=1):
self.path = path
self.baudrate = baudrate
self.timeout = 1
try:
self.serialObject = ser.Serial(path, baudrate, timeout=tout)
except:
print('An exception occured when opening the serial port at {}'.format(path))
ex(1)
raise Exception(
'An exception occured when opening the serial port at {}'.format(path))
else:
self.initializeSensor()
self.startDataCollection()
class LxMeter:
'''Class representing the APDS-9301 digital photometer.'''
def __init__(self, busNumber=1, addr=0x39):
self.addr = addr
try:
# initialize the SMBus interface
self.bus = smbus2.SMBus(busNumber)
except:
raise Exception(
'An exception occured opening the SMBus {}'.format(self.bus))
try:
self.bus.write_byte_data(
self.addr, 0xa0, 0x03) # enable the sensor
self.setGain(16)
except:
raise Exception('An exception occured when enabling lux meter')
def setGain(self, gain):
'''Set the sensor gain. Either 1 or 16.'''
if gain == 1:
try:
temp = self.bus.read_byte_data(self.addr, 0xa1)
self.bus.write_byte_data(self.addr, 0xa1, 0xef & temp)
except:
raise Exception(
'An exception occured when setting lux meter gain')
if gain == 16:
try:
temp = self.bus.read_byte_data(self.addr, 0xa1)
self.bus.write_byte_data(self.addr, 0xa1, 0x10 | temp)
except:
raise Exception(
'An exception occured when setting lux meter gain')
else:
raise Exception('Invalid gain')
def getGain(self):
'''Get the gain from the sensor.'''
try:
if self.bus.read_byte_data(self.addr, 0xa1) & 0x10 == 0x10:
return 16
if self.bus.read_byte_data(self.addr, 0xa1) & 0x10 == 0x00:
return 1
raise Exception('An error occured when getting lux meter gain')
# Under normal conditions, this raise is unreachable.
except:
raise Exception('An error occured when getting lux meter gain')
def setIntTime(self, time):
'''Set the lux sensor integration time. 0 to including 2'''
if time < 0 or time > 2:
raise Exception('Invalid integration time')
try:
temp = self.bus.read_byte_data(self.addr, 0xa1)
self.bus.write_byte_data(self.addr, 0xa1, (temp & 0xfc) | time)
except:
raise Exception(
'An exception occured setting lux integration time')
def getIntTime(self):
'''Get the lux sensor integration time.'''
try:
return self.bus.read_byte_data(self.addr, 0xa1) & 0x03
except:
raise Exception(
'An exception occured getting lux integration time')
def getData(self):
'''return the calculated lux value'''
try:
chA = self.bus.read_word_data(self.addr, 0xac)
chB = self.bus.read_word_data(self.addr, 0xae)
except:
raise Exception('An exception occured fetching lux channels')
# Refer to APDS-9301 datasheet!
if chB / chA <= 0.5 and chB / chA > 0:
lux = 0.0304 * chA - 0.062 * chA * (chB / chA)**1.4
elif chB / chA <= 0.61 and chB / chA > 0.5:
lux = 0.0224 * chA - 0.031 * chB
elif chB / chA <= 0.8 and chB / chA > 0.61:
lux = 0.0128 * chA - 0.0153 * chB
elif chB / chA <= 1.3 and chB / chA > 0.8:
lux = 0.00146 * chA - 0.00112 * chB
else:
lux = 0
return lux
class UVSensor:
'''Class representing VEML6075 UVA/B meter'''
def __init__(self, bus=1, addr=0x10):
self.addr = addr
try:
self.bus = smbus2.SMBus(bus)
except:
raise Exception(
'An exception occured opening SMBus {}'.format(bus))
try:
# enable the sensor and set the integration time
self.bus.write_byte_data(self.addr, 0x00, 0b00010000)
# trigger a measurement to prevent bus errors at first read
self.bus.write_byte_data(self.addr, 0x00, 0b00010010) # UV_AF=1
self.bus.write_byte_data(self.addr, 0x00, 0b00010110) # UV_TRIG=1
self.bus.write_byte_data(self.addr, 0x00, 0b00010000) # normal mode
except:
raise Exception(
'An exception occured when initalizing the UV Sensor')
def getABI(self):
'''Calculates the UVA and UVB irradiances,
along with UV index. Returns [a,b,i]'''
try:
# read the raw UVA, UVB and compensation values from the sensor
aRaw = self.bus.read_word_data(self.addr, 0x07)
bRaw = self.bus.read_word_data(self.addr, 0x09)
c1 = self.bus.read_word_data(self.addr, 0x0a)
c2 = self.bus.read_word_data(self.addr, 0x0b)
except:
raise Exception('An exception occured when fetching raw UV data')
# Refer to Vishay app note 84339 and Sparkfun VEML6075 documentation.
# The computed values may be negative if UV is vastly weaker than
# visible and IR light. This is not a bug!
a = (aRaw - 2.22 * c1 - 1.33 * c2) * 1.06
b = (bRaw - 2.95 * c1 - 1.74 * c2) * 0.48
i = (a + b) / 2 # calculate UV index
return [a, b, i]
def on(self):
'''Turns the UV sensor on after shutdown.'''
try:
# write the default value for power on
# no configurable params = no bitmask
self.bus.write_byte_data(self.addr, 0x00, 0x10)
except:
raise Exception(
'An exception occured when turning the UV sensor on')
def off(self):
'''Shuts the UV sensor down.'''
try:
# write the default value + the shutdown bit
# no configurable params = no bitmask
self.bus.write_byte_data(self.addr, 0x00, 0x11)
except:
raise Exception(
'An exception occured when shutting the UV sensor down')

37
backend/storage.py Normal file
View File

@@ -0,0 +1,37 @@
# storage.py - storage backend for TeraHz
'''TeraHz storage backend'''
# Copyright Kristjan Komloši 2019
# All code in this file is licensed under the ISC license,
# provided in LICENSE.txt
import sqlite3
class jsonStorage:
'''Class for simple sqlite3 database of JSON entries'''
def __init__(self, dbFile):
'''Storage object constructor. Argument is filename'''
self.db = sqlite3.connect(dbFile)
def listJSONs(self):
'''Returns a list of all existing entries.'''
c = self.db.cursor()
c.execute('SELECT * FROM storage')
result = c.fetchall()
c.close()
return result
def storeJSON(self, jsonString, comment):
'''Stores a JSON entry along with a timestamp and a comment.'''
c = self.db.cursor()
c.execute(('INSERT INTO storage VALUES (datetime'
'(\'now\', \'localtime\'), ?, ?)'), (comment, jsonString))
c.close()
self.db.commit()
def retrieveJSON(self, timestamp):
'''Retrieves a JSON entry. Takes a timestamp string'''
c = self.db.cursor()
c.execute('SELECT * FROM storage WHERE timestamp = ?', (timestamp,))
result = c.fetchall()
c.close()
return result

7
backend/terahz.fcgi Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/python3
# Minimal flup configuration for Flask
from flup.server.fcgi import WSGIServer
from app import app
if __name__ == '__main__':
WSGIServer(app, bindAddress='/var/www/api/terahz.sock').run()

View File

@@ -1,76 +0,0 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "$1" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/root/projekti/TeraHz/backend/venv"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
if [ "x(venv) " != x ] ; then
PS1="(venv) ${PS1:-}"
else
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
else
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
fi
fi
export PS1
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r
fi

View File

@@ -1,37 +0,0 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/root/projekti/TeraHz/backend/venv"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
if ("venv" != "") then
set env_name = "venv"
else
if (`basename "VIRTUAL_ENV"` == "__") then
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
else
set env_name = `basename "$VIRTUAL_ENV"`
endif
endif
set prompt = "[$env_name] $prompt"
unset env_name
endif
alias pydoc python -m pydoc
rehash

View File

@@ -1,75 +0,0 @@
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
# you cannot run it directly
function deactivate -d "Exit virtualenv and return to normal shell environment"
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
functions -e fish_prompt
set -e _OLD_FISH_PROMPT_OVERRIDE
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
set -e VIRTUAL_ENV
if test "$argv[1]" != "nondestructive"
# Self destruct!
functions -e deactivate
end
end
# unset irrelevant variables
deactivate nondestructive
set -gx VIRTUAL_ENV "/root/projekti/TeraHz/backend/venv"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# unset PYTHONHOME if set
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# fish uses a function instead of an env var to generate the prompt.
# save the current fish_prompt function as the function _old_fish_prompt
functions -c fish_prompt _old_fish_prompt
# with the original prompt function renamed, we can override with our own.
function fish_prompt
# Save the return status of the last command
set -l old_status $status
# Prompt override?
if test -n "(venv) "
printf "%s%s" "(venv) " (set_color normal)
else
# ...Otherwise, prepend env
set -l _checkbase (basename "$VIRTUAL_ENV")
if test $_checkbase = "__"
# special case for Aspen magic directories
# see http://www.zetadev.com/software/aspen/
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
else
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
end
end
# Restore the return status of the previous command.
echo "exit $old_status" | .
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
end

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from setuptools.command.easy_install import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from numpy.f2py.f2py2e import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from numpy.f2py.f2py2e import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from numpy.f2py.f2py2e import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from flask.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,12 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'future==0.17.1','console_scripts','futurize'
__requires__ = 'future==0.17.1'
import re
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(
load_entry_point('future==0.17.1', 'console_scripts', 'futurize')()
)

View File

@@ -1,976 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
#
# Very simple serial terminal
#
# This file is part of pySerial. https://github.com/pyserial/pyserial
# (C)2002-2015 Chris Liechti <cliechti@gmx.net>
#
# SPDX-License-Identifier: BSD-3-Clause
import codecs
import os
import sys
import threading
import serial
from serial.tools.list_ports import comports
from serial.tools import hexlify_codec
# pylint: disable=wrong-import-order,wrong-import-position
codecs.register(lambda c: hexlify_codec.getregentry() if c == 'hexlify' else None)
try:
raw_input
except NameError:
# pylint: disable=redefined-builtin,invalid-name
raw_input = input # in python3 it's "raw"
unichr = chr
def key_description(character):
"""generate a readable description for a key"""
ascii_code = ord(character)
if ascii_code < 32:
return 'Ctrl+{:c}'.format(ord('@') + ascii_code)
else:
return repr(character)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class ConsoleBase(object):
"""OS abstraction for console (input/output codec, no echo)"""
def __init__(self):
if sys.version_info >= (3, 0):
self.byte_output = sys.stdout.buffer
else:
self.byte_output = sys.stdout
self.output = sys.stdout
def setup(self):
"""Set console to read single characters, no echo"""
def cleanup(self):
"""Restore default console settings"""
def getkey(self):
"""Read a single key from the console"""
return None
def write_bytes(self, byte_string):
"""Write bytes (already encoded)"""
self.byte_output.write(byte_string)
self.byte_output.flush()
def write(self, text):
"""Write string"""
self.output.write(text)
self.output.flush()
def cancel(self):
"""Cancel getkey operation"""
# - - - - - - - - - - - - - - - - - - - - - - - -
# context manager:
# switch terminal temporary to normal mode (e.g. to get user input)
def __enter__(self):
self.cleanup()
return self
def __exit__(self, *args, **kwargs):
self.setup()
if os.name == 'nt': # noqa
import msvcrt
import ctypes
class Out(object):
"""file-like wrapper that uses os.write"""
def __init__(self, fd):
self.fd = fd
def flush(self):
pass
def write(self, s):
os.write(self.fd, s)
class Console(ConsoleBase):
def __init__(self):
super(Console, self).__init__()
self._saved_ocp = ctypes.windll.kernel32.GetConsoleOutputCP()
self._saved_icp = ctypes.windll.kernel32.GetConsoleCP()
ctypes.windll.kernel32.SetConsoleOutputCP(65001)
ctypes.windll.kernel32.SetConsoleCP(65001)
self.output = codecs.getwriter('UTF-8')(Out(sys.stdout.fileno()), 'replace')
# the change of the code page is not propagated to Python, manually fix it
sys.stderr = codecs.getwriter('UTF-8')(Out(sys.stderr.fileno()), 'replace')
sys.stdout = self.output
self.output.encoding = 'UTF-8' # needed for input
def __del__(self):
ctypes.windll.kernel32.SetConsoleOutputCP(self._saved_ocp)
ctypes.windll.kernel32.SetConsoleCP(self._saved_icp)
def getkey(self):
while True:
z = msvcrt.getwch()
if z == unichr(13):
return unichr(10)
elif z in (unichr(0), unichr(0x0e)): # functions keys, ignore
msvcrt.getwch()
else:
return z
def cancel(self):
# CancelIo, CancelSynchronousIo do not seem to work when using
# getwch, so instead, send a key to the window with the console
hwnd = ctypes.windll.kernel32.GetConsoleWindow()
ctypes.windll.user32.PostMessageA(hwnd, 0x100, 0x0d, 0)
elif os.name == 'posix':
import atexit
import termios
import fcntl
class Console(ConsoleBase):
def __init__(self):
super(Console, self).__init__()
self.fd = sys.stdin.fileno()
self.old = termios.tcgetattr(self.fd)
atexit.register(self.cleanup)
if sys.version_info < (3, 0):
self.enc_stdin = codecs.getreader(sys.stdin.encoding)(sys.stdin)
else:
self.enc_stdin = sys.stdin
def setup(self):
new = termios.tcgetattr(self.fd)
new[3] = new[3] & ~termios.ICANON & ~termios.ECHO & ~termios.ISIG
new[6][termios.VMIN] = 1
new[6][termios.VTIME] = 0
termios.tcsetattr(self.fd, termios.TCSANOW, new)
def getkey(self):
c = self.enc_stdin.read(1)
if c == unichr(0x7f):
c = unichr(8) # map the BS key (which yields DEL) to backspace
return c
def cancel(self):
fcntl.ioctl(self.fd, termios.TIOCSTI, b'\0')
def cleanup(self):
termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old)
else:
raise NotImplementedError(
'Sorry no implementation for your platform ({}) available.'.format(sys.platform))
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Transform(object):
"""do-nothing: forward all data unchanged"""
def rx(self, text):
"""text received from serial port"""
return text
def tx(self, text):
"""text to be sent to serial port"""
return text
def echo(self, text):
"""text to be sent but displayed on console"""
return text
class CRLF(Transform):
"""ENTER sends CR+LF"""
def tx(self, text):
return text.replace('\n', '\r\n')
class CR(Transform):
"""ENTER sends CR"""
def rx(self, text):
return text.replace('\r', '\n')
def tx(self, text):
return text.replace('\n', '\r')
class LF(Transform):
"""ENTER sends LF"""
class NoTerminal(Transform):
"""remove typical terminal control codes from input"""
REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32) if unichr(x) not in '\r\n\b\t')
REPLACEMENT_MAP.update(
{
0x7F: 0x2421, # DEL
0x9B: 0x2425, # CSI
})
def rx(self, text):
return text.translate(self.REPLACEMENT_MAP)
echo = rx
class NoControls(NoTerminal):
"""Remove all control codes, incl. CR+LF"""
REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32))
REPLACEMENT_MAP.update(
{
0x20: 0x2423, # visual space
0x7F: 0x2421, # DEL
0x9B: 0x2425, # CSI
})
class Printable(Transform):
"""Show decimal code for all non-ASCII characters and replace most control codes"""
def rx(self, text):
r = []
for c in text:
if ' ' <= c < '\x7f' or c in '\r\n\b\t':
r.append(c)
elif c < ' ':
r.append(unichr(0x2400 + ord(c)))
else:
r.extend(unichr(0x2080 + ord(d) - 48) for d in '{:d}'.format(ord(c)))
r.append(' ')
return ''.join(r)
echo = rx
class Colorize(Transform):
"""Apply different colors for received and echo"""
def __init__(self):
# XXX make it configurable, use colorama?
self.input_color = '\x1b[37m'
self.echo_color = '\x1b[31m'
def rx(self, text):
return self.input_color + text
def echo(self, text):
return self.echo_color + text
class DebugIO(Transform):
"""Print what is sent and received"""
def rx(self, text):
sys.stderr.write(' [RX:{}] '.format(repr(text)))
sys.stderr.flush()
return text
def tx(self, text):
sys.stderr.write(' [TX:{}] '.format(repr(text)))
sys.stderr.flush()
return text
# other ideas:
# - add date/time for each newline
# - insert newline after: a) timeout b) packet end character
EOL_TRANSFORMATIONS = {
'crlf': CRLF,
'cr': CR,
'lf': LF,
}
TRANSFORMATIONS = {
'direct': Transform, # no transformation
'default': NoTerminal,
'nocontrol': NoControls,
'printable': Printable,
'colorize': Colorize,
'debug': DebugIO,
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def ask_for_port():
"""\
Show a list of ports and ask the user for a choice. To make selection
easier on systems with long device names, also allow the input of an
index.
"""
sys.stderr.write('\n--- Available ports:\n')
ports = []
for n, (port, desc, hwid) in enumerate(sorted(comports()), 1):
sys.stderr.write('--- {:2}: {:20} {!r}\n'.format(n, port, desc))
ports.append(port)
while True:
port = raw_input('--- Enter port index or full name: ')
try:
index = int(port) - 1
if not 0 <= index < len(ports):
sys.stderr.write('--- Invalid index!\n')
continue
except ValueError:
pass
else:
port = ports[index]
return port
class Miniterm(object):
"""\
Terminal application. Copy data from serial port to console and vice versa.
Handle special keys from the console to show menu etc.
"""
def __init__(self, serial_instance, echo=False, eol='crlf', filters=()):
self.console = Console()
self.serial = serial_instance
self.echo = echo
self.raw = False
self.input_encoding = 'UTF-8'
self.output_encoding = 'UTF-8'
self.eol = eol
self.filters = filters
self.update_transformations()
self.exit_character = 0x1d # GS/CTRL+]
self.menu_character = 0x14 # Menu: CTRL+T
self.alive = None
self._reader_alive = None
self.receiver_thread = None
self.rx_decoder = None
self.tx_decoder = None
def _start_reader(self):
"""Start reader thread"""
self._reader_alive = True
# start serial->console thread
self.receiver_thread = threading.Thread(target=self.reader, name='rx')
self.receiver_thread.daemon = True
self.receiver_thread.start()
def _stop_reader(self):
"""Stop reader thread only, wait for clean exit of thread"""
self._reader_alive = False
if hasattr(self.serial, 'cancel_read'):
self.serial.cancel_read()
self.receiver_thread.join()
def start(self):
"""start worker threads"""
self.alive = True
self._start_reader()
# enter console->serial loop
self.transmitter_thread = threading.Thread(target=self.writer, name='tx')
self.transmitter_thread.daemon = True
self.transmitter_thread.start()
self.console.setup()
def stop(self):
"""set flag to stop worker threads"""
self.alive = False
def join(self, transmit_only=False):
"""wait for worker threads to terminate"""
self.transmitter_thread.join()
if not transmit_only:
if hasattr(self.serial, 'cancel_read'):
self.serial.cancel_read()
self.receiver_thread.join()
def close(self):
self.serial.close()
def update_transformations(self):
"""take list of transformation classes and instantiate them for rx and tx"""
transformations = [EOL_TRANSFORMATIONS[self.eol]] + [TRANSFORMATIONS[f]
for f in self.filters]
self.tx_transformations = [t() for t in transformations]
self.rx_transformations = list(reversed(self.tx_transformations))
def set_rx_encoding(self, encoding, errors='replace'):
"""set encoding for received data"""
self.input_encoding = encoding
self.rx_decoder = codecs.getincrementaldecoder(encoding)(errors)
def set_tx_encoding(self, encoding, errors='replace'):
"""set encoding for transmitted data"""
self.output_encoding = encoding
self.tx_encoder = codecs.getincrementalencoder(encoding)(errors)
def dump_port_settings(self):
"""Write current settings to sys.stderr"""
sys.stderr.write("\n--- Settings: {p.name} {p.baudrate},{p.bytesize},{p.parity},{p.stopbits}\n".format(
p=self.serial))
sys.stderr.write('--- RTS: {:8} DTR: {:8} BREAK: {:8}\n'.format(
('active' if self.serial.rts else 'inactive'),
('active' if self.serial.dtr else 'inactive'),
('active' if self.serial.break_condition else 'inactive')))
try:
sys.stderr.write('--- CTS: {:8} DSR: {:8} RI: {:8} CD: {:8}\n'.format(
('active' if self.serial.cts else 'inactive'),
('active' if self.serial.dsr else 'inactive'),
('active' if self.serial.ri else 'inactive'),
('active' if self.serial.cd else 'inactive')))
except serial.SerialException:
# on RFC 2217 ports, it can happen if no modem state notification was
# yet received. ignore this error.
pass
sys.stderr.write('--- software flow control: {}\n'.format('active' if self.serial.xonxoff else 'inactive'))
sys.stderr.write('--- hardware flow control: {}\n'.format('active' if self.serial.rtscts else 'inactive'))
sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))
sys.stderr.write('--- EOL: {}\n'.format(self.eol.upper()))
sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))
def reader(self):
"""loop and copy serial->console"""
try:
while self.alive and self._reader_alive:
# read all that is there or wait for one byte
data = self.serial.read(self.serial.in_waiting or 1)
if data:
if self.raw:
self.console.write_bytes(data)
else:
text = self.rx_decoder.decode(data)
for transformation in self.rx_transformations:
text = transformation.rx(text)
self.console.write(text)
except serial.SerialException:
self.alive = False
self.console.cancel()
raise # XXX handle instead of re-raise?
def writer(self):
"""\
Loop and copy console->serial until self.exit_character character is
found. When self.menu_character is found, interpret the next key
locally.
"""
menu_active = False
try:
while self.alive:
try:
c = self.console.getkey()
except KeyboardInterrupt:
c = '\x03'
if not self.alive:
break
if menu_active:
self.handle_menu_key(c)
menu_active = False
elif c == self.menu_character:
menu_active = True # next char will be for menu
elif c == self.exit_character:
self.stop() # exit app
break
else:
#~ if self.raw:
text = c
for transformation in self.tx_transformations:
text = transformation.tx(text)
self.serial.write(self.tx_encoder.encode(text))
if self.echo:
echo_text = c
for transformation in self.tx_transformations:
echo_text = transformation.echo(echo_text)
self.console.write(echo_text)
except:
self.alive = False
raise
def handle_menu_key(self, c):
"""Implement a simple menu / settings"""
if c == self.menu_character or c == self.exit_character:
# Menu/exit character again -> send itself
self.serial.write(self.tx_encoder.encode(c))
if self.echo:
self.console.write(c)
elif c == '\x15': # CTRL+U -> upload file
self.upload_file()
elif c in '\x08hH?': # CTRL+H, h, H, ? -> Show help
sys.stderr.write(self.get_help_text())
elif c == '\x12': # CTRL+R -> Toggle RTS
self.serial.rts = not self.serial.rts
sys.stderr.write('--- RTS {} ---\n'.format('active' if self.serial.rts else 'inactive'))
elif c == '\x04': # CTRL+D -> Toggle DTR
self.serial.dtr = not self.serial.dtr
sys.stderr.write('--- DTR {} ---\n'.format('active' if self.serial.dtr else 'inactive'))
elif c == '\x02': # CTRL+B -> toggle BREAK condition
self.serial.break_condition = not self.serial.break_condition
sys.stderr.write('--- BREAK {} ---\n'.format('active' if self.serial.break_condition else 'inactive'))
elif c == '\x05': # CTRL+E -> toggle local echo
self.echo = not self.echo
sys.stderr.write('--- local echo {} ---\n'.format('active' if self.echo else 'inactive'))
elif c == '\x06': # CTRL+F -> edit filters
self.change_filter()
elif c == '\x0c': # CTRL+L -> EOL mode
modes = list(EOL_TRANSFORMATIONS) # keys
eol = modes.index(self.eol) + 1
if eol >= len(modes):
eol = 0
self.eol = modes[eol]
sys.stderr.write('--- EOL: {} ---\n'.format(self.eol.upper()))
self.update_transformations()
elif c == '\x01': # CTRL+A -> set encoding
self.change_encoding()
elif c == '\x09': # CTRL+I -> info
self.dump_port_settings()
#~ elif c == '\x01': # CTRL+A -> cycle escape mode
#~ elif c == '\x0c': # CTRL+L -> cycle linefeed mode
elif c in 'pP': # P -> change port
self.change_port()
elif c in 'sS': # S -> suspend / open port temporarily
self.suspend_port()
elif c in 'bB': # B -> change baudrate
self.change_baudrate()
elif c == '8': # 8 -> change to 8 bits
self.serial.bytesize = serial.EIGHTBITS
self.dump_port_settings()
elif c == '7': # 7 -> change to 8 bits
self.serial.bytesize = serial.SEVENBITS
self.dump_port_settings()
elif c in 'eE': # E -> change to even parity
self.serial.parity = serial.PARITY_EVEN
self.dump_port_settings()
elif c in 'oO': # O -> change to odd parity
self.serial.parity = serial.PARITY_ODD
self.dump_port_settings()
elif c in 'mM': # M -> change to mark parity
self.serial.parity = serial.PARITY_MARK
self.dump_port_settings()
elif c in 'sS': # S -> change to space parity
self.serial.parity = serial.PARITY_SPACE
self.dump_port_settings()
elif c in 'nN': # N -> change to no parity
self.serial.parity = serial.PARITY_NONE
self.dump_port_settings()
elif c == '1': # 1 -> change to 1 stop bits
self.serial.stopbits = serial.STOPBITS_ONE
self.dump_port_settings()
elif c == '2': # 2 -> change to 2 stop bits
self.serial.stopbits = serial.STOPBITS_TWO
self.dump_port_settings()
elif c == '3': # 3 -> change to 1.5 stop bits
self.serial.stopbits = serial.STOPBITS_ONE_POINT_FIVE
self.dump_port_settings()
elif c in 'xX': # X -> change software flow control
self.serial.xonxoff = (c == 'X')
self.dump_port_settings()
elif c in 'rR': # R -> change hardware flow control
self.serial.rtscts = (c == 'R')
self.dump_port_settings()
else:
sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c)))
def upload_file(self):
"""Ask user for filenname and send its contents"""
sys.stderr.write('\n--- File to upload: ')
sys.stderr.flush()
with self.console:
filename = sys.stdin.readline().rstrip('\r\n')
if filename:
try:
with open(filename, 'rb') as f:
sys.stderr.write('--- Sending file {} ---\n'.format(filename))
while True:
block = f.read(1024)
if not block:
break
self.serial.write(block)
# Wait for output buffer to drain.
self.serial.flush()
sys.stderr.write('.') # Progress indicator.
sys.stderr.write('\n--- File {} sent ---\n'.format(filename))
except IOError as e:
sys.stderr.write('--- ERROR opening file {}: {} ---\n'.format(filename, e))
def change_filter(self):
"""change the i/o transformations"""
sys.stderr.write('\n--- Available Filters:\n')
sys.stderr.write('\n'.join(
'--- {:<10} = {.__doc__}'.format(k, v)
for k, v in sorted(TRANSFORMATIONS.items())))
sys.stderr.write('\n--- Enter new filter name(s) [{}]: '.format(' '.join(self.filters)))
with self.console:
new_filters = sys.stdin.readline().lower().split()
if new_filters:
for f in new_filters:
if f not in TRANSFORMATIONS:
sys.stderr.write('--- unknown filter: {}\n'.format(repr(f)))
break
else:
self.filters = new_filters
self.update_transformations()
sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))
def change_encoding(self):
"""change encoding on the serial port"""
sys.stderr.write('\n--- Enter new encoding name [{}]: '.format(self.input_encoding))
with self.console:
new_encoding = sys.stdin.readline().strip()
if new_encoding:
try:
codecs.lookup(new_encoding)
except LookupError:
sys.stderr.write('--- invalid encoding name: {}\n'.format(new_encoding))
else:
self.set_rx_encoding(new_encoding)
self.set_tx_encoding(new_encoding)
sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))
def change_baudrate(self):
"""change the baudrate"""
sys.stderr.write('\n--- Baudrate: ')
sys.stderr.flush()
with self.console:
backup = self.serial.baudrate
try:
self.serial.baudrate = int(sys.stdin.readline().strip())
except ValueError as e:
sys.stderr.write('--- ERROR setting baudrate: {} ---\n'.format(e))
self.serial.baudrate = backup
else:
self.dump_port_settings()
def change_port(self):
"""Have a conversation with the user to change the serial port"""
with self.console:
try:
port = ask_for_port()
except KeyboardInterrupt:
port = None
if port and port != self.serial.port:
# reader thread needs to be shut down
self._stop_reader()
# save settings
settings = self.serial.getSettingsDict()
try:
new_serial = serial.serial_for_url(port, do_not_open=True)
# restore settings and open
new_serial.applySettingsDict(settings)
new_serial.rts = self.serial.rts
new_serial.dtr = self.serial.dtr
new_serial.open()
new_serial.break_condition = self.serial.break_condition
except Exception as e:
sys.stderr.write('--- ERROR opening new port: {} ---\n'.format(e))
new_serial.close()
else:
self.serial.close()
self.serial = new_serial
sys.stderr.write('--- Port changed to: {} ---\n'.format(self.serial.port))
# and restart the reader thread
self._start_reader()
def suspend_port(self):
"""\
open port temporarily, allow reconnect, exit and port change to get
out of the loop
"""
# reader thread needs to be shut down
self._stop_reader()
self.serial.close()
sys.stderr.write('\n--- Port closed: {} ---\n'.format(self.serial.port))
do_change_port = False
while not self.serial.is_open:
sys.stderr.write('--- Quit: {exit} | p: port change | any other key to reconnect ---\n'.format(
exit=key_description(self.exit_character)))
k = self.console.getkey()
if k == self.exit_character:
self.stop() # exit app
break
elif k in 'pP':
do_change_port = True
break
try:
self.serial.open()
except Exception as e:
sys.stderr.write('--- ERROR opening port: {} ---\n'.format(e))
if do_change_port:
self.change_port()
else:
# and restart the reader thread
self._start_reader()
sys.stderr.write('--- Port opened: {} ---\n'.format(self.serial.port))
def get_help_text(self):
"""return the help text"""
# help text, starts with blank line!
return """
--- pySerial ({version}) - miniterm - help
---
--- {exit:8} Exit program
--- {menu:8} Menu escape key, followed by:
--- Menu keys:
--- {menu:7} Send the menu character itself to remote
--- {exit:7} Send the exit character itself to remote
--- {info:7} Show info
--- {upload:7} Upload file (prompt will be shown)
--- {repr:7} encoding
--- {filter:7} edit filters
--- Toggles:
--- {rts:7} RTS {dtr:7} DTR {brk:7} BREAK
--- {echo:7} echo {eol:7} EOL
---
--- Port settings ({menu} followed by the following):
--- p change port
--- 7 8 set data bits
--- N E O S M change parity (None, Even, Odd, Space, Mark)
--- 1 2 3 set stop bits (1, 2, 1.5)
--- b change baud rate
--- x X disable/enable software flow control
--- r R disable/enable hardware flow control
""".format(version=getattr(serial, 'VERSION', 'unknown version'),
exit=key_description(self.exit_character),
menu=key_description(self.menu_character),
rts=key_description('\x12'),
dtr=key_description('\x04'),
brk=key_description('\x02'),
echo=key_description('\x05'),
info=key_description('\x09'),
upload=key_description('\x15'),
repr=key_description('\x01'),
filter=key_description('\x06'),
eol=key_description('\x0c'))
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# default args can be used to override when calling main() from an other script
# e.g to create a miniterm-my-device.py
def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr=None):
"""Command line tool, entry point"""
import argparse
parser = argparse.ArgumentParser(
description="Miniterm - A simple terminal program for the serial port.")
parser.add_argument(
"port",
nargs='?',
help="serial port name ('-' to show port list)",
default=default_port)
parser.add_argument(
"baudrate",
nargs='?',
type=int,
help="set baud rate, default: %(default)s",
default=default_baudrate)
group = parser.add_argument_group("port settings")
group.add_argument(
"--parity",
choices=['N', 'E', 'O', 'S', 'M'],
type=lambda c: c.upper(),
help="set parity, one of {N E O S M}, default: N",
default='N')
group.add_argument(
"--rtscts",
action="store_true",
help="enable RTS/CTS flow control (default off)",
default=False)
group.add_argument(
"--xonxoff",
action="store_true",
help="enable software flow control (default off)",
default=False)
group.add_argument(
"--rts",
type=int,
help="set initial RTS line state (possible values: 0, 1)",
default=default_rts)
group.add_argument(
"--dtr",
type=int,
help="set initial DTR line state (possible values: 0, 1)",
default=default_dtr)
group.add_argument(
"--ask",
action="store_true",
help="ask again for port when open fails",
default=False)
group = parser.add_argument_group("data handling")
group.add_argument(
"-e", "--echo",
action="store_true",
help="enable local echo (default off)",
default=False)
group.add_argument(
"--encoding",
dest="serial_port_encoding",
metavar="CODEC",
help="set the encoding for the serial port (e.g. hexlify, Latin1, UTF-8), default: %(default)s",
default='UTF-8')
group.add_argument(
"-f", "--filter",
action="append",
metavar="NAME",
help="add text transformation",
default=[])
group.add_argument(
"--eol",
choices=['CR', 'LF', 'CRLF'],
type=lambda c: c.upper(),
help="end of line mode",
default='CRLF')
group.add_argument(
"--raw",
action="store_true",
help="Do no apply any encodings/transformations",
default=False)
group = parser.add_argument_group("hotkeys")
group.add_argument(
"--exit-char",
type=int,
metavar='NUM',
help="Unicode of special character that is used to exit the application, default: %(default)s",
default=0x1d) # GS/CTRL+]
group.add_argument(
"--menu-char",
type=int,
metavar='NUM',
help="Unicode code of special character that is used to control miniterm (menu), default: %(default)s",
default=0x14) # Menu: CTRL+T
group = parser.add_argument_group("diagnostics")
group.add_argument(
"-q", "--quiet",
action="store_true",
help="suppress non-error messages",
default=False)
group.add_argument(
"--develop",
action="store_true",
help="show Python traceback on error",
default=False)
args = parser.parse_args()
if args.menu_char == args.exit_char:
parser.error('--exit-char can not be the same as --menu-char')
if args.filter:
if 'help' in args.filter:
sys.stderr.write('Available filters:\n')
sys.stderr.write('\n'.join(
'{:<10} = {.__doc__}'.format(k, v)
for k, v in sorted(TRANSFORMATIONS.items())))
sys.stderr.write('\n')
sys.exit(1)
filters = args.filter
else:
filters = ['default']
while True:
# no port given on command line -> ask user now
if args.port is None or args.port == '-':
try:
args.port = ask_for_port()
except KeyboardInterrupt:
sys.stderr.write('\n')
parser.error('user aborted and port is not given')
else:
if not args.port:
parser.error('port is not given')
try:
serial_instance = serial.serial_for_url(
args.port,
args.baudrate,
parity=args.parity,
rtscts=args.rtscts,
xonxoff=args.xonxoff,
do_not_open=True)
if not hasattr(serial_instance, 'cancel_read'):
# enable timeout for alive flag polling if cancel_read is not available
serial_instance.timeout = 1
if args.dtr is not None:
if not args.quiet:
sys.stderr.write('--- forcing DTR {}\n'.format('active' if args.dtr else 'inactive'))
serial_instance.dtr = args.dtr
if args.rts is not None:
if not args.quiet:
sys.stderr.write('--- forcing RTS {}\n'.format('active' if args.rts else 'inactive'))
serial_instance.rts = args.rts
serial_instance.open()
except serial.SerialException as e:
sys.stderr.write('could not open port {}: {}\n'.format(repr(args.port), e))
if args.develop:
raise
if not args.ask:
sys.exit(1)
else:
args.port = '-'
else:
break
miniterm = Miniterm(
serial_instance,
echo=args.echo,
eol=args.eol.lower(),
filters=filters)
miniterm.exit_character = unichr(args.exit_char)
miniterm.menu_character = unichr(args.menu_char)
miniterm.raw = args.raw
miniterm.set_rx_encoding(args.serial_port_encoding)
miniterm.set_tx_encoding(args.serial_port_encoding)
if not args.quiet:
sys.stderr.write('--- Miniterm on {p.name} {p.baudrate},{p.bytesize},{p.parity},{p.stopbits} ---\n'.format(
p=miniterm.serial))
sys.stderr.write('--- Quit: {} | Menu: {} | Help: {} followed by {} ---\n'.format(
key_description(miniterm.exit_character),
key_description(miniterm.menu_character),
key_description(miniterm.menu_character),
key_description('\x08')))
miniterm.start()
try:
miniterm.join(True)
except KeyboardInterrupt:
pass
if not args.quiet:
sys.stderr.write("\n--- exit ---\n")
miniterm.join()
miniterm.close()
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if __name__ == '__main__':
main()

Binary file not shown.

View File

@@ -1,12 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'future==0.17.1','console_scripts','pasteurize'
__requires__ = 'future==0.17.1'
import re
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(
load_entry_point('future==0.17.1', 'console_scripts', 'pasteurize')()
)

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1,10 +0,0 @@
#!/root/projekti/TeraHz/backend/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -1 +0,0 @@
python3

View File

@@ -1 +0,0 @@
/usr/bin/python3

View File

@@ -1,39 +0,0 @@
Copyright © 2014 by the Pallets team.
Some rights reserved.
Redistribution and use in source and binary forms of the software as
well as documentation, with or without modification, are permitted
provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
----
Click uses parts of optparse written by Gregory P. Ward and maintained
by the Python Software Foundation. This is limited to code in parser.py.
Copyright © 2001-2006 Gregory P. Ward. All rights reserved.
Copyright © 2002-2006 Python Software Foundation. All rights reserved.

View File

@@ -1,121 +0,0 @@
Metadata-Version: 2.1
Name: Click
Version: 7.0
Summary: Composable command line interface toolkit
Home-page: https://palletsprojects.com/p/click/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Pallets Team
Maintainer-email: contact@palletsprojects.com
License: BSD
Project-URL: Documentation, https://click.palletsprojects.com/
Project-URL: Code, https://github.com/pallets/click
Project-URL: Issue tracker, https://github.com/pallets/click/issues
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
\$ click\_
==========
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to
implement an intended CLI API.
Click in three points:
- Arbitrary nesting of commands
- Automatic help page generation
- Supports lazy loading of subcommands at runtime
Installing
----------
Install and update using `pip`_:
.. code-block:: text
$ pip install click
Click supports Python 3.4 and newer, Python 2.7, and PyPy.
.. _pip: https://pip.pypa.io/en/stable/quickstart/
A Simple Example
----------------
What does it look like? Here is an example of a simple Click program:
.. code-block:: python
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name",
help="The person to greet.")
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
click.echo("Hello, %s!" % name)
if __name__ == '__main__':
hello()
And what it looks like when run:
.. code-block:: text
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!
Donate
------
The Pallets organization develops and supports Click and other popular
packages. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, `please
donate today`_.
.. _please donate today: https://palletsprojects.com/donate
Links
-----
* Website: https://palletsprojects.com/p/click/
* Documentation: https://click.palletsprojects.com/
* License: `BSD <https://github.com/pallets/click/blob/master/LICENSE.rst>`_
* Releases: https://pypi.org/project/click/
* Code: https://github.com/pallets/click
* Issue tracker: https://github.com/pallets/click/issues
* Test status:
* Linux, Mac: https://travis-ci.org/pallets/click
* Windows: https://ci.appveyor.com/project/pallets/click
* Test coverage: https://codecov.io/gh/pallets/click

View File

@@ -1,40 +0,0 @@
Click-7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Click-7.0.dist-info/LICENSE.txt,sha256=4hIxn676T0Wcisk3_chVcECjyrivKTZsoqSNI5AlIlw,1876
Click-7.0.dist-info/METADATA,sha256=-r8jeke3Zer4diRvT1MjFZuiJ6yTT_qFP39svLqdaLI,3516
Click-7.0.dist-info/RECORD,,
Click-7.0.dist-info/WHEEL,sha256=gduuPyBvFJQSQ0zdyxF7k0zynDXbIbvg5ZBHoXum5uk,110
Click-7.0.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6
click/__init__.py,sha256=HjGThQ7tef9kkwCV371TBnrf0SAi6fKfU_jtEnbYTvQ,2789
click/__pycache__/__init__.cpython-36.pyc,,
click/__pycache__/_bashcomplete.cpython-36.pyc,,
click/__pycache__/_compat.cpython-36.pyc,,
click/__pycache__/_termui_impl.cpython-36.pyc,,
click/__pycache__/_textwrap.cpython-36.pyc,,
click/__pycache__/_unicodefun.cpython-36.pyc,,
click/__pycache__/_winconsole.cpython-36.pyc,,
click/__pycache__/core.cpython-36.pyc,,
click/__pycache__/decorators.cpython-36.pyc,,
click/__pycache__/exceptions.cpython-36.pyc,,
click/__pycache__/formatting.cpython-36.pyc,,
click/__pycache__/globals.cpython-36.pyc,,
click/__pycache__/parser.cpython-36.pyc,,
click/__pycache__/termui.cpython-36.pyc,,
click/__pycache__/testing.cpython-36.pyc,,
click/__pycache__/types.cpython-36.pyc,,
click/__pycache__/utils.cpython-36.pyc,,
click/_bashcomplete.py,sha256=iaNUmtxag0YPfxba3TDYCNietiTMQIrvhRLj-H8okFU,11014
click/_compat.py,sha256=vYmvoj4opPxo-c-2GMQQjYT_r_QkOKybkfGoeVrt0dA,23399
click/_termui_impl.py,sha256=xHmLtOJhKUCVD6168yucJ9fknUJPAMs0eUTPgVUO-GQ,19611
click/_textwrap.py,sha256=gwS4m7bdQiJnzaDG8osFcRb-5vn4t4l2qSCy-5csCEc,1198
click/_unicodefun.py,sha256=QHy2_5jYlX-36O-JVrTHNnHOqg8tquUR0HmQFev7Ics,4364
click/_winconsole.py,sha256=PPWVak8Iikm_gAPsxMrzwsVFCvHgaW3jPaDWZ1JBl3U,8965
click/core.py,sha256=q8FLcDZsagBGSRe5Y9Hi_FGvAeZvusNfoO5EkhkSQ8Y,75305
click/decorators.py,sha256=idKt6duLUUfAFftrHoREi8MJSd39XW36pUVHthdglwk,11226
click/exceptions.py,sha256=CNpAjBAE7qjaV4WChxQeak95e5yUOau8AsvT-8m6wss,7663
click/formatting.py,sha256=eh-cypTUAhpI3HD-K4ZpR3vCiURIO62xXvKkR3tNUTM,8889
click/globals.py,sha256=oQkou3ZQ5DgrbVM6BwIBirwiqozbjfirzsLGAlLRRdg,1514
click/parser.py,sha256=m-nGZz4VwprM42_qtFlWFGo7yRJQxkBlRcZodoH593Y,15510
click/termui.py,sha256=o_ZXB2jyvL2Rce7P_bFGq452iyBq9ykJyRApIPMCZO0,23207
click/testing.py,sha256=aYGqY_iWLu2p4k7lkuJ6t3fqpf6aPGqTsyLzNY_ngKg,13062
click/types.py,sha256=2Q929p-aBP_ZYuMFJqJR-Ipucofv3fmDc5JzBDPmzJU,23287
click/utils.py,sha256=6-D0WkAxvv9FkgHXSHwDIv0l9Gdx9Mm6Z5vuKNLIfZI,15763

View File

@@ -1,6 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.31.1)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@@ -1,31 +0,0 @@
Copyright © 2010 by the Pallets team.
Some rights reserved.
Redistribution and use in source and binary forms of the software as
well as documentation, with or without modification, are permitted
provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -1,130 +0,0 @@
Metadata-Version: 2.1
Name: Flask
Version: 1.0.2
Summary: A simple framework for building complex web applications.
Home-page: https://www.palletsprojects.com/p/flask/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Pallets team
Maintainer-email: contact@palletsprojects.com
License: BSD
Project-URL: Documentation, http://flask.pocoo.org/docs/
Project-URL: Code, https://github.com/pallets/flask
Project-URL: Issue tracker, https://github.com/pallets/flask/issues
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Provides-Extra: dev
Provides-Extra: docs
Provides-Extra: dotenv
Requires-Dist: Werkzeug (>=0.14)
Requires-Dist: Jinja2 (>=2.10)
Requires-Dist: itsdangerous (>=0.24)
Requires-Dist: click (>=5.1)
Provides-Extra: dev
Requires-Dist: pytest (>=3); extra == 'dev'
Requires-Dist: coverage; extra == 'dev'
Requires-Dist: tox; extra == 'dev'
Requires-Dist: sphinx; extra == 'dev'
Requires-Dist: pallets-sphinx-themes; extra == 'dev'
Requires-Dist: sphinxcontrib-log-cabinet; extra == 'dev'
Provides-Extra: docs
Requires-Dist: sphinx; extra == 'docs'
Requires-Dist: pallets-sphinx-themes; extra == 'docs'
Requires-Dist: sphinxcontrib-log-cabinet; extra == 'docs'
Provides-Extra: dotenv
Requires-Dist: python-dotenv; extra == 'dotenv'
Flask
=====
Flask is a lightweight `WSGI`_ web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around `Werkzeug`_
and `Jinja`_ and has become one of the most popular Python web
application frameworks.
Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.
Installing
----------
Install and update using `pip`_:
.. code-block:: text
pip install -U Flask
A Simple Example
----------------
.. code-block:: python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
.. code-block:: text
$ FLASK_APP=hello.py flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Donate
------
The Pallets organization develops and supports Flask and the libraries
it uses. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, `please
donate today`_.
.. _please donate today: https://psfmember.org/civicrm/contribute/transact?reset=1&id=20
Links
-----
* Website: https://www.palletsprojects.com/p/flask/
* Documentation: http://flask.pocoo.org/docs/
* License: `BSD <https://github.com/pallets/flask/blob/master/LICENSE>`_
* Releases: https://pypi.org/project/Flask/
* Code: https://github.com/pallets/flask
* Issue tracker: https://github.com/pallets/flask/issues
* Test status:
* Linux, Mac: https://travis-ci.org/pallets/flask
* Windows: https://ci.appveyor.com/project/pallets/flask
* Test coverage: https://codecov.io/gh/pallets/flask
.. _WSGI: https://wsgi.readthedocs.io
.. _Werkzeug: https://www.palletsprojects.com/p/werkzeug/
.. _Jinja: https://www.palletsprojects.com/p/jinja/
.. _pip: https://pip.pypa.io/en/stable/quickstart/

View File

@@ -1,48 +0,0 @@
../../../bin/flask,sha256=ja9nrYfRFZV2nf3KLUUe1glXY9Jpqr193oPl5IT_Igw,241
Flask-1.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Flask-1.0.2.dist-info/LICENSE.txt,sha256=ziEXA3AIuaiUn1qe4cd1XxCESWTYrk4TjN7Qb06J3l8,1575
Flask-1.0.2.dist-info/METADATA,sha256=iA5tiNWzTtgCVe80aTZGNWsckj853fJyfvHs9U-WZRk,4182
Flask-1.0.2.dist-info/RECORD,,
Flask-1.0.2.dist-info/WHEEL,sha256=J3CsTk7Mf2JNUyhImI-mjX-fmI4oDjyiXgWT4qgZiCE,110
Flask-1.0.2.dist-info/entry_points.txt,sha256=gBLA1aKg0OYR8AhbAfg8lnburHtKcgJLDU52BBctN0k,42
Flask-1.0.2.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6
flask/__init__.py,sha256=qq8lK6QQbxJALf1igz7qsvUwOTAoKvFGfdLm7jPNsso,1673
flask/__main__.py,sha256=pgIXrHhxM5MAMvgzAqWpw_t6AXZ1zG38us4JRgJKtxk,291
flask/__pycache__/__init__.cpython-36.pyc,,
flask/__pycache__/__main__.cpython-36.pyc,,
flask/__pycache__/_compat.cpython-36.pyc,,
flask/__pycache__/app.cpython-36.pyc,,
flask/__pycache__/blueprints.cpython-36.pyc,,
flask/__pycache__/cli.cpython-36.pyc,,
flask/__pycache__/config.cpython-36.pyc,,
flask/__pycache__/ctx.cpython-36.pyc,,
flask/__pycache__/debughelpers.cpython-36.pyc,,
flask/__pycache__/globals.cpython-36.pyc,,
flask/__pycache__/helpers.cpython-36.pyc,,
flask/__pycache__/logging.cpython-36.pyc,,
flask/__pycache__/sessions.cpython-36.pyc,,
flask/__pycache__/signals.cpython-36.pyc,,
flask/__pycache__/templating.cpython-36.pyc,,
flask/__pycache__/testing.cpython-36.pyc,,
flask/__pycache__/views.cpython-36.pyc,,
flask/__pycache__/wrappers.cpython-36.pyc,,
flask/_compat.py,sha256=UDFGhosh6mOdNB-4evKPuneHum1OpcAlwTNJCRm0irQ,2892
flask/app.py,sha256=ahpe3T8w98rQd_Er5d7uDxK57S1nnqGQx3V3hirBovU,94147
flask/blueprints.py,sha256=Cyhl_x99tgwqEZPtNDJUFneAfVJxWfEU4bQA7zWS6VU,18331
flask/cli.py,sha256=30QYAO10Do9LbZYCLgfI_xhKjASdLopL8wKKVUGS2oA,29442
flask/config.py,sha256=kznUhj4DLYxsTF_4kfDG8GEHto1oZG_kqblyrLFtpqQ,9951
flask/ctx.py,sha256=leFzS9fzmo0uaLCdxpHc5_iiJZ1H0X_Ig4yPCOvT--g,16224
flask/debughelpers.py,sha256=1ceC-UyqZTd4KsJkf0OObHPsVt5R3T6vnmYhiWBjV-w,6479
flask/globals.py,sha256=pGg72QW_-4xUfsI33I5L_y76c21AeqfSqXDcbd8wvXU,1649
flask/helpers.py,sha256=YCl8D1plTO1evEYP4KIgaY3H8Izww5j4EdgRJ89oHTw,40106
flask/json/__init__.py,sha256=Ns1Hj805XIxuBMh2z0dYnMVfb_KUgLzDmP3WoUYaPhw,10729
flask/json/__pycache__/__init__.cpython-36.pyc,,
flask/json/__pycache__/tag.cpython-36.pyc,,
flask/json/tag.py,sha256=9ehzrmt5k7hxf7ZEK0NOs3swvQyU9fWNe-pnYe69N60,8223
flask/logging.py,sha256=qV9h0vt7NIRkKM9OHDWndzO61E5CeBMlqPJyTt-W2Wc,2231
flask/sessions.py,sha256=2XHV4ASREhSEZ8bsPQW6pNVNuFtbR-04BzfKg0AfvHo,14452
flask/signals.py,sha256=BGQbVyCYXnzKK2DVCzppKFyWN1qmrtW1QMAYUs-1Nr8,2211
flask/templating.py,sha256=FDfWMbpgpC3qObW8GGXRAVrkHFF8K4CHOJymB1wvULI,4914
flask/testing.py,sha256=XD3gWNvLUV8dqVHwKd9tZzsj81fSHtjOphQ1wTNtlMs,9379
flask/views.py,sha256=Wy-_WkUVtCfE2zCXYeJehNgHuEtviE4v3HYfJ--MpbY,5733
flask/wrappers.py,sha256=1Z9hF5-hXQajn_58XITQFRY8efv3Vy3uZ0avBfZu6XI,7511

View File

@@ -1,6 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.31.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@@ -1,3 +0,0 @@
[console_scripts]
flask = flask.cli:main

View File

@@ -1,37 +0,0 @@
Jinja2
~~~~~~
Jinja2 is a template engine written in pure Python. It provides a
`Django`_ inspired non-XML syntax but supports inline expressions and
an optional `sandboxed`_ environment.
Nutshell
--------
Here a small example of a Jinja template::
{% extends 'base.html' %}
{% block title %}Memberlist{% endblock %}
{% block content %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
Philosophy
----------
Application logic is for the controller but don't try to make the life
for the template designer too hard by giving him too few functionality.
For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security)
.. _Django: https://www.djangoproject.com/
.. _Jinja2 webpage: http://jinja.pocoo.org/
.. _documentation: http://jinja.pocoo.org/2/documentation/

View File

@@ -1,31 +0,0 @@
Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,68 +0,0 @@
Metadata-Version: 2.0
Name: Jinja2
Version: 2.10
Summary: A small but fast and easy to use stand-alone template engine written in pure python.
Home-page: http://jinja.pocoo.org/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
License: BSD
Description-Content-Type: UNKNOWN
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup :: HTML
Requires-Dist: MarkupSafe (>=0.23)
Provides-Extra: i18n
Requires-Dist: Babel (>=0.8); extra == 'i18n'
Jinja2
~~~~~~
Jinja2 is a template engine written in pure Python. It provides a
`Django`_ inspired non-XML syntax but supports inline expressions and
an optional `sandboxed`_ environment.
Nutshell
--------
Here a small example of a Jinja template::
{% extends 'base.html' %}
{% block title %}Memberlist{% endblock %}
{% block content %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
Philosophy
----------
Application logic is for the controller but don't try to make the life
for the template designer too hard by giving him too few functionality.
For more informations visit the new `Jinja2 webpage`_ and `documentation`_.
.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security)
.. _Django: https://www.djangoproject.com/
.. _Jinja2 webpage: http://jinja.pocoo.org/
.. _documentation: http://jinja.pocoo.org/2/documentation/

View File

@@ -1,63 +0,0 @@
Jinja2-2.10.dist-info/DESCRIPTION.rst,sha256=b5ckFDoM7vVtz_mAsJD4OPteFKCqE7beu353g4COoYI,978
Jinja2-2.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Jinja2-2.10.dist-info/LICENSE.txt,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554
Jinja2-2.10.dist-info/METADATA,sha256=18EgU8zR6-av-0-5y_gXebzK4GnBB_76lALUsl-6QHM,2258
Jinja2-2.10.dist-info/RECORD,,
Jinja2-2.10.dist-info/WHEEL,sha256=kdsN-5OJAZIiHN-iO4Rhl82KyS0bDWf4uBwMbkNafr8,110
Jinja2-2.10.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72
Jinja2-2.10.dist-info/metadata.json,sha256=NPUJ9TMBxVQAv_kTJzvU8HwmP-4XZvbK9mz6_4YUVl4,1473
Jinja2-2.10.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7
jinja2/__init__.py,sha256=xJHjaMoy51_KXn1wf0cysH6tUUifUxZCwSOfcJGEYZw,2614
jinja2/__pycache__/__init__.cpython-36.pyc,,
jinja2/__pycache__/_compat.cpython-36.pyc,,
jinja2/__pycache__/_identifier.cpython-36.pyc,,
jinja2/__pycache__/asyncfilters.cpython-36.pyc,,
jinja2/__pycache__/asyncsupport.cpython-36.pyc,,
jinja2/__pycache__/bccache.cpython-36.pyc,,
jinja2/__pycache__/compiler.cpython-36.pyc,,
jinja2/__pycache__/constants.cpython-36.pyc,,
jinja2/__pycache__/debug.cpython-36.pyc,,
jinja2/__pycache__/defaults.cpython-36.pyc,,
jinja2/__pycache__/environment.cpython-36.pyc,,
jinja2/__pycache__/exceptions.cpython-36.pyc,,
jinja2/__pycache__/ext.cpython-36.pyc,,
jinja2/__pycache__/filters.cpython-36.pyc,,
jinja2/__pycache__/idtracking.cpython-36.pyc,,
jinja2/__pycache__/lexer.cpython-36.pyc,,
jinja2/__pycache__/loaders.cpython-36.pyc,,
jinja2/__pycache__/meta.cpython-36.pyc,,
jinja2/__pycache__/nativetypes.cpython-36.pyc,,
jinja2/__pycache__/nodes.cpython-36.pyc,,
jinja2/__pycache__/optimizer.cpython-36.pyc,,
jinja2/__pycache__/parser.cpython-36.pyc,,
jinja2/__pycache__/runtime.cpython-36.pyc,,
jinja2/__pycache__/sandbox.cpython-36.pyc,,
jinja2/__pycache__/tests.cpython-36.pyc,,
jinja2/__pycache__/utils.cpython-36.pyc,,
jinja2/__pycache__/visitor.cpython-36.pyc,,
jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596
jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726
jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144
jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878
jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794
jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386
jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626
jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045
jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400
jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849
jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428
jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500
jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528
jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197
jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559
jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382
jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340
jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308
jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853
jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722
jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875
jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755
jinja2/sandbox.py,sha256=TVyZHlNqqTzsv9fv2NvJNmSdWRHTguhyMHdxjWms32U,16708
jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237
jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629
jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316

View File

@@ -1,6 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.30.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@@ -1,4 +0,0 @@
[babel.extractors]
jinja2 = jinja2.ext:babel_extract[i18n]

View File

@@ -1 +0,0 @@
{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: HTML"], "description_content_type": "UNKNOWN", "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://jinja.pocoo.org/"}}, "python.exports": {"babel.extractors": {"jinja2": "jinja2.ext:babel_extract [i18n]"}}}, "extras": ["i18n"], "generator": "bdist_wheel (0.30.0)", "license": "BSD", "metadata_version": "2.0", "name": "Jinja2", "run_requires": [{"extra": "i18n", "requires": ["Babel (>=0.8)"]}, {"requires": ["MarkupSafe (>=0.23)"]}], "summary": "A small but fast and easy to use stand-alone template engine written in pure python.", "version": "2.10"}

View File

@@ -1,33 +0,0 @@
`BSD 3-Clause <https://opensource.org/licenses/BSD-3-Clause>`_
Copyright © 2010 by the Pallets team.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -1,103 +0,0 @@
Metadata-Version: 2.1
Name: MarkupSafe
Version: 1.1.0
Summary: Safely add untrusted strings to HTML/XML markup.
Home-page: https://www.palletsprojects.com/p/markupsafe/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
Maintainer: Pallets Team
Maintainer-email: contact@palletsprojects.com
License: BSD
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
Project-URL: Code, https://github.com/pallets/markupsafe
Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup :: HTML
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
MarkupSafe
==========
MarkupSafe implements a text object that escapes characters so it is
safe to use in HTML and XML. Characters that have special meanings are
replaced so that they display as the actual characters. This mitigates
injection attacks, meaning untrusted user input can safely be displayed
on a page.
Installing
----------
Install and update using `pip`_:
.. code-block:: text
pip install -U MarkupSafe
.. _pip: https://pip.pypa.io/en/stable/quickstart/
Examples
--------
.. code-block:: pycon
>>> from markupsafe import Markup, escape
>>> # escape replaces special characters and wraps in Markup
>>> escape('<script>alert(document.cookie);</script>')
Markup(u'&lt;script&gt;alert(document.cookie);&lt;/script&gt;')
>>> # wrap in Markup to mark text "safe" and prevent escaping
>>> Markup('<strong>Hello</strong>')
Markup('<strong>hello</strong>')
>>> escape(Markup('<strong>Hello</strong>'))
Markup('<strong>hello</strong>')
>>> # Markup is a text subclass (str on Python 3, unicode on Python 2)
>>> # methods and operators escape their arguments
>>> template = Markup("Hello <em>%s</em>")
>>> template % '"World"'
Markup('Hello <em>&#34;World&#34;</em>')
Donate
------
The Pallets organization develops and supports MarkupSafe and other
libraries that use it. In order to grow the community of contributors
and users, and allow the maintainers to devote more time to the
projects, `please donate today`_.
.. _please donate today: https://psfmember.org/civicrm/contribute/transact?reset=1&id=20
Links
-----
* Website: https://www.palletsprojects.com/p/markupsafe/
* Documentation: https://markupsafe.palletsprojects.com/
* License: `BSD <https://github.com/pallets/markupsafe/blob/master/LICENSE.rst>`_
* Releases: https://pypi.org/project/MarkupSafe/
* Code: https://github.com/pallets/markupsafe
* Issue tracker: https://github.com/pallets/markupsafe/issues
* Test status:
* Linux, Mac: https://travis-ci.org/pallets/markupsafe
* Windows: https://ci.appveyor.com/project/pallets/markupsafe
* Test coverage: https://codecov.io/gh/pallets/markupsafe

View File

@@ -1,16 +0,0 @@
MarkupSafe-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
MarkupSafe-1.1.0.dist-info/LICENSE.txt,sha256=7V249lpOdvRv2m6SF9gCDtq_nsg8tFpdeTdsWWM_g9M,1614
MarkupSafe-1.1.0.dist-info/METADATA,sha256=usFnBges7tmAH4_Yt5Ypb8Bco4R9uLUdD0V6YHbvhLw,3585
MarkupSafe-1.1.0.dist-info/RECORD,,
MarkupSafe-1.1.0.dist-info/WHEEL,sha256=d2ILPScH-y2UwGxsW1PeA2TT-KW0Git4AJ6LeOK8sQo,109
MarkupSafe-1.1.0.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
markupsafe/__init__.py,sha256=T5J4pS7LRx1xRqfV3xz-QN_D9pSmfVDJnTrc2cTO4Ro,10164
markupsafe/__pycache__/__init__.cpython-36.pyc,,
markupsafe/__pycache__/_compat.cpython-36.pyc,,
markupsafe/__pycache__/_constants.cpython-36.pyc,,
markupsafe/__pycache__/_native.cpython-36.pyc,,
markupsafe/_compat.py,sha256=3oSvQpEFzsJ29NKVy-Fqk6ZlRxmlCB5k0G21aN0zNtQ,596
markupsafe/_constants.py,sha256=ueEz1Jxdw5TKWBbhPr4Ad_2L2MSEh73AYiYe4l3cZy4,4728
markupsafe/_native.py,sha256=fUrjjbRXIpHM-8l9QXFJ2xg5rv_48U2aN99plyL0kfs,1911
markupsafe/_speedups.c,sha256=VfElhhq9oulHEd2wBZ2MX9A80r4jFovsVGQD2zxmVk0,9883
markupsafe/_speedups.cpython-36m-x86_64-linux-gnu.so,sha256=BS7m4DA4L7J_sXAEFkmQeW3HJStGrC1yXYRifVOaTvc,38555

View File

@@ -1,5 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.31.1)
Root-Is-Purelib: false
Tag: cp36-cp36m-manylinux1_x86_64

View File

@@ -1,33 +0,0 @@
Metadata-Version: 1.1
Name: PyYAML
Version: 3.13
Summary: YAML parser and emitter for Python
Home-page: http://pyyaml.org/wiki/PyYAML
Author: Kirill Simonov
Author-email: xi@resolvent.net
License: MIT
Download-URL: http://pyyaml.org/download/pyyaml/PyYAML-3.13.tar.gz
Description: YAML is a data serialization format designed for human readability
and interaction with scripting languages. PyYAML is a YAML parser
and emitter for Python.
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
support, capable extension API, and sensible error messages. PyYAML
supports standard YAML tags and provides Python-specific tags that
allow to represent an arbitrary Python object.
PyYAML is applicable for a broad range of tasks from complex
configuration files to object serialization and persistance.
Platform: Any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup

View File

@@ -1,28 +0,0 @@
README
setup.cfg
setup.py
ext/_yaml.c
ext/_yaml.h
ext/_yaml.pxd
ext/_yaml.pyx
lib3/PyYAML.egg-info/PKG-INFO
lib3/PyYAML.egg-info/SOURCES.txt
lib3/PyYAML.egg-info/dependency_links.txt
lib3/PyYAML.egg-info/top_level.txt
lib3/yaml/__init__.py
lib3/yaml/composer.py
lib3/yaml/constructor.py
lib3/yaml/cyaml.py
lib3/yaml/dumper.py
lib3/yaml/emitter.py
lib3/yaml/error.py
lib3/yaml/events.py
lib3/yaml/loader.py
lib3/yaml/nodes.py
lib3/yaml/parser.py
lib3/yaml/reader.py
lib3/yaml/representer.py
lib3/yaml/resolver.py
lib3/yaml/scanner.py
lib3/yaml/serializer.py
lib3/yaml/tokens.py

View File

@@ -1,38 +0,0 @@
../yaml/__init__.py
../yaml/__pycache__/__init__.cpython-36.pyc
../yaml/__pycache__/composer.cpython-36.pyc
../yaml/__pycache__/constructor.cpython-36.pyc
../yaml/__pycache__/cyaml.cpython-36.pyc
../yaml/__pycache__/dumper.cpython-36.pyc
../yaml/__pycache__/emitter.cpython-36.pyc
../yaml/__pycache__/error.cpython-36.pyc
../yaml/__pycache__/events.cpython-36.pyc
../yaml/__pycache__/loader.cpython-36.pyc
../yaml/__pycache__/nodes.cpython-36.pyc
../yaml/__pycache__/parser.cpython-36.pyc
../yaml/__pycache__/reader.cpython-36.pyc
../yaml/__pycache__/representer.cpython-36.pyc
../yaml/__pycache__/resolver.cpython-36.pyc
../yaml/__pycache__/scanner.cpython-36.pyc
../yaml/__pycache__/serializer.cpython-36.pyc
../yaml/__pycache__/tokens.cpython-36.pyc
../yaml/composer.py
../yaml/constructor.py
../yaml/cyaml.py
../yaml/dumper.py
../yaml/emitter.py
../yaml/error.py
../yaml/events.py
../yaml/loader.py
../yaml/nodes.py
../yaml/parser.py
../yaml/reader.py
../yaml/representer.py
../yaml/resolver.py
../yaml/scanner.py
../yaml/serializer.py
../yaml/tokens.py
PKG-INFO
SOURCES.txt
dependency_links.txt
top_level.txt

View File

@@ -1,80 +0,0 @@
Werkzeug
========
Werkzeug is a comprehensive `WSGI`_ web application library. It began as
a simple collection of various utilities for WSGI applications and has
become one of the most advanced WSGI utility libraries.
It includes:
* An interactive debugger that allows inspecting stack traces and source
code in the browser with an interactive interpreter for any frame in
the stack.
* A full-featured request object with objects to interact with headers,
query args, form data, files, and cookies.
* A response object that can wrap other WSGI applications and handle
streaming data.
* A routing system for matching URLs to endpoints and generating URLs
for endpoints, with an extensible system for capturing variables from
URLs.
* HTTP utilities to handle entity tags, cache control, dates, user
agents, cookies, files, and more.
* A threaded WSGI server for use while developing applications locally.
* A test client for simulating HTTP requests during testing without
requiring running a server.
Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up
to the developer to choose a template engine, database adapter, and even
how to handle requests. It can be used to build all sorts of end user
applications such as blogs, wikis, or bulletin boards.
`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while
providing more structure and patterns for defining powerful
applications.
Installing
----------
Install and update using `pip`_:
.. code-block:: text
pip install -U Werkzeug
A Simple Example
----------------
.. code-block:: python
from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
return Response('Hello, World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
run_simple('localhost', 4000, application)
Links
-----
* Website: https://www.palletsprojects.com/p/werkzeug/
* Releases: https://pypi.org/project/Werkzeug/
* Code: https://github.com/pallets/werkzeug
* Issue tracker: https://github.com/pallets/werkzeug/issues
* Test status:
* Linux, Mac: https://travis-ci.org/pallets/werkzeug
* Windows: https://ci.appveyor.com/project/davidism/werkzeug
* Test coverage: https://codecov.io/gh/pallets/werkzeug
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
.. _Flask: https://www.palletsprojects.com/p/flask/
.. _pip: https://pip.pypa.io/en/stable/quickstart/

View File

@@ -1,31 +0,0 @@
Copyright © 2007 by the Pallets team.
Some rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -1,116 +0,0 @@
Metadata-Version: 2.0
Name: Werkzeug
Version: 0.14.1
Summary: The comprehensive WSGI web application library.
Home-page: https://www.palletsprojects.org/p/werkzeug/
Author: Armin Ronacher
Author-email: armin.ronacher@active-4.com
License: BSD
Description-Content-Type: UNKNOWN
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Provides-Extra: dev
Requires-Dist: coverage; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: sphinx; extra == 'dev'
Requires-Dist: tox; extra == 'dev'
Provides-Extra: termcolor
Requires-Dist: termcolor; extra == 'termcolor'
Provides-Extra: watchdog
Requires-Dist: watchdog; extra == 'watchdog'
Werkzeug
========
Werkzeug is a comprehensive `WSGI`_ web application library. It began as
a simple collection of various utilities for WSGI applications and has
become one of the most advanced WSGI utility libraries.
It includes:
* An interactive debugger that allows inspecting stack traces and source
code in the browser with an interactive interpreter for any frame in
the stack.
* A full-featured request object with objects to interact with headers,
query args, form data, files, and cookies.
* A response object that can wrap other WSGI applications and handle
streaming data.
* A routing system for matching URLs to endpoints and generating URLs
for endpoints, with an extensible system for capturing variables from
URLs.
* HTTP utilities to handle entity tags, cache control, dates, user
agents, cookies, files, and more.
* A threaded WSGI server for use while developing applications locally.
* A test client for simulating HTTP requests during testing without
requiring running a server.
Werkzeug is Unicode aware and doesn't enforce any dependencies. It is up
to the developer to choose a template engine, database adapter, and even
how to handle requests. It can be used to build all sorts of end user
applications such as blogs, wikis, or bulletin boards.
`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while
providing more structure and patterns for defining powerful
applications.
Installing
----------
Install and update using `pip`_:
.. code-block:: text
pip install -U Werkzeug
A Simple Example
----------------
.. code-block:: python
from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
return Response('Hello, World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
run_simple('localhost', 4000, application)
Links
-----
* Website: https://www.palletsprojects.com/p/werkzeug/
* Releases: https://pypi.org/project/Werkzeug/
* Code: https://github.com/pallets/werkzeug
* Issue tracker: https://github.com/pallets/werkzeug/issues
* Test status:
* Linux, Mac: https://travis-ci.org/pallets/werkzeug
* Windows: https://ci.appveyor.com/project/davidism/werkzeug
* Test coverage: https://codecov.io/gh/pallets/werkzeug
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
.. _Flask: https://www.palletsprojects.com/p/flask/
.. _pip: https://pip.pypa.io/en/stable/quickstart/

View File

@@ -1,97 +0,0 @@
Werkzeug-0.14.1.dist-info/DESCRIPTION.rst,sha256=rOCN36jwsWtWsTpqPG96z7FMilB5qI1CIARSKRuUmz8,2452
Werkzeug-0.14.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
Werkzeug-0.14.1.dist-info/LICENSE.txt,sha256=xndz_dD4m269AF9l_Xbl5V3tM1N3C1LoZC2PEPxWO-8,1534
Werkzeug-0.14.1.dist-info/METADATA,sha256=FbfadrPdJNUWAxMOKxGUtHe5R3IDSBKYYmAz3FvI3uY,3872
Werkzeug-0.14.1.dist-info/RECORD,,
Werkzeug-0.14.1.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110
Werkzeug-0.14.1.dist-info/metadata.json,sha256=4489UTt6HBp2NQil95-pBkjU4Je93SMHvMxZ_rjOpqA,1452
Werkzeug-0.14.1.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9
werkzeug/__init__.py,sha256=NR0d4n_-U9BLVKlOISean3zUt2vBwhvK-AZE6M0sC0k,6842
werkzeug/__pycache__/__init__.cpython-36.pyc,,
werkzeug/__pycache__/_compat.cpython-36.pyc,,
werkzeug/__pycache__/_internal.cpython-36.pyc,,
werkzeug/__pycache__/_reloader.cpython-36.pyc,,
werkzeug/__pycache__/datastructures.cpython-36.pyc,,
werkzeug/__pycache__/exceptions.cpython-36.pyc,,
werkzeug/__pycache__/filesystem.cpython-36.pyc,,
werkzeug/__pycache__/formparser.cpython-36.pyc,,
werkzeug/__pycache__/http.cpython-36.pyc,,
werkzeug/__pycache__/local.cpython-36.pyc,,
werkzeug/__pycache__/posixemulation.cpython-36.pyc,,
werkzeug/__pycache__/routing.cpython-36.pyc,,
werkzeug/__pycache__/script.cpython-36.pyc,,
werkzeug/__pycache__/security.cpython-36.pyc,,
werkzeug/__pycache__/serving.cpython-36.pyc,,
werkzeug/__pycache__/test.cpython-36.pyc,,
werkzeug/__pycache__/testapp.cpython-36.pyc,,
werkzeug/__pycache__/urls.cpython-36.pyc,,
werkzeug/__pycache__/useragents.cpython-36.pyc,,
werkzeug/__pycache__/utils.cpython-36.pyc,,
werkzeug/__pycache__/websocket.cpython-36.pyc,,
werkzeug/__pycache__/wrappers.cpython-36.pyc,,
werkzeug/__pycache__/wsgi.cpython-36.pyc,,
werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311
werkzeug/_internal.py,sha256=GhEyGMlsSz_tYjsDWO9TG35VN7304MM8gjKDrXLEdVc,13873
werkzeug/_reloader.py,sha256=AyPphcOHPbu6qzW0UbrVvTDJdre5WgpxbhIJN_TqzUc,9264
werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623
werkzeug/contrib/__pycache__/__init__.cpython-36.pyc,,
werkzeug/contrib/__pycache__/atom.cpython-36.pyc,,
werkzeug/contrib/__pycache__/cache.cpython-36.pyc,,
werkzeug/contrib/__pycache__/fixers.cpython-36.pyc,,
werkzeug/contrib/__pycache__/iterio.cpython-36.pyc,,
werkzeug/contrib/__pycache__/jsrouting.cpython-36.pyc,,
werkzeug/contrib/__pycache__/limiter.cpython-36.pyc,,
werkzeug/contrib/__pycache__/lint.cpython-36.pyc,,
werkzeug/contrib/__pycache__/profiler.cpython-36.pyc,,
werkzeug/contrib/__pycache__/securecookie.cpython-36.pyc,,
werkzeug/contrib/__pycache__/sessions.cpython-36.pyc,,
werkzeug/contrib/__pycache__/testtools.cpython-36.pyc,,
werkzeug/contrib/__pycache__/wrappers.cpython-36.pyc,,
werkzeug/contrib/atom.py,sha256=qqfJcfIn2RYY-3hO3Oz0aLq9YuNubcPQ_KZcNsDwVJo,15575
werkzeug/contrib/cache.py,sha256=xBImHNj09BmX_7kC5NUCx8f_l4L8_O7zi0jCL21UZKE,32163
werkzeug/contrib/fixers.py,sha256=gR06T-w71ur-tHQ_31kP_4jpOncPJ4Wc1dOqTvYusr8,10179
werkzeug/contrib/iterio.py,sha256=RlqDvGhz0RneTpzE8dVc-yWCUv4nkPl1jEc_EDp2fH0,10814
werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564
werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334
werkzeug/contrib/lint.py,sha256=Mj9NeUN7s4zIUWeQOAVjrmtZIcl3Mm2yDe9BSIr9YGE,12558
werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151
werkzeug/contrib/securecookie.py,sha256=uWMyHDHY3lkeBRiCSayGqWkAIy4a7xAbSE_Hln9ecqc,12196
werkzeug/contrib/sessions.py,sha256=39LVNvLbm5JWpbxM79WC2l87MJFbqeISARjwYbkJatw,12577
werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453
werkzeug/contrib/wrappers.py,sha256=v7OYlz7wQtDlS9fey75UiRZ1IkUWqCpzbhsLy4k14Hw,10398
werkzeug/datastructures.py,sha256=3IgNKNqrz-ZjmAG7y3YgEYK-enDiMT_b652PsypWcYg,90080
werkzeug/debug/__init__.py,sha256=uSn9BqCZ5E3ySgpoZtundpROGsn-uYvZtSFiTfAX24M,17452
werkzeug/debug/__pycache__/__init__.cpython-36.pyc,,
werkzeug/debug/__pycache__/console.cpython-36.pyc,,
werkzeug/debug/__pycache__/repr.cpython-36.pyc,,
werkzeug/debug/__pycache__/tbtools.cpython-36.pyc,,
werkzeug/debug/console.py,sha256=n3-dsKk1TsjnN-u4ZgmuWCU_HO0qw5IA7ttjhyyMM6I,5607
werkzeug/debug/repr.py,sha256=bKqstDYGfECpeLerd48s_hxuqK4b6UWnjMu3d_DHO8I,9340
werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673
werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507
werkzeug/debug/shared/debugger.js,sha256=PKPVYuyO4SX1hkqLOwCLvmIEO5154WatFYaXE-zIfKI,6264
werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957
werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191
werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200
werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818
werkzeug/debug/shared/style.css,sha256=IEO0PC2pWmh2aEyGCaN--txuWsRCliuhlbEhPDFwh0A,6270
werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220
werkzeug/debug/tbtools.py,sha256=rBudXCmkVdAKIcdhxANxgf09g6kQjJWW9_5bjSpr4OY,18451
werkzeug/exceptions.py,sha256=3wp95Hqj9FqV8MdikV99JRcHse_fSMn27V8tgP5Hw2c,20505
werkzeug/filesystem.py,sha256=hHWeWo_gqLMzTRfYt8-7n2wWcWUNTnDyudQDLOBEICE,2175
werkzeug/formparser.py,sha256=mUuCwjzjb8_E4RzrAT2AioLuZSYpqR1KXTK6LScRYzA,21722
werkzeug/http.py,sha256=RQg4MJuhRv2isNRiEh__Phh09ebpfT3Kuu_GfrZ54_c,40079
werkzeug/local.py,sha256=QdQhWV5L8p1Y1CJ1CDStwxaUs24SuN5aebHwjVD08C8,14553
werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519
werkzeug/routing.py,sha256=2JVtdSgxKGeANy4Z_FP-dKESvKtkYGCZ1J2fARCLGCY,67214
werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365
werkzeug/security.py,sha256=0m107exslz4QJLWQCpfQJ04z3re4eGHVggRvrQVAdWc,9193
werkzeug/serving.py,sha256=A0flnIJHufdn2QJ9oeuHfrXwP3LzP8fn3rNW6hbxKUg,31926
werkzeug/test.py,sha256=XmECSmnpASiYQTct4oMiWr0LT5jHWCtKqnpYKZd2ui8,36100
werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396
werkzeug/urls.py,sha256=dUeLg2IeTm0WLmSvFeD4hBZWGdOs-uHudR5-t8n9zPo,36771
werkzeug/useragents.py,sha256=BhYMf4cBTHyN4U0WsQedePIocmNlH_34C-UwqSThGCc,5865
werkzeug/utils.py,sha256=BrY1j0DHQ8RTb0K1StIobKuMJhN9SQQkWEARbrh2qpk,22972
werkzeug/websocket.py,sha256=PpSeDxXD_0UsPAa5hQhQNM6mxibeUgn8lA8eRqiS0vM,11344
werkzeug/wrappers.py,sha256=kbyL_aFjxELwPgMwfNCYjKu-CR6kNkh-oO8wv3GXbk8,84511
werkzeug/wsgi.py,sha256=1Nob-aeChWQf7MsiicO8RZt6J90iRzEcik44ev9Qu8s,49347

View File

@@ -1,6 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.26.0)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

View File

@@ -1 +0,0 @@
{"generator": "bdist_wheel (0.26.0)", "summary": "The comprehensive WSGI web application library.", "classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"], "description_content_type": "UNKNOWN", "extensions": {"python.details": {"project_urls": {"Home": "https://www.palletsprojects.org/p/werkzeug/"}, "contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}}}, "license": "BSD", "metadata_version": "2.0", "name": "Werkzeug", "platform": "any", "extras": ["dev", "termcolor", "watchdog"], "run_requires": [{"requires": ["coverage", "pytest", "sphinx", "tox"], "extra": "dev"}, {"requires": ["termcolor"], "extra": "termcolor"}, {"requires": ["watchdog"], "extra": "watchdog"}], "version": "0.14.1"}

View File

@@ -1,171 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from collections import MutableMapping
try:
from collections import UserDict
except ImportError:
from UserDict import UserDict
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from io import open
import sys
try:
from thread import get_ident
except ImportError:
try:
from _thread import get_ident
except ImportError:
from _dummy_thread import get_ident
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
str = type('str')
def from_none(exc):
"""raise from_none(ValueError('a')) == raise ValueError('a') from None"""
exc.__cause__ = None
exc.__suppress_context__ = True
return exc
# from reprlib 3.2.1
def recursive_repr(fillvalue='...'):
'Decorator to make a repr function return fillvalue for a recursive call'
def decorating_function(user_function):
repr_running = set()
def wrapper(self):
key = id(self), get_ident()
if key in repr_running:
return fillvalue
repr_running.add(key)
try:
result = user_function(self)
finally:
repr_running.discard(key)
return result
# Can't use functools.wraps() here because of bootstrap issues
wrapper.__module__ = getattr(user_function, '__module__')
wrapper.__doc__ = getattr(user_function, '__doc__')
wrapper.__name__ = getattr(user_function, '__name__')
wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
return wrapper
return decorating_function
# from collections 3.2.1
class _ChainMap(MutableMapping):
''' A ChainMap groups multiple dicts (or other mappings) together
to create a single, updateable view.
The underlying mappings are stored in a list. That list is public and can
accessed or updated using the *maps* attribute. There is no other state.
Lookups search the underlying mappings successively until a key is found.
In contrast, writes, updates, and deletions only operate on the first
mapping.
'''
def __init__(self, *maps):
'''Initialize a ChainMap by setting *maps* to the given mappings.
If no mappings are provided, a single empty dictionary is used.
'''
self.maps = list(maps) or [{}] # always at least one map
def __missing__(self, key):
raise KeyError(key)
def __getitem__(self, key):
for mapping in self.maps:
try:
return mapping[key] # can't use 'key in mapping' with defaultdict
except KeyError:
pass
return self.__missing__(key) # support subclasses that define __missing__
def get(self, key, default=None):
return self[key] if key in self else default
def __len__(self):
return len(set().union(*self.maps)) # reuses stored hash values if possible
def __iter__(self):
return iter(set().union(*self.maps))
def __contains__(self, key):
return any(key in m for m in self.maps)
@recursive_repr()
def __repr__(self):
return '{0.__class__.__name__}({1})'.format(
self, ', '.join(map(repr, self.maps)))
@classmethod
def fromkeys(cls, iterable, *args):
'Create a ChainMap with a single dict created from the iterable.'
return cls(dict.fromkeys(iterable, *args))
def copy(self):
'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
return self.__class__(self.maps[0].copy(), *self.maps[1:])
__copy__ = copy
def new_child(self): # like Django's Context.push()
'New ChainMap with a new dict followed by all previous maps.'
return self.__class__({}, *self.maps)
@property
def parents(self): # like Django's Context.pop()
'New ChainMap from maps[1:].'
return self.__class__(*self.maps[1:])
def __setitem__(self, key, value):
self.maps[0][key] = value
def __delitem__(self, key):
try:
del self.maps[0][key]
except KeyError:
raise KeyError('Key not found in the first mapping: {!r}'.format(key))
def popitem(self):
'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
try:
return self.maps[0].popitem()
except KeyError:
raise KeyError('No keys found in the first mapping.')
def pop(self, key, *args):
'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
try:
return self.maps[0].pop(key, *args)
except KeyError:
raise KeyError('Key not found in the first mapping: {!r}'.format(key))
def clear(self):
'Clear maps[0], leaving maps[1:] intact.'
self.maps[0].clear()
try:
from collections import ChainMap
except ImportError:
ChainMap = _ChainMap

View File

@@ -1,101 +0,0 @@
Metadata-Version: 1.1
Name: blinker
Version: 1.4
Summary: Fast, simple object-to-object and broadcast signaling
Home-page: http://pythonhosted.org/blinker/
Author: Jason Kirtland
Author-email: jek@discorporate.us
License: MIT License
Description: [![Build Status](https://travis-ci.org/jek/blinker.svg?branch=master)](https://travis-ci.org/jek/blinker)
# Blinker
Blinker provides a fast dispatching system that allows any number of
interested parties to subscribe to events, or "signals".
Signal receivers can subscribe to specific senders or receive signals
sent by any sender.
>>> from blinker import signal
>>> started = signal('round-started')
>>> def each(round):
... print "Round %s!" % round
...
>>> started.connect(each)
>>> def round_two(round):
... print "This is round two."
...
>>> started.connect(round_two, sender=2)
>>> for round in range(1, 4):
... started.send(round)
...
Round 1!
Round 2!
This is round two.
Round 3!
See the [Blinker documentation](https://pythonhosted.org/blinker/) for more information.
## Requirements
Blinker requires Python 2.4 or higher, Python 3.0 or higher, or Jython 2.5 or higher.
## Changelog Summary
1.3 (July 3, 2013)
- The global signal stash behind blinker.signal() is now backed by a
regular name-to-Signal dictionary. Previously, weak references were
held in the mapping and ephemeral usage in code like
``signal('foo').connect(...)`` could have surprising program behavior
depending on import order of modules.
- blinker.Namespace is now built on a regular dict. Use
blinker.WeakNamespace for the older, weak-referencing behavior.
- Signal.connect('text-sender') uses an alternate hashing strategy to
avoid sharp edges in text identity.
1.2 (October 26, 2011)
- Added Signal.receiver_connected and Signal.receiver_disconnected
per-Signal signals.
- Deprecated the global 'receiver_connected' signal.
- Verified Python 3.2 support (no changes needed!)
1.1 (July 21, 2010)
- Added ``@signal.connect_via(sender)`` decorator
- Added ``signal.connected_to`` shorthand name for the
``temporarily_connected_to`` context manager.
1.0 (March 28, 2010)
- Python 3.x compatibility
0.9 (February 26, 2010)
- Sphinx docs, project website
- Added ``with a_signal.temporarily_connected_to(receiver): ...`` support
Keywords: signal emit events broadcast
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.4
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.0
Classifier: Programming Language :: Python :: 3.1
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Utilities

View File

@@ -1,49 +0,0 @@
AUTHORS
CHANGES
LICENSE
MANIFEST.in
README.md
setup.cfg
setup.py
blinker/__init__.py
blinker/_saferef.py
blinker/_utilities.py
blinker/base.py
blinker.egg-info/PKG-INFO
blinker.egg-info/SOURCES.txt
blinker.egg-info/dependency_links.txt
blinker.egg-info/top_level.txt
docs/html/genindex.html
docs/html/index.html
docs/html/objects.inv
docs/html/search.html
docs/html/searchindex.js
docs/html/_sources/index.txt
docs/html/_static/basic.css
docs/html/_static/blinker-named.png
docs/html/_static/blinker64.png
docs/html/_static/comment-bright.png
docs/html/_static/comment-close.png
docs/html/_static/comment.png
docs/html/_static/doctools.js
docs/html/_static/down-pressed.png
docs/html/_static/down.png
docs/html/_static/file.png
docs/html/_static/flasky.css
docs/html/_static/jquery.js
docs/html/_static/minus.png
docs/html/_static/plus.png
docs/html/_static/pygments.css
docs/html/_static/searchtools.js
docs/html/_static/underscore.js
docs/html/_static/up-pressed.png
docs/html/_static/up.png
docs/html/_static/websupport.js
docs/source/conf.py
docs/source/index.rst
docs/source/_themes/flask_theme_support.py
docs/text/index.txt
tests/test_context.py
tests/test_saferef.py
tests/test_signals.py
tests/test_utilities.py

View File

@@ -1,12 +0,0 @@
../blinker/__init__.py
../blinker/__pycache__/__init__.cpython-36.pyc
../blinker/__pycache__/_saferef.cpython-36.pyc
../blinker/__pycache__/_utilities.cpython-36.pyc
../blinker/__pycache__/base.cpython-36.pyc
../blinker/_saferef.py
../blinker/_utilities.py
../blinker/base.py
PKG-INFO
SOURCES.txt
dependency_links.txt
top_level.txt

View File

@@ -1,22 +0,0 @@
from blinker.base import (
ANY,
NamedSignal,
Namespace,
Signal,
WeakNamespace,
receiver_connected,
signal,
)
__all__ = [
'ANY',
'NamedSignal',
'Namespace',
'Signal',
'WeakNamespace',
'receiver_connected',
'signal',
]
__version__ = '1.4'

View File

@@ -1,234 +0,0 @@
# extracted from Louie, http://pylouie.org/
# updated for Python 3
#
# Copyright (c) 2006 Patrick K. O'Brien, Mike C. Fletcher,
# Matthew R. Scott
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# * Neither the name of the <ORGANIZATION> nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""Refactored 'safe reference from dispatcher.py"""
import operator
import sys
import traceback
import weakref
try:
callable
except NameError:
def callable(object):
return hasattr(object, '__call__')
if sys.version_info < (3,):
get_self = operator.attrgetter('im_self')
get_func = operator.attrgetter('im_func')
else:
get_self = operator.attrgetter('__self__')
get_func = operator.attrgetter('__func__')
def safe_ref(target, on_delete=None):
"""Return a *safe* weak reference to a callable target.
- ``target``: The object to be weakly referenced, if it's a bound
method reference, will create a BoundMethodWeakref, otherwise
creates a simple weakref.
- ``on_delete``: If provided, will have a hard reference stored to
the callable to be called after the safe reference goes out of
scope with the reference object, (either a weakref or a
BoundMethodWeakref) as argument.
"""
try:
im_self = get_self(target)
except AttributeError:
if callable(on_delete):
return weakref.ref(target, on_delete)
else:
return weakref.ref(target)
else:
if im_self is not None:
# Turn a bound method into a BoundMethodWeakref instance.
# Keep track of these instances for lookup by disconnect().
assert hasattr(target, 'im_func') or hasattr(target, '__func__'), (
"safe_ref target %r has im_self, but no im_func, "
"don't know how to create reference" % target)
reference = BoundMethodWeakref(target=target, on_delete=on_delete)
return reference
class BoundMethodWeakref(object):
"""'Safe' and reusable weak references to instance methods.
BoundMethodWeakref objects provide a mechanism for referencing a
bound method without requiring that the method object itself
(which is normally a transient object) is kept alive. Instead,
the BoundMethodWeakref object keeps weak references to both the
object and the function which together define the instance method.
Attributes:
- ``key``: The identity key for the reference, calculated by the
class's calculate_key method applied to the target instance method.
- ``deletion_methods``: Sequence of callable objects taking single
argument, a reference to this object which will be called when
*either* the target object or target function is garbage
collected (i.e. when this object becomes invalid). These are
specified as the on_delete parameters of safe_ref calls.
- ``weak_self``: Weak reference to the target object.
- ``weak_func``: Weak reference to the target function.
Class Attributes:
- ``_all_instances``: Class attribute pointing to all live
BoundMethodWeakref objects indexed by the class's
calculate_key(target) method applied to the target objects.
This weak value dictionary is used to short-circuit creation so
that multiple references to the same (object, function) pair
produce the same BoundMethodWeakref instance.
"""
_all_instances = weakref.WeakValueDictionary()
def __new__(cls, target, on_delete=None, *arguments, **named):
"""Create new instance or return current instance.
Basically this method of construction allows us to
short-circuit creation of references to already- referenced
instance methods. The key corresponding to the target is
calculated, and if there is already an existing reference,
that is returned, with its deletion_methods attribute updated.
Otherwise the new instance is created and registered in the
table of already-referenced methods.
"""
key = cls.calculate_key(target)
current = cls._all_instances.get(key)
if current is not None:
current.deletion_methods.append(on_delete)
return current
else:
base = super(BoundMethodWeakref, cls).__new__(cls)
cls._all_instances[key] = base
base.__init__(target, on_delete, *arguments, **named)
return base
def __init__(self, target, on_delete=None):
"""Return a weak-reference-like instance for a bound method.
- ``target``: The instance-method target for the weak reference,
must have im_self and im_func attributes and be
reconstructable via the following, which is true of built-in
instance methods::
target.im_func.__get__( target.im_self )
- ``on_delete``: Optional callback which will be called when
this weak reference ceases to be valid (i.e. either the
object or the function is garbage collected). Should take a
single argument, which will be passed a pointer to this
object.
"""
def remove(weak, self=self):
"""Set self.isDead to True when method or instance is destroyed."""
methods = self.deletion_methods[:]
del self.deletion_methods[:]
try:
del self.__class__._all_instances[self.key]
except KeyError:
pass
for function in methods:
try:
if callable(function):
function(self)
except Exception:
try:
traceback.print_exc()
except AttributeError:
e = sys.exc_info()[1]
print ('Exception during saferef %s '
'cleanup function %s: %s' % (self, function, e))
self.deletion_methods = [on_delete]
self.key = self.calculate_key(target)
im_self = get_self(target)
im_func = get_func(target)
self.weak_self = weakref.ref(im_self, remove)
self.weak_func = weakref.ref(im_func, remove)
self.self_name = str(im_self)
self.func_name = str(im_func.__name__)
def calculate_key(cls, target):
"""Calculate the reference key for this reference.
Currently this is a two-tuple of the id()'s of the target
object and the target function respectively.
"""
return (id(get_self(target)), id(get_func(target)))
calculate_key = classmethod(calculate_key)
def __str__(self):
"""Give a friendly representation of the object."""
return "%s(%s.%s)" % (
self.__class__.__name__,
self.self_name,
self.func_name,
)
__repr__ = __str__
def __nonzero__(self):
"""Whether we are still a valid reference."""
return self() is not None
def __cmp__(self, other):
"""Compare with another reference."""
if not isinstance(other, self.__class__):
return cmp(self.__class__, type(other))
return cmp(self.key, other.key)
def __call__(self):
"""Return a strong reference to the bound method.
If the target cannot be retrieved, then will return None,
otherwise returns a bound instance method for our object and
function.
Note: You may call this method any number of times, as it does
not invalidate the reference.
"""
target = self.weak_self()
if target is not None:
function = self.weak_func()
if function is not None:
return function.__get__(target)
return None

View File

@@ -1,163 +0,0 @@
from weakref import ref
from blinker._saferef import BoundMethodWeakref
try:
callable
except NameError:
def callable(object):
return hasattr(object, '__call__')
try:
from collections import defaultdict
except:
class defaultdict(dict):
def __init__(self, default_factory=None, *a, **kw):
if (default_factory is not None and
not hasattr(default_factory, '__call__')):
raise TypeError('first argument must be callable')
dict.__init__(self, *a, **kw)
self.default_factory = default_factory
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory()
return value
def __reduce__(self):
if self.default_factory is None:
args = tuple()
else:
args = self.default_factory,
return type(self), args, None, None, self.items()
def copy(self):
return self.__copy__()
def __copy__(self):
return type(self)(self.default_factory, self)
def __deepcopy__(self, memo):
import copy
return type(self)(self.default_factory,
copy.deepcopy(self.items()))
def __repr__(self):
return 'defaultdict(%s, %s)' % (self.default_factory,
dict.__repr__(self))
try:
from contextlib import contextmanager
except ImportError:
def contextmanager(fn):
def oops(*args, **kw):
raise RuntimeError("Python 2.5 or above is required to use "
"context managers.")
oops.__name__ = fn.__name__
return oops
class _symbol(object):
def __init__(self, name):
"""Construct a new named symbol."""
self.__name__ = self.name = name
def __reduce__(self):
return symbol, (self.name,)
def __repr__(self):
return self.name
_symbol.__name__ = 'symbol'
class symbol(object):
"""A constant symbol.
>>> symbol('foo') is symbol('foo')
True
>>> symbol('foo')
foo
A slight refinement of the MAGICCOOKIE=object() pattern. The primary
advantage of symbol() is its repr(). They are also singletons.
Repeated calls of symbol('name') will all return the same instance.
"""
symbols = {}
def __new__(cls, name):
try:
return cls.symbols[name]
except KeyError:
return cls.symbols.setdefault(name, _symbol(name))
try:
text = (str, unicode)
except NameError:
text = str
def hashable_identity(obj):
if hasattr(obj, '__func__'):
return (id(obj.__func__), id(obj.__self__))
elif hasattr(obj, 'im_func'):
return (id(obj.im_func), id(obj.im_self))
elif isinstance(obj, text):
return obj
else:
return id(obj)
WeakTypes = (ref, BoundMethodWeakref)
class annotatable_weakref(ref):
"""A weakref.ref that supports custom instance attributes."""
def reference(object, callback=None, **annotations):
"""Return an annotated weak ref."""
if callable(object):
weak = callable_reference(object, callback)
else:
weak = annotatable_weakref(object, callback)
for key, value in annotations.items():
setattr(weak, key, value)
return weak
def callable_reference(object, callback=None):
"""Return an annotated weak ref, supporting bound instance methods."""
if hasattr(object, 'im_self') and object.im_self is not None:
return BoundMethodWeakref(target=object, on_delete=callback)
elif hasattr(object, '__self__') and object.__self__ is not None:
return BoundMethodWeakref(target=object, on_delete=callback)
return annotatable_weakref(object, callback)
class lazy_property(object):
"""A @property that is only evaluated once."""
def __init__(self, deferred):
self._deferred = deferred
self.__doc__ = deferred.__doc__
def __get__(self, obj, cls):
if obj is None:
return self
value = self._deferred(obj)
setattr(obj, self._deferred.__name__, value)
return value

View File

@@ -1,455 +0,0 @@
# -*- coding: utf-8; fill-column: 76 -*-
"""Signals and events.
A small implementation of signals, inspired by a snippet of Django signal
API client code seen in a blog post. Signals are first-class objects and
each manages its own receivers and message emission.
The :func:`signal` function provides singleton behavior for named signals.
"""
from warnings import warn
from weakref import WeakValueDictionary
from blinker._utilities import (
WeakTypes,
contextmanager,
defaultdict,
hashable_identity,
lazy_property,
reference,
symbol,
)
ANY = symbol('ANY')
ANY.__doc__ = 'Token for "any sender".'
ANY_ID = 0
class Signal(object):
"""A notification emitter."""
#: An :obj:`ANY` convenience synonym, allows ``Signal.ANY``
#: without an additional import.
ANY = ANY
@lazy_property
def receiver_connected(self):
"""Emitted after each :meth:`connect`.
The signal sender is the signal instance, and the :meth:`connect`
arguments are passed through: *receiver*, *sender*, and *weak*.
.. versionadded:: 1.2
"""
return Signal(doc="Emitted after a receiver connects.")
@lazy_property
def receiver_disconnected(self):
"""Emitted after :meth:`disconnect`.
The sender is the signal instance, and the :meth:`disconnect` arguments
are passed through: *receiver* and *sender*.
Note, this signal is emitted **only** when :meth:`disconnect` is
called explicitly.
The disconnect signal can not be emitted by an automatic disconnect
(due to a weakly referenced receiver or sender going out of scope),
as the receiver and/or sender instances are no longer available for
use at the time this signal would be emitted.
An alternative approach is available by subscribing to
:attr:`receiver_connected` and setting up a custom weakref cleanup
callback on weak receivers and senders.
.. versionadded:: 1.2
"""
return Signal(doc="Emitted after a receiver disconnects.")
def __init__(self, doc=None):
"""
:param doc: optional. If provided, will be assigned to the signal's
__doc__ attribute.
"""
if doc:
self.__doc__ = doc
#: A mapping of connected receivers.
#:
#: The values of this mapping are not meaningful outside of the
#: internal :class:`Signal` implementation, however the boolean value
#: of the mapping is useful as an extremely efficient check to see if
#: any receivers are connected to the signal.
self.receivers = {}
self._by_receiver = defaultdict(set)
self._by_sender = defaultdict(set)
self._weak_senders = {}
def connect(self, receiver, sender=ANY, weak=True):
"""Connect *receiver* to signal events sent by *sender*.
:param receiver: A callable. Will be invoked by :meth:`send` with
`sender=` as a single positional argument and any \*\*kwargs that
were provided to a call to :meth:`send`.
:param sender: Any object or :obj:`ANY`, defaults to ``ANY``.
Restricts notifications delivered to *receiver* to only those
:meth:`send` emissions sent by *sender*. If ``ANY``, the receiver
will always be notified. A *receiver* may be connected to
multiple *sender* values on the same Signal through multiple calls
to :meth:`connect`.
:param weak: If true, the Signal will hold a weakref to *receiver*
and automatically disconnect when *receiver* goes out of scope or
is garbage collected. Defaults to True.
"""
receiver_id = hashable_identity(receiver)
if weak:
receiver_ref = reference(receiver, self._cleanup_receiver)
receiver_ref.receiver_id = receiver_id
else:
receiver_ref = receiver
if sender is ANY:
sender_id = ANY_ID
else:
sender_id = hashable_identity(sender)
self.receivers.setdefault(receiver_id, receiver_ref)
self._by_sender[sender_id].add(receiver_id)
self._by_receiver[receiver_id].add(sender_id)
del receiver_ref
if sender is not ANY and sender_id not in self._weak_senders:
# wire together a cleanup for weakref-able senders
try:
sender_ref = reference(sender, self._cleanup_sender)
sender_ref.sender_id = sender_id
except TypeError:
pass
else:
self._weak_senders.setdefault(sender_id, sender_ref)
del sender_ref
# broadcast this connection. if receivers raise, disconnect.
if ('receiver_connected' in self.__dict__ and
self.receiver_connected.receivers):
try:
self.receiver_connected.send(self,
receiver=receiver,
sender=sender,
weak=weak)
except:
self.disconnect(receiver, sender)
raise
if receiver_connected.receivers and self is not receiver_connected:
try:
receiver_connected.send(self,
receiver_arg=receiver,
sender_arg=sender,
weak_arg=weak)
except:
self.disconnect(receiver, sender)
raise
return receiver
def connect_via(self, sender, weak=False):
"""Connect the decorated function as a receiver for *sender*.
:param sender: Any object or :obj:`ANY`. The decorated function
will only receive :meth:`send` emissions sent by *sender*. If
``ANY``, the receiver will always be notified. A function may be
decorated multiple times with differing *sender* values.
:param weak: If true, the Signal will hold a weakref to the
decorated function and automatically disconnect when *receiver*
goes out of scope or is garbage collected. Unlike
:meth:`connect`, this defaults to False.
The decorated function will be invoked by :meth:`send` with
`sender=` as a single positional argument and any \*\*kwargs that
were provided to the call to :meth:`send`.
.. versionadded:: 1.1
"""
def decorator(fn):
self.connect(fn, sender, weak)
return fn
return decorator
@contextmanager
def connected_to(self, receiver, sender=ANY):
"""Execute a block with the signal temporarily connected to *receiver*.
:param receiver: a receiver callable
:param sender: optional, a sender to filter on
This is a context manager for use in the ``with`` statement. It can
be useful in unit tests. *receiver* is connected to the signal for
the duration of the ``with`` block, and will be disconnected
automatically when exiting the block:
.. testsetup::
from __future__ import with_statement
from blinker import Signal
on_ready = Signal()
receiver = lambda sender: None
.. testcode::
with on_ready.connected_to(receiver):
# do stuff
on_ready.send(123)
.. versionadded:: 1.1
"""
self.connect(receiver, sender=sender, weak=False)
try:
yield None
except:
self.disconnect(receiver)
raise
else:
self.disconnect(receiver)
def temporarily_connected_to(self, receiver, sender=ANY):
"""An alias for :meth:`connected_to`.
:param receiver: a receiver callable
:param sender: optional, a sender to filter on
.. versionadded:: 0.9
.. versionchanged:: 1.1
Renamed to :meth:`connected_to`. ``temporarily_connected_to`` was
deprecated in 1.2 and will be removed in a subsequent version.
"""
warn("temporarily_connected_to is deprecated; "
"use connected_to instead.",
DeprecationWarning)
return self.connected_to(receiver, sender)
def send(self, *sender, **kwargs):
"""Emit this signal on behalf of *sender*, passing on \*\*kwargs.
Returns a list of 2-tuples, pairing receivers with their return
value. The ordering of receiver notification is undefined.
:param \*sender: Any object or ``None``. If omitted, synonymous
with ``None``. Only accepts one positional argument.
:param \*\*kwargs: Data to be sent to receivers.
"""
# Using '*sender' rather than 'sender=None' allows 'sender' to be
# used as a keyword argument- i.e. it's an invisible name in the
# function signature.
if len(sender) == 0:
sender = None
elif len(sender) > 1:
raise TypeError('send() accepts only one positional argument, '
'%s given' % len(sender))
else:
sender = sender[0]
if not self.receivers:
return []
else:
return [(receiver, receiver(sender, **kwargs))
for receiver in self.receivers_for(sender)]
def has_receivers_for(self, sender):
"""True if there is probably a receiver for *sender*.
Performs an optimistic check only. Does not guarantee that all
weakly referenced receivers are still alive. See
:meth:`receivers_for` for a stronger search.
"""
if not self.receivers:
return False
if self._by_sender[ANY_ID]:
return True
if sender is ANY:
return False
return hashable_identity(sender) in self._by_sender
def receivers_for(self, sender):
"""Iterate all live receivers listening for *sender*."""
# TODO: test receivers_for(ANY)
if self.receivers:
sender_id = hashable_identity(sender)
if sender_id in self._by_sender:
ids = (self._by_sender[ANY_ID] |
self._by_sender[sender_id])
else:
ids = self._by_sender[ANY_ID].copy()
for receiver_id in ids:
receiver = self.receivers.get(receiver_id)
if receiver is None:
continue
if isinstance(receiver, WeakTypes):
strong = receiver()
if strong is None:
self._disconnect(receiver_id, ANY_ID)
continue
receiver = strong
yield receiver
def disconnect(self, receiver, sender=ANY):
"""Disconnect *receiver* from this signal's events.
:param receiver: a previously :meth:`connected<connect>` callable
:param sender: a specific sender to disconnect from, or :obj:`ANY`
to disconnect from all senders. Defaults to ``ANY``.
"""
if sender is ANY:
sender_id = ANY_ID
else:
sender_id = hashable_identity(sender)
receiver_id = hashable_identity(receiver)
self._disconnect(receiver_id, sender_id)
if ('receiver_disconnected' in self.__dict__ and
self.receiver_disconnected.receivers):
self.receiver_disconnected.send(self,
receiver=receiver,
sender=sender)
def _disconnect(self, receiver_id, sender_id):
if sender_id == ANY_ID:
if self._by_receiver.pop(receiver_id, False):
for bucket in self._by_sender.values():
bucket.discard(receiver_id)
self.receivers.pop(receiver_id, None)
else:
self._by_sender[sender_id].discard(receiver_id)
self._by_receiver[receiver_id].discard(sender_id)
def _cleanup_receiver(self, receiver_ref):
"""Disconnect a receiver from all senders."""
self._disconnect(receiver_ref.receiver_id, ANY_ID)
def _cleanup_sender(self, sender_ref):
"""Disconnect all receivers from a sender."""
sender_id = sender_ref.sender_id
assert sender_id != ANY_ID
self._weak_senders.pop(sender_id, None)
for receiver_id in self._by_sender.pop(sender_id, ()):
self._by_receiver[receiver_id].discard(sender_id)
def _cleanup_bookkeeping(self):
"""Prune unused sender/receiver bookeeping. Not threadsafe.
Connecting & disconnecting leave behind a small amount of bookeeping
for the receiver and sender values. Typical workloads using Blinker,
for example in most web apps, Flask, CLI scripts, etc., are not
adversely affected by this bookkeeping.
With a long-running Python process performing dynamic signal routing
with high volume- e.g. connecting to function closures, "senders" are
all unique object instances, and doing all of this over and over- you
may see memory usage will grow due to extraneous bookeeping. (An empty
set() for each stale sender/receiver pair.)
This method will prune that bookeeping away, with the caveat that such
pruning is not threadsafe. The risk is that cleanup of a fully
disconnected receiver/sender pair occurs while another thread is
connecting that same pair. If you are in the highly dynamic, unique
receiver/sender situation that has lead you to this method, that
failure mode is perhaps not a big deal for you.
"""
for mapping in (self._by_sender, self._by_receiver):
for _id, bucket in list(mapping.items()):
if not bucket:
mapping.pop(_id, None)
def _clear_state(self):
"""Throw away all signal state. Useful for unit tests."""
self._weak_senders.clear()
self.receivers.clear()
self._by_sender.clear()
self._by_receiver.clear()
receiver_connected = Signal("""\
Sent by a :class:`Signal` after a receiver connects.
:argument: the Signal that was connected to
:keyword receiver_arg: the connected receiver
:keyword sender_arg: the sender to connect to
:keyword weak_arg: true if the connection to receiver_arg is a weak reference
.. deprecated:: 1.2
As of 1.2, individual signals have their own private
:attr:`~Signal.receiver_connected` and
:attr:`~Signal.receiver_disconnected` signals with a slightly simplified
call signature. This global signal is planned to be removed in 1.6.
""")
class NamedSignal(Signal):
"""A named generic notification emitter."""
def __init__(self, name, doc=None):
Signal.__init__(self, doc)
#: The name of this signal.
self.name = name
def __repr__(self):
base = Signal.__repr__(self)
return "%s; %r>" % (base[:-1], self.name)
class Namespace(dict):
"""A mapping of signal names to signals."""
def signal(self, name, doc=None):
"""Return the :class:`NamedSignal` *name*, creating it if required.
Repeated calls to this function will return the same signal object.
"""
try:
return self[name]
except KeyError:
return self.setdefault(name, NamedSignal(name, doc))
class WeakNamespace(WeakValueDictionary):
"""A weak mapping of signal names to signals.
Automatically cleans up unused Signals when the last reference goes out
of scope. This namespace implementation exists for a measure of legacy
compatibility with Blinker <= 1.2, and may be dropped in the future.
.. versionadded:: 1.3
"""
def signal(self, name, doc=None):
"""Return the :class:`NamedSignal` *name*, creating it if required.
Repeated calls to this function will return the same signal object.
"""
try:
return self[name]
except KeyError:
return self.setdefault(name, NamedSignal(name, doc))
signal = Namespace().signal

View File

@@ -1,97 +0,0 @@
# -*- coding: utf-8 -*-
"""
click
~~~~~
Click is a simple Python module inspired by the stdlib optparse to make
writing command line scripts fun. Unlike other modules, it's based
around a simple API that does not come with too much magic and is
composable.
:copyright: © 2014 by the Pallets team.
:license: BSD, see LICENSE.rst for more details.
"""
# Core classes
from .core import Context, BaseCommand, Command, MultiCommand, Group, \
CommandCollection, Parameter, Option, Argument
# Globals
from .globals import get_current_context
# Decorators
from .decorators import pass_context, pass_obj, make_pass_decorator, \
command, group, argument, option, confirmation_option, \
password_option, version_option, help_option
# Types
from .types import ParamType, File, Path, Choice, IntRange, Tuple, \
DateTime, STRING, INT, FLOAT, BOOL, UUID, UNPROCESSED, FloatRange
# Utilities
from .utils import echo, get_binary_stream, get_text_stream, open_file, \
format_filename, get_app_dir, get_os_args
# Terminal functions
from .termui import prompt, confirm, get_terminal_size, echo_via_pager, \
progressbar, clear, style, unstyle, secho, edit, launch, getchar, \
pause
# Exceptions
from .exceptions import ClickException, UsageError, BadParameter, \
FileError, Abort, NoSuchOption, BadOptionUsage, BadArgumentUsage, \
MissingParameter
# Formatting
from .formatting import HelpFormatter, wrap_text
# Parsing
from .parser import OptionParser
__all__ = [
# Core classes
'Context', 'BaseCommand', 'Command', 'MultiCommand', 'Group',
'CommandCollection', 'Parameter', 'Option', 'Argument',
# Globals
'get_current_context',
# Decorators
'pass_context', 'pass_obj', 'make_pass_decorator', 'command', 'group',
'argument', 'option', 'confirmation_option', 'password_option',
'version_option', 'help_option',
# Types
'ParamType', 'File', 'Path', 'Choice', 'IntRange', 'Tuple',
'DateTime', 'STRING', 'INT', 'FLOAT', 'BOOL', 'UUID', 'UNPROCESSED',
'FloatRange',
# Utilities
'echo', 'get_binary_stream', 'get_text_stream', 'open_file',
'format_filename', 'get_app_dir', 'get_os_args',
# Terminal functions
'prompt', 'confirm', 'get_terminal_size', 'echo_via_pager',
'progressbar', 'clear', 'style', 'unstyle', 'secho', 'edit', 'launch',
'getchar', 'pause',
# Exceptions
'ClickException', 'UsageError', 'BadParameter', 'FileError',
'Abort', 'NoSuchOption', 'BadOptionUsage', 'BadArgumentUsage',
'MissingParameter',
# Formatting
'HelpFormatter', 'wrap_text',
# Parsing
'OptionParser',
]
# Controls if click should emit the warning about the use of unicode
# literals.
disable_unicode_literals_warning = False
__version__ = '7.0'

Some files were not shown because too many files have changed in this diff Show More