##// END OF EJS Templates
issue-trackers: implemented more sophisticated ticket data extraction based on advanced regex module, and special...
marcink -
r4498:2fce90e4 stable
parent child Browse files
Show More
@@ -1,2497 +1,2509 b''
1 # Generated by pip2nix 0.8.0.dev1
1 # Generated by pip2nix 0.8.0.dev1
2 # See https://github.com/johbo/pip2nix
2 # See https://github.com/johbo/pip2nix
3
3
4 { pkgs, fetchurl, fetchgit, fetchhg }:
4 { pkgs, fetchurl, fetchgit, fetchhg }:
5
5
6 self: super: {
6 self: super: {
7 "alembic" = super.buildPythonPackage {
7 "alembic" = super.buildPythonPackage {
8 name = "alembic-1.4.2";
8 name = "alembic-1.4.2";
9 doCheck = false;
9 doCheck = false;
10 propagatedBuildInputs = [
10 propagatedBuildInputs = [
11 self."sqlalchemy"
11 self."sqlalchemy"
12 self."mako"
12 self."mako"
13 self."python-editor"
13 self."python-editor"
14 self."python-dateutil"
14 self."python-dateutil"
15 ];
15 ];
16 src = fetchurl {
16 src = fetchurl {
17 url = "https://files.pythonhosted.org/packages/60/1e/cabc75a189de0fbb2841d0975243e59bde8b7822bacbb95008ac6fe9ad47/alembic-1.4.2.tar.gz";
17 url = "https://files.pythonhosted.org/packages/60/1e/cabc75a189de0fbb2841d0975243e59bde8b7822bacbb95008ac6fe9ad47/alembic-1.4.2.tar.gz";
18 sha256 = "1gsdrzx9h7wfva200qvvsc9sn4w79mk2vs0bbnzjhxi1jw2b0nh3";
18 sha256 = "1gsdrzx9h7wfva200qvvsc9sn4w79mk2vs0bbnzjhxi1jw2b0nh3";
19 };
19 };
20 meta = {
20 meta = {
21 license = [ pkgs.lib.licenses.mit ];
21 license = [ pkgs.lib.licenses.mit ];
22 };
22 };
23 };
23 };
24 "amqp" = super.buildPythonPackage {
24 "amqp" = super.buildPythonPackage {
25 name = "amqp-2.5.2";
25 name = "amqp-2.5.2";
26 doCheck = false;
26 doCheck = false;
27 propagatedBuildInputs = [
27 propagatedBuildInputs = [
28 self."vine"
28 self."vine"
29 ];
29 ];
30 src = fetchurl {
30 src = fetchurl {
31 url = "https://files.pythonhosted.org/packages/92/1d/433541994a5a69f4ad2fff39746ddbb0bdedb0ea0d85673eb0db68a7edd9/amqp-2.5.2.tar.gz";
31 url = "https://files.pythonhosted.org/packages/92/1d/433541994a5a69f4ad2fff39746ddbb0bdedb0ea0d85673eb0db68a7edd9/amqp-2.5.2.tar.gz";
32 sha256 = "13dhhfxjrqcjybnq4zahg92mydhpg2l76nxcmq7d560687wsxwbp";
32 sha256 = "13dhhfxjrqcjybnq4zahg92mydhpg2l76nxcmq7d560687wsxwbp";
33 };
33 };
34 meta = {
34 meta = {
35 license = [ pkgs.lib.licenses.bsdOriginal ];
35 license = [ pkgs.lib.licenses.bsdOriginal ];
36 };
36 };
37 };
37 };
38 "apispec" = super.buildPythonPackage {
38 "apispec" = super.buildPythonPackage {
39 name = "apispec-1.0.0";
39 name = "apispec-1.0.0";
40 doCheck = false;
40 doCheck = false;
41 propagatedBuildInputs = [
41 propagatedBuildInputs = [
42 self."PyYAML"
42 self."PyYAML"
43 ];
43 ];
44 src = fetchurl {
44 src = fetchurl {
45 url = "https://files.pythonhosted.org/packages/67/15/346c04988dd67d36007e28145504c520491930c878b1f484a97b27a8f497/apispec-1.0.0.tar.gz";
45 url = "https://files.pythonhosted.org/packages/67/15/346c04988dd67d36007e28145504c520491930c878b1f484a97b27a8f497/apispec-1.0.0.tar.gz";
46 sha256 = "1712w1anvqrvadjjpvai84vbaygaxabd3zz5lxihdzwzs4gvi9sp";
46 sha256 = "1712w1anvqrvadjjpvai84vbaygaxabd3zz5lxihdzwzs4gvi9sp";
47 };
47 };
48 meta = {
48 meta = {
49 license = [ pkgs.lib.licenses.mit ];
49 license = [ pkgs.lib.licenses.mit ];
50 };
50 };
51 };
51 };
52 "appenlight-client" = super.buildPythonPackage {
52 "appenlight-client" = super.buildPythonPackage {
53 name = "appenlight-client-0.6.26";
53 name = "appenlight-client-0.6.26";
54 doCheck = false;
54 doCheck = false;
55 propagatedBuildInputs = [
55 propagatedBuildInputs = [
56 self."webob"
56 self."webob"
57 self."requests"
57 self."requests"
58 self."six"
58 self."six"
59 ];
59 ];
60 src = fetchurl {
60 src = fetchurl {
61 url = "https://files.pythonhosted.org/packages/2e/56/418fc10379b96e795ee39a15e69a730c222818af04c3821fa354eaa859ec/appenlight_client-0.6.26.tar.gz";
61 url = "https://files.pythonhosted.org/packages/2e/56/418fc10379b96e795ee39a15e69a730c222818af04c3821fa354eaa859ec/appenlight_client-0.6.26.tar.gz";
62 sha256 = "0s9xw3sb8s3pk73k78nnq4jil3q4mk6bczfa1fmgfx61kdxl2712";
62 sha256 = "0s9xw3sb8s3pk73k78nnq4jil3q4mk6bczfa1fmgfx61kdxl2712";
63 };
63 };
64 meta = {
64 meta = {
65 license = [ pkgs.lib.licenses.bsdOriginal ];
65 license = [ pkgs.lib.licenses.bsdOriginal ];
66 };
66 };
67 };
67 };
68 "asn1crypto" = super.buildPythonPackage {
68 "asn1crypto" = super.buildPythonPackage {
69 name = "asn1crypto-0.24.0";
69 name = "asn1crypto-0.24.0";
70 doCheck = false;
70 doCheck = false;
71 src = fetchurl {
71 src = fetchurl {
72 url = "https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz";
72 url = "https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz";
73 sha256 = "0jaf8rf9dx1lf23xfv2cdd5h52f1qr3w8k63985bc35g3d220p4x";
73 sha256 = "0jaf8rf9dx1lf23xfv2cdd5h52f1qr3w8k63985bc35g3d220p4x";
74 };
74 };
75 meta = {
75 meta = {
76 license = [ pkgs.lib.licenses.mit ];
76 license = [ pkgs.lib.licenses.mit ];
77 };
77 };
78 };
78 };
79 "atomicwrites" = super.buildPythonPackage {
79 "atomicwrites" = super.buildPythonPackage {
80 name = "atomicwrites-1.3.0";
80 name = "atomicwrites-1.3.0";
81 doCheck = false;
81 doCheck = false;
82 src = fetchurl {
82 src = fetchurl {
83 url = "https://files.pythonhosted.org/packages/ec/0f/cd484ac8820fed363b374af30049adc8fd13065720fd4f4c6be8a2309da7/atomicwrites-1.3.0.tar.gz";
83 url = "https://files.pythonhosted.org/packages/ec/0f/cd484ac8820fed363b374af30049adc8fd13065720fd4f4c6be8a2309da7/atomicwrites-1.3.0.tar.gz";
84 sha256 = "19ngcscdf3jsqmpcxn6zl5b6anmsajb6izp1smcd1n02midl9abm";
84 sha256 = "19ngcscdf3jsqmpcxn6zl5b6anmsajb6izp1smcd1n02midl9abm";
85 };
85 };
86 meta = {
86 meta = {
87 license = [ pkgs.lib.licenses.mit ];
87 license = [ pkgs.lib.licenses.mit ];
88 };
88 };
89 };
89 };
90 "attrs" = super.buildPythonPackage {
90 "attrs" = super.buildPythonPackage {
91 name = "attrs-19.3.0";
91 name = "attrs-19.3.0";
92 doCheck = false;
92 doCheck = false;
93 src = fetchurl {
93 src = fetchurl {
94 url = "https://files.pythonhosted.org/packages/98/c3/2c227e66b5e896e15ccdae2e00bbc69aa46e9a8ce8869cc5fa96310bf612/attrs-19.3.0.tar.gz";
94 url = "https://files.pythonhosted.org/packages/98/c3/2c227e66b5e896e15ccdae2e00bbc69aa46e9a8ce8869cc5fa96310bf612/attrs-19.3.0.tar.gz";
95 sha256 = "0wky4h28n7xnr6xv69p9z6kv8bzn50d10c3drmd9ds8gawbcxdzp";
95 sha256 = "0wky4h28n7xnr6xv69p9z6kv8bzn50d10c3drmd9ds8gawbcxdzp";
96 };
96 };
97 meta = {
97 meta = {
98 license = [ pkgs.lib.licenses.mit ];
98 license = [ pkgs.lib.licenses.mit ];
99 };
99 };
100 };
100 };
101 "babel" = super.buildPythonPackage {
101 "babel" = super.buildPythonPackage {
102 name = "babel-1.3";
102 name = "babel-1.3";
103 doCheck = false;
103 doCheck = false;
104 propagatedBuildInputs = [
104 propagatedBuildInputs = [
105 self."pytz"
105 self."pytz"
106 ];
106 ];
107 src = fetchurl {
107 src = fetchurl {
108 url = "https://files.pythonhosted.org/packages/33/27/e3978243a03a76398c384c83f7ca879bc6e8f1511233a621fcada135606e/Babel-1.3.tar.gz";
108 url = "https://files.pythonhosted.org/packages/33/27/e3978243a03a76398c384c83f7ca879bc6e8f1511233a621fcada135606e/Babel-1.3.tar.gz";
109 sha256 = "0bnin777lc53nxd1hp3apq410jj5wx92n08h7h4izpl4f4sx00lz";
109 sha256 = "0bnin777lc53nxd1hp3apq410jj5wx92n08h7h4izpl4f4sx00lz";
110 };
110 };
111 meta = {
111 meta = {
112 license = [ pkgs.lib.licenses.bsdOriginal ];
112 license = [ pkgs.lib.licenses.bsdOriginal ];
113 };
113 };
114 };
114 };
115 "backports.shutil-get-terminal-size" = super.buildPythonPackage {
115 "backports.shutil-get-terminal-size" = super.buildPythonPackage {
116 name = "backports.shutil-get-terminal-size-1.0.0";
116 name = "backports.shutil-get-terminal-size-1.0.0";
117 doCheck = false;
117 doCheck = false;
118 src = fetchurl {
118 src = fetchurl {
119 url = "https://files.pythonhosted.org/packages/ec/9c/368086faa9c016efce5da3e0e13ba392c9db79e3ab740b763fe28620b18b/backports.shutil_get_terminal_size-1.0.0.tar.gz";
119 url = "https://files.pythonhosted.org/packages/ec/9c/368086faa9c016efce5da3e0e13ba392c9db79e3ab740b763fe28620b18b/backports.shutil_get_terminal_size-1.0.0.tar.gz";
120 sha256 = "107cmn7g3jnbkp826zlj8rrj19fam301qvaqf0f3905f5217lgki";
120 sha256 = "107cmn7g3jnbkp826zlj8rrj19fam301qvaqf0f3905f5217lgki";
121 };
121 };
122 meta = {
122 meta = {
123 license = [ pkgs.lib.licenses.mit ];
123 license = [ pkgs.lib.licenses.mit ];
124 };
124 };
125 };
125 };
126 "beaker" = super.buildPythonPackage {
126 "beaker" = super.buildPythonPackage {
127 name = "beaker-1.9.1";
127 name = "beaker-1.9.1";
128 doCheck = false;
128 doCheck = false;
129 propagatedBuildInputs = [
129 propagatedBuildInputs = [
130 self."funcsigs"
130 self."funcsigs"
131 ];
131 ];
132 src = fetchurl {
132 src = fetchurl {
133 url = "https://files.pythonhosted.org/packages/ca/14/a626188d0d0c7b55dd7cf1902046c2743bd392a7078bb53073e13280eb1e/Beaker-1.9.1.tar.gz";
133 url = "https://files.pythonhosted.org/packages/ca/14/a626188d0d0c7b55dd7cf1902046c2743bd392a7078bb53073e13280eb1e/Beaker-1.9.1.tar.gz";
134 sha256 = "08arsn61r255lhz6hcpn2lsiqpg30clla805ysx06wmbhvb6w9rj";
134 sha256 = "08arsn61r255lhz6hcpn2lsiqpg30clla805ysx06wmbhvb6w9rj";
135 };
135 };
136 meta = {
136 meta = {
137 license = [ pkgs.lib.licenses.bsdOriginal ];
137 license = [ pkgs.lib.licenses.bsdOriginal ];
138 };
138 };
139 };
139 };
140 "beautifulsoup4" = super.buildPythonPackage {
140 "beautifulsoup4" = super.buildPythonPackage {
141 name = "beautifulsoup4-4.6.3";
141 name = "beautifulsoup4-4.6.3";
142 doCheck = false;
142 doCheck = false;
143 src = fetchurl {
143 src = fetchurl {
144 url = "https://files.pythonhosted.org/packages/88/df/86bffad6309f74f3ff85ea69344a078fc30003270c8df6894fca7a3c72ff/beautifulsoup4-4.6.3.tar.gz";
144 url = "https://files.pythonhosted.org/packages/88/df/86bffad6309f74f3ff85ea69344a078fc30003270c8df6894fca7a3c72ff/beautifulsoup4-4.6.3.tar.gz";
145 sha256 = "041dhalzjciw6qyzzq7a2k4h1yvyk76xigp35hv5ibnn448ydy4h";
145 sha256 = "041dhalzjciw6qyzzq7a2k4h1yvyk76xigp35hv5ibnn448ydy4h";
146 };
146 };
147 meta = {
147 meta = {
148 license = [ pkgs.lib.licenses.mit ];
148 license = [ pkgs.lib.licenses.mit ];
149 };
149 };
150 };
150 };
151 "billiard" = super.buildPythonPackage {
151 "billiard" = super.buildPythonPackage {
152 name = "billiard-3.6.1.0";
152 name = "billiard-3.6.1.0";
153 doCheck = false;
153 doCheck = false;
154 src = fetchurl {
154 src = fetchurl {
155 url = "https://files.pythonhosted.org/packages/68/1d/2aea8fbb0b1e1260a8a2e77352de2983d36d7ac01207cf14c2b9c6cc860e/billiard-3.6.1.0.tar.gz";
155 url = "https://files.pythonhosted.org/packages/68/1d/2aea8fbb0b1e1260a8a2e77352de2983d36d7ac01207cf14c2b9c6cc860e/billiard-3.6.1.0.tar.gz";
156 sha256 = "09hzy3aqi7visy4vmf4xiish61n0rq5nd3iwjydydps8yrs9r05q";
156 sha256 = "09hzy3aqi7visy4vmf4xiish61n0rq5nd3iwjydydps8yrs9r05q";
157 };
157 };
158 meta = {
158 meta = {
159 license = [ pkgs.lib.licenses.bsdOriginal ];
159 license = [ pkgs.lib.licenses.bsdOriginal ];
160 };
160 };
161 };
161 };
162 "bleach" = super.buildPythonPackage {
162 "bleach" = super.buildPythonPackage {
163 name = "bleach-3.1.3";
163 name = "bleach-3.1.3";
164 doCheck = false;
164 doCheck = false;
165 propagatedBuildInputs = [
165 propagatedBuildInputs = [
166 self."six"
166 self."six"
167 self."webencodings"
167 self."webencodings"
168 ];
168 ];
169 src = fetchurl {
169 src = fetchurl {
170 url = "https://files.pythonhosted.org/packages/de/09/5267f8577a92487ed43bc694476c4629c6eca2e3c93fcf690a26bfe39e1d/bleach-3.1.3.tar.gz";
170 url = "https://files.pythonhosted.org/packages/de/09/5267f8577a92487ed43bc694476c4629c6eca2e3c93fcf690a26bfe39e1d/bleach-3.1.3.tar.gz";
171 sha256 = "0al437aw4p2xp83az5hhlrp913nsf0cg6kg4qj3fjhv4wakxipzq";
171 sha256 = "0al437aw4p2xp83az5hhlrp913nsf0cg6kg4qj3fjhv4wakxipzq";
172 };
172 };
173 meta = {
173 meta = {
174 license = [ pkgs.lib.licenses.asl20 ];
174 license = [ pkgs.lib.licenses.asl20 ];
175 };
175 };
176 };
176 };
177 "bumpversion" = super.buildPythonPackage {
177 "bumpversion" = super.buildPythonPackage {
178 name = "bumpversion-0.5.3";
178 name = "bumpversion-0.5.3";
179 doCheck = false;
179 doCheck = false;
180 src = fetchurl {
180 src = fetchurl {
181 url = "https://files.pythonhosted.org/packages/14/41/8c9da3549f8e00c84f0432c3a8cf8ed6898374714676aab91501d48760db/bumpversion-0.5.3.tar.gz";
181 url = "https://files.pythonhosted.org/packages/14/41/8c9da3549f8e00c84f0432c3a8cf8ed6898374714676aab91501d48760db/bumpversion-0.5.3.tar.gz";
182 sha256 = "0zn7694yfipxg35ikkfh7kvgl2fissha3dnqad2c5bvsvmrwhi37";
182 sha256 = "0zn7694yfipxg35ikkfh7kvgl2fissha3dnqad2c5bvsvmrwhi37";
183 };
183 };
184 meta = {
184 meta = {
185 license = [ pkgs.lib.licenses.mit ];
185 license = [ pkgs.lib.licenses.mit ];
186 };
186 };
187 };
187 };
188 "cachetools" = super.buildPythonPackage {
188 "cachetools" = super.buildPythonPackage {
189 name = "cachetools-3.1.1";
189 name = "cachetools-3.1.1";
190 doCheck = false;
190 doCheck = false;
191 src = fetchurl {
191 src = fetchurl {
192 url = "https://files.pythonhosted.org/packages/ae/37/7fd45996b19200e0cb2027a0b6bef4636951c4ea111bfad36c71287247f6/cachetools-3.1.1.tar.gz";
192 url = "https://files.pythonhosted.org/packages/ae/37/7fd45996b19200e0cb2027a0b6bef4636951c4ea111bfad36c71287247f6/cachetools-3.1.1.tar.gz";
193 sha256 = "16m69l6n6y1r1y7cklm92rr7v69ldig2n3lbl3j323w5jz7d78lf";
193 sha256 = "16m69l6n6y1r1y7cklm92rr7v69ldig2n3lbl3j323w5jz7d78lf";
194 };
194 };
195 meta = {
195 meta = {
196 license = [ pkgs.lib.licenses.mit ];
196 license = [ pkgs.lib.licenses.mit ];
197 };
197 };
198 };
198 };
199 "celery" = super.buildPythonPackage {
199 "celery" = super.buildPythonPackage {
200 name = "celery-4.3.0";
200 name = "celery-4.3.0";
201 doCheck = false;
201 doCheck = false;
202 propagatedBuildInputs = [
202 propagatedBuildInputs = [
203 self."pytz"
203 self."pytz"
204 self."billiard"
204 self."billiard"
205 self."kombu"
205 self."kombu"
206 self."vine"
206 self."vine"
207 ];
207 ];
208 src = fetchurl {
208 src = fetchurl {
209 url = "https://files.pythonhosted.org/packages/a2/4b/d020836f751617e907e84753a41c92231cd4b673ff991b8ee9da52361323/celery-4.3.0.tar.gz";
209 url = "https://files.pythonhosted.org/packages/a2/4b/d020836f751617e907e84753a41c92231cd4b673ff991b8ee9da52361323/celery-4.3.0.tar.gz";
210 sha256 = "1y8y0gbgkwimpxqnxq2rm5qz2vy01fvjiybnpm00y5rzd2m34iac";
210 sha256 = "1y8y0gbgkwimpxqnxq2rm5qz2vy01fvjiybnpm00y5rzd2m34iac";
211 };
211 };
212 meta = {
212 meta = {
213 license = [ pkgs.lib.licenses.bsdOriginal ];
213 license = [ pkgs.lib.licenses.bsdOriginal ];
214 };
214 };
215 };
215 };
216 "certifi" = super.buildPythonPackage {
216 "certifi" = super.buildPythonPackage {
217 name = "certifi-2020.4.5.1";
217 name = "certifi-2020.4.5.1";
218 doCheck = false;
218 doCheck = false;
219 src = fetchurl {
219 src = fetchurl {
220 url = "https://files.pythonhosted.org/packages/b8/e2/a3a86a67c3fc8249ed305fc7b7d290ebe5e4d46ad45573884761ef4dea7b/certifi-2020.4.5.1.tar.gz";
220 url = "https://files.pythonhosted.org/packages/b8/e2/a3a86a67c3fc8249ed305fc7b7d290ebe5e4d46ad45573884761ef4dea7b/certifi-2020.4.5.1.tar.gz";
221 sha256 = "06b5gfs7wmmipln8f3z928d2mmx2j4b3x7pnqmj6cvmyfh8v7z2i";
221 sha256 = "06b5gfs7wmmipln8f3z928d2mmx2j4b3x7pnqmj6cvmyfh8v7z2i";
222 };
222 };
223 meta = {
223 meta = {
224 license = [ pkgs.lib.licenses.mpl20 { fullName = "Mozilla Public License 2.0 (MPL 2.0)"; } ];
224 license = [ pkgs.lib.licenses.mpl20 { fullName = "Mozilla Public License 2.0 (MPL 2.0)"; } ];
225 };
225 };
226 };
226 };
227 "cffi" = super.buildPythonPackage {
227 "cffi" = super.buildPythonPackage {
228 name = "cffi-1.12.3";
228 name = "cffi-1.12.3";
229 doCheck = false;
229 doCheck = false;
230 propagatedBuildInputs = [
230 propagatedBuildInputs = [
231 self."pycparser"
231 self."pycparser"
232 ];
232 ];
233 src = fetchurl {
233 src = fetchurl {
234 url = "https://files.pythonhosted.org/packages/93/1a/ab8c62b5838722f29f3daffcc8d4bd61844aa9b5f437341cc890ceee483b/cffi-1.12.3.tar.gz";
234 url = "https://files.pythonhosted.org/packages/93/1a/ab8c62b5838722f29f3daffcc8d4bd61844aa9b5f437341cc890ceee483b/cffi-1.12.3.tar.gz";
235 sha256 = "0x075521fxwv0mfp4cqzk7lvmw4n94bjw601qkcv314z5s182704";
235 sha256 = "0x075521fxwv0mfp4cqzk7lvmw4n94bjw601qkcv314z5s182704";
236 };
236 };
237 meta = {
237 meta = {
238 license = [ pkgs.lib.licenses.mit ];
238 license = [ pkgs.lib.licenses.mit ];
239 };
239 };
240 };
240 };
241 "chameleon" = super.buildPythonPackage {
241 "chameleon" = super.buildPythonPackage {
242 name = "chameleon-2.24";
242 name = "chameleon-2.24";
243 doCheck = false;
243 doCheck = false;
244 src = fetchurl {
244 src = fetchurl {
245 url = "https://files.pythonhosted.org/packages/5a/9e/637379ffa13c5172b5c0e704833ffea6bf51cec7567f93fd6e903d53ed74/Chameleon-2.24.tar.gz";
245 url = "https://files.pythonhosted.org/packages/5a/9e/637379ffa13c5172b5c0e704833ffea6bf51cec7567f93fd6e903d53ed74/Chameleon-2.24.tar.gz";
246 sha256 = "0ykqr7syxfa6h9adjfnsv1gdsca2xzm22vmic8859n0f0j09abj5";
246 sha256 = "0ykqr7syxfa6h9adjfnsv1gdsca2xzm22vmic8859n0f0j09abj5";
247 };
247 };
248 meta = {
248 meta = {
249 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
249 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
250 };
250 };
251 };
251 };
252 "channelstream" = super.buildPythonPackage {
252 "channelstream" = super.buildPythonPackage {
253 name = "channelstream-0.6.14";
253 name = "channelstream-0.6.14";
254 doCheck = false;
254 doCheck = false;
255 propagatedBuildInputs = [
255 propagatedBuildInputs = [
256 self."gevent"
256 self."gevent"
257 self."ws4py"
257 self."ws4py"
258 self."marshmallow"
258 self."marshmallow"
259 self."python-dateutil"
259 self."python-dateutil"
260 self."pyramid"
260 self."pyramid"
261 self."pyramid-jinja2"
261 self."pyramid-jinja2"
262 self."pyramid-apispec"
262 self."pyramid-apispec"
263 self."itsdangerous"
263 self."itsdangerous"
264 self."requests"
264 self."requests"
265 self."six"
265 self."six"
266 ];
266 ];
267 src = fetchurl {
267 src = fetchurl {
268 url = "https://files.pythonhosted.org/packages/d4/2d/86d6757ccd06ce673ee224123471da3d45251d061da7c580bfc259bad853/channelstream-0.6.14.tar.gz";
268 url = "https://files.pythonhosted.org/packages/d4/2d/86d6757ccd06ce673ee224123471da3d45251d061da7c580bfc259bad853/channelstream-0.6.14.tar.gz";
269 sha256 = "0qgy5j3rj6c8cslzidh32glhkrhbbdxjc008y69v8a0y3zyaz2d3";
269 sha256 = "0qgy5j3rj6c8cslzidh32glhkrhbbdxjc008y69v8a0y3zyaz2d3";
270 };
270 };
271 meta = {
271 meta = {
272 license = [ pkgs.lib.licenses.bsdOriginal ];
272 license = [ pkgs.lib.licenses.bsdOriginal ];
273 };
273 };
274 };
274 };
275 "chardet" = super.buildPythonPackage {
275 "chardet" = super.buildPythonPackage {
276 name = "chardet-3.0.4";
276 name = "chardet-3.0.4";
277 doCheck = false;
277 doCheck = false;
278 src = fetchurl {
278 src = fetchurl {
279 url = "https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz";
279 url = "https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz";
280 sha256 = "1bpalpia6r5x1kknbk11p1fzph56fmmnp405ds8icksd3knr5aw4";
280 sha256 = "1bpalpia6r5x1kknbk11p1fzph56fmmnp405ds8icksd3knr5aw4";
281 };
281 };
282 meta = {
282 meta = {
283 license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
283 license = [ { fullName = "LGPL"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
284 };
284 };
285 };
285 };
286 "click" = super.buildPythonPackage {
286 "click" = super.buildPythonPackage {
287 name = "click-7.0";
287 name = "click-7.0";
288 doCheck = false;
288 doCheck = false;
289 src = fetchurl {
289 src = fetchurl {
290 url = "https://files.pythonhosted.org/packages/f8/5c/f60e9d8a1e77005f664b76ff8aeaee5bc05d0a91798afd7f53fc998dbc47/Click-7.0.tar.gz";
290 url = "https://files.pythonhosted.org/packages/f8/5c/f60e9d8a1e77005f664b76ff8aeaee5bc05d0a91798afd7f53fc998dbc47/Click-7.0.tar.gz";
291 sha256 = "1mzjixd4vjbjvzb6vylki9w1556a9qmdh35kzmq6cign46av952v";
291 sha256 = "1mzjixd4vjbjvzb6vylki9w1556a9qmdh35kzmq6cign46av952v";
292 };
292 };
293 meta = {
293 meta = {
294 license = [ pkgs.lib.licenses.bsdOriginal ];
294 license = [ pkgs.lib.licenses.bsdOriginal ];
295 };
295 };
296 };
296 };
297 "colander" = super.buildPythonPackage {
297 "colander" = super.buildPythonPackage {
298 name = "colander-1.7.0";
298 name = "colander-1.7.0";
299 doCheck = false;
299 doCheck = false;
300 propagatedBuildInputs = [
300 propagatedBuildInputs = [
301 self."translationstring"
301 self."translationstring"
302 self."iso8601"
302 self."iso8601"
303 self."enum34"
303 self."enum34"
304 ];
304 ];
305 src = fetchurl {
305 src = fetchurl {
306 url = "https://files.pythonhosted.org/packages/db/e4/74ab06f54211917b41865cafc987ce511e35503de48da9bfe9358a1bdc3e/colander-1.7.0.tar.gz";
306 url = "https://files.pythonhosted.org/packages/db/e4/74ab06f54211917b41865cafc987ce511e35503de48da9bfe9358a1bdc3e/colander-1.7.0.tar.gz";
307 sha256 = "1wl1bqab307lbbcjx81i28s3yl6dlm4rf15fxawkjb6j48x1cn6p";
307 sha256 = "1wl1bqab307lbbcjx81i28s3yl6dlm4rf15fxawkjb6j48x1cn6p";
308 };
308 };
309 meta = {
309 meta = {
310 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
310 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
311 };
311 };
312 };
312 };
313 "configobj" = super.buildPythonPackage {
313 "configobj" = super.buildPythonPackage {
314 name = "configobj-5.0.6";
314 name = "configobj-5.0.6";
315 doCheck = false;
315 doCheck = false;
316 propagatedBuildInputs = [
316 propagatedBuildInputs = [
317 self."six"
317 self."six"
318 ];
318 ];
319 src = fetchurl {
319 src = fetchurl {
320 url = "https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626";
320 url = "https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626";
321 sha256 = "0kqfrdfr14mw8yd8qwq14dv2xghpkjmd3yjsy8dfcbvpcc17xnxp";
321 sha256 = "0kqfrdfr14mw8yd8qwq14dv2xghpkjmd3yjsy8dfcbvpcc17xnxp";
322 };
322 };
323 meta = {
323 meta = {
324 license = [ pkgs.lib.licenses.bsdOriginal ];
324 license = [ pkgs.lib.licenses.bsdOriginal ];
325 };
325 };
326 };
326 };
327 "configparser" = super.buildPythonPackage {
327 "configparser" = super.buildPythonPackage {
328 name = "configparser-4.0.2";
328 name = "configparser-4.0.2";
329 doCheck = false;
329 doCheck = false;
330 src = fetchurl {
330 src = fetchurl {
331 url = "https://files.pythonhosted.org/packages/16/4f/48975536bd488d3a272549eb795ac4a13a5f7fcdc8995def77fbef3532ee/configparser-4.0.2.tar.gz";
331 url = "https://files.pythonhosted.org/packages/16/4f/48975536bd488d3a272549eb795ac4a13a5f7fcdc8995def77fbef3532ee/configparser-4.0.2.tar.gz";
332 sha256 = "1priacxym85yjcf68hh38w55nqswaxp71ryjyfdk222kg9l85ln7";
332 sha256 = "1priacxym85yjcf68hh38w55nqswaxp71ryjyfdk222kg9l85ln7";
333 };
333 };
334 meta = {
334 meta = {
335 license = [ pkgs.lib.licenses.mit ];
335 license = [ pkgs.lib.licenses.mit ];
336 };
336 };
337 };
337 };
338 "contextlib2" = super.buildPythonPackage {
338 "contextlib2" = super.buildPythonPackage {
339 name = "contextlib2-0.6.0.post1";
339 name = "contextlib2-0.6.0.post1";
340 doCheck = false;
340 doCheck = false;
341 src = fetchurl {
341 src = fetchurl {
342 url = "https://files.pythonhosted.org/packages/02/54/669207eb72e3d8ae8b38aa1f0703ee87a0e9f88f30d3c0a47bebdb6de242/contextlib2-0.6.0.post1.tar.gz";
342 url = "https://files.pythonhosted.org/packages/02/54/669207eb72e3d8ae8b38aa1f0703ee87a0e9f88f30d3c0a47bebdb6de242/contextlib2-0.6.0.post1.tar.gz";
343 sha256 = "0bhnr2ac7wy5l85ji909gyljyk85n92w8pdvslmrvc8qih4r1x01";
343 sha256 = "0bhnr2ac7wy5l85ji909gyljyk85n92w8pdvslmrvc8qih4r1x01";
344 };
344 };
345 meta = {
345 meta = {
346 license = [ pkgs.lib.licenses.psfl ];
346 license = [ pkgs.lib.licenses.psfl ];
347 };
347 };
348 };
348 };
349 "cov-core" = super.buildPythonPackage {
349 "cov-core" = super.buildPythonPackage {
350 name = "cov-core-1.15.0";
350 name = "cov-core-1.15.0";
351 doCheck = false;
351 doCheck = false;
352 propagatedBuildInputs = [
352 propagatedBuildInputs = [
353 self."coverage"
353 self."coverage"
354 ];
354 ];
355 src = fetchurl {
355 src = fetchurl {
356 url = "https://files.pythonhosted.org/packages/4b/87/13e75a47b4ba1be06f29f6d807ca99638bedc6b57fa491cd3de891ca2923/cov-core-1.15.0.tar.gz";
356 url = "https://files.pythonhosted.org/packages/4b/87/13e75a47b4ba1be06f29f6d807ca99638bedc6b57fa491cd3de891ca2923/cov-core-1.15.0.tar.gz";
357 sha256 = "0k3np9ymh06yv1ib96sb6wfsxjkqhmik8qfsn119vnhga9ywc52a";
357 sha256 = "0k3np9ymh06yv1ib96sb6wfsxjkqhmik8qfsn119vnhga9ywc52a";
358 };
358 };
359 meta = {
359 meta = {
360 license = [ pkgs.lib.licenses.mit ];
360 license = [ pkgs.lib.licenses.mit ];
361 };
361 };
362 };
362 };
363 "coverage" = super.buildPythonPackage {
363 "coverage" = super.buildPythonPackage {
364 name = "coverage-4.5.4";
364 name = "coverage-4.5.4";
365 doCheck = false;
365 doCheck = false;
366 src = fetchurl {
366 src = fetchurl {
367 url = "https://files.pythonhosted.org/packages/85/d5/818d0e603685c4a613d56f065a721013e942088047ff1027a632948bdae6/coverage-4.5.4.tar.gz";
367 url = "https://files.pythonhosted.org/packages/85/d5/818d0e603685c4a613d56f065a721013e942088047ff1027a632948bdae6/coverage-4.5.4.tar.gz";
368 sha256 = "0p0j4di6h8k6ica7jwwj09azdcg4ycxq60i9qsskmsg94cd9yzg0";
368 sha256 = "0p0j4di6h8k6ica7jwwj09azdcg4ycxq60i9qsskmsg94cd9yzg0";
369 };
369 };
370 meta = {
370 meta = {
371 license = [ pkgs.lib.licenses.asl20 ];
371 license = [ pkgs.lib.licenses.asl20 ];
372 };
372 };
373 };
373 };
374 "cryptography" = super.buildPythonPackage {
374 "cryptography" = super.buildPythonPackage {
375 name = "cryptography-2.6.1";
375 name = "cryptography-2.6.1";
376 doCheck = false;
376 doCheck = false;
377 propagatedBuildInputs = [
377 propagatedBuildInputs = [
378 self."asn1crypto"
378 self."asn1crypto"
379 self."six"
379 self."six"
380 self."cffi"
380 self."cffi"
381 self."enum34"
381 self."enum34"
382 self."ipaddress"
382 self."ipaddress"
383 ];
383 ];
384 src = fetchurl {
384 src = fetchurl {
385 url = "https://files.pythonhosted.org/packages/07/ca/bc827c5e55918ad223d59d299fff92f3563476c3b00d0a9157d9c0217449/cryptography-2.6.1.tar.gz";
385 url = "https://files.pythonhosted.org/packages/07/ca/bc827c5e55918ad223d59d299fff92f3563476c3b00d0a9157d9c0217449/cryptography-2.6.1.tar.gz";
386 sha256 = "19iwz5avym5zl6jrrrkym1rdaa9h61j20ph4cswsqgv8xg5j3j16";
386 sha256 = "19iwz5avym5zl6jrrrkym1rdaa9h61j20ph4cswsqgv8xg5j3j16";
387 };
387 };
388 meta = {
388 meta = {
389 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ];
389 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ];
390 };
390 };
391 };
391 };
392 "cssselect" = super.buildPythonPackage {
392 "cssselect" = super.buildPythonPackage {
393 name = "cssselect-1.0.3";
393 name = "cssselect-1.0.3";
394 doCheck = false;
394 doCheck = false;
395 src = fetchurl {
395 src = fetchurl {
396 url = "https://files.pythonhosted.org/packages/52/ea/f31e1d2e9eb130fda2a631e22eac369dc644e8807345fbed5113f2d6f92b/cssselect-1.0.3.tar.gz";
396 url = "https://files.pythonhosted.org/packages/52/ea/f31e1d2e9eb130fda2a631e22eac369dc644e8807345fbed5113f2d6f92b/cssselect-1.0.3.tar.gz";
397 sha256 = "011jqa2jhmydhi0iz4v1w3cr540z5zas8g2bw8brdw4s4b2qnv86";
397 sha256 = "011jqa2jhmydhi0iz4v1w3cr540z5zas8g2bw8brdw4s4b2qnv86";
398 };
398 };
399 meta = {
399 meta = {
400 license = [ pkgs.lib.licenses.bsdOriginal ];
400 license = [ pkgs.lib.licenses.bsdOriginal ];
401 };
401 };
402 };
402 };
403 "cssutils" = super.buildPythonPackage {
403 "cssutils" = super.buildPythonPackage {
404 name = "cssutils-1.0.2";
404 name = "cssutils-1.0.2";
405 doCheck = false;
405 doCheck = false;
406 src = fetchurl {
406 src = fetchurl {
407 url = "https://files.pythonhosted.org/packages/5c/0b/c5f29d29c037e97043770b5e7c740b6252993e4b57f029b3cd03c78ddfec/cssutils-1.0.2.tar.gz";
407 url = "https://files.pythonhosted.org/packages/5c/0b/c5f29d29c037e97043770b5e7c740b6252993e4b57f029b3cd03c78ddfec/cssutils-1.0.2.tar.gz";
408 sha256 = "1bxchrbqzapwijap0yhlxdil1w9bmwvgx77aizlkhc2mcxjg1z52";
408 sha256 = "1bxchrbqzapwijap0yhlxdil1w9bmwvgx77aizlkhc2mcxjg1z52";
409 };
409 };
410 meta = {
410 meta = {
411 license = [ { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL 2.1 or later, see also http://cthedot.de/cssutils/"; } ];
411 license = [ { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL 2.1 or later, see also http://cthedot.de/cssutils/"; } ];
412 };
412 };
413 };
413 };
414 "decorator" = super.buildPythonPackage {
414 "decorator" = super.buildPythonPackage {
415 name = "decorator-4.1.2";
415 name = "decorator-4.1.2";
416 doCheck = false;
416 doCheck = false;
417 src = fetchurl {
417 src = fetchurl {
418 url = "https://files.pythonhosted.org/packages/bb/e0/f6e41e9091e130bf16d4437dabbac3993908e4d6485ecbc985ef1352db94/decorator-4.1.2.tar.gz";
418 url = "https://files.pythonhosted.org/packages/bb/e0/f6e41e9091e130bf16d4437dabbac3993908e4d6485ecbc985ef1352db94/decorator-4.1.2.tar.gz";
419 sha256 = "1d8npb11kxyi36mrvjdpcjij76l5zfyrz2f820brf0l0rcw4vdkw";
419 sha256 = "1d8npb11kxyi36mrvjdpcjij76l5zfyrz2f820brf0l0rcw4vdkw";
420 };
420 };
421 meta = {
421 meta = {
422 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "new BSD License"; } ];
422 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "new BSD License"; } ];
423 };
423 };
424 };
424 };
425 "deform" = super.buildPythonPackage {
425 "deform" = super.buildPythonPackage {
426 name = "deform-2.0.8";
426 name = "deform-2.0.8";
427 doCheck = false;
427 doCheck = false;
428 propagatedBuildInputs = [
428 propagatedBuildInputs = [
429 self."chameleon"
429 self."chameleon"
430 self."colander"
430 self."colander"
431 self."iso8601"
431 self."iso8601"
432 self."peppercorn"
432 self."peppercorn"
433 self."translationstring"
433 self."translationstring"
434 self."zope.deprecation"
434 self."zope.deprecation"
435 ];
435 ];
436 src = fetchurl {
436 src = fetchurl {
437 url = "https://files.pythonhosted.org/packages/21/d0/45fdf891a82722c02fc2da319cf2d1ae6b5abf9e470ad3762135a895a868/deform-2.0.8.tar.gz";
437 url = "https://files.pythonhosted.org/packages/21/d0/45fdf891a82722c02fc2da319cf2d1ae6b5abf9e470ad3762135a895a868/deform-2.0.8.tar.gz";
438 sha256 = "0wbjv98sib96649aqaygzxnrkclyy50qij2rha6fn1i4c86bfdl9";
438 sha256 = "0wbjv98sib96649aqaygzxnrkclyy50qij2rha6fn1i4c86bfdl9";
439 };
439 };
440 meta = {
440 meta = {
441 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
441 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
442 };
442 };
443 };
443 };
444 "defusedxml" = super.buildPythonPackage {
444 "defusedxml" = super.buildPythonPackage {
445 name = "defusedxml-0.6.0";
445 name = "defusedxml-0.6.0";
446 doCheck = false;
446 doCheck = false;
447 src = fetchurl {
447 src = fetchurl {
448 url = "https://files.pythonhosted.org/packages/a4/5f/f8aa58ca0cf01cbcee728abc9d88bfeb74e95e6cb4334cfd5bed5673ea77/defusedxml-0.6.0.tar.gz";
448 url = "https://files.pythonhosted.org/packages/a4/5f/f8aa58ca0cf01cbcee728abc9d88bfeb74e95e6cb4334cfd5bed5673ea77/defusedxml-0.6.0.tar.gz";
449 sha256 = "1xbp8fivl3wlbyg2jrvs4lalaqv1xp9a9f29p75wdx2s2d6h717n";
449 sha256 = "1xbp8fivl3wlbyg2jrvs4lalaqv1xp9a9f29p75wdx2s2d6h717n";
450 };
450 };
451 meta = {
451 meta = {
452 license = [ pkgs.lib.licenses.psfl ];
452 license = [ pkgs.lib.licenses.psfl ];
453 };
453 };
454 };
454 };
455 "dm.xmlsec.binding" = super.buildPythonPackage {
455 "dm.xmlsec.binding" = super.buildPythonPackage {
456 name = "dm.xmlsec.binding-1.3.7";
456 name = "dm.xmlsec.binding-1.3.7";
457 doCheck = false;
457 doCheck = false;
458 propagatedBuildInputs = [
458 propagatedBuildInputs = [
459 self."setuptools"
459 self."setuptools"
460 self."lxml"
460 self."lxml"
461 ];
461 ];
462 src = fetchurl {
462 src = fetchurl {
463 url = "https://files.pythonhosted.org/packages/2c/9e/7651982d50252692991acdae614af821fd6c79bc8dcd598ad71d55be8fc7/dm.xmlsec.binding-1.3.7.tar.gz";
463 url = "https://files.pythonhosted.org/packages/2c/9e/7651982d50252692991acdae614af821fd6c79bc8dcd598ad71d55be8fc7/dm.xmlsec.binding-1.3.7.tar.gz";
464 sha256 = "03jjjscx1pz2nc0dwiw9nia02qbz1c6f0f9zkyr8fmvys2n5jkb3";
464 sha256 = "03jjjscx1pz2nc0dwiw9nia02qbz1c6f0f9zkyr8fmvys2n5jkb3";
465 };
465 };
466 meta = {
466 meta = {
467 license = [ pkgs.lib.licenses.bsdOriginal ];
467 license = [ pkgs.lib.licenses.bsdOriginal ];
468 };
468 };
469 };
469 };
470 "docutils" = super.buildPythonPackage {
470 "docutils" = super.buildPythonPackage {
471 name = "docutils-0.16";
471 name = "docutils-0.16";
472 doCheck = false;
472 doCheck = false;
473 src = fetchurl {
473 src = fetchurl {
474 url = "https://files.pythonhosted.org/packages/2f/e0/3d435b34abd2d62e8206171892f174b180cd37b09d57b924ca5c2ef2219d/docutils-0.16.tar.gz";
474 url = "https://files.pythonhosted.org/packages/2f/e0/3d435b34abd2d62e8206171892f174b180cd37b09d57b924ca5c2ef2219d/docutils-0.16.tar.gz";
475 sha256 = "1z3qliszqca9m719q3qhdkh0ghh90g500avzdgi7pl77x5h3mpn2";
475 sha256 = "1z3qliszqca9m719q3qhdkh0ghh90g500avzdgi7pl77x5h3mpn2";
476 };
476 };
477 meta = {
477 meta = {
478 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.publicDomain pkgs.lib.licenses.gpl1 { fullName = "public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)"; } pkgs.lib.licenses.psfl ];
478 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.publicDomain pkgs.lib.licenses.gpl1 { fullName = "public domain, Python, 2-Clause BSD, GPL 3 (see COPYING.txt)"; } pkgs.lib.licenses.psfl ];
479 };
479 };
480 };
480 };
481 "dogpile.cache" = super.buildPythonPackage {
481 "dogpile.cache" = super.buildPythonPackage {
482 name = "dogpile.cache-0.9.0";
482 name = "dogpile.cache-0.9.0";
483 doCheck = false;
483 doCheck = false;
484 propagatedBuildInputs = [
484 propagatedBuildInputs = [
485 self."decorator"
485 self."decorator"
486 ];
486 ];
487 src = fetchurl {
487 src = fetchurl {
488 url = "https://files.pythonhosted.org/packages/ac/6a/9ac405686a94b7f009a20a50070a5786b0e1aedc707b88d40d0c4b51a82e/dogpile.cache-0.9.0.tar.gz";
488 url = "https://files.pythonhosted.org/packages/ac/6a/9ac405686a94b7f009a20a50070a5786b0e1aedc707b88d40d0c4b51a82e/dogpile.cache-0.9.0.tar.gz";
489 sha256 = "0sr1fn6b4k5bh0cscd9yi8csqxvj4ngzildav58x5p694mc86j5k";
489 sha256 = "0sr1fn6b4k5bh0cscd9yi8csqxvj4ngzildav58x5p694mc86j5k";
490 };
490 };
491 meta = {
491 meta = {
492 license = [ pkgs.lib.licenses.bsdOriginal ];
492 license = [ pkgs.lib.licenses.bsdOriginal ];
493 };
493 };
494 };
494 };
495 "dogpile.core" = super.buildPythonPackage {
495 "dogpile.core" = super.buildPythonPackage {
496 name = "dogpile.core-0.4.1";
496 name = "dogpile.core-0.4.1";
497 doCheck = false;
497 doCheck = false;
498 src = fetchurl {
498 src = fetchurl {
499 url = "https://files.pythonhosted.org/packages/0e/77/e72abc04c22aedf874301861e5c1e761231c288b5de369c18be8f4b5c9bb/dogpile.core-0.4.1.tar.gz";
499 url = "https://files.pythonhosted.org/packages/0e/77/e72abc04c22aedf874301861e5c1e761231c288b5de369c18be8f4b5c9bb/dogpile.core-0.4.1.tar.gz";
500 sha256 = "0xpdvg4kr1isfkrh1rfsh7za4q5a5s6l2kf9wpvndbwf3aqjyrdy";
500 sha256 = "0xpdvg4kr1isfkrh1rfsh7za4q5a5s6l2kf9wpvndbwf3aqjyrdy";
501 };
501 };
502 meta = {
502 meta = {
503 license = [ pkgs.lib.licenses.bsdOriginal ];
503 license = [ pkgs.lib.licenses.bsdOriginal ];
504 };
504 };
505 };
505 };
506 "ecdsa" = super.buildPythonPackage {
506 "ecdsa" = super.buildPythonPackage {
507 name = "ecdsa-0.13.2";
507 name = "ecdsa-0.13.2";
508 doCheck = false;
508 doCheck = false;
509 src = fetchurl {
509 src = fetchurl {
510 url = "https://files.pythonhosted.org/packages/51/76/139bf6e9b7b6684d5891212cdbd9e0739f2bfc03f380a1a6ffa700f392ac/ecdsa-0.13.2.tar.gz";
510 url = "https://files.pythonhosted.org/packages/51/76/139bf6e9b7b6684d5891212cdbd9e0739f2bfc03f380a1a6ffa700f392ac/ecdsa-0.13.2.tar.gz";
511 sha256 = "116qaq7bh4lcynzi613960jhsnn19v0kmsqwahiwjfj14gx4y0sw";
511 sha256 = "116qaq7bh4lcynzi613960jhsnn19v0kmsqwahiwjfj14gx4y0sw";
512 };
512 };
513 meta = {
513 meta = {
514 license = [ pkgs.lib.licenses.mit ];
514 license = [ pkgs.lib.licenses.mit ];
515 };
515 };
516 };
516 };
517 "elasticsearch" = super.buildPythonPackage {
517 "elasticsearch" = super.buildPythonPackage {
518 name = "elasticsearch-6.3.1";
518 name = "elasticsearch-6.3.1";
519 doCheck = false;
519 doCheck = false;
520 propagatedBuildInputs = [
520 propagatedBuildInputs = [
521 self."urllib3"
521 self."urllib3"
522 ];
522 ];
523 src = fetchurl {
523 src = fetchurl {
524 url = "https://files.pythonhosted.org/packages/9d/ce/c4664e8380e379a9402ecfbaf158e56396da90d520daba21cfa840e0eb71/elasticsearch-6.3.1.tar.gz";
524 url = "https://files.pythonhosted.org/packages/9d/ce/c4664e8380e379a9402ecfbaf158e56396da90d520daba21cfa840e0eb71/elasticsearch-6.3.1.tar.gz";
525 sha256 = "12y93v0yn7a4xmf969239g8gb3l4cdkclfpbk1qc8hx5qkymrnma";
525 sha256 = "12y93v0yn7a4xmf969239g8gb3l4cdkclfpbk1qc8hx5qkymrnma";
526 };
526 };
527 meta = {
527 meta = {
528 license = [ pkgs.lib.licenses.asl20 ];
528 license = [ pkgs.lib.licenses.asl20 ];
529 };
529 };
530 };
530 };
531 "elasticsearch-dsl" = super.buildPythonPackage {
531 "elasticsearch-dsl" = super.buildPythonPackage {
532 name = "elasticsearch-dsl-6.3.1";
532 name = "elasticsearch-dsl-6.3.1";
533 doCheck = false;
533 doCheck = false;
534 propagatedBuildInputs = [
534 propagatedBuildInputs = [
535 self."six"
535 self."six"
536 self."python-dateutil"
536 self."python-dateutil"
537 self."elasticsearch"
537 self."elasticsearch"
538 self."ipaddress"
538 self."ipaddress"
539 ];
539 ];
540 src = fetchurl {
540 src = fetchurl {
541 url = "https://files.pythonhosted.org/packages/4c/0d/1549f50c591db6bb4e66cbcc8d34a6e537c3d89aa426b167c244fd46420a/elasticsearch-dsl-6.3.1.tar.gz";
541 url = "https://files.pythonhosted.org/packages/4c/0d/1549f50c591db6bb4e66cbcc8d34a6e537c3d89aa426b167c244fd46420a/elasticsearch-dsl-6.3.1.tar.gz";
542 sha256 = "1gh8a0shqi105k325hgwb9avrpdjh0mc6mxwfg9ba7g6lssb702z";
542 sha256 = "1gh8a0shqi105k325hgwb9avrpdjh0mc6mxwfg9ba7g6lssb702z";
543 };
543 };
544 meta = {
544 meta = {
545 license = [ pkgs.lib.licenses.asl20 ];
545 license = [ pkgs.lib.licenses.asl20 ];
546 };
546 };
547 };
547 };
548 "elasticsearch1" = super.buildPythonPackage {
548 "elasticsearch1" = super.buildPythonPackage {
549 name = "elasticsearch1-1.10.0";
549 name = "elasticsearch1-1.10.0";
550 doCheck = false;
550 doCheck = false;
551 propagatedBuildInputs = [
551 propagatedBuildInputs = [
552 self."urllib3"
552 self."urllib3"
553 ];
553 ];
554 src = fetchurl {
554 src = fetchurl {
555 url = "https://files.pythonhosted.org/packages/a6/eb/73e75f9681fa71e3157b8ee878534235d57f24ee64f0e77f8d995fb57076/elasticsearch1-1.10.0.tar.gz";
555 url = "https://files.pythonhosted.org/packages/a6/eb/73e75f9681fa71e3157b8ee878534235d57f24ee64f0e77f8d995fb57076/elasticsearch1-1.10.0.tar.gz";
556 sha256 = "0g89444kd5zwql4vbvyrmi2m6l6dcj6ga98j4hqxyyyz6z20aki2";
556 sha256 = "0g89444kd5zwql4vbvyrmi2m6l6dcj6ga98j4hqxyyyz6z20aki2";
557 };
557 };
558 meta = {
558 meta = {
559 license = [ pkgs.lib.licenses.asl20 ];
559 license = [ pkgs.lib.licenses.asl20 ];
560 };
560 };
561 };
561 };
562 "elasticsearch1-dsl" = super.buildPythonPackage {
562 "elasticsearch1-dsl" = super.buildPythonPackage {
563 name = "elasticsearch1-dsl-0.0.12";
563 name = "elasticsearch1-dsl-0.0.12";
564 doCheck = false;
564 doCheck = false;
565 propagatedBuildInputs = [
565 propagatedBuildInputs = [
566 self."six"
566 self."six"
567 self."python-dateutil"
567 self."python-dateutil"
568 self."elasticsearch1"
568 self."elasticsearch1"
569 ];
569 ];
570 src = fetchurl {
570 src = fetchurl {
571 url = "https://files.pythonhosted.org/packages/eb/9d/785342775cb10eddc9b8d7457d618a423b4f0b89d8b2b2d1bc27190d71db/elasticsearch1-dsl-0.0.12.tar.gz";
571 url = "https://files.pythonhosted.org/packages/eb/9d/785342775cb10eddc9b8d7457d618a423b4f0b89d8b2b2d1bc27190d71db/elasticsearch1-dsl-0.0.12.tar.gz";
572 sha256 = "0ig1ly39v93hba0z975wnhbmzwj28w6w1sqlr2g7cn5spp732bhk";
572 sha256 = "0ig1ly39v93hba0z975wnhbmzwj28w6w1sqlr2g7cn5spp732bhk";
573 };
573 };
574 meta = {
574 meta = {
575 license = [ pkgs.lib.licenses.asl20 ];
575 license = [ pkgs.lib.licenses.asl20 ];
576 };
576 };
577 };
577 };
578 "elasticsearch2" = super.buildPythonPackage {
578 "elasticsearch2" = super.buildPythonPackage {
579 name = "elasticsearch2-2.5.1";
579 name = "elasticsearch2-2.5.1";
580 doCheck = false;
580 doCheck = false;
581 propagatedBuildInputs = [
581 propagatedBuildInputs = [
582 self."urllib3"
582 self."urllib3"
583 ];
583 ];
584 src = fetchurl {
584 src = fetchurl {
585 url = "https://files.pythonhosted.org/packages/f6/09/f9b24aa6b1120bea371cd57ef6f57c7694cf16660469456a8be6c2bdbe22/elasticsearch2-2.5.1.tar.gz";
585 url = "https://files.pythonhosted.org/packages/f6/09/f9b24aa6b1120bea371cd57ef6f57c7694cf16660469456a8be6c2bdbe22/elasticsearch2-2.5.1.tar.gz";
586 sha256 = "19k2znpjfyp0hrq73cz7pjyj289040xpsxsm0xhh4jfh6y551g7k";
586 sha256 = "19k2znpjfyp0hrq73cz7pjyj289040xpsxsm0xhh4jfh6y551g7k";
587 };
587 };
588 meta = {
588 meta = {
589 license = [ pkgs.lib.licenses.asl20 ];
589 license = [ pkgs.lib.licenses.asl20 ];
590 };
590 };
591 };
591 };
592 "entrypoints" = super.buildPythonPackage {
592 "entrypoints" = super.buildPythonPackage {
593 name = "entrypoints-0.2.2";
593 name = "entrypoints-0.2.2";
594 doCheck = false;
594 doCheck = false;
595 propagatedBuildInputs = [
595 propagatedBuildInputs = [
596 self."configparser"
596 self."configparser"
597 ];
597 ];
598 src = fetchurl {
598 src = fetchurl {
599 url = "https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d";
599 url = "https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d";
600 sha256 = "0qih72n2myclanplqipqxpgpj9d2yhff1pz5d02zq1cfqyd173w5";
600 sha256 = "0qih72n2myclanplqipqxpgpj9d2yhff1pz5d02zq1cfqyd173w5";
601 };
601 };
602 meta = {
602 meta = {
603 license = [ pkgs.lib.licenses.mit ];
603 license = [ pkgs.lib.licenses.mit ];
604 };
604 };
605 };
605 };
606 "enum34" = super.buildPythonPackage {
606 "enum34" = super.buildPythonPackage {
607 name = "enum34-1.1.10";
607 name = "enum34-1.1.10";
608 doCheck = false;
608 doCheck = false;
609 src = fetchurl {
609 src = fetchurl {
610 url = "https://files.pythonhosted.org/packages/11/c4/2da1f4952ba476677a42f25cd32ab8aaf0e1c0d0e00b89822b835c7e654c/enum34-1.1.10.tar.gz";
610 url = "https://files.pythonhosted.org/packages/11/c4/2da1f4952ba476677a42f25cd32ab8aaf0e1c0d0e00b89822b835c7e654c/enum34-1.1.10.tar.gz";
611 sha256 = "0j7ji699fwswm4vg6w1v07fkbf8dkzdm6gfh88jvs5nqgr3sgrnc";
611 sha256 = "0j7ji699fwswm4vg6w1v07fkbf8dkzdm6gfh88jvs5nqgr3sgrnc";
612 };
612 };
613 meta = {
613 meta = {
614 license = [ pkgs.lib.licenses.bsdOriginal ];
614 license = [ pkgs.lib.licenses.bsdOriginal ];
615 };
615 };
616 };
616 };
617 "formencode" = super.buildPythonPackage {
617 "formencode" = super.buildPythonPackage {
618 name = "formencode-1.2.4";
618 name = "formencode-1.2.4";
619 doCheck = false;
619 doCheck = false;
620 src = fetchurl {
620 src = fetchurl {
621 url = "https://files.pythonhosted.org/packages/8e/59/0174271a6f004512e0201188593e6d319db139d14cb7490e488bbb078015/FormEncode-1.2.4.tar.gz";
621 url = "https://files.pythonhosted.org/packages/8e/59/0174271a6f004512e0201188593e6d319db139d14cb7490e488bbb078015/FormEncode-1.2.4.tar.gz";
622 sha256 = "1fgy04sdy4yry5xcjls3x3xy30dqwj58ycnkndim819jx0788w42";
622 sha256 = "1fgy04sdy4yry5xcjls3x3xy30dqwj58ycnkndim819jx0788w42";
623 };
623 };
624 meta = {
624 meta = {
625 license = [ pkgs.lib.licenses.psfl ];
625 license = [ pkgs.lib.licenses.psfl ];
626 };
626 };
627 };
627 };
628 "funcsigs" = super.buildPythonPackage {
628 "funcsigs" = super.buildPythonPackage {
629 name = "funcsigs-1.0.2";
629 name = "funcsigs-1.0.2";
630 doCheck = false;
630 doCheck = false;
631 src = fetchurl {
631 src = fetchurl {
632 url = "https://files.pythonhosted.org/packages/94/4a/db842e7a0545de1cdb0439bb80e6e42dfe82aaeaadd4072f2263a4fbed23/funcsigs-1.0.2.tar.gz";
632 url = "https://files.pythonhosted.org/packages/94/4a/db842e7a0545de1cdb0439bb80e6e42dfe82aaeaadd4072f2263a4fbed23/funcsigs-1.0.2.tar.gz";
633 sha256 = "0l4g5818ffyfmfs1a924811azhjj8ax9xd1cffr1mzd3ycn0zfx7";
633 sha256 = "0l4g5818ffyfmfs1a924811azhjj8ax9xd1cffr1mzd3ycn0zfx7";
634 };
634 };
635 meta = {
635 meta = {
636 license = [ { fullName = "ASL"; } pkgs.lib.licenses.asl20 ];
636 license = [ { fullName = "ASL"; } pkgs.lib.licenses.asl20 ];
637 };
637 };
638 };
638 };
639 "functools32" = super.buildPythonPackage {
639 "functools32" = super.buildPythonPackage {
640 name = "functools32-3.2.3.post2";
640 name = "functools32-3.2.3.post2";
641 doCheck = false;
641 doCheck = false;
642 src = fetchurl {
642 src = fetchurl {
643 url = "https://files.pythonhosted.org/packages/c5/60/6ac26ad05857c601308d8fb9e87fa36d0ebf889423f47c3502ef034365db/functools32-3.2.3-2.tar.gz";
643 url = "https://files.pythonhosted.org/packages/c5/60/6ac26ad05857c601308d8fb9e87fa36d0ebf889423f47c3502ef034365db/functools32-3.2.3-2.tar.gz";
644 sha256 = "0v8ya0b58x47wp216n1zamimv4iw57cxz3xxhzix52jkw3xks9gn";
644 sha256 = "0v8ya0b58x47wp216n1zamimv4iw57cxz3xxhzix52jkw3xks9gn";
645 };
645 };
646 meta = {
646 meta = {
647 license = [ pkgs.lib.licenses.psfl ];
647 license = [ pkgs.lib.licenses.psfl ];
648 };
648 };
649 };
649 };
650 "future" = super.buildPythonPackage {
650 "future" = super.buildPythonPackage {
651 name = "future-0.14.3";
651 name = "future-0.14.3";
652 doCheck = false;
652 doCheck = false;
653 src = fetchurl {
653 src = fetchurl {
654 url = "https://files.pythonhosted.org/packages/83/80/8ef3a11a15f8eaafafa0937b20c1b3f73527e69ab6b3fa1cf94a5a96aabb/future-0.14.3.tar.gz";
654 url = "https://files.pythonhosted.org/packages/83/80/8ef3a11a15f8eaafafa0937b20c1b3f73527e69ab6b3fa1cf94a5a96aabb/future-0.14.3.tar.gz";
655 sha256 = "1savk7jx7hal032f522c5ajhh8fra6gmnadrj9adv5qxi18pv1b2";
655 sha256 = "1savk7jx7hal032f522c5ajhh8fra6gmnadrj9adv5qxi18pv1b2";
656 };
656 };
657 meta = {
657 meta = {
658 license = [ { fullName = "OSI Approved"; } pkgs.lib.licenses.mit ];
658 license = [ { fullName = "OSI Approved"; } pkgs.lib.licenses.mit ];
659 };
659 };
660 };
660 };
661 "futures" = super.buildPythonPackage {
661 "futures" = super.buildPythonPackage {
662 name = "futures-3.0.2";
662 name = "futures-3.0.2";
663 doCheck = false;
663 doCheck = false;
664 src = fetchurl {
664 src = fetchurl {
665 url = "https://files.pythonhosted.org/packages/f8/e7/fc0fcbeb9193ba2d4de00b065e7fd5aecd0679e93ce95a07322b2b1434f4/futures-3.0.2.tar.gz";
665 url = "https://files.pythonhosted.org/packages/f8/e7/fc0fcbeb9193ba2d4de00b065e7fd5aecd0679e93ce95a07322b2b1434f4/futures-3.0.2.tar.gz";
666 sha256 = "0mz2pbgxbc2nbib1szifi07whjbfs4r02pv2z390z7p410awjgyw";
666 sha256 = "0mz2pbgxbc2nbib1szifi07whjbfs4r02pv2z390z7p410awjgyw";
667 };
667 };
668 meta = {
668 meta = {
669 license = [ pkgs.lib.licenses.bsdOriginal ];
669 license = [ pkgs.lib.licenses.bsdOriginal ];
670 };
670 };
671 };
671 };
672 "gevent" = super.buildPythonPackage {
672 "gevent" = super.buildPythonPackage {
673 name = "gevent-1.5.0";
673 name = "gevent-1.5.0";
674 doCheck = false;
674 doCheck = false;
675 propagatedBuildInputs = [
675 propagatedBuildInputs = [
676 self."greenlet"
676 self."greenlet"
677 ];
677 ];
678 src = fetchurl {
678 src = fetchurl {
679 url = "https://files.pythonhosted.org/packages/5a/79/2c63d385d017b5dd7d70983a463dfd25befae70c824fedb857df6e72eff2/gevent-1.5.0.tar.gz";
679 url = "https://files.pythonhosted.org/packages/5a/79/2c63d385d017b5dd7d70983a463dfd25befae70c824fedb857df6e72eff2/gevent-1.5.0.tar.gz";
680 sha256 = "0aac3d4vhv5n4rsb6cqzq0d1xx9immqz4fmpddw35yxkwdc450dj";
680 sha256 = "0aac3d4vhv5n4rsb6cqzq0d1xx9immqz4fmpddw35yxkwdc450dj";
681 };
681 };
682 meta = {
682 meta = {
683 license = [ pkgs.lib.licenses.mit ];
683 license = [ pkgs.lib.licenses.mit ];
684 };
684 };
685 };
685 };
686 "gnureadline" = super.buildPythonPackage {
686 "gnureadline" = super.buildPythonPackage {
687 name = "gnureadline-6.3.8";
687 name = "gnureadline-6.3.8";
688 doCheck = false;
688 doCheck = false;
689 src = fetchurl {
689 src = fetchurl {
690 url = "https://files.pythonhosted.org/packages/50/64/86085c823cd78f9df9d8e33dce0baa71618016f8860460b82cf6610e1eb3/gnureadline-6.3.8.tar.gz";
690 url = "https://files.pythonhosted.org/packages/50/64/86085c823cd78f9df9d8e33dce0baa71618016f8860460b82cf6610e1eb3/gnureadline-6.3.8.tar.gz";
691 sha256 = "0ddhj98x2nv45iz4aadk4b9m0b1kpsn1xhcbypn5cd556knhiqjq";
691 sha256 = "0ddhj98x2nv45iz4aadk4b9m0b1kpsn1xhcbypn5cd556knhiqjq";
692 };
692 };
693 meta = {
693 meta = {
694 license = [ { fullName = "GNU General Public License v3 (GPLv3)"; } pkgs.lib.licenses.gpl1 ];
694 license = [ { fullName = "GNU General Public License v3 (GPLv3)"; } pkgs.lib.licenses.gpl1 ];
695 };
695 };
696 };
696 };
697 "gprof2dot" = super.buildPythonPackage {
697 "gprof2dot" = super.buildPythonPackage {
698 name = "gprof2dot-2017.9.19";
698 name = "gprof2dot-2017.9.19";
699 doCheck = false;
699 doCheck = false;
700 src = fetchurl {
700 src = fetchurl {
701 url = "https://files.pythonhosted.org/packages/9d/36/f977122502979f3dfb50704979c9ed70e6b620787942b089bf1af15f5aba/gprof2dot-2017.9.19.tar.gz";
701 url = "https://files.pythonhosted.org/packages/9d/36/f977122502979f3dfb50704979c9ed70e6b620787942b089bf1af15f5aba/gprof2dot-2017.9.19.tar.gz";
702 sha256 = "17ih23ld2nzgc3xwgbay911l6lh96jp1zshmskm17n1gg2i7mg6f";
702 sha256 = "17ih23ld2nzgc3xwgbay911l6lh96jp1zshmskm17n1gg2i7mg6f";
703 };
703 };
704 meta = {
704 meta = {
705 license = [ { fullName = "GNU Lesser General Public License v3 or later (LGPLv3+)"; } { fullName = "LGPL"; } ];
705 license = [ { fullName = "GNU Lesser General Public License v3 or later (LGPLv3+)"; } { fullName = "LGPL"; } ];
706 };
706 };
707 };
707 };
708 "greenlet" = super.buildPythonPackage {
708 "greenlet" = super.buildPythonPackage {
709 name = "greenlet-0.4.15";
709 name = "greenlet-0.4.15";
710 doCheck = false;
710 doCheck = false;
711 src = fetchurl {
711 src = fetchurl {
712 url = "https://files.pythonhosted.org/packages/f8/e8/b30ae23b45f69aa3f024b46064c0ac8e5fcb4f22ace0dca8d6f9c8bbe5e7/greenlet-0.4.15.tar.gz";
712 url = "https://files.pythonhosted.org/packages/f8/e8/b30ae23b45f69aa3f024b46064c0ac8e5fcb4f22ace0dca8d6f9c8bbe5e7/greenlet-0.4.15.tar.gz";
713 sha256 = "1g4g1wwc472ds89zmqlpyan3fbnzpa8qm48z3z1y6mlk44z485ll";
713 sha256 = "1g4g1wwc472ds89zmqlpyan3fbnzpa8qm48z3z1y6mlk44z485ll";
714 };
714 };
715 meta = {
715 meta = {
716 license = [ pkgs.lib.licenses.mit ];
716 license = [ pkgs.lib.licenses.mit ];
717 };
717 };
718 };
718 };
719 "gunicorn" = super.buildPythonPackage {
719 "gunicorn" = super.buildPythonPackage {
720 name = "gunicorn-19.9.0";
720 name = "gunicorn-19.9.0";
721 doCheck = false;
721 doCheck = false;
722 src = fetchurl {
722 src = fetchurl {
723 url = "https://files.pythonhosted.org/packages/47/52/68ba8e5e8ba251e54006a49441f7ccabca83b6bef5aedacb4890596c7911/gunicorn-19.9.0.tar.gz";
723 url = "https://files.pythonhosted.org/packages/47/52/68ba8e5e8ba251e54006a49441f7ccabca83b6bef5aedacb4890596c7911/gunicorn-19.9.0.tar.gz";
724 sha256 = "1wzlf4xmn6qjirh5w81l6i6kqjnab1n1qqkh7zsj1yb6gh4n49ps";
724 sha256 = "1wzlf4xmn6qjirh5w81l6i6kqjnab1n1qqkh7zsj1yb6gh4n49ps";
725 };
725 };
726 meta = {
726 meta = {
727 license = [ pkgs.lib.licenses.mit ];
727 license = [ pkgs.lib.licenses.mit ];
728 };
728 };
729 };
729 };
730 "hupper" = super.buildPythonPackage {
730 "hupper" = super.buildPythonPackage {
731 name = "hupper-1.10.2";
731 name = "hupper-1.10.2";
732 doCheck = false;
732 doCheck = false;
733 src = fetchurl {
733 src = fetchurl {
734 url = "https://files.pythonhosted.org/packages/41/24/ea90fef04706e54bd1635c05c50dc9cf87cda543c59303a03e7aa7dda0ce/hupper-1.10.2.tar.gz";
734 url = "https://files.pythonhosted.org/packages/41/24/ea90fef04706e54bd1635c05c50dc9cf87cda543c59303a03e7aa7dda0ce/hupper-1.10.2.tar.gz";
735 sha256 = "0am0p6g5cz6xmcaf04xq8q6dzdd9qz0phj6gcmpsckf2mcyza61q";
735 sha256 = "0am0p6g5cz6xmcaf04xq8q6dzdd9qz0phj6gcmpsckf2mcyza61q";
736 };
736 };
737 meta = {
737 meta = {
738 license = [ pkgs.lib.licenses.mit ];
738 license = [ pkgs.lib.licenses.mit ];
739 };
739 };
740 };
740 };
741 "idna" = super.buildPythonPackage {
741 "idna" = super.buildPythonPackage {
742 name = "idna-2.8";
742 name = "idna-2.8";
743 doCheck = false;
743 doCheck = false;
744 src = fetchurl {
744 src = fetchurl {
745 url = "https://files.pythonhosted.org/packages/ad/13/eb56951b6f7950cadb579ca166e448ba77f9d24efc03edd7e55fa57d04b7/idna-2.8.tar.gz";
745 url = "https://files.pythonhosted.org/packages/ad/13/eb56951b6f7950cadb579ca166e448ba77f9d24efc03edd7e55fa57d04b7/idna-2.8.tar.gz";
746 sha256 = "01rlkigdxg17sf9yar1jl8n18ls59367wqh59hnawlyg53vb6my3";
746 sha256 = "01rlkigdxg17sf9yar1jl8n18ls59367wqh59hnawlyg53vb6my3";
747 };
747 };
748 meta = {
748 meta = {
749 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD-like"; } ];
749 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD-like"; } ];
750 };
750 };
751 };
751 };
752 "importlib-metadata" = super.buildPythonPackage {
752 "importlib-metadata" = super.buildPythonPackage {
753 name = "importlib-metadata-1.6.0";
753 name = "importlib-metadata-1.6.0";
754 doCheck = false;
754 doCheck = false;
755 propagatedBuildInputs = [
755 propagatedBuildInputs = [
756 self."zipp"
756 self."zipp"
757 self."pathlib2"
757 self."pathlib2"
758 self."contextlib2"
758 self."contextlib2"
759 self."configparser"
759 self."configparser"
760 ];
760 ];
761 src = fetchurl {
761 src = fetchurl {
762 url = "https://files.pythonhosted.org/packages/b4/1b/baab42e3cd64c9d5caac25a9d6c054f8324cdc38975a44d600569f1f7158/importlib_metadata-1.6.0.tar.gz";
762 url = "https://files.pythonhosted.org/packages/b4/1b/baab42e3cd64c9d5caac25a9d6c054f8324cdc38975a44d600569f1f7158/importlib_metadata-1.6.0.tar.gz";
763 sha256 = "07icyggasn38yv2swdrd8z6i0plazmc9adavsdkbqqj91j53ll9l";
763 sha256 = "07icyggasn38yv2swdrd8z6i0plazmc9adavsdkbqqj91j53ll9l";
764 };
764 };
765 meta = {
765 meta = {
766 license = [ pkgs.lib.licenses.asl20 ];
766 license = [ pkgs.lib.licenses.asl20 ];
767 };
767 };
768 };
768 };
769 "infrae.cache" = super.buildPythonPackage {
769 "infrae.cache" = super.buildPythonPackage {
770 name = "infrae.cache-1.0.1";
770 name = "infrae.cache-1.0.1";
771 doCheck = false;
771 doCheck = false;
772 propagatedBuildInputs = [
772 propagatedBuildInputs = [
773 self."beaker"
773 self."beaker"
774 self."repoze.lru"
774 self."repoze.lru"
775 ];
775 ];
776 src = fetchurl {
776 src = fetchurl {
777 url = "https://files.pythonhosted.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz";
777 url = "https://files.pythonhosted.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz";
778 sha256 = "1dvqsjn8vw253wz9d1pz17j79mf4bs53dvp2qxck2qdp1am1njw4";
778 sha256 = "1dvqsjn8vw253wz9d1pz17j79mf4bs53dvp2qxck2qdp1am1njw4";
779 };
779 };
780 meta = {
780 meta = {
781 license = [ pkgs.lib.licenses.zpl21 ];
781 license = [ pkgs.lib.licenses.zpl21 ];
782 };
782 };
783 };
783 };
784 "invoke" = super.buildPythonPackage {
784 "invoke" = super.buildPythonPackage {
785 name = "invoke-0.13.0";
785 name = "invoke-0.13.0";
786 doCheck = false;
786 doCheck = false;
787 src = fetchurl {
787 src = fetchurl {
788 url = "https://files.pythonhosted.org/packages/47/bf/d07ef52fa1ac645468858bbac7cb95b246a972a045e821493d17d89c81be/invoke-0.13.0.tar.gz";
788 url = "https://files.pythonhosted.org/packages/47/bf/d07ef52fa1ac645468858bbac7cb95b246a972a045e821493d17d89c81be/invoke-0.13.0.tar.gz";
789 sha256 = "0794vhgxfmkh0vzkkg5cfv1w82g3jc3xr18wim29far9qpx9468s";
789 sha256 = "0794vhgxfmkh0vzkkg5cfv1w82g3jc3xr18wim29far9qpx9468s";
790 };
790 };
791 meta = {
791 meta = {
792 license = [ pkgs.lib.licenses.bsdOriginal ];
792 license = [ pkgs.lib.licenses.bsdOriginal ];
793 };
793 };
794 };
794 };
795 "ipaddress" = super.buildPythonPackage {
795 "ipaddress" = super.buildPythonPackage {
796 name = "ipaddress-1.0.23";
796 name = "ipaddress-1.0.23";
797 doCheck = false;
797 doCheck = false;
798 src = fetchurl {
798 src = fetchurl {
799 url = "https://files.pythonhosted.org/packages/b9/9a/3e9da40ea28b8210dd6504d3fe9fe7e013b62bf45902b458d1cdc3c34ed9/ipaddress-1.0.23.tar.gz";
799 url = "https://files.pythonhosted.org/packages/b9/9a/3e9da40ea28b8210dd6504d3fe9fe7e013b62bf45902b458d1cdc3c34ed9/ipaddress-1.0.23.tar.gz";
800 sha256 = "1qp743h30s04m3cg3yk3fycad930jv17q7dsslj4mfw0jlvf1y5p";
800 sha256 = "1qp743h30s04m3cg3yk3fycad930jv17q7dsslj4mfw0jlvf1y5p";
801 };
801 };
802 meta = {
802 meta = {
803 license = [ pkgs.lib.licenses.psfl ];
803 license = [ pkgs.lib.licenses.psfl ];
804 };
804 };
805 };
805 };
806 "ipdb" = super.buildPythonPackage {
806 "ipdb" = super.buildPythonPackage {
807 name = "ipdb-0.13.2";
807 name = "ipdb-0.13.2";
808 doCheck = false;
808 doCheck = false;
809 propagatedBuildInputs = [
809 propagatedBuildInputs = [
810 self."setuptools"
810 self."setuptools"
811 self."ipython"
811 self."ipython"
812 ];
812 ];
813 src = fetchurl {
813 src = fetchurl {
814 url = "https://files.pythonhosted.org/packages/2c/bb/a3e1a441719ebd75c6dac8170d3ddba884b7ee8a5c0f9aefa7297386627a/ipdb-0.13.2.tar.gz";
814 url = "https://files.pythonhosted.org/packages/2c/bb/a3e1a441719ebd75c6dac8170d3ddba884b7ee8a5c0f9aefa7297386627a/ipdb-0.13.2.tar.gz";
815 sha256 = "0jcd849rx30y3wcgzsqbn06v0yjlzvb9x3076q0yxpycdwm1ryvp";
815 sha256 = "0jcd849rx30y3wcgzsqbn06v0yjlzvb9x3076q0yxpycdwm1ryvp";
816 };
816 };
817 meta = {
817 meta = {
818 license = [ pkgs.lib.licenses.bsdOriginal ];
818 license = [ pkgs.lib.licenses.bsdOriginal ];
819 };
819 };
820 };
820 };
821 "ipython" = super.buildPythonPackage {
821 "ipython" = super.buildPythonPackage {
822 name = "ipython-5.1.0";
822 name = "ipython-5.1.0";
823 doCheck = false;
823 doCheck = false;
824 propagatedBuildInputs = [
824 propagatedBuildInputs = [
825 self."setuptools"
825 self."setuptools"
826 self."decorator"
826 self."decorator"
827 self."pickleshare"
827 self."pickleshare"
828 self."simplegeneric"
828 self."simplegeneric"
829 self."traitlets"
829 self."traitlets"
830 self."prompt-toolkit"
830 self."prompt-toolkit"
831 self."pygments"
831 self."pygments"
832 self."pexpect"
832 self."pexpect"
833 self."backports.shutil-get-terminal-size"
833 self."backports.shutil-get-terminal-size"
834 self."pathlib2"
834 self."pathlib2"
835 self."pexpect"
835 self."pexpect"
836 ];
836 ];
837 src = fetchurl {
837 src = fetchurl {
838 url = "https://files.pythonhosted.org/packages/89/63/a9292f7cd9d0090a0f995e1167f3f17d5889dcbc9a175261719c513b9848/ipython-5.1.0.tar.gz";
838 url = "https://files.pythonhosted.org/packages/89/63/a9292f7cd9d0090a0f995e1167f3f17d5889dcbc9a175261719c513b9848/ipython-5.1.0.tar.gz";
839 sha256 = "0qdrf6aj9kvjczd5chj1my8y2iq09am9l8bb2a1334a52d76kx3y";
839 sha256 = "0qdrf6aj9kvjczd5chj1my8y2iq09am9l8bb2a1334a52d76kx3y";
840 };
840 };
841 meta = {
841 meta = {
842 license = [ pkgs.lib.licenses.bsdOriginal ];
842 license = [ pkgs.lib.licenses.bsdOriginal ];
843 };
843 };
844 };
844 };
845 "ipython-genutils" = super.buildPythonPackage {
845 "ipython-genutils" = super.buildPythonPackage {
846 name = "ipython-genutils-0.2.0";
846 name = "ipython-genutils-0.2.0";
847 doCheck = false;
847 doCheck = false;
848 src = fetchurl {
848 src = fetchurl {
849 url = "https://files.pythonhosted.org/packages/e8/69/fbeffffc05236398ebfcfb512b6d2511c622871dca1746361006da310399/ipython_genutils-0.2.0.tar.gz";
849 url = "https://files.pythonhosted.org/packages/e8/69/fbeffffc05236398ebfcfb512b6d2511c622871dca1746361006da310399/ipython_genutils-0.2.0.tar.gz";
850 sha256 = "1a4bc9y8hnvq6cp08qs4mckgm6i6ajpndp4g496rvvzcfmp12bpb";
850 sha256 = "1a4bc9y8hnvq6cp08qs4mckgm6i6ajpndp4g496rvvzcfmp12bpb";
851 };
851 };
852 meta = {
852 meta = {
853 license = [ pkgs.lib.licenses.bsdOriginal ];
853 license = [ pkgs.lib.licenses.bsdOriginal ];
854 };
854 };
855 };
855 };
856 "iso8601" = super.buildPythonPackage {
856 "iso8601" = super.buildPythonPackage {
857 name = "iso8601-0.1.12";
857 name = "iso8601-0.1.12";
858 doCheck = false;
858 doCheck = false;
859 src = fetchurl {
859 src = fetchurl {
860 url = "https://files.pythonhosted.org/packages/45/13/3db24895497345fb44c4248c08b16da34a9eb02643cea2754b21b5ed08b0/iso8601-0.1.12.tar.gz";
860 url = "https://files.pythonhosted.org/packages/45/13/3db24895497345fb44c4248c08b16da34a9eb02643cea2754b21b5ed08b0/iso8601-0.1.12.tar.gz";
861 sha256 = "10nyvvnrhw2w3p09v1ica4lgj6f4g9j3kkfx17qmraiq3w7b5i29";
861 sha256 = "10nyvvnrhw2w3p09v1ica4lgj6f4g9j3kkfx17qmraiq3w7b5i29";
862 };
862 };
863 meta = {
863 meta = {
864 license = [ pkgs.lib.licenses.mit ];
864 license = [ pkgs.lib.licenses.mit ];
865 };
865 };
866 };
866 };
867 "isodate" = super.buildPythonPackage {
867 "isodate" = super.buildPythonPackage {
868 name = "isodate-0.6.0";
868 name = "isodate-0.6.0";
869 doCheck = false;
869 doCheck = false;
870 propagatedBuildInputs = [
870 propagatedBuildInputs = [
871 self."six"
871 self."six"
872 ];
872 ];
873 src = fetchurl {
873 src = fetchurl {
874 url = "https://files.pythonhosted.org/packages/b1/80/fb8c13a4cd38eb5021dc3741a9e588e4d1de88d895c1910c6fc8a08b7a70/isodate-0.6.0.tar.gz";
874 url = "https://files.pythonhosted.org/packages/b1/80/fb8c13a4cd38eb5021dc3741a9e588e4d1de88d895c1910c6fc8a08b7a70/isodate-0.6.0.tar.gz";
875 sha256 = "1n7jkz68kk5pwni540pr5zdh99bf6ywydk1p5pdrqisrawylldif";
875 sha256 = "1n7jkz68kk5pwni540pr5zdh99bf6ywydk1p5pdrqisrawylldif";
876 };
876 };
877 meta = {
877 meta = {
878 license = [ pkgs.lib.licenses.bsdOriginal ];
878 license = [ pkgs.lib.licenses.bsdOriginal ];
879 };
879 };
880 };
880 };
881 "itsdangerous" = super.buildPythonPackage {
881 "itsdangerous" = super.buildPythonPackage {
882 name = "itsdangerous-1.1.0";
882 name = "itsdangerous-1.1.0";
883 doCheck = false;
883 doCheck = false;
884 src = fetchurl {
884 src = fetchurl {
885 url = "https://files.pythonhosted.org/packages/68/1a/f27de07a8a304ad5fa817bbe383d1238ac4396da447fa11ed937039fa04b/itsdangerous-1.1.0.tar.gz";
885 url = "https://files.pythonhosted.org/packages/68/1a/f27de07a8a304ad5fa817bbe383d1238ac4396da447fa11ed937039fa04b/itsdangerous-1.1.0.tar.gz";
886 sha256 = "068zpbksq5q2z4dckh2k1zbcq43ay74ylqn77rni797j0wyh66rj";
886 sha256 = "068zpbksq5q2z4dckh2k1zbcq43ay74ylqn77rni797j0wyh66rj";
887 };
887 };
888 meta = {
888 meta = {
889 license = [ pkgs.lib.licenses.bsdOriginal ];
889 license = [ pkgs.lib.licenses.bsdOriginal ];
890 };
890 };
891 };
891 };
892 "jinja2" = super.buildPythonPackage {
892 "jinja2" = super.buildPythonPackage {
893 name = "jinja2-2.9.6";
893 name = "jinja2-2.9.6";
894 doCheck = false;
894 doCheck = false;
895 propagatedBuildInputs = [
895 propagatedBuildInputs = [
896 self."markupsafe"
896 self."markupsafe"
897 ];
897 ];
898 src = fetchurl {
898 src = fetchurl {
899 url = "https://files.pythonhosted.org/packages/90/61/f820ff0076a2599dd39406dcb858ecb239438c02ce706c8e91131ab9c7f1/Jinja2-2.9.6.tar.gz";
899 url = "https://files.pythonhosted.org/packages/90/61/f820ff0076a2599dd39406dcb858ecb239438c02ce706c8e91131ab9c7f1/Jinja2-2.9.6.tar.gz";
900 sha256 = "1zzrkywhziqffrzks14kzixz7nd4yh2vc0fb04a68vfd2ai03anx";
900 sha256 = "1zzrkywhziqffrzks14kzixz7nd4yh2vc0fb04a68vfd2ai03anx";
901 };
901 };
902 meta = {
902 meta = {
903 license = [ pkgs.lib.licenses.bsdOriginal ];
903 license = [ pkgs.lib.licenses.bsdOriginal ];
904 };
904 };
905 };
905 };
906 "jsonschema" = super.buildPythonPackage {
906 "jsonschema" = super.buildPythonPackage {
907 name = "jsonschema-2.6.0";
907 name = "jsonschema-2.6.0";
908 doCheck = false;
908 doCheck = false;
909 propagatedBuildInputs = [
909 propagatedBuildInputs = [
910 self."functools32"
910 self."functools32"
911 ];
911 ];
912 src = fetchurl {
912 src = fetchurl {
913 url = "https://files.pythonhosted.org/packages/58/b9/171dbb07e18c6346090a37f03c7e74410a1a56123f847efed59af260a298/jsonschema-2.6.0.tar.gz";
913 url = "https://files.pythonhosted.org/packages/58/b9/171dbb07e18c6346090a37f03c7e74410a1a56123f847efed59af260a298/jsonschema-2.6.0.tar.gz";
914 sha256 = "00kf3zmpp9ya4sydffpifn0j0mzm342a2vzh82p6r0vh10cg7xbg";
914 sha256 = "00kf3zmpp9ya4sydffpifn0j0mzm342a2vzh82p6r0vh10cg7xbg";
915 };
915 };
916 meta = {
916 meta = {
917 license = [ pkgs.lib.licenses.mit ];
917 license = [ pkgs.lib.licenses.mit ];
918 };
918 };
919 };
919 };
920 "jupyter-client" = super.buildPythonPackage {
920 "jupyter-client" = super.buildPythonPackage {
921 name = "jupyter-client-5.0.0";
921 name = "jupyter-client-5.0.0";
922 doCheck = false;
922 doCheck = false;
923 propagatedBuildInputs = [
923 propagatedBuildInputs = [
924 self."traitlets"
924 self."traitlets"
925 self."jupyter-core"
925 self."jupyter-core"
926 self."pyzmq"
926 self."pyzmq"
927 self."python-dateutil"
927 self."python-dateutil"
928 ];
928 ];
929 src = fetchurl {
929 src = fetchurl {
930 url = "https://files.pythonhosted.org/packages/e5/6f/65412ed462202b90134b7e761b0b7e7f949e07a549c1755475333727b3d0/jupyter_client-5.0.0.tar.gz";
930 url = "https://files.pythonhosted.org/packages/e5/6f/65412ed462202b90134b7e761b0b7e7f949e07a549c1755475333727b3d0/jupyter_client-5.0.0.tar.gz";
931 sha256 = "0nxw4rqk4wsjhc87gjqd7pv89cb9dnimcfnmcmp85bmrvv1gjri7";
931 sha256 = "0nxw4rqk4wsjhc87gjqd7pv89cb9dnimcfnmcmp85bmrvv1gjri7";
932 };
932 };
933 meta = {
933 meta = {
934 license = [ pkgs.lib.licenses.bsdOriginal ];
934 license = [ pkgs.lib.licenses.bsdOriginal ];
935 };
935 };
936 };
936 };
937 "jupyter-core" = super.buildPythonPackage {
937 "jupyter-core" = super.buildPythonPackage {
938 name = "jupyter-core-4.5.0";
938 name = "jupyter-core-4.5.0";
939 doCheck = false;
939 doCheck = false;
940 propagatedBuildInputs = [
940 propagatedBuildInputs = [
941 self."traitlets"
941 self."traitlets"
942 ];
942 ];
943 src = fetchurl {
943 src = fetchurl {
944 url = "https://files.pythonhosted.org/packages/4a/de/ff4ca734656d17ebe0450807b59d728f45277e2e7f4b82bc9aae6cb82961/jupyter_core-4.5.0.tar.gz";
944 url = "https://files.pythonhosted.org/packages/4a/de/ff4ca734656d17ebe0450807b59d728f45277e2e7f4b82bc9aae6cb82961/jupyter_core-4.5.0.tar.gz";
945 sha256 = "1xr4pbghwk5hayn5wwnhb7z95380r45p79gf5if5pi1akwg7qvic";
945 sha256 = "1xr4pbghwk5hayn5wwnhb7z95380r45p79gf5if5pi1akwg7qvic";
946 };
946 };
947 meta = {
947 meta = {
948 license = [ pkgs.lib.licenses.bsdOriginal ];
948 license = [ pkgs.lib.licenses.bsdOriginal ];
949 };
949 };
950 };
950 };
951 "kombu" = super.buildPythonPackage {
951 "kombu" = super.buildPythonPackage {
952 name = "kombu-4.6.6";
952 name = "kombu-4.6.6";
953 doCheck = false;
953 doCheck = false;
954 propagatedBuildInputs = [
954 propagatedBuildInputs = [
955 self."amqp"
955 self."amqp"
956 self."importlib-metadata"
956 self."importlib-metadata"
957 ];
957 ];
958 src = fetchurl {
958 src = fetchurl {
959 url = "https://files.pythonhosted.org/packages/20/e6/bc2d9affba6138a1dc143f77fef253e9e08e238fa7c0688d917c09005e96/kombu-4.6.6.tar.gz";
959 url = "https://files.pythonhosted.org/packages/20/e6/bc2d9affba6138a1dc143f77fef253e9e08e238fa7c0688d917c09005e96/kombu-4.6.6.tar.gz";
960 sha256 = "11mxpcy8mg1l35bgbhba70v29bydr2hrhdbdlb4lg98m3m5vaq0p";
960 sha256 = "11mxpcy8mg1l35bgbhba70v29bydr2hrhdbdlb4lg98m3m5vaq0p";
961 };
961 };
962 meta = {
962 meta = {
963 license = [ pkgs.lib.licenses.bsdOriginal ];
963 license = [ pkgs.lib.licenses.bsdOriginal ];
964 };
964 };
965 };
965 };
966 "lxml" = super.buildPythonPackage {
966 "lxml" = super.buildPythonPackage {
967 name = "lxml-4.2.5";
967 name = "lxml-4.2.5";
968 doCheck = false;
968 doCheck = false;
969 src = fetchurl {
969 src = fetchurl {
970 url = "https://files.pythonhosted.org/packages/4b/20/ddf5eb3bd5c57582d2b4652b4bbcf8da301bdfe5d805cb94e805f4d7464d/lxml-4.2.5.tar.gz";
970 url = "https://files.pythonhosted.org/packages/4b/20/ddf5eb3bd5c57582d2b4652b4bbcf8da301bdfe5d805cb94e805f4d7464d/lxml-4.2.5.tar.gz";
971 sha256 = "0zw0y9hs0nflxhl9cs6ipwwh53szi3w2x06wl0k9cylyqac0cwin";
971 sha256 = "0zw0y9hs0nflxhl9cs6ipwwh53szi3w2x06wl0k9cylyqac0cwin";
972 };
972 };
973 meta = {
973 meta = {
974 license = [ pkgs.lib.licenses.bsdOriginal ];
974 license = [ pkgs.lib.licenses.bsdOriginal ];
975 };
975 };
976 };
976 };
977 "mako" = super.buildPythonPackage {
977 "mako" = super.buildPythonPackage {
978 name = "mako-1.1.0";
978 name = "mako-1.1.0";
979 doCheck = false;
979 doCheck = false;
980 propagatedBuildInputs = [
980 propagatedBuildInputs = [
981 self."markupsafe"
981 self."markupsafe"
982 ];
982 ];
983 src = fetchurl {
983 src = fetchurl {
984 url = "https://files.pythonhosted.org/packages/b0/3c/8dcd6883d009f7cae0f3157fb53e9afb05a0d3d33b3db1268ec2e6f4a56b/Mako-1.1.0.tar.gz";
984 url = "https://files.pythonhosted.org/packages/b0/3c/8dcd6883d009f7cae0f3157fb53e9afb05a0d3d33b3db1268ec2e6f4a56b/Mako-1.1.0.tar.gz";
985 sha256 = "0jqa3qfpykyn4fmkn0kh6043sfls7br8i2bsdbccazcvk9cijsd3";
985 sha256 = "0jqa3qfpykyn4fmkn0kh6043sfls7br8i2bsdbccazcvk9cijsd3";
986 };
986 };
987 meta = {
987 meta = {
988 license = [ pkgs.lib.licenses.mit ];
988 license = [ pkgs.lib.licenses.mit ];
989 };
989 };
990 };
990 };
991 "markdown" = super.buildPythonPackage {
991 "markdown" = super.buildPythonPackage {
992 name = "markdown-2.6.11";
992 name = "markdown-2.6.11";
993 doCheck = false;
993 doCheck = false;
994 src = fetchurl {
994 src = fetchurl {
995 url = "https://files.pythonhosted.org/packages/b3/73/fc5c850f44af5889192dff783b7b0d8f3fe8d30b65c8e3f78f8f0265fecf/Markdown-2.6.11.tar.gz";
995 url = "https://files.pythonhosted.org/packages/b3/73/fc5c850f44af5889192dff783b7b0d8f3fe8d30b65c8e3f78f8f0265fecf/Markdown-2.6.11.tar.gz";
996 sha256 = "108g80ryzykh8bj0i7jfp71510wrcixdi771lf2asyghgyf8cmm8";
996 sha256 = "108g80ryzykh8bj0i7jfp71510wrcixdi771lf2asyghgyf8cmm8";
997 };
997 };
998 meta = {
998 meta = {
999 license = [ pkgs.lib.licenses.bsdOriginal ];
999 license = [ pkgs.lib.licenses.bsdOriginal ];
1000 };
1000 };
1001 };
1001 };
1002 "markupsafe" = super.buildPythonPackage {
1002 "markupsafe" = super.buildPythonPackage {
1003 name = "markupsafe-1.1.1";
1003 name = "markupsafe-1.1.1";
1004 doCheck = false;
1004 doCheck = false;
1005 src = fetchurl {
1005 src = fetchurl {
1006 url = "https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz";
1006 url = "https://files.pythonhosted.org/packages/b9/2e/64db92e53b86efccfaea71321f597fa2e1b2bd3853d8ce658568f7a13094/MarkupSafe-1.1.1.tar.gz";
1007 sha256 = "0sqipg4fk7xbixqd8kq6rlkxj664d157bdwbh93farcphf92x1r9";
1007 sha256 = "0sqipg4fk7xbixqd8kq6rlkxj664d157bdwbh93farcphf92x1r9";
1008 };
1008 };
1009 meta = {
1009 meta = {
1010 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd3 ];
1010 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd3 ];
1011 };
1011 };
1012 };
1012 };
1013 "marshmallow" = super.buildPythonPackage {
1013 "marshmallow" = super.buildPythonPackage {
1014 name = "marshmallow-2.18.0";
1014 name = "marshmallow-2.18.0";
1015 doCheck = false;
1015 doCheck = false;
1016 src = fetchurl {
1016 src = fetchurl {
1017 url = "https://files.pythonhosted.org/packages/ad/0b/5799965d1c6d5f608d684e2c0dce8a828e0309a3bfe8327d9418a89f591c/marshmallow-2.18.0.tar.gz";
1017 url = "https://files.pythonhosted.org/packages/ad/0b/5799965d1c6d5f608d684e2c0dce8a828e0309a3bfe8327d9418a89f591c/marshmallow-2.18.0.tar.gz";
1018 sha256 = "1g0aafpjn7yaxq06yndy8c7rs9n42adxkqq1ayhlr869pr06d3lm";
1018 sha256 = "1g0aafpjn7yaxq06yndy8c7rs9n42adxkqq1ayhlr869pr06d3lm";
1019 };
1019 };
1020 meta = {
1020 meta = {
1021 license = [ pkgs.lib.licenses.mit ];
1021 license = [ pkgs.lib.licenses.mit ];
1022 };
1022 };
1023 };
1023 };
1024 "mistune" = super.buildPythonPackage {
1024 "mistune" = super.buildPythonPackage {
1025 name = "mistune-0.8.4";
1025 name = "mistune-0.8.4";
1026 doCheck = false;
1026 doCheck = false;
1027 src = fetchurl {
1027 src = fetchurl {
1028 url = "https://files.pythonhosted.org/packages/2d/a4/509f6e7783ddd35482feda27bc7f72e65b5e7dc910eca4ab2164daf9c577/mistune-0.8.4.tar.gz";
1028 url = "https://files.pythonhosted.org/packages/2d/a4/509f6e7783ddd35482feda27bc7f72e65b5e7dc910eca4ab2164daf9c577/mistune-0.8.4.tar.gz";
1029 sha256 = "0vkmsh0x480rni51lhyvigfdf06b9247z868pk3bal1wnnfl58sr";
1029 sha256 = "0vkmsh0x480rni51lhyvigfdf06b9247z868pk3bal1wnnfl58sr";
1030 };
1030 };
1031 meta = {
1031 meta = {
1032 license = [ pkgs.lib.licenses.bsdOriginal ];
1032 license = [ pkgs.lib.licenses.bsdOriginal ];
1033 };
1033 };
1034 };
1034 };
1035 "mock" = super.buildPythonPackage {
1035 "mock" = super.buildPythonPackage {
1036 name = "mock-3.0.5";
1036 name = "mock-3.0.5";
1037 doCheck = false;
1037 doCheck = false;
1038 propagatedBuildInputs = [
1038 propagatedBuildInputs = [
1039 self."six"
1039 self."six"
1040 self."funcsigs"
1040 self."funcsigs"
1041 ];
1041 ];
1042 src = fetchurl {
1042 src = fetchurl {
1043 url = "https://files.pythonhosted.org/packages/2e/ab/4fe657d78b270aa6a32f027849513b829b41b0f28d9d8d7f8c3d29ea559a/mock-3.0.5.tar.gz";
1043 url = "https://files.pythonhosted.org/packages/2e/ab/4fe657d78b270aa6a32f027849513b829b41b0f28d9d8d7f8c3d29ea559a/mock-3.0.5.tar.gz";
1044 sha256 = "1hrp6j0yrx2xzylfv02qa8kph661m6yq4p0mc8fnimch9j4psrc3";
1044 sha256 = "1hrp6j0yrx2xzylfv02qa8kph661m6yq4p0mc8fnimch9j4psrc3";
1045 };
1045 };
1046 meta = {
1046 meta = {
1047 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "OSI Approved :: BSD License"; } ];
1047 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "OSI Approved :: BSD License"; } ];
1048 };
1048 };
1049 };
1049 };
1050 "more-itertools" = super.buildPythonPackage {
1050 "more-itertools" = super.buildPythonPackage {
1051 name = "more-itertools-5.0.0";
1051 name = "more-itertools-5.0.0";
1052 doCheck = false;
1052 doCheck = false;
1053 propagatedBuildInputs = [
1053 propagatedBuildInputs = [
1054 self."six"
1054 self."six"
1055 ];
1055 ];
1056 src = fetchurl {
1056 src = fetchurl {
1057 url = "https://files.pythonhosted.org/packages/dd/26/30fc0d541d9fdf55faf5ba4b0fd68f81d5bd2447579224820ad525934178/more-itertools-5.0.0.tar.gz";
1057 url = "https://files.pythonhosted.org/packages/dd/26/30fc0d541d9fdf55faf5ba4b0fd68f81d5bd2447579224820ad525934178/more-itertools-5.0.0.tar.gz";
1058 sha256 = "1r12cm6mcdwdzz7d47a6g4l437xsvapdlgyhqay3i2nrlv03da9q";
1058 sha256 = "1r12cm6mcdwdzz7d47a6g4l437xsvapdlgyhqay3i2nrlv03da9q";
1059 };
1059 };
1060 meta = {
1060 meta = {
1061 license = [ pkgs.lib.licenses.mit ];
1061 license = [ pkgs.lib.licenses.mit ];
1062 };
1062 };
1063 };
1063 };
1064 "msgpack-python" = super.buildPythonPackage {
1064 "msgpack-python" = super.buildPythonPackage {
1065 name = "msgpack-python-0.5.6";
1065 name = "msgpack-python-0.5.6";
1066 doCheck = false;
1066 doCheck = false;
1067 src = fetchurl {
1067 src = fetchurl {
1068 url = "https://files.pythonhosted.org/packages/8a/20/6eca772d1a5830336f84aca1d8198e5a3f4715cd1c7fc36d3cc7f7185091/msgpack-python-0.5.6.tar.gz";
1068 url = "https://files.pythonhosted.org/packages/8a/20/6eca772d1a5830336f84aca1d8198e5a3f4715cd1c7fc36d3cc7f7185091/msgpack-python-0.5.6.tar.gz";
1069 sha256 = "16wh8qgybmfh4pjp8vfv78mdlkxfmcasg78lzlnm6nslsfkci31p";
1069 sha256 = "16wh8qgybmfh4pjp8vfv78mdlkxfmcasg78lzlnm6nslsfkci31p";
1070 };
1070 };
1071 meta = {
1071 meta = {
1072 license = [ pkgs.lib.licenses.asl20 ];
1072 license = [ pkgs.lib.licenses.asl20 ];
1073 };
1073 };
1074 };
1074 };
1075 "mysql-python" = super.buildPythonPackage {
1075 "mysql-python" = super.buildPythonPackage {
1076 name = "mysql-python-1.2.5";
1076 name = "mysql-python-1.2.5";
1077 doCheck = false;
1077 doCheck = false;
1078 src = fetchurl {
1078 src = fetchurl {
1079 url = "https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip";
1079 url = "https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip";
1080 sha256 = "0x0c2jg0bb3pp84njaqiic050qkyd7ymwhfvhipnimg58yv40441";
1080 sha256 = "0x0c2jg0bb3pp84njaqiic050qkyd7ymwhfvhipnimg58yv40441";
1081 };
1081 };
1082 meta = {
1082 meta = {
1083 license = [ pkgs.lib.licenses.gpl1 ];
1083 license = [ pkgs.lib.licenses.gpl1 ];
1084 };
1084 };
1085 };
1085 };
1086 "nbconvert" = super.buildPythonPackage {
1086 "nbconvert" = super.buildPythonPackage {
1087 name = "nbconvert-5.3.1";
1087 name = "nbconvert-5.3.1";
1088 doCheck = false;
1088 doCheck = false;
1089 propagatedBuildInputs = [
1089 propagatedBuildInputs = [
1090 self."mistune"
1090 self."mistune"
1091 self."jinja2"
1091 self."jinja2"
1092 self."pygments"
1092 self."pygments"
1093 self."traitlets"
1093 self."traitlets"
1094 self."jupyter-core"
1094 self."jupyter-core"
1095 self."nbformat"
1095 self."nbformat"
1096 self."entrypoints"
1096 self."entrypoints"
1097 self."bleach"
1097 self."bleach"
1098 self."pandocfilters"
1098 self."pandocfilters"
1099 self."testpath"
1099 self."testpath"
1100 ];
1100 ];
1101 src = fetchurl {
1101 src = fetchurl {
1102 url = "https://files.pythonhosted.org/packages/b9/a4/d0a0938ad6f5eeb4dea4e73d255c617ef94b0b2849d51194c9bbdb838412/nbconvert-5.3.1.tar.gz";
1102 url = "https://files.pythonhosted.org/packages/b9/a4/d0a0938ad6f5eeb4dea4e73d255c617ef94b0b2849d51194c9bbdb838412/nbconvert-5.3.1.tar.gz";
1103 sha256 = "1f9dkvpx186xjm4xab0qbph588mncp4vqk3fmxrsnqs43mks9c8j";
1103 sha256 = "1f9dkvpx186xjm4xab0qbph588mncp4vqk3fmxrsnqs43mks9c8j";
1104 };
1104 };
1105 meta = {
1105 meta = {
1106 license = [ pkgs.lib.licenses.bsdOriginal ];
1106 license = [ pkgs.lib.licenses.bsdOriginal ];
1107 };
1107 };
1108 };
1108 };
1109 "nbformat" = super.buildPythonPackage {
1109 "nbformat" = super.buildPythonPackage {
1110 name = "nbformat-4.4.0";
1110 name = "nbformat-4.4.0";
1111 doCheck = false;
1111 doCheck = false;
1112 propagatedBuildInputs = [
1112 propagatedBuildInputs = [
1113 self."ipython-genutils"
1113 self."ipython-genutils"
1114 self."traitlets"
1114 self."traitlets"
1115 self."jsonschema"
1115 self."jsonschema"
1116 self."jupyter-core"
1116 self."jupyter-core"
1117 ];
1117 ];
1118 src = fetchurl {
1118 src = fetchurl {
1119 url = "https://files.pythonhosted.org/packages/6e/0e/160754f7ae3e984863f585a3743b0ed1702043a81245907c8fae2d537155/nbformat-4.4.0.tar.gz";
1119 url = "https://files.pythonhosted.org/packages/6e/0e/160754f7ae3e984863f585a3743b0ed1702043a81245907c8fae2d537155/nbformat-4.4.0.tar.gz";
1120 sha256 = "00nlf08h8yc4q73nphfvfhxrcnilaqanb8z0mdy6nxk0vzq4wjgp";
1120 sha256 = "00nlf08h8yc4q73nphfvfhxrcnilaqanb8z0mdy6nxk0vzq4wjgp";
1121 };
1121 };
1122 meta = {
1122 meta = {
1123 license = [ pkgs.lib.licenses.bsdOriginal ];
1123 license = [ pkgs.lib.licenses.bsdOriginal ];
1124 };
1124 };
1125 };
1125 };
1126 "packaging" = super.buildPythonPackage {
1126 "packaging" = super.buildPythonPackage {
1127 name = "packaging-20.3";
1127 name = "packaging-20.3";
1128 doCheck = false;
1128 doCheck = false;
1129 propagatedBuildInputs = [
1129 propagatedBuildInputs = [
1130 self."pyparsing"
1130 self."pyparsing"
1131 self."six"
1131 self."six"
1132 ];
1132 ];
1133 src = fetchurl {
1133 src = fetchurl {
1134 url = "https://files.pythonhosted.org/packages/65/37/83e3f492eb52d771e2820e88105f605335553fe10422cba9d256faeb1702/packaging-20.3.tar.gz";
1134 url = "https://files.pythonhosted.org/packages/65/37/83e3f492eb52d771e2820e88105f605335553fe10422cba9d256faeb1702/packaging-20.3.tar.gz";
1135 sha256 = "18xpablq278janh03bai9xd4kz9b0yfp6vflazn725ns9x3jna9w";
1135 sha256 = "18xpablq278janh03bai9xd4kz9b0yfp6vflazn725ns9x3jna9w";
1136 };
1136 };
1137 meta = {
1137 meta = {
1138 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ];
1138 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "BSD or Apache License, Version 2.0"; } pkgs.lib.licenses.asl20 ];
1139 };
1139 };
1140 };
1140 };
1141 "pandocfilters" = super.buildPythonPackage {
1141 "pandocfilters" = super.buildPythonPackage {
1142 name = "pandocfilters-1.4.2";
1142 name = "pandocfilters-1.4.2";
1143 doCheck = false;
1143 doCheck = false;
1144 src = fetchurl {
1144 src = fetchurl {
1145 url = "https://files.pythonhosted.org/packages/4c/ea/236e2584af67bb6df960832731a6e5325fd4441de001767da328c33368ce/pandocfilters-1.4.2.tar.gz";
1145 url = "https://files.pythonhosted.org/packages/4c/ea/236e2584af67bb6df960832731a6e5325fd4441de001767da328c33368ce/pandocfilters-1.4.2.tar.gz";
1146 sha256 = "1a8d9b7s48gmq9zj0pmbyv2sivn5i7m6mybgpkk4jm5vd7hp1pdk";
1146 sha256 = "1a8d9b7s48gmq9zj0pmbyv2sivn5i7m6mybgpkk4jm5vd7hp1pdk";
1147 };
1147 };
1148 meta = {
1148 meta = {
1149 license = [ pkgs.lib.licenses.bsdOriginal ];
1149 license = [ pkgs.lib.licenses.bsdOriginal ];
1150 };
1150 };
1151 };
1151 };
1152 "paste" = super.buildPythonPackage {
1152 "paste" = super.buildPythonPackage {
1153 name = "paste-3.4.0";
1153 name = "paste-3.4.0";
1154 doCheck = false;
1154 doCheck = false;
1155 propagatedBuildInputs = [
1155 propagatedBuildInputs = [
1156 self."six"
1156 self."six"
1157 ];
1157 ];
1158 src = fetchurl {
1158 src = fetchurl {
1159 url = "https://files.pythonhosted.org/packages/79/4a/45821b71dd40000507549afd1491546afad8279c0a87527c88776a794158/Paste-3.4.0.tar.gz";
1159 url = "https://files.pythonhosted.org/packages/79/4a/45821b71dd40000507549afd1491546afad8279c0a87527c88776a794158/Paste-3.4.0.tar.gz";
1160 sha256 = "16sichvhyci1gaarkjs35mai8vphh7b244qm14hj1isw38nx4c03";
1160 sha256 = "16sichvhyci1gaarkjs35mai8vphh7b244qm14hj1isw38nx4c03";
1161 };
1161 };
1162 meta = {
1162 meta = {
1163 license = [ pkgs.lib.licenses.mit ];
1163 license = [ pkgs.lib.licenses.mit ];
1164 };
1164 };
1165 };
1165 };
1166 "pastedeploy" = super.buildPythonPackage {
1166 "pastedeploy" = super.buildPythonPackage {
1167 name = "pastedeploy-2.1.0";
1167 name = "pastedeploy-2.1.0";
1168 doCheck = false;
1168 doCheck = false;
1169 src = fetchurl {
1169 src = fetchurl {
1170 url = "https://files.pythonhosted.org/packages/c4/e9/972a1c20318b3ae9edcab11a6cef64308fbae5d0d45ab52c6f8b2b8f35b8/PasteDeploy-2.1.0.tar.gz";
1170 url = "https://files.pythonhosted.org/packages/c4/e9/972a1c20318b3ae9edcab11a6cef64308fbae5d0d45ab52c6f8b2b8f35b8/PasteDeploy-2.1.0.tar.gz";
1171 sha256 = "16qsq5y6mryslmbp5pn35x4z8z3ndp5rpgl42h226879nrw9hmg7";
1171 sha256 = "16qsq5y6mryslmbp5pn35x4z8z3ndp5rpgl42h226879nrw9hmg7";
1172 };
1172 };
1173 meta = {
1173 meta = {
1174 license = [ pkgs.lib.licenses.mit ];
1174 license = [ pkgs.lib.licenses.mit ];
1175 };
1175 };
1176 };
1176 };
1177 "pastescript" = super.buildPythonPackage {
1177 "pastescript" = super.buildPythonPackage {
1178 name = "pastescript-3.2.0";
1178 name = "pastescript-3.2.0";
1179 doCheck = false;
1179 doCheck = false;
1180 propagatedBuildInputs = [
1180 propagatedBuildInputs = [
1181 self."paste"
1181 self."paste"
1182 self."pastedeploy"
1182 self."pastedeploy"
1183 self."six"
1183 self."six"
1184 ];
1184 ];
1185 src = fetchurl {
1185 src = fetchurl {
1186 url = "https://files.pythonhosted.org/packages/ff/47/45c6f5a3cb8f5abf786fea98dbb8d02400a55768a9b623afb7df12346c61/PasteScript-3.2.0.tar.gz";
1186 url = "https://files.pythonhosted.org/packages/ff/47/45c6f5a3cb8f5abf786fea98dbb8d02400a55768a9b623afb7df12346c61/PasteScript-3.2.0.tar.gz";
1187 sha256 = "1b3jq7xh383nvrrlblk05m37345bv97xrhx77wshllba3h7mq3wv";
1187 sha256 = "1b3jq7xh383nvrrlblk05m37345bv97xrhx77wshllba3h7mq3wv";
1188 };
1188 };
1189 meta = {
1189 meta = {
1190 license = [ pkgs.lib.licenses.mit ];
1190 license = [ pkgs.lib.licenses.mit ];
1191 };
1191 };
1192 };
1192 };
1193 "pathlib2" = super.buildPythonPackage {
1193 "pathlib2" = super.buildPythonPackage {
1194 name = "pathlib2-2.3.5";
1194 name = "pathlib2-2.3.5";
1195 doCheck = false;
1195 doCheck = false;
1196 propagatedBuildInputs = [
1196 propagatedBuildInputs = [
1197 self."six"
1197 self."six"
1198 self."scandir"
1198 self."scandir"
1199 ];
1199 ];
1200 src = fetchurl {
1200 src = fetchurl {
1201 url = "https://files.pythonhosted.org/packages/94/d8/65c86584e7e97ef824a1845c72bbe95d79f5b306364fa778a3c3e401b309/pathlib2-2.3.5.tar.gz";
1201 url = "https://files.pythonhosted.org/packages/94/d8/65c86584e7e97ef824a1845c72bbe95d79f5b306364fa778a3c3e401b309/pathlib2-2.3.5.tar.gz";
1202 sha256 = "0s4qa8c082fdkb17izh4mfgwrjd1n5pya18wvrbwqdvvb5xs9nbc";
1202 sha256 = "0s4qa8c082fdkb17izh4mfgwrjd1n5pya18wvrbwqdvvb5xs9nbc";
1203 };
1203 };
1204 meta = {
1204 meta = {
1205 license = [ pkgs.lib.licenses.mit ];
1205 license = [ pkgs.lib.licenses.mit ];
1206 };
1206 };
1207 };
1207 };
1208 "peppercorn" = super.buildPythonPackage {
1208 "peppercorn" = super.buildPythonPackage {
1209 name = "peppercorn-0.6";
1209 name = "peppercorn-0.6";
1210 doCheck = false;
1210 doCheck = false;
1211 src = fetchurl {
1211 src = fetchurl {
1212 url = "https://files.pythonhosted.org/packages/e4/77/93085de7108cdf1a0b092ff443872a8f9442c736d7ddebdf2f27627935f4/peppercorn-0.6.tar.gz";
1212 url = "https://files.pythonhosted.org/packages/e4/77/93085de7108cdf1a0b092ff443872a8f9442c736d7ddebdf2f27627935f4/peppercorn-0.6.tar.gz";
1213 sha256 = "1ip4bfwcpwkq9hz2dai14k2cyabvwrnvcvrcmzxmqm04g8fnimwn";
1213 sha256 = "1ip4bfwcpwkq9hz2dai14k2cyabvwrnvcvrcmzxmqm04g8fnimwn";
1214 };
1214 };
1215 meta = {
1215 meta = {
1216 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1216 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1217 };
1217 };
1218 };
1218 };
1219 "pexpect" = super.buildPythonPackage {
1219 "pexpect" = super.buildPythonPackage {
1220 name = "pexpect-4.8.0";
1220 name = "pexpect-4.8.0";
1221 doCheck = false;
1221 doCheck = false;
1222 propagatedBuildInputs = [
1222 propagatedBuildInputs = [
1223 self."ptyprocess"
1223 self."ptyprocess"
1224 ];
1224 ];
1225 src = fetchurl {
1225 src = fetchurl {
1226 url = "https://files.pythonhosted.org/packages/e5/9b/ff402e0e930e70467a7178abb7c128709a30dfb22d8777c043e501bc1b10/pexpect-4.8.0.tar.gz";
1226 url = "https://files.pythonhosted.org/packages/e5/9b/ff402e0e930e70467a7178abb7c128709a30dfb22d8777c043e501bc1b10/pexpect-4.8.0.tar.gz";
1227 sha256 = "032cg337h8awydgypz6f4wx848lw8dyrj4zy988x0lyib4ws8rgw";
1227 sha256 = "032cg337h8awydgypz6f4wx848lw8dyrj4zy988x0lyib4ws8rgw";
1228 };
1228 };
1229 meta = {
1229 meta = {
1230 license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
1230 license = [ pkgs.lib.licenses.isc { fullName = "ISC License (ISCL)"; } ];
1231 };
1231 };
1232 };
1232 };
1233 "pickleshare" = super.buildPythonPackage {
1233 "pickleshare" = super.buildPythonPackage {
1234 name = "pickleshare-0.7.5";
1234 name = "pickleshare-0.7.5";
1235 doCheck = false;
1235 doCheck = false;
1236 propagatedBuildInputs = [
1236 propagatedBuildInputs = [
1237 self."pathlib2"
1237 self."pathlib2"
1238 ];
1238 ];
1239 src = fetchurl {
1239 src = fetchurl {
1240 url = "https://files.pythonhosted.org/packages/d8/b6/df3c1c9b616e9c0edbc4fbab6ddd09df9535849c64ba51fcb6531c32d4d8/pickleshare-0.7.5.tar.gz";
1240 url = "https://files.pythonhosted.org/packages/d8/b6/df3c1c9b616e9c0edbc4fbab6ddd09df9535849c64ba51fcb6531c32d4d8/pickleshare-0.7.5.tar.gz";
1241 sha256 = "1jmghg3c53yp1i8cm6pcrm280ayi8621rwyav9fac7awjr3kss47";
1241 sha256 = "1jmghg3c53yp1i8cm6pcrm280ayi8621rwyav9fac7awjr3kss47";
1242 };
1242 };
1243 meta = {
1243 meta = {
1244 license = [ pkgs.lib.licenses.mit ];
1244 license = [ pkgs.lib.licenses.mit ];
1245 };
1245 };
1246 };
1246 };
1247 "plaster" = super.buildPythonPackage {
1247 "plaster" = super.buildPythonPackage {
1248 name = "plaster-1.0";
1248 name = "plaster-1.0";
1249 doCheck = false;
1249 doCheck = false;
1250 propagatedBuildInputs = [
1250 propagatedBuildInputs = [
1251 self."setuptools"
1251 self."setuptools"
1252 ];
1252 ];
1253 src = fetchurl {
1253 src = fetchurl {
1254 url = "https://files.pythonhosted.org/packages/37/e1/56d04382d718d32751017d32f351214384e529b794084eee20bb52405563/plaster-1.0.tar.gz";
1254 url = "https://files.pythonhosted.org/packages/37/e1/56d04382d718d32751017d32f351214384e529b794084eee20bb52405563/plaster-1.0.tar.gz";
1255 sha256 = "1hy8k0nv2mxq94y5aysk6hjk9ryb4bsd13g83m60hcyzxz3wflc3";
1255 sha256 = "1hy8k0nv2mxq94y5aysk6hjk9ryb4bsd13g83m60hcyzxz3wflc3";
1256 };
1256 };
1257 meta = {
1257 meta = {
1258 license = [ pkgs.lib.licenses.mit ];
1258 license = [ pkgs.lib.licenses.mit ];
1259 };
1259 };
1260 };
1260 };
1261 "plaster-pastedeploy" = super.buildPythonPackage {
1261 "plaster-pastedeploy" = super.buildPythonPackage {
1262 name = "plaster-pastedeploy-0.7";
1262 name = "plaster-pastedeploy-0.7";
1263 doCheck = false;
1263 doCheck = false;
1264 propagatedBuildInputs = [
1264 propagatedBuildInputs = [
1265 self."pastedeploy"
1265 self."pastedeploy"
1266 self."plaster"
1266 self."plaster"
1267 ];
1267 ];
1268 src = fetchurl {
1268 src = fetchurl {
1269 url = "https://files.pythonhosted.org/packages/99/69/2d3bc33091249266a1bd3cf24499e40ab31d54dffb4a7d76fe647950b98c/plaster_pastedeploy-0.7.tar.gz";
1269 url = "https://files.pythonhosted.org/packages/99/69/2d3bc33091249266a1bd3cf24499e40ab31d54dffb4a7d76fe647950b98c/plaster_pastedeploy-0.7.tar.gz";
1270 sha256 = "1zg7gcsvc1kzay1ry5p699rg2qavfsxqwl17mqxzr0gzw6j9679r";
1270 sha256 = "1zg7gcsvc1kzay1ry5p699rg2qavfsxqwl17mqxzr0gzw6j9679r";
1271 };
1271 };
1272 meta = {
1272 meta = {
1273 license = [ pkgs.lib.licenses.mit ];
1273 license = [ pkgs.lib.licenses.mit ];
1274 };
1274 };
1275 };
1275 };
1276 "pluggy" = super.buildPythonPackage {
1276 "pluggy" = super.buildPythonPackage {
1277 name = "pluggy-0.13.1";
1277 name = "pluggy-0.13.1";
1278 doCheck = false;
1278 doCheck = false;
1279 propagatedBuildInputs = [
1279 propagatedBuildInputs = [
1280 self."importlib-metadata"
1280 self."importlib-metadata"
1281 ];
1281 ];
1282 src = fetchurl {
1282 src = fetchurl {
1283 url = "https://files.pythonhosted.org/packages/f8/04/7a8542bed4b16a65c2714bf76cf5a0b026157da7f75e87cc88774aa10b14/pluggy-0.13.1.tar.gz";
1283 url = "https://files.pythonhosted.org/packages/f8/04/7a8542bed4b16a65c2714bf76cf5a0b026157da7f75e87cc88774aa10b14/pluggy-0.13.1.tar.gz";
1284 sha256 = "1c35qyhvy27q9ih9n899f3h4sdnpgq027dbiilly2qb5cvgarchm";
1284 sha256 = "1c35qyhvy27q9ih9n899f3h4sdnpgq027dbiilly2qb5cvgarchm";
1285 };
1285 };
1286 meta = {
1286 meta = {
1287 license = [ pkgs.lib.licenses.mit ];
1287 license = [ pkgs.lib.licenses.mit ];
1288 };
1288 };
1289 };
1289 };
1290 "premailer" = super.buildPythonPackage {
1290 "premailer" = super.buildPythonPackage {
1291 name = "premailer-3.6.1";
1291 name = "premailer-3.6.1";
1292 doCheck = false;
1292 doCheck = false;
1293 propagatedBuildInputs = [
1293 propagatedBuildInputs = [
1294 self."lxml"
1294 self."lxml"
1295 self."cssselect"
1295 self."cssselect"
1296 self."cssutils"
1296 self."cssutils"
1297 self."requests"
1297 self."requests"
1298 self."cachetools"
1298 self."cachetools"
1299 ];
1299 ];
1300 src = fetchurl {
1300 src = fetchurl {
1301 url = "https://files.pythonhosted.org/packages/62/da/2f43cdf9d3d79c80c4856a12389a1f257d65fe9ccc44bc6b4383c8a18e33/premailer-3.6.1.tar.gz";
1301 url = "https://files.pythonhosted.org/packages/62/da/2f43cdf9d3d79c80c4856a12389a1f257d65fe9ccc44bc6b4383c8a18e33/premailer-3.6.1.tar.gz";
1302 sha256 = "08pshx7a110k4ll20x0xhpvyn3kkipkrbgxjjn7ncdxs54ihdhgw";
1302 sha256 = "08pshx7a110k4ll20x0xhpvyn3kkipkrbgxjjn7ncdxs54ihdhgw";
1303 };
1303 };
1304 meta = {
1304 meta = {
1305 license = [ pkgs.lib.licenses.psfl { fullName = "Python"; } ];
1305 license = [ pkgs.lib.licenses.psfl { fullName = "Python"; } ];
1306 };
1306 };
1307 };
1307 };
1308 "prompt-toolkit" = super.buildPythonPackage {
1308 "prompt-toolkit" = super.buildPythonPackage {
1309 name = "prompt-toolkit-1.0.18";
1309 name = "prompt-toolkit-1.0.18";
1310 doCheck = false;
1310 doCheck = false;
1311 propagatedBuildInputs = [
1311 propagatedBuildInputs = [
1312 self."six"
1312 self."six"
1313 self."wcwidth"
1313 self."wcwidth"
1314 ];
1314 ];
1315 src = fetchurl {
1315 src = fetchurl {
1316 url = "https://files.pythonhosted.org/packages/c5/64/c170e5b1913b540bf0c8ab7676b21fdd1d25b65ddeb10025c6ca43cccd4c/prompt_toolkit-1.0.18.tar.gz";
1316 url = "https://files.pythonhosted.org/packages/c5/64/c170e5b1913b540bf0c8ab7676b21fdd1d25b65ddeb10025c6ca43cccd4c/prompt_toolkit-1.0.18.tar.gz";
1317 sha256 = "09h1153wgr5x2ny7ds0w2m81n3bb9j8hjb8sjfnrg506r01clkyx";
1317 sha256 = "09h1153wgr5x2ny7ds0w2m81n3bb9j8hjb8sjfnrg506r01clkyx";
1318 };
1318 };
1319 meta = {
1319 meta = {
1320 license = [ pkgs.lib.licenses.bsdOriginal ];
1320 license = [ pkgs.lib.licenses.bsdOriginal ];
1321 };
1321 };
1322 };
1322 };
1323 "psutil" = super.buildPythonPackage {
1323 "psutil" = super.buildPythonPackage {
1324 name = "psutil-5.7.0";
1324 name = "psutil-5.7.0";
1325 doCheck = false;
1325 doCheck = false;
1326 src = fetchurl {
1326 src = fetchurl {
1327 url = "https://files.pythonhosted.org/packages/c4/b8/3512f0e93e0db23a71d82485ba256071ebef99b227351f0f5540f744af41/psutil-5.7.0.tar.gz";
1327 url = "https://files.pythonhosted.org/packages/c4/b8/3512f0e93e0db23a71d82485ba256071ebef99b227351f0f5540f744af41/psutil-5.7.0.tar.gz";
1328 sha256 = "03jykdi3dgf1cdal9bv4fq9zjvzj9l9bs99gi5ar81sdl5nc2pk8";
1328 sha256 = "03jykdi3dgf1cdal9bv4fq9zjvzj9l9bs99gi5ar81sdl5nc2pk8";
1329 };
1329 };
1330 meta = {
1330 meta = {
1331 license = [ pkgs.lib.licenses.bsdOriginal ];
1331 license = [ pkgs.lib.licenses.bsdOriginal ];
1332 };
1332 };
1333 };
1333 };
1334 "psycopg2" = super.buildPythonPackage {
1334 "psycopg2" = super.buildPythonPackage {
1335 name = "psycopg2-2.8.4";
1335 name = "psycopg2-2.8.4";
1336 doCheck = false;
1336 doCheck = false;
1337 src = fetchurl {
1337 src = fetchurl {
1338 url = "https://files.pythonhosted.org/packages/84/d7/6a93c99b5ba4d4d22daa3928b983cec66df4536ca50b22ce5dcac65e4e71/psycopg2-2.8.4.tar.gz";
1338 url = "https://files.pythonhosted.org/packages/84/d7/6a93c99b5ba4d4d22daa3928b983cec66df4536ca50b22ce5dcac65e4e71/psycopg2-2.8.4.tar.gz";
1339 sha256 = "1djvh98pi4hjd8rxbq8qzc63bg8v78k33yg6pl99wak61b6fb67q";
1339 sha256 = "1djvh98pi4hjd8rxbq8qzc63bg8v78k33yg6pl99wak61b6fb67q";
1340 };
1340 };
1341 meta = {
1341 meta = {
1342 license = [ pkgs.lib.licenses.zpl21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
1342 license = [ pkgs.lib.licenses.zpl21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
1343 };
1343 };
1344 };
1344 };
1345 "ptyprocess" = super.buildPythonPackage {
1345 "ptyprocess" = super.buildPythonPackage {
1346 name = "ptyprocess-0.6.0";
1346 name = "ptyprocess-0.6.0";
1347 doCheck = false;
1347 doCheck = false;
1348 src = fetchurl {
1348 src = fetchurl {
1349 url = "https://files.pythonhosted.org/packages/7d/2d/e4b8733cf79b7309d84c9081a4ab558c89d8c89da5961bf4ddb050ca1ce0/ptyprocess-0.6.0.tar.gz";
1349 url = "https://files.pythonhosted.org/packages/7d/2d/e4b8733cf79b7309d84c9081a4ab558c89d8c89da5961bf4ddb050ca1ce0/ptyprocess-0.6.0.tar.gz";
1350 sha256 = "1h4lcd3w5nrxnsk436ar7fwkiy5rfn5wj2xwy9l0r4mdqnf2jgwj";
1350 sha256 = "1h4lcd3w5nrxnsk436ar7fwkiy5rfn5wj2xwy9l0r4mdqnf2jgwj";
1351 };
1351 };
1352 meta = {
1352 meta = {
1353 license = [ ];
1353 license = [ ];
1354 };
1354 };
1355 };
1355 };
1356 "py" = super.buildPythonPackage {
1356 "py" = super.buildPythonPackage {
1357 name = "py-1.8.0";
1357 name = "py-1.8.0";
1358 doCheck = false;
1358 doCheck = false;
1359 src = fetchurl {
1359 src = fetchurl {
1360 url = "https://files.pythonhosted.org/packages/f1/5a/87ca5909f400a2de1561f1648883af74345fe96349f34f737cdfc94eba8c/py-1.8.0.tar.gz";
1360 url = "https://files.pythonhosted.org/packages/f1/5a/87ca5909f400a2de1561f1648883af74345fe96349f34f737cdfc94eba8c/py-1.8.0.tar.gz";
1361 sha256 = "0lsy1gajva083pzc7csj1cvbmminb7b4l6a0prdzyb3fd829nqyw";
1361 sha256 = "0lsy1gajva083pzc7csj1cvbmminb7b4l6a0prdzyb3fd829nqyw";
1362 };
1362 };
1363 meta = {
1363 meta = {
1364 license = [ pkgs.lib.licenses.mit ];
1364 license = [ pkgs.lib.licenses.mit ];
1365 };
1365 };
1366 };
1366 };
1367 "py-bcrypt" = super.buildPythonPackage {
1367 "py-bcrypt" = super.buildPythonPackage {
1368 name = "py-bcrypt-0.4";
1368 name = "py-bcrypt-0.4";
1369 doCheck = false;
1369 doCheck = false;
1370 src = fetchurl {
1370 src = fetchurl {
1371 url = "https://files.pythonhosted.org/packages/68/b1/1c3068c5c4d2e35c48b38dcc865301ebfdf45f54507086ac65ced1fd3b3d/py-bcrypt-0.4.tar.gz";
1371 url = "https://files.pythonhosted.org/packages/68/b1/1c3068c5c4d2e35c48b38dcc865301ebfdf45f54507086ac65ced1fd3b3d/py-bcrypt-0.4.tar.gz";
1372 sha256 = "0y6smdggwi5s72v6p1nn53dg6w05hna3d264cq6kas0lap73p8az";
1372 sha256 = "0y6smdggwi5s72v6p1nn53dg6w05hna3d264cq6kas0lap73p8az";
1373 };
1373 };
1374 meta = {
1374 meta = {
1375 license = [ pkgs.lib.licenses.bsdOriginal ];
1375 license = [ pkgs.lib.licenses.bsdOriginal ];
1376 };
1376 };
1377 };
1377 };
1378 "py-gfm" = super.buildPythonPackage {
1378 "py-gfm" = super.buildPythonPackage {
1379 name = "py-gfm-0.1.4";
1379 name = "py-gfm-0.1.4";
1380 doCheck = false;
1380 doCheck = false;
1381 propagatedBuildInputs = [
1381 propagatedBuildInputs = [
1382 self."setuptools"
1382 self."setuptools"
1383 self."markdown"
1383 self."markdown"
1384 ];
1384 ];
1385 src = fetchurl {
1385 src = fetchurl {
1386 url = "https://files.pythonhosted.org/packages/06/ee/004a03a1d92bb386dae44f6dd087db541bc5093374f1637d4d4ae5596cc2/py-gfm-0.1.4.tar.gz";
1386 url = "https://files.pythonhosted.org/packages/06/ee/004a03a1d92bb386dae44f6dd087db541bc5093374f1637d4d4ae5596cc2/py-gfm-0.1.4.tar.gz";
1387 sha256 = "0zip06g2isivx8fzgqd4n9qzsa22c25jas1rsb7m2rnjg72m0rzg";
1387 sha256 = "0zip06g2isivx8fzgqd4n9qzsa22c25jas1rsb7m2rnjg72m0rzg";
1388 };
1388 };
1389 meta = {
1389 meta = {
1390 license = [ pkgs.lib.licenses.bsdOriginal ];
1390 license = [ pkgs.lib.licenses.bsdOriginal ];
1391 };
1391 };
1392 };
1392 };
1393 "pyasn1" = super.buildPythonPackage {
1393 "pyasn1" = super.buildPythonPackage {
1394 name = "pyasn1-0.4.8";
1394 name = "pyasn1-0.4.8";
1395 doCheck = false;
1395 doCheck = false;
1396 src = fetchurl {
1396 src = fetchurl {
1397 url = "https://files.pythonhosted.org/packages/a4/db/fffec68299e6d7bad3d504147f9094830b704527a7fc098b721d38cc7fa7/pyasn1-0.4.8.tar.gz";
1397 url = "https://files.pythonhosted.org/packages/a4/db/fffec68299e6d7bad3d504147f9094830b704527a7fc098b721d38cc7fa7/pyasn1-0.4.8.tar.gz";
1398 sha256 = "1fnhbi3rmk47l9851gbik0flfr64vs5j0hbqx24cafjap6gprxxf";
1398 sha256 = "1fnhbi3rmk47l9851gbik0flfr64vs5j0hbqx24cafjap6gprxxf";
1399 };
1399 };
1400 meta = {
1400 meta = {
1401 license = [ pkgs.lib.licenses.bsdOriginal ];
1401 license = [ pkgs.lib.licenses.bsdOriginal ];
1402 };
1402 };
1403 };
1403 };
1404 "pyasn1-modules" = super.buildPythonPackage {
1404 "pyasn1-modules" = super.buildPythonPackage {
1405 name = "pyasn1-modules-0.2.6";
1405 name = "pyasn1-modules-0.2.6";
1406 doCheck = false;
1406 doCheck = false;
1407 propagatedBuildInputs = [
1407 propagatedBuildInputs = [
1408 self."pyasn1"
1408 self."pyasn1"
1409 ];
1409 ];
1410 src = fetchurl {
1410 src = fetchurl {
1411 url = "https://files.pythonhosted.org/packages/f1/a9/a1ef72a0e43feff643cf0130a08123dea76205e7a0dda37e3efb5f054a31/pyasn1-modules-0.2.6.tar.gz";
1411 url = "https://files.pythonhosted.org/packages/f1/a9/a1ef72a0e43feff643cf0130a08123dea76205e7a0dda37e3efb5f054a31/pyasn1-modules-0.2.6.tar.gz";
1412 sha256 = "08hph9j1r018drnrny29l7dl2q0cin78csswrhwrh8jmq61pmha3";
1412 sha256 = "08hph9j1r018drnrny29l7dl2q0cin78csswrhwrh8jmq61pmha3";
1413 };
1413 };
1414 meta = {
1414 meta = {
1415 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ];
1415 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ];
1416 };
1416 };
1417 };
1417 };
1418 "pycparser" = super.buildPythonPackage {
1418 "pycparser" = super.buildPythonPackage {
1419 name = "pycparser-2.20";
1419 name = "pycparser-2.20";
1420 doCheck = false;
1420 doCheck = false;
1421 src = fetchurl {
1421 src = fetchurl {
1422 url = "https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz";
1422 url = "https://files.pythonhosted.org/packages/0f/86/e19659527668d70be91d0369aeaa055b4eb396b0f387a4f92293a20035bd/pycparser-2.20.tar.gz";
1423 sha256 = "1w0m3xvlrzq4lkbvd1ngfm8mdw64r1yxy6n7djlw6qj5d0km6ird";
1423 sha256 = "1w0m3xvlrzq4lkbvd1ngfm8mdw64r1yxy6n7djlw6qj5d0km6ird";
1424 };
1424 };
1425 meta = {
1425 meta = {
1426 license = [ pkgs.lib.licenses.bsdOriginal ];
1426 license = [ pkgs.lib.licenses.bsdOriginal ];
1427 };
1427 };
1428 };
1428 };
1429 "pycrypto" = super.buildPythonPackage {
1429 "pycrypto" = super.buildPythonPackage {
1430 name = "pycrypto-2.6.1";
1430 name = "pycrypto-2.6.1";
1431 doCheck = false;
1431 doCheck = false;
1432 src = fetchurl {
1432 src = fetchurl {
1433 url = "https://files.pythonhosted.org/packages/60/db/645aa9af249f059cc3a368b118de33889219e0362141e75d4eaf6f80f163/pycrypto-2.6.1.tar.gz";
1433 url = "https://files.pythonhosted.org/packages/60/db/645aa9af249f059cc3a368b118de33889219e0362141e75d4eaf6f80f163/pycrypto-2.6.1.tar.gz";
1434 sha256 = "0g0ayql5b9mkjam8hym6zyg6bv77lbh66rv1fyvgqb17kfc1xkpj";
1434 sha256 = "0g0ayql5b9mkjam8hym6zyg6bv77lbh66rv1fyvgqb17kfc1xkpj";
1435 };
1435 };
1436 meta = {
1436 meta = {
1437 license = [ pkgs.lib.licenses.publicDomain ];
1437 license = [ pkgs.lib.licenses.publicDomain ];
1438 };
1438 };
1439 };
1439 };
1440 "pycurl" = super.buildPythonPackage {
1440 "pycurl" = super.buildPythonPackage {
1441 name = "pycurl-7.43.0.3";
1441 name = "pycurl-7.43.0.3";
1442 doCheck = false;
1442 doCheck = false;
1443 src = fetchurl {
1443 src = fetchurl {
1444 url = "https://files.pythonhosted.org/packages/ac/b3/0f3979633b7890bab6098d84c84467030b807a1e2b31f5d30103af5a71ca/pycurl-7.43.0.3.tar.gz";
1444 url = "https://files.pythonhosted.org/packages/ac/b3/0f3979633b7890bab6098d84c84467030b807a1e2b31f5d30103af5a71ca/pycurl-7.43.0.3.tar.gz";
1445 sha256 = "13nsvqhvnmnvfk75s8iynqsgszyv06cjp4drd3psi7zpbh63623g";
1445 sha256 = "13nsvqhvnmnvfk75s8iynqsgszyv06cjp4drd3psi7zpbh63623g";
1446 };
1446 };
1447 meta = {
1447 meta = {
1448 license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1448 license = [ pkgs.lib.licenses.mit { fullName = "LGPL/MIT"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1449 };
1449 };
1450 };
1450 };
1451 "pygments" = super.buildPythonPackage {
1451 "pygments" = super.buildPythonPackage {
1452 name = "pygments-2.4.2";
1452 name = "pygments-2.4.2";
1453 doCheck = false;
1453 doCheck = false;
1454 src = fetchurl {
1454 src = fetchurl {
1455 url = "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz";
1455 url = "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz";
1456 sha256 = "15v2sqm5g12bqa0c7wikfh9ck2nl97ayizy1hpqhmws5gqalq748";
1456 sha256 = "15v2sqm5g12bqa0c7wikfh9ck2nl97ayizy1hpqhmws5gqalq748";
1457 };
1457 };
1458 meta = {
1458 meta = {
1459 license = [ pkgs.lib.licenses.bsdOriginal ];
1459 license = [ pkgs.lib.licenses.bsdOriginal ];
1460 };
1460 };
1461 };
1461 };
1462 "pymysql" = super.buildPythonPackage {
1462 "pymysql" = super.buildPythonPackage {
1463 name = "pymysql-0.8.1";
1463 name = "pymysql-0.8.1";
1464 doCheck = false;
1464 doCheck = false;
1465 src = fetchurl {
1465 src = fetchurl {
1466 url = "https://files.pythonhosted.org/packages/44/39/6bcb83cae0095a31b6be4511707fdf2009d3e29903a55a0494d3a9a2fac0/PyMySQL-0.8.1.tar.gz";
1466 url = "https://files.pythonhosted.org/packages/44/39/6bcb83cae0095a31b6be4511707fdf2009d3e29903a55a0494d3a9a2fac0/PyMySQL-0.8.1.tar.gz";
1467 sha256 = "0a96crz55bw4h6myh833skrli7b0ck89m3x673y2z2ryy7zrpq9l";
1467 sha256 = "0a96crz55bw4h6myh833skrli7b0ck89m3x673y2z2ryy7zrpq9l";
1468 };
1468 };
1469 meta = {
1469 meta = {
1470 license = [ pkgs.lib.licenses.mit ];
1470 license = [ pkgs.lib.licenses.mit ];
1471 };
1471 };
1472 };
1472 };
1473 "pyotp" = super.buildPythonPackage {
1473 "pyotp" = super.buildPythonPackage {
1474 name = "pyotp-2.3.0";
1474 name = "pyotp-2.3.0";
1475 doCheck = false;
1475 doCheck = false;
1476 src = fetchurl {
1476 src = fetchurl {
1477 url = "https://files.pythonhosted.org/packages/f7/15/395c4945ea6bc37e8811280bb675615cb4c2b2c1cd70bdc43329da91a386/pyotp-2.3.0.tar.gz";
1477 url = "https://files.pythonhosted.org/packages/f7/15/395c4945ea6bc37e8811280bb675615cb4c2b2c1cd70bdc43329da91a386/pyotp-2.3.0.tar.gz";
1478 sha256 = "18d13ikra1iq0xyfqfm72zhgwxi2qi9ps6z1a6zmqp4qrn57wlzw";
1478 sha256 = "18d13ikra1iq0xyfqfm72zhgwxi2qi9ps6z1a6zmqp4qrn57wlzw";
1479 };
1479 };
1480 meta = {
1480 meta = {
1481 license = [ pkgs.lib.licenses.mit ];
1481 license = [ pkgs.lib.licenses.mit ];
1482 };
1482 };
1483 };
1483 };
1484 "pyparsing" = super.buildPythonPackage {
1484 "pyparsing" = super.buildPythonPackage {
1485 name = "pyparsing-2.4.7";
1485 name = "pyparsing-2.4.7";
1486 doCheck = false;
1486 doCheck = false;
1487 src = fetchurl {
1487 src = fetchurl {
1488 url = "https://files.pythonhosted.org/packages/c1/47/dfc9c342c9842bbe0036c7f763d2d6686bcf5eb1808ba3e170afdb282210/pyparsing-2.4.7.tar.gz";
1488 url = "https://files.pythonhosted.org/packages/c1/47/dfc9c342c9842bbe0036c7f763d2d6686bcf5eb1808ba3e170afdb282210/pyparsing-2.4.7.tar.gz";
1489 sha256 = "1hgc8qrbq1ymxbwfbjghv01fm3fbpjwpjwi0bcailxxzhf3yq0y2";
1489 sha256 = "1hgc8qrbq1ymxbwfbjghv01fm3fbpjwpjwi0bcailxxzhf3yq0y2";
1490 };
1490 };
1491 meta = {
1491 meta = {
1492 license = [ pkgs.lib.licenses.mit ];
1492 license = [ pkgs.lib.licenses.mit ];
1493 };
1493 };
1494 };
1494 };
1495 "pyramid" = super.buildPythonPackage {
1495 "pyramid" = super.buildPythonPackage {
1496 name = "pyramid-1.10.4";
1496 name = "pyramid-1.10.4";
1497 doCheck = false;
1497 doCheck = false;
1498 propagatedBuildInputs = [
1498 propagatedBuildInputs = [
1499 self."hupper"
1499 self."hupper"
1500 self."plaster"
1500 self."plaster"
1501 self."plaster-pastedeploy"
1501 self."plaster-pastedeploy"
1502 self."setuptools"
1502 self."setuptools"
1503 self."translationstring"
1503 self."translationstring"
1504 self."venusian"
1504 self."venusian"
1505 self."webob"
1505 self."webob"
1506 self."zope.deprecation"
1506 self."zope.deprecation"
1507 self."zope.interface"
1507 self."zope.interface"
1508 self."repoze.lru"
1508 self."repoze.lru"
1509 ];
1509 ];
1510 src = fetchurl {
1510 src = fetchurl {
1511 url = "https://files.pythonhosted.org/packages/c2/43/1ae701c9c6bb3a434358e678a5e72c96e8aa55cf4cb1d2fa2041b5dd38b7/pyramid-1.10.4.tar.gz";
1511 url = "https://files.pythonhosted.org/packages/c2/43/1ae701c9c6bb3a434358e678a5e72c96e8aa55cf4cb1d2fa2041b5dd38b7/pyramid-1.10.4.tar.gz";
1512 sha256 = "0rkxs1ajycg2zh1c94xlmls56mx5m161sn8112skj0amza6cn36q";
1512 sha256 = "0rkxs1ajycg2zh1c94xlmls56mx5m161sn8112skj0amza6cn36q";
1513 };
1513 };
1514 meta = {
1514 meta = {
1515 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1515 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1516 };
1516 };
1517 };
1517 };
1518 "pyramid-debugtoolbar" = super.buildPythonPackage {
1518 "pyramid-debugtoolbar" = super.buildPythonPackage {
1519 name = "pyramid-debugtoolbar-4.6.1";
1519 name = "pyramid-debugtoolbar-4.6.1";
1520 doCheck = false;
1520 doCheck = false;
1521 propagatedBuildInputs = [
1521 propagatedBuildInputs = [
1522 self."pyramid"
1522 self."pyramid"
1523 self."pyramid-mako"
1523 self."pyramid-mako"
1524 self."repoze.lru"
1524 self."repoze.lru"
1525 self."pygments"
1525 self."pygments"
1526 self."ipaddress"
1526 self."ipaddress"
1527 ];
1527 ];
1528 src = fetchurl {
1528 src = fetchurl {
1529 url = "https://files.pythonhosted.org/packages/99/f6/b8603f82c18275be293921bc3a2184205056ca505747bf64ab8a0c08e124/pyramid_debugtoolbar-4.6.1.tar.gz";
1529 url = "https://files.pythonhosted.org/packages/99/f6/b8603f82c18275be293921bc3a2184205056ca505747bf64ab8a0c08e124/pyramid_debugtoolbar-4.6.1.tar.gz";
1530 sha256 = "185z7q8n959ga5331iczwra2iljwkidfx4qn6bbd7vm3rm4w6llv";
1530 sha256 = "185z7q8n959ga5331iczwra2iljwkidfx4qn6bbd7vm3rm4w6llv";
1531 };
1531 };
1532 meta = {
1532 meta = {
1533 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
1533 license = [ { fullName = "Repoze Public License"; } pkgs.lib.licenses.bsdOriginal ];
1534 };
1534 };
1535 };
1535 };
1536 "pyramid-jinja2" = super.buildPythonPackage {
1536 "pyramid-jinja2" = super.buildPythonPackage {
1537 name = "pyramid-jinja2-2.7";
1537 name = "pyramid-jinja2-2.7";
1538 doCheck = false;
1538 doCheck = false;
1539 propagatedBuildInputs = [
1539 propagatedBuildInputs = [
1540 self."pyramid"
1540 self."pyramid"
1541 self."zope.deprecation"
1541 self."zope.deprecation"
1542 self."jinja2"
1542 self."jinja2"
1543 self."markupsafe"
1543 self."markupsafe"
1544 ];
1544 ];
1545 src = fetchurl {
1545 src = fetchurl {
1546 url = "https://files.pythonhosted.org/packages/d8/80/d60a7233823de22ce77bd864a8a83736a1fe8b49884b08303a2e68b2c853/pyramid_jinja2-2.7.tar.gz";
1546 url = "https://files.pythonhosted.org/packages/d8/80/d60a7233823de22ce77bd864a8a83736a1fe8b49884b08303a2e68b2c853/pyramid_jinja2-2.7.tar.gz";
1547 sha256 = "1sz5s0pp5jqhf4w22w9527yz8hgdi4mhr6apd6vw1gm5clghh8aw";
1547 sha256 = "1sz5s0pp5jqhf4w22w9527yz8hgdi4mhr6apd6vw1gm5clghh8aw";
1548 };
1548 };
1549 meta = {
1549 meta = {
1550 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1550 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1551 };
1551 };
1552 };
1552 };
1553 "pyramid-apispec" = super.buildPythonPackage {
1553 "pyramid-apispec" = super.buildPythonPackage {
1554 name = "pyramid-apispec-0.3.2";
1554 name = "pyramid-apispec-0.3.2";
1555 doCheck = false;
1555 doCheck = false;
1556 propagatedBuildInputs = [
1556 propagatedBuildInputs = [
1557 self."apispec"
1557 self."apispec"
1558 ];
1558 ];
1559 src = fetchurl {
1559 src = fetchurl {
1560 url = "https://files.pythonhosted.org/packages/2a/30/1dea5d81ea635449572ba60ec3148310d75ae4530c3c695f54b0991bb8c7/pyramid_apispec-0.3.2.tar.gz";
1560 url = "https://files.pythonhosted.org/packages/2a/30/1dea5d81ea635449572ba60ec3148310d75ae4530c3c695f54b0991bb8c7/pyramid_apispec-0.3.2.tar.gz";
1561 sha256 = "0ffrcqp9dkykivhfcq0v9lgy6w0qhwl6x78925vfjmayly9r8da0";
1561 sha256 = "0ffrcqp9dkykivhfcq0v9lgy6w0qhwl6x78925vfjmayly9r8da0";
1562 };
1562 };
1563 meta = {
1563 meta = {
1564 license = [ pkgs.lib.licenses.bsdOriginal ];
1564 license = [ pkgs.lib.licenses.bsdOriginal ];
1565 };
1565 };
1566 };
1566 };
1567 "pyramid-mailer" = super.buildPythonPackage {
1567 "pyramid-mailer" = super.buildPythonPackage {
1568 name = "pyramid-mailer-0.15.1";
1568 name = "pyramid-mailer-0.15.1";
1569 doCheck = false;
1569 doCheck = false;
1570 propagatedBuildInputs = [
1570 propagatedBuildInputs = [
1571 self."pyramid"
1571 self."pyramid"
1572 self."repoze.sendmail"
1572 self."repoze.sendmail"
1573 self."transaction"
1573 self."transaction"
1574 ];
1574 ];
1575 src = fetchurl {
1575 src = fetchurl {
1576 url = "https://files.pythonhosted.org/packages/a0/f2/6febf5459dff4d7e653314d575469ad2e11b9d2af2c3606360e1c67202f2/pyramid_mailer-0.15.1.tar.gz";
1576 url = "https://files.pythonhosted.org/packages/a0/f2/6febf5459dff4d7e653314d575469ad2e11b9d2af2c3606360e1c67202f2/pyramid_mailer-0.15.1.tar.gz";
1577 sha256 = "16vg8jb203jgb7b0hd6wllfqvp542qh2ry1gjai2m6qpv5agy2pc";
1577 sha256 = "16vg8jb203jgb7b0hd6wllfqvp542qh2ry1gjai2m6qpv5agy2pc";
1578 };
1578 };
1579 meta = {
1579 meta = {
1580 license = [ pkgs.lib.licenses.bsdOriginal ];
1580 license = [ pkgs.lib.licenses.bsdOriginal ];
1581 };
1581 };
1582 };
1582 };
1583 "pyramid-mako" = super.buildPythonPackage {
1583 "pyramid-mako" = super.buildPythonPackage {
1584 name = "pyramid-mako-1.1.0";
1584 name = "pyramid-mako-1.1.0";
1585 doCheck = false;
1585 doCheck = false;
1586 propagatedBuildInputs = [
1586 propagatedBuildInputs = [
1587 self."pyramid"
1587 self."pyramid"
1588 self."mako"
1588 self."mako"
1589 ];
1589 ];
1590 src = fetchurl {
1590 src = fetchurl {
1591 url = "https://files.pythonhosted.org/packages/63/7b/5e2af68f675071a6bad148c1c393928f0ef5fcd94e95cbf53b89d6471a83/pyramid_mako-1.1.0.tar.gz";
1591 url = "https://files.pythonhosted.org/packages/63/7b/5e2af68f675071a6bad148c1c393928f0ef5fcd94e95cbf53b89d6471a83/pyramid_mako-1.1.0.tar.gz";
1592 sha256 = "1qj0m091mnii86j2q1d82yir22nha361rvhclvg3s70z8iiwhrh0";
1592 sha256 = "1qj0m091mnii86j2q1d82yir22nha361rvhclvg3s70z8iiwhrh0";
1593 };
1593 };
1594 meta = {
1594 meta = {
1595 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1595 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1596 };
1596 };
1597 };
1597 };
1598 "pysqlite" = super.buildPythonPackage {
1598 "pysqlite" = super.buildPythonPackage {
1599 name = "pysqlite-2.8.3";
1599 name = "pysqlite-2.8.3";
1600 doCheck = false;
1600 doCheck = false;
1601 src = fetchurl {
1601 src = fetchurl {
1602 url = "https://files.pythonhosted.org/packages/42/02/981b6703e3c83c5b25a829c6e77aad059f9481b0bbacb47e6e8ca12bd731/pysqlite-2.8.3.tar.gz";
1602 url = "https://files.pythonhosted.org/packages/42/02/981b6703e3c83c5b25a829c6e77aad059f9481b0bbacb47e6e8ca12bd731/pysqlite-2.8.3.tar.gz";
1603 sha256 = "1424gwq9sil2ffmnizk60q36vydkv8rxs6m7xs987kz8cdc37lqp";
1603 sha256 = "1424gwq9sil2ffmnizk60q36vydkv8rxs6m7xs987kz8cdc37lqp";
1604 };
1604 };
1605 meta = {
1605 meta = {
1606 license = [ { fullName = "zlib/libpng License"; } { fullName = "zlib/libpng license"; } ];
1606 license = [ { fullName = "zlib/libpng License"; } { fullName = "zlib/libpng license"; } ];
1607 };
1607 };
1608 };
1608 };
1609 "pytest" = super.buildPythonPackage {
1609 "pytest" = super.buildPythonPackage {
1610 name = "pytest-4.6.5";
1610 name = "pytest-4.6.5";
1611 doCheck = false;
1611 doCheck = false;
1612 propagatedBuildInputs = [
1612 propagatedBuildInputs = [
1613 self."py"
1613 self."py"
1614 self."six"
1614 self."six"
1615 self."packaging"
1615 self."packaging"
1616 self."attrs"
1616 self."attrs"
1617 self."atomicwrites"
1617 self."atomicwrites"
1618 self."pluggy"
1618 self."pluggy"
1619 self."importlib-metadata"
1619 self."importlib-metadata"
1620 self."wcwidth"
1620 self."wcwidth"
1621 self."funcsigs"
1621 self."funcsigs"
1622 self."pathlib2"
1622 self."pathlib2"
1623 self."more-itertools"
1623 self."more-itertools"
1624 ];
1624 ];
1625 src = fetchurl {
1625 src = fetchurl {
1626 url = "https://files.pythonhosted.org/packages/2a/c6/1d1f32f6a5009900521b12e6560fb6b7245b0d4bc3fb771acd63d10e30e1/pytest-4.6.5.tar.gz";
1626 url = "https://files.pythonhosted.org/packages/2a/c6/1d1f32f6a5009900521b12e6560fb6b7245b0d4bc3fb771acd63d10e30e1/pytest-4.6.5.tar.gz";
1627 sha256 = "0iykwwfp4h181nd7rsihh2120b0rkawlw7rvbl19sgfspncr3hwg";
1627 sha256 = "0iykwwfp4h181nd7rsihh2120b0rkawlw7rvbl19sgfspncr3hwg";
1628 };
1628 };
1629 meta = {
1629 meta = {
1630 license = [ pkgs.lib.licenses.mit ];
1630 license = [ pkgs.lib.licenses.mit ];
1631 };
1631 };
1632 };
1632 };
1633 "pytest-cov" = super.buildPythonPackage {
1633 "pytest-cov" = super.buildPythonPackage {
1634 name = "pytest-cov-2.7.1";
1634 name = "pytest-cov-2.7.1";
1635 doCheck = false;
1635 doCheck = false;
1636 propagatedBuildInputs = [
1636 propagatedBuildInputs = [
1637 self."pytest"
1637 self."pytest"
1638 self."coverage"
1638 self."coverage"
1639 ];
1639 ];
1640 src = fetchurl {
1640 src = fetchurl {
1641 url = "https://files.pythonhosted.org/packages/bb/0f/3db7ff86801883b21d5353b258c994b1b8e2abbc804e2273b8d0fd19004b/pytest-cov-2.7.1.tar.gz";
1641 url = "https://files.pythonhosted.org/packages/bb/0f/3db7ff86801883b21d5353b258c994b1b8e2abbc804e2273b8d0fd19004b/pytest-cov-2.7.1.tar.gz";
1642 sha256 = "0filvmmyqm715azsl09ql8hy2x7h286n6d8z5x42a1wpvvys83p0";
1642 sha256 = "0filvmmyqm715azsl09ql8hy2x7h286n6d8z5x42a1wpvvys83p0";
1643 };
1643 };
1644 meta = {
1644 meta = {
1645 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.mit ];
1645 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.mit ];
1646 };
1646 };
1647 };
1647 };
1648 "pytest-profiling" = super.buildPythonPackage {
1648 "pytest-profiling" = super.buildPythonPackage {
1649 name = "pytest-profiling-1.7.0";
1649 name = "pytest-profiling-1.7.0";
1650 doCheck = false;
1650 doCheck = false;
1651 propagatedBuildInputs = [
1651 propagatedBuildInputs = [
1652 self."six"
1652 self."six"
1653 self."pytest"
1653 self."pytest"
1654 self."gprof2dot"
1654 self."gprof2dot"
1655 ];
1655 ];
1656 src = fetchurl {
1656 src = fetchurl {
1657 url = "https://files.pythonhosted.org/packages/39/70/22a4b33739f07f1732a63e33bbfbf68e0fa58cfba9d200e76d01921eddbf/pytest-profiling-1.7.0.tar.gz";
1657 url = "https://files.pythonhosted.org/packages/39/70/22a4b33739f07f1732a63e33bbfbf68e0fa58cfba9d200e76d01921eddbf/pytest-profiling-1.7.0.tar.gz";
1658 sha256 = "0abz9gi26jpcfdzgsvwad91555lpgdc8kbymicmms8k2fqa8z4wk";
1658 sha256 = "0abz9gi26jpcfdzgsvwad91555lpgdc8kbymicmms8k2fqa8z4wk";
1659 };
1659 };
1660 meta = {
1660 meta = {
1661 license = [ pkgs.lib.licenses.mit ];
1661 license = [ pkgs.lib.licenses.mit ];
1662 };
1662 };
1663 };
1663 };
1664 "pytest-runner" = super.buildPythonPackage {
1664 "pytest-runner" = super.buildPythonPackage {
1665 name = "pytest-runner-5.1";
1665 name = "pytest-runner-5.1";
1666 doCheck = false;
1666 doCheck = false;
1667 src = fetchurl {
1667 src = fetchurl {
1668 url = "https://files.pythonhosted.org/packages/d9/6d/4b41a74b31720e25abd4799be72d54811da4b4d0233e38b75864dcc1f7ad/pytest-runner-5.1.tar.gz";
1668 url = "https://files.pythonhosted.org/packages/d9/6d/4b41a74b31720e25abd4799be72d54811da4b4d0233e38b75864dcc1f7ad/pytest-runner-5.1.tar.gz";
1669 sha256 = "0ykfcnpp8c22winj63qzc07l5axwlc9ikl8vn05sc32gv3417815";
1669 sha256 = "0ykfcnpp8c22winj63qzc07l5axwlc9ikl8vn05sc32gv3417815";
1670 };
1670 };
1671 meta = {
1671 meta = {
1672 license = [ pkgs.lib.licenses.mit ];
1672 license = [ pkgs.lib.licenses.mit ];
1673 };
1673 };
1674 };
1674 };
1675 "pytest-sugar" = super.buildPythonPackage {
1675 "pytest-sugar" = super.buildPythonPackage {
1676 name = "pytest-sugar-0.9.2";
1676 name = "pytest-sugar-0.9.2";
1677 doCheck = false;
1677 doCheck = false;
1678 propagatedBuildInputs = [
1678 propagatedBuildInputs = [
1679 self."pytest"
1679 self."pytest"
1680 self."termcolor"
1680 self."termcolor"
1681 self."packaging"
1681 self."packaging"
1682 ];
1682 ];
1683 src = fetchurl {
1683 src = fetchurl {
1684 url = "https://files.pythonhosted.org/packages/55/59/f02f78d1c80f7e03e23177f60624c8106d4f23d124c921df103f65692464/pytest-sugar-0.9.2.tar.gz";
1684 url = "https://files.pythonhosted.org/packages/55/59/f02f78d1c80f7e03e23177f60624c8106d4f23d124c921df103f65692464/pytest-sugar-0.9.2.tar.gz";
1685 sha256 = "1asq7yc4g8bx2sn7yy974mhc9ywvaihasjab4inkirdwn9s7mn7w";
1685 sha256 = "1asq7yc4g8bx2sn7yy974mhc9ywvaihasjab4inkirdwn9s7mn7w";
1686 };
1686 };
1687 meta = {
1687 meta = {
1688 license = [ pkgs.lib.licenses.bsdOriginal ];
1688 license = [ pkgs.lib.licenses.bsdOriginal ];
1689 };
1689 };
1690 };
1690 };
1691 "pytest-timeout" = super.buildPythonPackage {
1691 "pytest-timeout" = super.buildPythonPackage {
1692 name = "pytest-timeout-1.3.3";
1692 name = "pytest-timeout-1.3.3";
1693 doCheck = false;
1693 doCheck = false;
1694 propagatedBuildInputs = [
1694 propagatedBuildInputs = [
1695 self."pytest"
1695 self."pytest"
1696 ];
1696 ];
1697 src = fetchurl {
1697 src = fetchurl {
1698 url = "https://files.pythonhosted.org/packages/13/48/7a166eaa29c1dca6cc253e3ba5773ff2e4aa4f567c1ea3905808e95ac5c1/pytest-timeout-1.3.3.tar.gz";
1698 url = "https://files.pythonhosted.org/packages/13/48/7a166eaa29c1dca6cc253e3ba5773ff2e4aa4f567c1ea3905808e95ac5c1/pytest-timeout-1.3.3.tar.gz";
1699 sha256 = "1cczcjhw4xx5sjkhxlhc5c1bkr7x6fcyx12wrnvwfckshdvblc2a";
1699 sha256 = "1cczcjhw4xx5sjkhxlhc5c1bkr7x6fcyx12wrnvwfckshdvblc2a";
1700 };
1700 };
1701 meta = {
1701 meta = {
1702 license = [ pkgs.lib.licenses.mit { fullName = "DFSG approved"; } ];
1702 license = [ pkgs.lib.licenses.mit { fullName = "DFSG approved"; } ];
1703 };
1703 };
1704 };
1704 };
1705 "python-dateutil" = super.buildPythonPackage {
1705 "python-dateutil" = super.buildPythonPackage {
1706 name = "python-dateutil-2.8.1";
1706 name = "python-dateutil-2.8.1";
1707 doCheck = false;
1707 doCheck = false;
1708 propagatedBuildInputs = [
1708 propagatedBuildInputs = [
1709 self."six"
1709 self."six"
1710 ];
1710 ];
1711 src = fetchurl {
1711 src = fetchurl {
1712 url = "https://files.pythonhosted.org/packages/be/ed/5bbc91f03fa4c839c4c7360375da77f9659af5f7086b7a7bdda65771c8e0/python-dateutil-2.8.1.tar.gz";
1712 url = "https://files.pythonhosted.org/packages/be/ed/5bbc91f03fa4c839c4c7360375da77f9659af5f7086b7a7bdda65771c8e0/python-dateutil-2.8.1.tar.gz";
1713 sha256 = "0g42w7k5007iv9dam6gnja2ry8ydwirh99mgdll35s12pyfzxsvk";
1713 sha256 = "0g42w7k5007iv9dam6gnja2ry8ydwirh99mgdll35s12pyfzxsvk";
1714 };
1714 };
1715 meta = {
1715 meta = {
1716 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ];
1716 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ];
1717 };
1717 };
1718 };
1718 };
1719 "python-editor" = super.buildPythonPackage {
1719 "python-editor" = super.buildPythonPackage {
1720 name = "python-editor-1.0.4";
1720 name = "python-editor-1.0.4";
1721 doCheck = false;
1721 doCheck = false;
1722 src = fetchurl {
1722 src = fetchurl {
1723 url = "https://files.pythonhosted.org/packages/0a/85/78f4a216d28343a67b7397c99825cff336330893f00601443f7c7b2f2234/python-editor-1.0.4.tar.gz";
1723 url = "https://files.pythonhosted.org/packages/0a/85/78f4a216d28343a67b7397c99825cff336330893f00601443f7c7b2f2234/python-editor-1.0.4.tar.gz";
1724 sha256 = "0yrjh8w72ivqxi4i7xsg5b1vz15x8fg51xra7c3bgfyxqnyadzai";
1724 sha256 = "0yrjh8w72ivqxi4i7xsg5b1vz15x8fg51xra7c3bgfyxqnyadzai";
1725 };
1725 };
1726 meta = {
1726 meta = {
1727 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
1727 license = [ pkgs.lib.licenses.asl20 { fullName = "Apache"; } ];
1728 };
1728 };
1729 };
1729 };
1730 "python-ldap" = super.buildPythonPackage {
1730 "python-ldap" = super.buildPythonPackage {
1731 name = "python-ldap-3.2.0";
1731 name = "python-ldap-3.2.0";
1732 doCheck = false;
1732 doCheck = false;
1733 propagatedBuildInputs = [
1733 propagatedBuildInputs = [
1734 self."pyasn1"
1734 self."pyasn1"
1735 self."pyasn1-modules"
1735 self."pyasn1-modules"
1736 ];
1736 ];
1737 src = fetchurl {
1737 src = fetchurl {
1738 url = "https://files.pythonhosted.org/packages/ea/93/596f875e003c770447f4b99267820a0c769dd2dc3ae3ed19afe460fcbad0/python-ldap-3.2.0.tar.gz";
1738 url = "https://files.pythonhosted.org/packages/ea/93/596f875e003c770447f4b99267820a0c769dd2dc3ae3ed19afe460fcbad0/python-ldap-3.2.0.tar.gz";
1739 sha256 = "13nvrhp85yr0jyxixcjj012iw8l9wynxxlykm9j3alss6waln73x";
1739 sha256 = "13nvrhp85yr0jyxixcjj012iw8l9wynxxlykm9j3alss6waln73x";
1740 };
1740 };
1741 meta = {
1741 meta = {
1742 license = [ pkgs.lib.licenses.psfl ];
1742 license = [ pkgs.lib.licenses.psfl ];
1743 };
1743 };
1744 };
1744 };
1745 "python-memcached" = super.buildPythonPackage {
1745 "python-memcached" = super.buildPythonPackage {
1746 name = "python-memcached-1.59";
1746 name = "python-memcached-1.59";
1747 doCheck = false;
1747 doCheck = false;
1748 propagatedBuildInputs = [
1748 propagatedBuildInputs = [
1749 self."six"
1749 self."six"
1750 ];
1750 ];
1751 src = fetchurl {
1751 src = fetchurl {
1752 url = "https://files.pythonhosted.org/packages/90/59/5faf6e3cd8a568dd4f737ddae4f2e54204fd8c51f90bf8df99aca6c22318/python-memcached-1.59.tar.gz";
1752 url = "https://files.pythonhosted.org/packages/90/59/5faf6e3cd8a568dd4f737ddae4f2e54204fd8c51f90bf8df99aca6c22318/python-memcached-1.59.tar.gz";
1753 sha256 = "0kvyapavbirk2x3n1jx4yb9nyigrj1s3x15nm3qhpvhkpqvqdqm2";
1753 sha256 = "0kvyapavbirk2x3n1jx4yb9nyigrj1s3x15nm3qhpvhkpqvqdqm2";
1754 };
1754 };
1755 meta = {
1755 meta = {
1756 license = [ pkgs.lib.licenses.psfl ];
1756 license = [ pkgs.lib.licenses.psfl ];
1757 };
1757 };
1758 };
1758 };
1759 "python-pam" = super.buildPythonPackage {
1759 "python-pam" = super.buildPythonPackage {
1760 name = "python-pam-1.8.4";
1760 name = "python-pam-1.8.4";
1761 doCheck = false;
1761 doCheck = false;
1762 src = fetchurl {
1762 src = fetchurl {
1763 url = "https://files.pythonhosted.org/packages/01/16/544d01cae9f28e0292dbd092b6b8b0bf222b528f362ee768a5bed2140111/python-pam-1.8.4.tar.gz";
1763 url = "https://files.pythonhosted.org/packages/01/16/544d01cae9f28e0292dbd092b6b8b0bf222b528f362ee768a5bed2140111/python-pam-1.8.4.tar.gz";
1764 sha256 = "16whhc0vr7gxsbzvsnq65nq8fs3wwmx755cavm8kkczdkz4djmn8";
1764 sha256 = "16whhc0vr7gxsbzvsnq65nq8fs3wwmx755cavm8kkczdkz4djmn8";
1765 };
1765 };
1766 meta = {
1766 meta = {
1767 license = [ { fullName = "License :: OSI Approved :: MIT License"; } pkgs.lib.licenses.mit ];
1767 license = [ { fullName = "License :: OSI Approved :: MIT License"; } pkgs.lib.licenses.mit ];
1768 };
1768 };
1769 };
1769 };
1770 "python-saml" = super.buildPythonPackage {
1770 "python-saml" = super.buildPythonPackage {
1771 name = "python-saml-2.4.2";
1771 name = "python-saml-2.4.2";
1772 doCheck = false;
1772 doCheck = false;
1773 propagatedBuildInputs = [
1773 propagatedBuildInputs = [
1774 self."dm.xmlsec.binding"
1774 self."dm.xmlsec.binding"
1775 self."isodate"
1775 self."isodate"
1776 self."defusedxml"
1776 self."defusedxml"
1777 ];
1777 ];
1778 src = fetchurl {
1778 src = fetchurl {
1779 url = "https://files.pythonhosted.org/packages/79/a8/a6611017e0883102fd5e2b73c9d90691b8134e38247c04ee1531d3dc647c/python-saml-2.4.2.tar.gz";
1779 url = "https://files.pythonhosted.org/packages/79/a8/a6611017e0883102fd5e2b73c9d90691b8134e38247c04ee1531d3dc647c/python-saml-2.4.2.tar.gz";
1780 sha256 = "0dls4hwvf13yg7x5yfjrghbywg8g38vn5vr0rsf70hli3ydbfm43";
1780 sha256 = "0dls4hwvf13yg7x5yfjrghbywg8g38vn5vr0rsf70hli3ydbfm43";
1781 };
1781 };
1782 meta = {
1782 meta = {
1783 license = [ pkgs.lib.licenses.mit ];
1783 license = [ pkgs.lib.licenses.mit ];
1784 };
1784 };
1785 };
1785 };
1786 "pytz" = super.buildPythonPackage {
1786 "pytz" = super.buildPythonPackage {
1787 name = "pytz-2019.3";
1787 name = "pytz-2019.3";
1788 doCheck = false;
1788 doCheck = false;
1789 src = fetchurl {
1789 src = fetchurl {
1790 url = "https://files.pythonhosted.org/packages/82/c3/534ddba230bd4fbbd3b7a3d35f3341d014cca213f369a9940925e7e5f691/pytz-2019.3.tar.gz";
1790 url = "https://files.pythonhosted.org/packages/82/c3/534ddba230bd4fbbd3b7a3d35f3341d014cca213f369a9940925e7e5f691/pytz-2019.3.tar.gz";
1791 sha256 = "1ghrk1wg45d3nymj7bf4zj03n3bh64xmczhk4pfi577hdkdhcb5h";
1791 sha256 = "1ghrk1wg45d3nymj7bf4zj03n3bh64xmczhk4pfi577hdkdhcb5h";
1792 };
1792 };
1793 meta = {
1793 meta = {
1794 license = [ pkgs.lib.licenses.mit ];
1794 license = [ pkgs.lib.licenses.mit ];
1795 };
1795 };
1796 };
1796 };
1797 "pyzmq" = super.buildPythonPackage {
1797 "pyzmq" = super.buildPythonPackage {
1798 name = "pyzmq-14.6.0";
1798 name = "pyzmq-14.6.0";
1799 doCheck = false;
1799 doCheck = false;
1800 src = fetchurl {
1800 src = fetchurl {
1801 url = "https://files.pythonhosted.org/packages/8a/3b/5463d5a9d712cd8bbdac335daece0d69f6a6792da4e3dd89956c0db4e4e6/pyzmq-14.6.0.tar.gz";
1801 url = "https://files.pythonhosted.org/packages/8a/3b/5463d5a9d712cd8bbdac335daece0d69f6a6792da4e3dd89956c0db4e4e6/pyzmq-14.6.0.tar.gz";
1802 sha256 = "1frmbjykvhmdg64g7sn20c9fpamrsfxwci1nhhg8q7jgz5pq0ikp";
1802 sha256 = "1frmbjykvhmdg64g7sn20c9fpamrsfxwci1nhhg8q7jgz5pq0ikp";
1803 };
1803 };
1804 meta = {
1804 meta = {
1805 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1805 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "LGPL+BSD"; } { fullName = "GNU Library or Lesser General Public License (LGPL)"; } ];
1806 };
1806 };
1807 };
1807 };
1808 "PyYAML" = super.buildPythonPackage {
1808 "PyYAML" = super.buildPythonPackage {
1809 name = "PyYAML-5.3.1";
1809 name = "PyYAML-5.3.1";
1810 doCheck = false;
1810 doCheck = false;
1811 src = fetchurl {
1811 src = fetchurl {
1812 url = "https://files.pythonhosted.org/packages/64/c2/b80047c7ac2478f9501676c988a5411ed5572f35d1beff9cae07d321512c/PyYAML-5.3.1.tar.gz";
1812 url = "https://files.pythonhosted.org/packages/64/c2/b80047c7ac2478f9501676c988a5411ed5572f35d1beff9cae07d321512c/PyYAML-5.3.1.tar.gz";
1813 sha256 = "0pb4zvkfxfijkpgd1b86xjsqql97ssf1knbd1v53wkg1qm9cgsmq";
1813 sha256 = "0pb4zvkfxfijkpgd1b86xjsqql97ssf1knbd1v53wkg1qm9cgsmq";
1814 };
1814 };
1815 meta = {
1815 meta = {
1816 license = [ pkgs.lib.licenses.mit ];
1816 license = [ pkgs.lib.licenses.mit ];
1817 };
1817 };
1818 };
1818 };
1819 "regex" = super.buildPythonPackage {
1820 name = "regex-2020.9.27";
1821 doCheck = false;
1822 src = fetchurl {
1823 url = "https://files.pythonhosted.org/packages/93/8c/17f45cdfb39b13d4b5f909e4b4c2917abcbdef9c0036919a0399769148cf/regex-2020.9.27.tar.gz";
1824 sha256 = "179ngfzwbsjvn5vhyzdahvmg0f7acahkwwy9bpjy1pv08bm2mwx6";
1825 };
1826 meta = {
1827 license = [ pkgs.lib.licenses.psfl ];
1828 };
1829 };
1819 "redis" = super.buildPythonPackage {
1830 "redis" = super.buildPythonPackage {
1820 name = "redis-3.4.1";
1831 name = "redis-3.4.1";
1821 doCheck = false;
1832 doCheck = false;
1822 src = fetchurl {
1833 src = fetchurl {
1823 url = "https://files.pythonhosted.org/packages/ef/2e/2c0f59891db7db087a7eeaa79bc7c7f2c039e71a2b5b0a41391e9d462926/redis-3.4.1.tar.gz";
1834 url = "https://files.pythonhosted.org/packages/ef/2e/2c0f59891db7db087a7eeaa79bc7c7f2c039e71a2b5b0a41391e9d462926/redis-3.4.1.tar.gz";
1824 sha256 = "07yaj0j9fs7xdkg5bg926fa990khyigjbp31si8ai20vj8sv7kqd";
1835 sha256 = "07yaj0j9fs7xdkg5bg926fa990khyigjbp31si8ai20vj8sv7kqd";
1825 };
1836 };
1826 meta = {
1837 meta = {
1827 license = [ pkgs.lib.licenses.mit ];
1838 license = [ pkgs.lib.licenses.mit ];
1828 };
1839 };
1829 };
1840 };
1830 "repoze.lru" = super.buildPythonPackage {
1841 "repoze.lru" = super.buildPythonPackage {
1831 name = "repoze.lru-0.7";
1842 name = "repoze.lru-0.7";
1832 doCheck = false;
1843 doCheck = false;
1833 src = fetchurl {
1844 src = fetchurl {
1834 url = "https://files.pythonhosted.org/packages/12/bc/595a77c4b5e204847fdf19268314ef59c85193a9dc9f83630fc459c0fee5/repoze.lru-0.7.tar.gz";
1845 url = "https://files.pythonhosted.org/packages/12/bc/595a77c4b5e204847fdf19268314ef59c85193a9dc9f83630fc459c0fee5/repoze.lru-0.7.tar.gz";
1835 sha256 = "0xzz1aw2smy8hdszrq8yhnklx6w1r1mf55061kalw3iq35gafa84";
1846 sha256 = "0xzz1aw2smy8hdszrq8yhnklx6w1r1mf55061kalw3iq35gafa84";
1836 };
1847 };
1837 meta = {
1848 meta = {
1838 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1849 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
1839 };
1850 };
1840 };
1851 };
1841 "repoze.sendmail" = super.buildPythonPackage {
1852 "repoze.sendmail" = super.buildPythonPackage {
1842 name = "repoze.sendmail-4.4.1";
1853 name = "repoze.sendmail-4.4.1";
1843 doCheck = false;
1854 doCheck = false;
1844 propagatedBuildInputs = [
1855 propagatedBuildInputs = [
1845 self."setuptools"
1856 self."setuptools"
1846 self."zope.interface"
1857 self."zope.interface"
1847 self."transaction"
1858 self."transaction"
1848 ];
1859 ];
1849 src = fetchurl {
1860 src = fetchurl {
1850 url = "https://files.pythonhosted.org/packages/12/4e/8ef1fd5c42765d712427b9c391419a77bd48877886d2cbc5e9f23c8cad9b/repoze.sendmail-4.4.1.tar.gz";
1861 url = "https://files.pythonhosted.org/packages/12/4e/8ef1fd5c42765d712427b9c391419a77bd48877886d2cbc5e9f23c8cad9b/repoze.sendmail-4.4.1.tar.gz";
1851 sha256 = "096ln02jr2afk7ab9j2czxqv2ryqq7m86ah572nqplx52iws73ks";
1862 sha256 = "096ln02jr2afk7ab9j2czxqv2ryqq7m86ah572nqplx52iws73ks";
1852 };
1863 };
1853 meta = {
1864 meta = {
1854 license = [ pkgs.lib.licenses.zpl21 ];
1865 license = [ pkgs.lib.licenses.zpl21 ];
1855 };
1866 };
1856 };
1867 };
1857 "requests" = super.buildPythonPackage {
1868 "requests" = super.buildPythonPackage {
1858 name = "requests-2.22.0";
1869 name = "requests-2.22.0";
1859 doCheck = false;
1870 doCheck = false;
1860 propagatedBuildInputs = [
1871 propagatedBuildInputs = [
1861 self."chardet"
1872 self."chardet"
1862 self."idna"
1873 self."idna"
1863 self."urllib3"
1874 self."urllib3"
1864 self."certifi"
1875 self."certifi"
1865 ];
1876 ];
1866 src = fetchurl {
1877 src = fetchurl {
1867 url = "https://files.pythonhosted.org/packages/01/62/ddcf76d1d19885e8579acb1b1df26a852b03472c0e46d2b959a714c90608/requests-2.22.0.tar.gz";
1878 url = "https://files.pythonhosted.org/packages/01/62/ddcf76d1d19885e8579acb1b1df26a852b03472c0e46d2b959a714c90608/requests-2.22.0.tar.gz";
1868 sha256 = "1d5ybh11jr5sm7xp6mz8fyc7vrp4syifds91m7sj60xalal0gq0i";
1879 sha256 = "1d5ybh11jr5sm7xp6mz8fyc7vrp4syifds91m7sj60xalal0gq0i";
1869 };
1880 };
1870 meta = {
1881 meta = {
1871 license = [ pkgs.lib.licenses.asl20 ];
1882 license = [ pkgs.lib.licenses.asl20 ];
1872 };
1883 };
1873 };
1884 };
1874 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1885 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1875 name = "rhodecode-enterprise-ce-4.21.0";
1886 name = "rhodecode-enterprise-ce-4.21.0";
1876 buildInputs = [
1887 buildInputs = [
1877 self."pytest"
1888 self."pytest"
1878 self."py"
1889 self."py"
1879 self."pytest-cov"
1890 self."pytest-cov"
1880 self."pytest-sugar"
1891 self."pytest-sugar"
1881 self."pytest-runner"
1892 self."pytest-runner"
1882 self."pytest-profiling"
1893 self."pytest-profiling"
1883 self."pytest-timeout"
1894 self."pytest-timeout"
1884 self."gprof2dot"
1895 self."gprof2dot"
1885 self."mock"
1896 self."mock"
1886 self."cov-core"
1897 self."cov-core"
1887 self."coverage"
1898 self."coverage"
1888 self."webtest"
1899 self."webtest"
1889 self."beautifulsoup4"
1900 self."beautifulsoup4"
1890 self."configobj"
1901 self."configobj"
1891 ];
1902 ];
1892 doCheck = true;
1903 doCheck = true;
1893 propagatedBuildInputs = [
1904 propagatedBuildInputs = [
1894 self."amqp"
1905 self."amqp"
1895 self."babel"
1906 self."babel"
1896 self."beaker"
1907 self."beaker"
1897 self."bleach"
1908 self."bleach"
1898 self."celery"
1909 self."celery"
1899 self."channelstream"
1910 self."channelstream"
1900 self."click"
1911 self."click"
1901 self."colander"
1912 self."colander"
1902 self."configobj"
1913 self."configobj"
1903 self."cssselect"
1914 self."cssselect"
1904 self."cryptography"
1915 self."cryptography"
1905 self."decorator"
1916 self."decorator"
1906 self."deform"
1917 self."deform"
1907 self."docutils"
1918 self."docutils"
1908 self."dogpile.cache"
1919 self."dogpile.cache"
1909 self."dogpile.core"
1920 self."dogpile.core"
1910 self."formencode"
1921 self."formencode"
1911 self."future"
1922 self."future"
1912 self."futures"
1923 self."futures"
1913 self."infrae.cache"
1924 self."infrae.cache"
1914 self."iso8601"
1925 self."iso8601"
1915 self."itsdangerous"
1926 self."itsdangerous"
1916 self."kombu"
1927 self."kombu"
1917 self."lxml"
1928 self."lxml"
1918 self."mako"
1929 self."mako"
1919 self."markdown"
1930 self."markdown"
1920 self."markupsafe"
1931 self."markupsafe"
1921 self."msgpack-python"
1932 self."msgpack-python"
1922 self."pyotp"
1933 self."pyotp"
1923 self."packaging"
1934 self."packaging"
1924 self."pathlib2"
1935 self."pathlib2"
1925 self."paste"
1936 self."paste"
1926 self."pastedeploy"
1937 self."pastedeploy"
1927 self."pastescript"
1938 self."pastescript"
1928 self."peppercorn"
1939 self."peppercorn"
1929 self."premailer"
1940 self."premailer"
1930 self."psutil"
1941 self."psutil"
1931 self."py-bcrypt"
1942 self."py-bcrypt"
1932 self."pycurl"
1943 self."pycurl"
1933 self."pycrypto"
1944 self."pycrypto"
1934 self."pygments"
1945 self."pygments"
1935 self."pyparsing"
1946 self."pyparsing"
1936 self."pyramid-debugtoolbar"
1947 self."pyramid-debugtoolbar"
1937 self."pyramid-mako"
1948 self."pyramid-mako"
1938 self."pyramid"
1949 self."pyramid"
1939 self."pyramid-mailer"
1950 self."pyramid-mailer"
1940 self."python-dateutil"
1951 self."python-dateutil"
1941 self."python-ldap"
1952 self."python-ldap"
1942 self."python-memcached"
1953 self."python-memcached"
1943 self."python-pam"
1954 self."python-pam"
1944 self."python-saml"
1955 self."python-saml"
1945 self."pytz"
1956 self."pytz"
1946 self."tzlocal"
1957 self."tzlocal"
1947 self."pyzmq"
1958 self."pyzmq"
1948 self."py-gfm"
1959 self."py-gfm"
1960 self."regex"
1949 self."redis"
1961 self."redis"
1950 self."repoze.lru"
1962 self."repoze.lru"
1951 self."requests"
1963 self."requests"
1952 self."routes"
1964 self."routes"
1953 self."simplejson"
1965 self."simplejson"
1954 self."six"
1966 self."six"
1955 self."sqlalchemy"
1967 self."sqlalchemy"
1956 self."sshpubkeys"
1968 self."sshpubkeys"
1957 self."subprocess32"
1969 self."subprocess32"
1958 self."supervisor"
1970 self."supervisor"
1959 self."translationstring"
1971 self."translationstring"
1960 self."urllib3"
1972 self."urllib3"
1961 self."urlobject"
1973 self."urlobject"
1962 self."venusian"
1974 self."venusian"
1963 self."weberror"
1975 self."weberror"
1964 self."webhelpers2"
1976 self."webhelpers2"
1965 self."webob"
1977 self."webob"
1966 self."whoosh"
1978 self."whoosh"
1967 self."wsgiref"
1979 self."wsgiref"
1968 self."zope.cachedescriptors"
1980 self."zope.cachedescriptors"
1969 self."zope.deprecation"
1981 self."zope.deprecation"
1970 self."zope.event"
1982 self."zope.event"
1971 self."zope.interface"
1983 self."zope.interface"
1972 self."mysql-python"
1984 self."mysql-python"
1973 self."pymysql"
1985 self."pymysql"
1974 self."pysqlite"
1986 self."pysqlite"
1975 self."psycopg2"
1987 self."psycopg2"
1976 self."nbconvert"
1988 self."nbconvert"
1977 self."nbformat"
1989 self."nbformat"
1978 self."jupyter-client"
1990 self."jupyter-client"
1979 self."jupyter-core"
1991 self."jupyter-core"
1980 self."alembic"
1992 self."alembic"
1981 self."invoke"
1993 self."invoke"
1982 self."bumpversion"
1994 self."bumpversion"
1983 self."gevent"
1995 self."gevent"
1984 self."greenlet"
1996 self."greenlet"
1985 self."gunicorn"
1997 self."gunicorn"
1986 self."waitress"
1998 self."waitress"
1987 self."ipdb"
1999 self."ipdb"
1988 self."ipython"
2000 self."ipython"
1989 self."rhodecode-tools"
2001 self."rhodecode-tools"
1990 self."appenlight-client"
2002 self."appenlight-client"
1991 self."pytest"
2003 self."pytest"
1992 self."py"
2004 self."py"
1993 self."pytest-cov"
2005 self."pytest-cov"
1994 self."pytest-sugar"
2006 self."pytest-sugar"
1995 self."pytest-runner"
2007 self."pytest-runner"
1996 self."pytest-profiling"
2008 self."pytest-profiling"
1997 self."pytest-timeout"
2009 self."pytest-timeout"
1998 self."gprof2dot"
2010 self."gprof2dot"
1999 self."mock"
2011 self."mock"
2000 self."cov-core"
2012 self."cov-core"
2001 self."coverage"
2013 self."coverage"
2002 self."webtest"
2014 self."webtest"
2003 self."beautifulsoup4"
2015 self."beautifulsoup4"
2004 ];
2016 ];
2005 src = ./.;
2017 src = ./.;
2006 meta = {
2018 meta = {
2007 license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
2019 license = [ { fullName = "Affero GNU General Public License v3 or later (AGPLv3+)"; } { fullName = "AGPLv3, and Commercial License"; } ];
2008 };
2020 };
2009 };
2021 };
2010 "rhodecode-tools" = super.buildPythonPackage {
2022 "rhodecode-tools" = super.buildPythonPackage {
2011 name = "rhodecode-tools-1.4.0";
2023 name = "rhodecode-tools-1.4.0";
2012 doCheck = false;
2024 doCheck = false;
2013 propagatedBuildInputs = [
2025 propagatedBuildInputs = [
2014 self."click"
2026 self."click"
2015 self."future"
2027 self."future"
2016 self."six"
2028 self."six"
2017 self."mako"
2029 self."mako"
2018 self."markupsafe"
2030 self."markupsafe"
2019 self."requests"
2031 self."requests"
2020 self."urllib3"
2032 self."urllib3"
2021 self."whoosh"
2033 self."whoosh"
2022 self."elasticsearch"
2034 self."elasticsearch"
2023 self."elasticsearch-dsl"
2035 self."elasticsearch-dsl"
2024 self."elasticsearch2"
2036 self."elasticsearch2"
2025 self."elasticsearch1-dsl"
2037 self."elasticsearch1-dsl"
2026 ];
2038 ];
2027 src = fetchurl {
2039 src = fetchurl {
2028 url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a";
2040 url = "https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a";
2029 sha256 = "0fjszppj3zhh47g1i6b9xqps28gzfxdkzwb47pdmzrd1sfx29w3n";
2041 sha256 = "0fjszppj3zhh47g1i6b9xqps28gzfxdkzwb47pdmzrd1sfx29w3n";
2030 };
2042 };
2031 meta = {
2043 meta = {
2032 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
2044 license = [ { fullName = "Apache 2.0 and Proprietary"; } ];
2033 };
2045 };
2034 };
2046 };
2035 "routes" = super.buildPythonPackage {
2047 "routes" = super.buildPythonPackage {
2036 name = "routes-2.4.1";
2048 name = "routes-2.4.1";
2037 doCheck = false;
2049 doCheck = false;
2038 propagatedBuildInputs = [
2050 propagatedBuildInputs = [
2039 self."six"
2051 self."six"
2040 self."repoze.lru"
2052 self."repoze.lru"
2041 ];
2053 ];
2042 src = fetchurl {
2054 src = fetchurl {
2043 url = "https://files.pythonhosted.org/packages/33/38/ea827837e68d9c7dde4cff7ec122a93c319f0effc08ce92a17095576603f/Routes-2.4.1.tar.gz";
2055 url = "https://files.pythonhosted.org/packages/33/38/ea827837e68d9c7dde4cff7ec122a93c319f0effc08ce92a17095576603f/Routes-2.4.1.tar.gz";
2044 sha256 = "1zamff3m0kc4vyfniyhxpkkcqv1rrgnmh37ykxv34nna1ws47vi6";
2056 sha256 = "1zamff3m0kc4vyfniyhxpkkcqv1rrgnmh37ykxv34nna1ws47vi6";
2045 };
2057 };
2046 meta = {
2058 meta = {
2047 license = [ pkgs.lib.licenses.mit ];
2059 license = [ pkgs.lib.licenses.mit ];
2048 };
2060 };
2049 };
2061 };
2050 "scandir" = super.buildPythonPackage {
2062 "scandir" = super.buildPythonPackage {
2051 name = "scandir-1.10.0";
2063 name = "scandir-1.10.0";
2052 doCheck = false;
2064 doCheck = false;
2053 src = fetchurl {
2065 src = fetchurl {
2054 url = "https://files.pythonhosted.org/packages/df/f5/9c052db7bd54d0cbf1bc0bb6554362bba1012d03e5888950a4f5c5dadc4e/scandir-1.10.0.tar.gz";
2066 url = "https://files.pythonhosted.org/packages/df/f5/9c052db7bd54d0cbf1bc0bb6554362bba1012d03e5888950a4f5c5dadc4e/scandir-1.10.0.tar.gz";
2055 sha256 = "1bkqwmf056pkchf05ywbnf659wqlp6lljcdb0y88wr9f0vv32ijd";
2067 sha256 = "1bkqwmf056pkchf05ywbnf659wqlp6lljcdb0y88wr9f0vv32ijd";
2056 };
2068 };
2057 meta = {
2069 meta = {
2058 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ];
2070 license = [ pkgs.lib.licenses.bsdOriginal { fullName = "New BSD License"; } ];
2059 };
2071 };
2060 };
2072 };
2061 "setproctitle" = super.buildPythonPackage {
2073 "setproctitle" = super.buildPythonPackage {
2062 name = "setproctitle-1.1.10";
2074 name = "setproctitle-1.1.10";
2063 doCheck = false;
2075 doCheck = false;
2064 src = fetchurl {
2076 src = fetchurl {
2065 url = "https://files.pythonhosted.org/packages/5a/0d/dc0d2234aacba6cf1a729964383e3452c52096dc695581248b548786f2b3/setproctitle-1.1.10.tar.gz";
2077 url = "https://files.pythonhosted.org/packages/5a/0d/dc0d2234aacba6cf1a729964383e3452c52096dc695581248b548786f2b3/setproctitle-1.1.10.tar.gz";
2066 sha256 = "163kplw9dcrw0lffq1bvli5yws3rngpnvrxrzdw89pbphjjvg0v2";
2078 sha256 = "163kplw9dcrw0lffq1bvli5yws3rngpnvrxrzdw89pbphjjvg0v2";
2067 };
2079 };
2068 meta = {
2080 meta = {
2069 license = [ pkgs.lib.licenses.bsdOriginal ];
2081 license = [ pkgs.lib.licenses.bsdOriginal ];
2070 };
2082 };
2071 };
2083 };
2072 "setuptools" = super.buildPythonPackage {
2084 "setuptools" = super.buildPythonPackage {
2073 name = "setuptools-44.1.0";
2085 name = "setuptools-44.1.0";
2074 doCheck = false;
2086 doCheck = false;
2075 src = fetchurl {
2087 src = fetchurl {
2076 url = "https://files.pythonhosted.org/packages/ed/7b/bbf89ca71e722b7f9464ebffe4b5ee20a9e5c9a555a56e2d3914bb9119a6/setuptools-44.1.0.zip";
2088 url = "https://files.pythonhosted.org/packages/ed/7b/bbf89ca71e722b7f9464ebffe4b5ee20a9e5c9a555a56e2d3914bb9119a6/setuptools-44.1.0.zip";
2077 sha256 = "1jja896zvd1ppccnjbhkgagxbwchgq6vfamp6qn1hvywq6q9cjkr";
2089 sha256 = "1jja896zvd1ppccnjbhkgagxbwchgq6vfamp6qn1hvywq6q9cjkr";
2078 };
2090 };
2079 meta = {
2091 meta = {
2080 license = [ pkgs.lib.licenses.mit ];
2092 license = [ pkgs.lib.licenses.mit ];
2081 };
2093 };
2082 };
2094 };
2083 "simplegeneric" = super.buildPythonPackage {
2095 "simplegeneric" = super.buildPythonPackage {
2084 name = "simplegeneric-0.8.1";
2096 name = "simplegeneric-0.8.1";
2085 doCheck = false;
2097 doCheck = false;
2086 src = fetchurl {
2098 src = fetchurl {
2087 url = "https://files.pythonhosted.org/packages/3d/57/4d9c9e3ae9a255cd4e1106bb57e24056d3d0709fc01b2e3e345898e49d5b/simplegeneric-0.8.1.zip";
2099 url = "https://files.pythonhosted.org/packages/3d/57/4d9c9e3ae9a255cd4e1106bb57e24056d3d0709fc01b2e3e345898e49d5b/simplegeneric-0.8.1.zip";
2088 sha256 = "0wwi1c6md4vkbcsfsf8dklf3vr4mcdj4mpxkanwgb6jb1432x5yw";
2100 sha256 = "0wwi1c6md4vkbcsfsf8dklf3vr4mcdj4mpxkanwgb6jb1432x5yw";
2089 };
2101 };
2090 meta = {
2102 meta = {
2091 license = [ pkgs.lib.licenses.zpl21 ];
2103 license = [ pkgs.lib.licenses.zpl21 ];
2092 };
2104 };
2093 };
2105 };
2094 "simplejson" = super.buildPythonPackage {
2106 "simplejson" = super.buildPythonPackage {
2095 name = "simplejson-3.16.0";
2107 name = "simplejson-3.16.0";
2096 doCheck = false;
2108 doCheck = false;
2097 src = fetchurl {
2109 src = fetchurl {
2098 url = "https://files.pythonhosted.org/packages/e3/24/c35fb1c1c315fc0fffe61ea00d3f88e85469004713dab488dee4f35b0aff/simplejson-3.16.0.tar.gz";
2110 url = "https://files.pythonhosted.org/packages/e3/24/c35fb1c1c315fc0fffe61ea00d3f88e85469004713dab488dee4f35b0aff/simplejson-3.16.0.tar.gz";
2099 sha256 = "19cws1syk8jzq2pw43878dv6fjkb0ifvjpx0i9aajix6kc9jkwxi";
2111 sha256 = "19cws1syk8jzq2pw43878dv6fjkb0ifvjpx0i9aajix6kc9jkwxi";
2100 };
2112 };
2101 meta = {
2113 meta = {
2102 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
2114 license = [ { fullName = "Academic Free License (AFL)"; } pkgs.lib.licenses.mit ];
2103 };
2115 };
2104 };
2116 };
2105 "six" = super.buildPythonPackage {
2117 "six" = super.buildPythonPackage {
2106 name = "six-1.11.0";
2118 name = "six-1.11.0";
2107 doCheck = false;
2119 doCheck = false;
2108 src = fetchurl {
2120 src = fetchurl {
2109 url = "https://files.pythonhosted.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz";
2121 url = "https://files.pythonhosted.org/packages/16/d8/bc6316cf98419719bd59c91742194c111b6f2e85abac88e496adefaf7afe/six-1.11.0.tar.gz";
2110 sha256 = "1scqzwc51c875z23phj48gircqjgnn3af8zy2izjwmnlxrxsgs3h";
2122 sha256 = "1scqzwc51c875z23phj48gircqjgnn3af8zy2izjwmnlxrxsgs3h";
2111 };
2123 };
2112 meta = {
2124 meta = {
2113 license = [ pkgs.lib.licenses.mit ];
2125 license = [ pkgs.lib.licenses.mit ];
2114 };
2126 };
2115 };
2127 };
2116 "sqlalchemy" = super.buildPythonPackage {
2128 "sqlalchemy" = super.buildPythonPackage {
2117 name = "sqlalchemy-1.3.15";
2129 name = "sqlalchemy-1.3.15";
2118 doCheck = false;
2130 doCheck = false;
2119 src = fetchurl {
2131 src = fetchurl {
2120 url = "https://files.pythonhosted.org/packages/8c/30/4134e726dd5ed13728ff814fa91fc01c447ad8700504653fe99d91fdd34b/SQLAlchemy-1.3.15.tar.gz";
2132 url = "https://files.pythonhosted.org/packages/8c/30/4134e726dd5ed13728ff814fa91fc01c447ad8700504653fe99d91fdd34b/SQLAlchemy-1.3.15.tar.gz";
2121 sha256 = "0iglkvymfp35zm5pxy5kzqvcv96kkas0chqdx7xpla86sspa9k64";
2133 sha256 = "0iglkvymfp35zm5pxy5kzqvcv96kkas0chqdx7xpla86sspa9k64";
2122 };
2134 };
2123 meta = {
2135 meta = {
2124 license = [ pkgs.lib.licenses.mit ];
2136 license = [ pkgs.lib.licenses.mit ];
2125 };
2137 };
2126 };
2138 };
2127 "sshpubkeys" = super.buildPythonPackage {
2139 "sshpubkeys" = super.buildPythonPackage {
2128 name = "sshpubkeys-3.1.0";
2140 name = "sshpubkeys-3.1.0";
2129 doCheck = false;
2141 doCheck = false;
2130 propagatedBuildInputs = [
2142 propagatedBuildInputs = [
2131 self."cryptography"
2143 self."cryptography"
2132 self."ecdsa"
2144 self."ecdsa"
2133 ];
2145 ];
2134 src = fetchurl {
2146 src = fetchurl {
2135 url = "https://files.pythonhosted.org/packages/00/23/f7508a12007c96861c3da811992f14283d79c819d71a217b3e12d5196649/sshpubkeys-3.1.0.tar.gz";
2147 url = "https://files.pythonhosted.org/packages/00/23/f7508a12007c96861c3da811992f14283d79c819d71a217b3e12d5196649/sshpubkeys-3.1.0.tar.gz";
2136 sha256 = "105g2li04nm1hb15a2y6hm9m9k7fbrkd5l3gy12w3kgcmsf3k25k";
2148 sha256 = "105g2li04nm1hb15a2y6hm9m9k7fbrkd5l3gy12w3kgcmsf3k25k";
2137 };
2149 };
2138 meta = {
2150 meta = {
2139 license = [ pkgs.lib.licenses.bsdOriginal ];
2151 license = [ pkgs.lib.licenses.bsdOriginal ];
2140 };
2152 };
2141 };
2153 };
2142 "subprocess32" = super.buildPythonPackage {
2154 "subprocess32" = super.buildPythonPackage {
2143 name = "subprocess32-3.5.4";
2155 name = "subprocess32-3.5.4";
2144 doCheck = false;
2156 doCheck = false;
2145 src = fetchurl {
2157 src = fetchurl {
2146 url = "https://files.pythonhosted.org/packages/32/c8/564be4d12629b912ea431f1a50eb8b3b9d00f1a0b1ceff17f266be190007/subprocess32-3.5.4.tar.gz";
2158 url = "https://files.pythonhosted.org/packages/32/c8/564be4d12629b912ea431f1a50eb8b3b9d00f1a0b1ceff17f266be190007/subprocess32-3.5.4.tar.gz";
2147 sha256 = "17f7mvwx2271s1wrl0qac3wjqqnrqag866zs3qc8v5wp0k43fagb";
2159 sha256 = "17f7mvwx2271s1wrl0qac3wjqqnrqag866zs3qc8v5wp0k43fagb";
2148 };
2160 };
2149 meta = {
2161 meta = {
2150 license = [ pkgs.lib.licenses.psfl ];
2162 license = [ pkgs.lib.licenses.psfl ];
2151 };
2163 };
2152 };
2164 };
2153 "supervisor" = super.buildPythonPackage {
2165 "supervisor" = super.buildPythonPackage {
2154 name = "supervisor-4.1.0";
2166 name = "supervisor-4.1.0";
2155 doCheck = false;
2167 doCheck = false;
2156 src = fetchurl {
2168 src = fetchurl {
2157 url = "https://files.pythonhosted.org/packages/de/87/ee1ad8fa533a4b5f2c7623f4a2b585d3c1947af7bed8e65bc7772274320e/supervisor-4.1.0.tar.gz";
2169 url = "https://files.pythonhosted.org/packages/de/87/ee1ad8fa533a4b5f2c7623f4a2b585d3c1947af7bed8e65bc7772274320e/supervisor-4.1.0.tar.gz";
2158 sha256 = "10q36sa1jqljyyyl7cif52akpygl5kmlqq9x91hmx53f8zh6zj1d";
2170 sha256 = "10q36sa1jqljyyyl7cif52akpygl5kmlqq9x91hmx53f8zh6zj1d";
2159 };
2171 };
2160 meta = {
2172 meta = {
2161 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2173 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2162 };
2174 };
2163 };
2175 };
2164 "tempita" = super.buildPythonPackage {
2176 "tempita" = super.buildPythonPackage {
2165 name = "tempita-0.5.2";
2177 name = "tempita-0.5.2";
2166 doCheck = false;
2178 doCheck = false;
2167 src = fetchurl {
2179 src = fetchurl {
2168 url = "https://files.pythonhosted.org/packages/56/c8/8ed6eee83dbddf7b0fc64dd5d4454bc05e6ccaafff47991f73f2894d9ff4/Tempita-0.5.2.tar.gz";
2180 url = "https://files.pythonhosted.org/packages/56/c8/8ed6eee83dbddf7b0fc64dd5d4454bc05e6ccaafff47991f73f2894d9ff4/Tempita-0.5.2.tar.gz";
2169 sha256 = "177wwq45slfyajd8csy477bmdmzipyw0dm7i85k3akb7m85wzkna";
2181 sha256 = "177wwq45slfyajd8csy477bmdmzipyw0dm7i85k3akb7m85wzkna";
2170 };
2182 };
2171 meta = {
2183 meta = {
2172 license = [ pkgs.lib.licenses.mit ];
2184 license = [ pkgs.lib.licenses.mit ];
2173 };
2185 };
2174 };
2186 };
2175 "termcolor" = super.buildPythonPackage {
2187 "termcolor" = super.buildPythonPackage {
2176 name = "termcolor-1.1.0";
2188 name = "termcolor-1.1.0";
2177 doCheck = false;
2189 doCheck = false;
2178 src = fetchurl {
2190 src = fetchurl {
2179 url = "https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz";
2191 url = "https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz";
2180 sha256 = "0fv1vq14rpqwgazxg4981904lfyp84mnammw7y046491cv76jv8x";
2192 sha256 = "0fv1vq14rpqwgazxg4981904lfyp84mnammw7y046491cv76jv8x";
2181 };
2193 };
2182 meta = {
2194 meta = {
2183 license = [ pkgs.lib.licenses.mit ];
2195 license = [ pkgs.lib.licenses.mit ];
2184 };
2196 };
2185 };
2197 };
2186 "testpath" = super.buildPythonPackage {
2198 "testpath" = super.buildPythonPackage {
2187 name = "testpath-0.4.4";
2199 name = "testpath-0.4.4";
2188 doCheck = false;
2200 doCheck = false;
2189 src = fetchurl {
2201 src = fetchurl {
2190 url = "https://files.pythonhosted.org/packages/2c/b3/5d57205e896d8998d77ad12aa42ebce75cd97d8b9a97d00ba078c4c9ffeb/testpath-0.4.4.tar.gz";
2202 url = "https://files.pythonhosted.org/packages/2c/b3/5d57205e896d8998d77ad12aa42ebce75cd97d8b9a97d00ba078c4c9ffeb/testpath-0.4.4.tar.gz";
2191 sha256 = "0zpcmq22dz79ipvvsfnw1ykpjcaj6xyzy7ws77s5b5ql3hka7q30";
2203 sha256 = "0zpcmq22dz79ipvvsfnw1ykpjcaj6xyzy7ws77s5b5ql3hka7q30";
2192 };
2204 };
2193 meta = {
2205 meta = {
2194 license = [ ];
2206 license = [ ];
2195 };
2207 };
2196 };
2208 };
2197 "traitlets" = super.buildPythonPackage {
2209 "traitlets" = super.buildPythonPackage {
2198 name = "traitlets-4.3.3";
2210 name = "traitlets-4.3.3";
2199 doCheck = false;
2211 doCheck = false;
2200 propagatedBuildInputs = [
2212 propagatedBuildInputs = [
2201 self."ipython-genutils"
2213 self."ipython-genutils"
2202 self."six"
2214 self."six"
2203 self."decorator"
2215 self."decorator"
2204 self."enum34"
2216 self."enum34"
2205 ];
2217 ];
2206 src = fetchurl {
2218 src = fetchurl {
2207 url = "https://files.pythonhosted.org/packages/75/b0/43deb021bc943f18f07cbe3dac1d681626a48997b7ffa1e7fb14ef922b21/traitlets-4.3.3.tar.gz";
2219 url = "https://files.pythonhosted.org/packages/75/b0/43deb021bc943f18f07cbe3dac1d681626a48997b7ffa1e7fb14ef922b21/traitlets-4.3.3.tar.gz";
2208 sha256 = "1xsrwgivpkxlbr4dfndfsi098s29yqgswgjc1qqn69yxklvfw8yh";
2220 sha256 = "1xsrwgivpkxlbr4dfndfsi098s29yqgswgjc1qqn69yxklvfw8yh";
2209 };
2221 };
2210 meta = {
2222 meta = {
2211 license = [ pkgs.lib.licenses.bsdOriginal ];
2223 license = [ pkgs.lib.licenses.bsdOriginal ];
2212 };
2224 };
2213 };
2225 };
2214 "transaction" = super.buildPythonPackage {
2226 "transaction" = super.buildPythonPackage {
2215 name = "transaction-2.4.0";
2227 name = "transaction-2.4.0";
2216 doCheck = false;
2228 doCheck = false;
2217 propagatedBuildInputs = [
2229 propagatedBuildInputs = [
2218 self."zope.interface"
2230 self."zope.interface"
2219 ];
2231 ];
2220 src = fetchurl {
2232 src = fetchurl {
2221 url = "https://files.pythonhosted.org/packages/9d/7d/0e8af0d059e052b9dcf2bb5a08aad20ae3e238746bdd3f8701a60969b363/transaction-2.4.0.tar.gz";
2233 url = "https://files.pythonhosted.org/packages/9d/7d/0e8af0d059e052b9dcf2bb5a08aad20ae3e238746bdd3f8701a60969b363/transaction-2.4.0.tar.gz";
2222 sha256 = "17wz1y524ca07vr03yddy8dv0gbscs06dbdywmllxv5rc725jq3j";
2234 sha256 = "17wz1y524ca07vr03yddy8dv0gbscs06dbdywmllxv5rc725jq3j";
2223 };
2235 };
2224 meta = {
2236 meta = {
2225 license = [ pkgs.lib.licenses.zpl21 ];
2237 license = [ pkgs.lib.licenses.zpl21 ];
2226 };
2238 };
2227 };
2239 };
2228 "translationstring" = super.buildPythonPackage {
2240 "translationstring" = super.buildPythonPackage {
2229 name = "translationstring-1.3";
2241 name = "translationstring-1.3";
2230 doCheck = false;
2242 doCheck = false;
2231 src = fetchurl {
2243 src = fetchurl {
2232 url = "https://files.pythonhosted.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz";
2244 url = "https://files.pythonhosted.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz";
2233 sha256 = "0bdpcnd9pv0131dl08h4zbcwmgc45lyvq3pa224xwan5b3x4rr2f";
2245 sha256 = "0bdpcnd9pv0131dl08h4zbcwmgc45lyvq3pa224xwan5b3x4rr2f";
2234 };
2246 };
2235 meta = {
2247 meta = {
2236 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
2248 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
2237 };
2249 };
2238 };
2250 };
2239 "tzlocal" = super.buildPythonPackage {
2251 "tzlocal" = super.buildPythonPackage {
2240 name = "tzlocal-1.5.1";
2252 name = "tzlocal-1.5.1";
2241 doCheck = false;
2253 doCheck = false;
2242 propagatedBuildInputs = [
2254 propagatedBuildInputs = [
2243 self."pytz"
2255 self."pytz"
2244 ];
2256 ];
2245 src = fetchurl {
2257 src = fetchurl {
2246 url = "https://files.pythonhosted.org/packages/cb/89/e3687d3ed99bc882793f82634e9824e62499fdfdc4b1ae39e211c5b05017/tzlocal-1.5.1.tar.gz";
2258 url = "https://files.pythonhosted.org/packages/cb/89/e3687d3ed99bc882793f82634e9824e62499fdfdc4b1ae39e211c5b05017/tzlocal-1.5.1.tar.gz";
2247 sha256 = "0kiciwiqx0bv0fbc913idxibc4ygg4cb7f8rcpd9ij2shi4bigjf";
2259 sha256 = "0kiciwiqx0bv0fbc913idxibc4ygg4cb7f8rcpd9ij2shi4bigjf";
2248 };
2260 };
2249 meta = {
2261 meta = {
2250 license = [ pkgs.lib.licenses.mit ];
2262 license = [ pkgs.lib.licenses.mit ];
2251 };
2263 };
2252 };
2264 };
2253 "urllib3" = super.buildPythonPackage {
2265 "urllib3" = super.buildPythonPackage {
2254 name = "urllib3-1.25.2";
2266 name = "urllib3-1.25.2";
2255 doCheck = false;
2267 doCheck = false;
2256 src = fetchurl {
2268 src = fetchurl {
2257 url = "https://files.pythonhosted.org/packages/9a/8b/ea6d2beb2da6e331e9857d0a60b79ed4f72dcbc4e2c7f2d2521b0480fda2/urllib3-1.25.2.tar.gz";
2269 url = "https://files.pythonhosted.org/packages/9a/8b/ea6d2beb2da6e331e9857d0a60b79ed4f72dcbc4e2c7f2d2521b0480fda2/urllib3-1.25.2.tar.gz";
2258 sha256 = "1nq2k4pss1ihsjh02r41sqpjpm5rfqkjfysyq7g7n2i1p7c66c55";
2270 sha256 = "1nq2k4pss1ihsjh02r41sqpjpm5rfqkjfysyq7g7n2i1p7c66c55";
2259 };
2271 };
2260 meta = {
2272 meta = {
2261 license = [ pkgs.lib.licenses.mit ];
2273 license = [ pkgs.lib.licenses.mit ];
2262 };
2274 };
2263 };
2275 };
2264 "urlobject" = super.buildPythonPackage {
2276 "urlobject" = super.buildPythonPackage {
2265 name = "urlobject-2.4.3";
2277 name = "urlobject-2.4.3";
2266 doCheck = false;
2278 doCheck = false;
2267 src = fetchurl {
2279 src = fetchurl {
2268 url = "https://files.pythonhosted.org/packages/e2/b8/1d0a916f4b34c4618846e6da0e4eeaa8fcb4a2f39e006434fe38acb74b34/URLObject-2.4.3.tar.gz";
2280 url = "https://files.pythonhosted.org/packages/e2/b8/1d0a916f4b34c4618846e6da0e4eeaa8fcb4a2f39e006434fe38acb74b34/URLObject-2.4.3.tar.gz";
2269 sha256 = "1ahc8ficzfvr2avln71immfh4ls0zyv6cdaa5xmkdj5rd87f5cj7";
2281 sha256 = "1ahc8ficzfvr2avln71immfh4ls0zyv6cdaa5xmkdj5rd87f5cj7";
2270 };
2282 };
2271 meta = {
2283 meta = {
2272 license = [ pkgs.lib.licenses.publicDomain ];
2284 license = [ pkgs.lib.licenses.publicDomain ];
2273 };
2285 };
2274 };
2286 };
2275 "venusian" = super.buildPythonPackage {
2287 "venusian" = super.buildPythonPackage {
2276 name = "venusian-1.2.0";
2288 name = "venusian-1.2.0";
2277 doCheck = false;
2289 doCheck = false;
2278 src = fetchurl {
2290 src = fetchurl {
2279 url = "https://files.pythonhosted.org/packages/7e/6f/40a9d43ac77cb51cb62be5b5662d170f43f8037bdc4eab56336c4ca92bb7/venusian-1.2.0.tar.gz";
2291 url = "https://files.pythonhosted.org/packages/7e/6f/40a9d43ac77cb51cb62be5b5662d170f43f8037bdc4eab56336c4ca92bb7/venusian-1.2.0.tar.gz";
2280 sha256 = "0ghyx66g8ikx9nx1mnwqvdcqm11i1vlq0hnvwl50s48bp22q5v34";
2292 sha256 = "0ghyx66g8ikx9nx1mnwqvdcqm11i1vlq0hnvwl50s48bp22q5v34";
2281 };
2293 };
2282 meta = {
2294 meta = {
2283 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2295 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
2284 };
2296 };
2285 };
2297 };
2286 "vine" = super.buildPythonPackage {
2298 "vine" = super.buildPythonPackage {
2287 name = "vine-1.3.0";
2299 name = "vine-1.3.0";
2288 doCheck = false;
2300 doCheck = false;
2289 src = fetchurl {
2301 src = fetchurl {
2290 url = "https://files.pythonhosted.org/packages/1c/e1/79fb8046e607dd6c2ad05c9b8ebac9d0bd31d086a08f02699e96fc5b3046/vine-1.3.0.tar.gz";
2302 url = "https://files.pythonhosted.org/packages/1c/e1/79fb8046e607dd6c2ad05c9b8ebac9d0bd31d086a08f02699e96fc5b3046/vine-1.3.0.tar.gz";
2291 sha256 = "11ydsbhl1vabndc2r979dv61s6j2b0giq6dgvryifvq1m7bycghk";
2303 sha256 = "11ydsbhl1vabndc2r979dv61s6j2b0giq6dgvryifvq1m7bycghk";
2292 };
2304 };
2293 meta = {
2305 meta = {
2294 license = [ pkgs.lib.licenses.bsdOriginal ];
2306 license = [ pkgs.lib.licenses.bsdOriginal ];
2295 };
2307 };
2296 };
2308 };
2297 "waitress" = super.buildPythonPackage {
2309 "waitress" = super.buildPythonPackage {
2298 name = "waitress-1.3.1";
2310 name = "waitress-1.3.1";
2299 doCheck = false;
2311 doCheck = false;
2300 src = fetchurl {
2312 src = fetchurl {
2301 url = "https://files.pythonhosted.org/packages/a6/e6/708da7bba65898e5d759ade8391b1077e49d07be0b0223c39f5be04def56/waitress-1.3.1.tar.gz";
2313 url = "https://files.pythonhosted.org/packages/a6/e6/708da7bba65898e5d759ade8391b1077e49d07be0b0223c39f5be04def56/waitress-1.3.1.tar.gz";
2302 sha256 = "1iysl8ka3l4cdrr0r19fh1cv28q41mwpvgsb81ji7k4shkb0k3i7";
2314 sha256 = "1iysl8ka3l4cdrr0r19fh1cv28q41mwpvgsb81ji7k4shkb0k3i7";
2303 };
2315 };
2304 meta = {
2316 meta = {
2305 license = [ pkgs.lib.licenses.zpl21 ];
2317 license = [ pkgs.lib.licenses.zpl21 ];
2306 };
2318 };
2307 };
2319 };
2308 "wcwidth" = super.buildPythonPackage {
2320 "wcwidth" = super.buildPythonPackage {
2309 name = "wcwidth-0.1.9";
2321 name = "wcwidth-0.1.9";
2310 doCheck = false;
2322 doCheck = false;
2311 src = fetchurl {
2323 src = fetchurl {
2312 url = "https://files.pythonhosted.org/packages/25/9d/0acbed6e4a4be4fc99148f275488580968f44ddb5e69b8ceb53fc9df55a0/wcwidth-0.1.9.tar.gz";
2324 url = "https://files.pythonhosted.org/packages/25/9d/0acbed6e4a4be4fc99148f275488580968f44ddb5e69b8ceb53fc9df55a0/wcwidth-0.1.9.tar.gz";
2313 sha256 = "1wf5ycjx8s066rdvr0fgz4xds9a8zhs91c4jzxvvymm1c8l8cwzf";
2325 sha256 = "1wf5ycjx8s066rdvr0fgz4xds9a8zhs91c4jzxvvymm1c8l8cwzf";
2314 };
2326 };
2315 meta = {
2327 meta = {
2316 license = [ pkgs.lib.licenses.mit ];
2328 license = [ pkgs.lib.licenses.mit ];
2317 };
2329 };
2318 };
2330 };
2319 "webencodings" = super.buildPythonPackage {
2331 "webencodings" = super.buildPythonPackage {
2320 name = "webencodings-0.5.1";
2332 name = "webencodings-0.5.1";
2321 doCheck = false;
2333 doCheck = false;
2322 src = fetchurl {
2334 src = fetchurl {
2323 url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz";
2335 url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz";
2324 sha256 = "08qrgrc4hrximb2gqnl69g01s93rhf2842jfxdjljc1dbwj1qsmk";
2336 sha256 = "08qrgrc4hrximb2gqnl69g01s93rhf2842jfxdjljc1dbwj1qsmk";
2325 };
2337 };
2326 meta = {
2338 meta = {
2327 license = [ pkgs.lib.licenses.bsdOriginal ];
2339 license = [ pkgs.lib.licenses.bsdOriginal ];
2328 };
2340 };
2329 };
2341 };
2330 "weberror" = super.buildPythonPackage {
2342 "weberror" = super.buildPythonPackage {
2331 name = "weberror-0.13.1";
2343 name = "weberror-0.13.1";
2332 doCheck = false;
2344 doCheck = false;
2333 propagatedBuildInputs = [
2345 propagatedBuildInputs = [
2334 self."webob"
2346 self."webob"
2335 self."tempita"
2347 self."tempita"
2336 self."pygments"
2348 self."pygments"
2337 self."paste"
2349 self."paste"
2338 ];
2350 ];
2339 src = fetchurl {
2351 src = fetchurl {
2340 url = "https://files.pythonhosted.org/packages/07/0a/09ca5eb0fab5c0d17b380026babe81c96ecebb13f2b06c3203432dd7be72/WebError-0.13.1.tar.gz";
2352 url = "https://files.pythonhosted.org/packages/07/0a/09ca5eb0fab5c0d17b380026babe81c96ecebb13f2b06c3203432dd7be72/WebError-0.13.1.tar.gz";
2341 sha256 = "0r4qvnf2r92gfnpa1kwygh4j2x6j3axg2i4an6hyxwg2gpaqp7y1";
2353 sha256 = "0r4qvnf2r92gfnpa1kwygh4j2x6j3axg2i4an6hyxwg2gpaqp7y1";
2342 };
2354 };
2343 meta = {
2355 meta = {
2344 license = [ pkgs.lib.licenses.mit ];
2356 license = [ pkgs.lib.licenses.mit ];
2345 };
2357 };
2346 };
2358 };
2347 "webhelpers2" = super.buildPythonPackage {
2359 "webhelpers2" = super.buildPythonPackage {
2348 name = "webhelpers2-2.0";
2360 name = "webhelpers2-2.0";
2349 doCheck = false;
2361 doCheck = false;
2350 propagatedBuildInputs = [
2362 propagatedBuildInputs = [
2351 self."markupsafe"
2363 self."markupsafe"
2352 self."six"
2364 self."six"
2353 ];
2365 ];
2354 src = fetchurl {
2366 src = fetchurl {
2355 url = "https://files.pythonhosted.org/packages/ff/30/56342c6ea522439e3662427c8d7b5e5b390dff4ff2dc92d8afcb8ab68b75/WebHelpers2-2.0.tar.gz";
2367 url = "https://files.pythonhosted.org/packages/ff/30/56342c6ea522439e3662427c8d7b5e5b390dff4ff2dc92d8afcb8ab68b75/WebHelpers2-2.0.tar.gz";
2356 sha256 = "0aphva1qmxh83n01p53f5fd43m4srzbnfbz5ajvbx9aj2aipwmcs";
2368 sha256 = "0aphva1qmxh83n01p53f5fd43m4srzbnfbz5ajvbx9aj2aipwmcs";
2357 };
2369 };
2358 meta = {
2370 meta = {
2359 license = [ pkgs.lib.licenses.mit ];
2371 license = [ pkgs.lib.licenses.mit ];
2360 };
2372 };
2361 };
2373 };
2362 "webob" = super.buildPythonPackage {
2374 "webob" = super.buildPythonPackage {
2363 name = "webob-1.8.5";
2375 name = "webob-1.8.5";
2364 doCheck = false;
2376 doCheck = false;
2365 src = fetchurl {
2377 src = fetchurl {
2366 url = "https://files.pythonhosted.org/packages/9d/1a/0c89c070ee2829c934cb6c7082287c822e28236a4fcf90063e6be7c35532/WebOb-1.8.5.tar.gz";
2378 url = "https://files.pythonhosted.org/packages/9d/1a/0c89c070ee2829c934cb6c7082287c822e28236a4fcf90063e6be7c35532/WebOb-1.8.5.tar.gz";
2367 sha256 = "11khpzaxc88q31v25ic330gsf56fwmbdc9b30br8mvp0fmwspah5";
2379 sha256 = "11khpzaxc88q31v25ic330gsf56fwmbdc9b30br8mvp0fmwspah5";
2368 };
2380 };
2369 meta = {
2381 meta = {
2370 license = [ pkgs.lib.licenses.mit ];
2382 license = [ pkgs.lib.licenses.mit ];
2371 };
2383 };
2372 };
2384 };
2373 "webtest" = super.buildPythonPackage {
2385 "webtest" = super.buildPythonPackage {
2374 name = "webtest-2.0.34";
2386 name = "webtest-2.0.34";
2375 doCheck = false;
2387 doCheck = false;
2376 propagatedBuildInputs = [
2388 propagatedBuildInputs = [
2377 self."six"
2389 self."six"
2378 self."webob"
2390 self."webob"
2379 self."waitress"
2391 self."waitress"
2380 self."beautifulsoup4"
2392 self."beautifulsoup4"
2381 ];
2393 ];
2382 src = fetchurl {
2394 src = fetchurl {
2383 url = "https://files.pythonhosted.org/packages/2c/74/a0e63feee438735d628631e2b70d82280276a930637ac535479e5fad9427/WebTest-2.0.34.tar.gz";
2395 url = "https://files.pythonhosted.org/packages/2c/74/a0e63feee438735d628631e2b70d82280276a930637ac535479e5fad9427/WebTest-2.0.34.tar.gz";
2384 sha256 = "0x1y2c8z4fmpsny4hbp6ka37si2g10r5r2jwxhvv5mx7g3blq4bi";
2396 sha256 = "0x1y2c8z4fmpsny4hbp6ka37si2g10r5r2jwxhvv5mx7g3blq4bi";
2385 };
2397 };
2386 meta = {
2398 meta = {
2387 license = [ pkgs.lib.licenses.mit ];
2399 license = [ pkgs.lib.licenses.mit ];
2388 };
2400 };
2389 };
2401 };
2390 "whoosh" = super.buildPythonPackage {
2402 "whoosh" = super.buildPythonPackage {
2391 name = "whoosh-2.7.4";
2403 name = "whoosh-2.7.4";
2392 doCheck = false;
2404 doCheck = false;
2393 src = fetchurl {
2405 src = fetchurl {
2394 url = "https://files.pythonhosted.org/packages/25/2b/6beed2107b148edc1321da0d489afc4617b9ed317ef7b72d4993cad9b684/Whoosh-2.7.4.tar.gz";
2406 url = "https://files.pythonhosted.org/packages/25/2b/6beed2107b148edc1321da0d489afc4617b9ed317ef7b72d4993cad9b684/Whoosh-2.7.4.tar.gz";
2395 sha256 = "10qsqdjpbc85fykc1vgcs8xwbgn4l2l52c8d83xf1q59pwyn79bw";
2407 sha256 = "10qsqdjpbc85fykc1vgcs8xwbgn4l2l52c8d83xf1q59pwyn79bw";
2396 };
2408 };
2397 meta = {
2409 meta = {
2398 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ];
2410 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.bsd2 ];
2399 };
2411 };
2400 };
2412 };
2401 "ws4py" = super.buildPythonPackage {
2413 "ws4py" = super.buildPythonPackage {
2402 name = "ws4py-0.5.1";
2414 name = "ws4py-0.5.1";
2403 doCheck = false;
2415 doCheck = false;
2404 src = fetchurl {
2416 src = fetchurl {
2405 url = "https://files.pythonhosted.org/packages/53/20/4019a739b2eefe9282d3822ef6a225250af964b117356971bd55e274193c/ws4py-0.5.1.tar.gz";
2417 url = "https://files.pythonhosted.org/packages/53/20/4019a739b2eefe9282d3822ef6a225250af964b117356971bd55e274193c/ws4py-0.5.1.tar.gz";
2406 sha256 = "10slbbf2jm4hpr92jx7kh7mhf48sjl01v2w4d8z3f1p0ybbp7l19";
2418 sha256 = "10slbbf2jm4hpr92jx7kh7mhf48sjl01v2w4d8z3f1p0ybbp7l19";
2407 };
2419 };
2408 meta = {
2420 meta = {
2409 license = [ pkgs.lib.licenses.bsdOriginal ];
2421 license = [ pkgs.lib.licenses.bsdOriginal ];
2410 };
2422 };
2411 };
2423 };
2412 "wsgiref" = super.buildPythonPackage {
2424 "wsgiref" = super.buildPythonPackage {
2413 name = "wsgiref-0.1.2";
2425 name = "wsgiref-0.1.2";
2414 doCheck = false;
2426 doCheck = false;
2415 src = fetchurl {
2427 src = fetchurl {
2416 url = "https://files.pythonhosted.org/packages/41/9e/309259ce8dff8c596e8c26df86dbc4e848b9249fd36797fd60be456f03fc/wsgiref-0.1.2.zip";
2428 url = "https://files.pythonhosted.org/packages/41/9e/309259ce8dff8c596e8c26df86dbc4e848b9249fd36797fd60be456f03fc/wsgiref-0.1.2.zip";
2417 sha256 = "0y8fyjmpq7vwwm4x732w97qbkw78rjwal5409k04cw4m03411rn7";
2429 sha256 = "0y8fyjmpq7vwwm4x732w97qbkw78rjwal5409k04cw4m03411rn7";
2418 };
2430 };
2419 meta = {
2431 meta = {
2420 license = [ { fullName = "PSF or ZPL"; } ];
2432 license = [ { fullName = "PSF or ZPL"; } ];
2421 };
2433 };
2422 };
2434 };
2423 "zipp" = super.buildPythonPackage {
2435 "zipp" = super.buildPythonPackage {
2424 name = "zipp-1.2.0";
2436 name = "zipp-1.2.0";
2425 doCheck = false;
2437 doCheck = false;
2426 propagatedBuildInputs = [
2438 propagatedBuildInputs = [
2427 self."contextlib2"
2439 self."contextlib2"
2428 ];
2440 ];
2429 src = fetchurl {
2441 src = fetchurl {
2430 url = "https://files.pythonhosted.org/packages/78/08/d52f0ea643bc1068d6dc98b412f4966a9b63255d20911a23ac3220c033c4/zipp-1.2.0.tar.gz";
2442 url = "https://files.pythonhosted.org/packages/78/08/d52f0ea643bc1068d6dc98b412f4966a9b63255d20911a23ac3220c033c4/zipp-1.2.0.tar.gz";
2431 sha256 = "1c91lnv1bxjimh8as27hz7bghsjkkbxn1d37xq7in9c82iai0167";
2443 sha256 = "1c91lnv1bxjimh8as27hz7bghsjkkbxn1d37xq7in9c82iai0167";
2432 };
2444 };
2433 meta = {
2445 meta = {
2434 license = [ pkgs.lib.licenses.mit ];
2446 license = [ pkgs.lib.licenses.mit ];
2435 };
2447 };
2436 };
2448 };
2437 "zope.cachedescriptors" = super.buildPythonPackage {
2449 "zope.cachedescriptors" = super.buildPythonPackage {
2438 name = "zope.cachedescriptors-4.3.1";
2450 name = "zope.cachedescriptors-4.3.1";
2439 doCheck = false;
2451 doCheck = false;
2440 propagatedBuildInputs = [
2452 propagatedBuildInputs = [
2441 self."setuptools"
2453 self."setuptools"
2442 ];
2454 ];
2443 src = fetchurl {
2455 src = fetchurl {
2444 url = "https://files.pythonhosted.org/packages/2f/89/ebe1890cc6d3291ebc935558fa764d5fffe571018dbbee200e9db78762cb/zope.cachedescriptors-4.3.1.tar.gz";
2456 url = "https://files.pythonhosted.org/packages/2f/89/ebe1890cc6d3291ebc935558fa764d5fffe571018dbbee200e9db78762cb/zope.cachedescriptors-4.3.1.tar.gz";
2445 sha256 = "0jhr3m5p74c6r7k8iv0005b8bfsialih9d7zl5vx38rf5xq1lk8z";
2457 sha256 = "0jhr3m5p74c6r7k8iv0005b8bfsialih9d7zl5vx38rf5xq1lk8z";
2446 };
2458 };
2447 meta = {
2459 meta = {
2448 license = [ pkgs.lib.licenses.zpl21 ];
2460 license = [ pkgs.lib.licenses.zpl21 ];
2449 };
2461 };
2450 };
2462 };
2451 "zope.deprecation" = super.buildPythonPackage {
2463 "zope.deprecation" = super.buildPythonPackage {
2452 name = "zope.deprecation-4.4.0";
2464 name = "zope.deprecation-4.4.0";
2453 doCheck = false;
2465 doCheck = false;
2454 propagatedBuildInputs = [
2466 propagatedBuildInputs = [
2455 self."setuptools"
2467 self."setuptools"
2456 ];
2468 ];
2457 src = fetchurl {
2469 src = fetchurl {
2458 url = "https://files.pythonhosted.org/packages/34/da/46e92d32d545dd067b9436279d84c339e8b16de2ca393d7b892bc1e1e9fd/zope.deprecation-4.4.0.tar.gz";
2470 url = "https://files.pythonhosted.org/packages/34/da/46e92d32d545dd067b9436279d84c339e8b16de2ca393d7b892bc1e1e9fd/zope.deprecation-4.4.0.tar.gz";
2459 sha256 = "1pz2cv7gv9y1r3m0bdv7ks1alagmrn5msm5spwdzkb2by0w36i8d";
2471 sha256 = "1pz2cv7gv9y1r3m0bdv7ks1alagmrn5msm5spwdzkb2by0w36i8d";
2460 };
2472 };
2461 meta = {
2473 meta = {
2462 license = [ pkgs.lib.licenses.zpl21 ];
2474 license = [ pkgs.lib.licenses.zpl21 ];
2463 };
2475 };
2464 };
2476 };
2465 "zope.event" = super.buildPythonPackage {
2477 "zope.event" = super.buildPythonPackage {
2466 name = "zope.event-4.4";
2478 name = "zope.event-4.4";
2467 doCheck = false;
2479 doCheck = false;
2468 propagatedBuildInputs = [
2480 propagatedBuildInputs = [
2469 self."setuptools"
2481 self."setuptools"
2470 ];
2482 ];
2471 src = fetchurl {
2483 src = fetchurl {
2472 url = "https://files.pythonhosted.org/packages/4c/b2/51c0369adcf5be2334280eed230192ab3b03f81f8efda9ddea6f65cc7b32/zope.event-4.4.tar.gz";
2484 url = "https://files.pythonhosted.org/packages/4c/b2/51c0369adcf5be2334280eed230192ab3b03f81f8efda9ddea6f65cc7b32/zope.event-4.4.tar.gz";
2473 sha256 = "1ksbc726av9xacml6jhcfyn828hlhb9xlddpx6fcvnlvmpmpvhk9";
2485 sha256 = "1ksbc726av9xacml6jhcfyn828hlhb9xlddpx6fcvnlvmpmpvhk9";
2474 };
2486 };
2475 meta = {
2487 meta = {
2476 license = [ pkgs.lib.licenses.zpl21 ];
2488 license = [ pkgs.lib.licenses.zpl21 ];
2477 };
2489 };
2478 };
2490 };
2479 "zope.interface" = super.buildPythonPackage {
2491 "zope.interface" = super.buildPythonPackage {
2480 name = "zope.interface-4.6.0";
2492 name = "zope.interface-4.6.0";
2481 doCheck = false;
2493 doCheck = false;
2482 propagatedBuildInputs = [
2494 propagatedBuildInputs = [
2483 self."setuptools"
2495 self."setuptools"
2484 ];
2496 ];
2485 src = fetchurl {
2497 src = fetchurl {
2486 url = "https://files.pythonhosted.org/packages/4e/d0/c9d16bd5b38de44a20c6dc5d5ed80a49626fafcb3db9f9efdc2a19026db6/zope.interface-4.6.0.tar.gz";
2498 url = "https://files.pythonhosted.org/packages/4e/d0/c9d16bd5b38de44a20c6dc5d5ed80a49626fafcb3db9f9efdc2a19026db6/zope.interface-4.6.0.tar.gz";
2487 sha256 = "1rgh2x3rcl9r0v0499kf78xy86rnmanajf4ywmqb943wpk50sg8v";
2499 sha256 = "1rgh2x3rcl9r0v0499kf78xy86rnmanajf4ywmqb943wpk50sg8v";
2488 };
2500 };
2489 meta = {
2501 meta = {
2490 license = [ pkgs.lib.licenses.zpl21 ];
2502 license = [ pkgs.lib.licenses.zpl21 ];
2491 };
2503 };
2492 };
2504 };
2493
2505
2494 ### Test requirements
2506 ### Test requirements
2495
2507
2496
2508
2497 }
2509 }
@@ -1,123 +1,124 b''
1 ## dependencies
1 ## dependencies
2
2
3 amqp==2.5.2
3 amqp==2.5.2
4 babel==1.3
4 babel==1.3
5 beaker==1.9.1
5 beaker==1.9.1
6 bleach==3.1.3
6 bleach==3.1.3
7 celery==4.3.0
7 celery==4.3.0
8 channelstream==0.6.14
8 channelstream==0.6.14
9 click==7.0
9 click==7.0
10 colander==1.7.0
10 colander==1.7.0
11 # our custom configobj
11 # our custom configobj
12 https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626#egg=configobj==5.0.6
12 https://code.rhodecode.com/upstream/configobj/artifacts/download/0-012de99a-b1e1-4f64-a5c0-07a98a41b324.tar.gz?md5=6a513f51fe04b2c18cf84c1395a7c626#egg=configobj==5.0.6
13 cssselect==1.0.3
13 cssselect==1.0.3
14 cryptography==2.6.1
14 cryptography==2.6.1
15 decorator==4.1.2
15 decorator==4.1.2
16 deform==2.0.8
16 deform==2.0.8
17 docutils==0.16.0
17 docutils==0.16.0
18 dogpile.cache==0.9.0
18 dogpile.cache==0.9.0
19 dogpile.core==0.4.1
19 dogpile.core==0.4.1
20 formencode==1.2.4
20 formencode==1.2.4
21 future==0.14.3
21 future==0.14.3
22 futures==3.0.2
22 futures==3.0.2
23 infrae.cache==1.0.1
23 infrae.cache==1.0.1
24 iso8601==0.1.12
24 iso8601==0.1.12
25 itsdangerous==1.1.0
25 itsdangerous==1.1.0
26 kombu==4.6.6
26 kombu==4.6.6
27 lxml==4.2.5
27 lxml==4.2.5
28 mako==1.1.0
28 mako==1.1.0
29 markdown==2.6.11
29 markdown==2.6.11
30 markupsafe==1.1.1
30 markupsafe==1.1.1
31 msgpack-python==0.5.6
31 msgpack-python==0.5.6
32 pyotp==2.3.0
32 pyotp==2.3.0
33 packaging==20.3
33 packaging==20.3
34 pathlib2==2.3.5
34 pathlib2==2.3.5
35 paste==3.4.0
35 paste==3.4.0
36 pastedeploy==2.1.0
36 pastedeploy==2.1.0
37 pastescript==3.2.0
37 pastescript==3.2.0
38 peppercorn==0.6
38 peppercorn==0.6
39 premailer==3.6.1
39 premailer==3.6.1
40 psutil==5.7.0
40 psutil==5.7.0
41 py-bcrypt==0.4
41 py-bcrypt==0.4
42 pycurl==7.43.0.3
42 pycurl==7.43.0.3
43 pycrypto==2.6.1
43 pycrypto==2.6.1
44 pygments==2.4.2
44 pygments==2.4.2
45 pyparsing==2.4.7
45 pyparsing==2.4.7
46 pyramid-debugtoolbar==4.6.1
46 pyramid-debugtoolbar==4.6.1
47 pyramid-mako==1.1.0
47 pyramid-mako==1.1.0
48 pyramid==1.10.4
48 pyramid==1.10.4
49 pyramid_mailer==0.15.1
49 pyramid_mailer==0.15.1
50 python-dateutil==2.8.1
50 python-dateutil==2.8.1
51 python-ldap==3.2.0
51 python-ldap==3.2.0
52 python-memcached==1.59
52 python-memcached==1.59
53 python-pam==1.8.4
53 python-pam==1.8.4
54 python-saml==2.4.2
54 python-saml==2.4.2
55 pytz==2019.3
55 pytz==2019.3
56 tzlocal==1.5.1
56 tzlocal==1.5.1
57 pyzmq==14.6.0
57 pyzmq==14.6.0
58 py-gfm==0.1.4
58 py-gfm==0.1.4
59 regex==2020.9.27
59 redis==3.4.1
60 redis==3.4.1
60 repoze.lru==0.7
61 repoze.lru==0.7
61 requests==2.22.0
62 requests==2.22.0
62 routes==2.4.1
63 routes==2.4.1
63 simplejson==3.16.0
64 simplejson==3.16.0
64 six==1.11.0
65 six==1.11.0
65 sqlalchemy==1.3.15
66 sqlalchemy==1.3.15
66 sshpubkeys==3.1.0
67 sshpubkeys==3.1.0
67 subprocess32==3.5.4
68 subprocess32==3.5.4
68 supervisor==4.1.0
69 supervisor==4.1.0
69 translationstring==1.3
70 translationstring==1.3
70 urllib3==1.25.2
71 urllib3==1.25.2
71 urlobject==2.4.3
72 urlobject==2.4.3
72 venusian==1.2.0
73 venusian==1.2.0
73 weberror==0.13.1
74 weberror==0.13.1
74 webhelpers2==2.0
75 webhelpers2==2.0
75 webob==1.8.5
76 webob==1.8.5
76 whoosh==2.7.4
77 whoosh==2.7.4
77 wsgiref==0.1.2
78 wsgiref==0.1.2
78 zope.cachedescriptors==4.3.1
79 zope.cachedescriptors==4.3.1
79 zope.deprecation==4.4.0
80 zope.deprecation==4.4.0
80 zope.event==4.4.0
81 zope.event==4.4.0
81 zope.interface==4.6.0
82 zope.interface==4.6.0
82
83
83 # DB drivers
84 # DB drivers
84 mysql-python==1.2.5
85 mysql-python==1.2.5
85 pymysql==0.8.1
86 pymysql==0.8.1
86 pysqlite==2.8.3
87 pysqlite==2.8.3
87 psycopg2==2.8.4
88 psycopg2==2.8.4
88
89
89 # IPYTHON RENDERING
90 # IPYTHON RENDERING
90 # entrypoints backport, pypi version doesn't support egg installs
91 # entrypoints backport, pypi version doesn't support egg installs
91 https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d#egg=entrypoints==0.2.2.rhodecode-upstream1
92 https://code.rhodecode.com/upstream/entrypoints/artifacts/download/0-8e9ee9e4-c4db-409c-b07e-81568fd1832d.tar.gz?md5=3a027b8ff1d257b91fe257de6c43357d#egg=entrypoints==0.2.2.rhodecode-upstream1
92 nbconvert==5.3.1
93 nbconvert==5.3.1
93 nbformat==4.4.0
94 nbformat==4.4.0
94 jupyter-client==5.0.0
95 jupyter-client==5.0.0
95 jupyter-core==4.5.0
96 jupyter-core==4.5.0
96
97
97 ## cli tools
98 ## cli tools
98 alembic==1.4.2
99 alembic==1.4.2
99 invoke==0.13.0
100 invoke==0.13.0
100 bumpversion==0.5.3
101 bumpversion==0.5.3
101
102
102 ## http servers
103 ## http servers
103 gevent==1.5.0
104 gevent==1.5.0
104 greenlet==0.4.15
105 greenlet==0.4.15
105 gunicorn==19.9.0
106 gunicorn==19.9.0
106 waitress==1.3.1
107 waitress==1.3.1
107
108
108 ## debug
109 ## debug
109 ipdb==0.13.2
110 ipdb==0.13.2
110 ipython==5.1.0
111 ipython==5.1.0
111
112
112 ## rhodecode-tools, special case, use file://PATH.tar.gz#egg=rhodecode-tools==X.Y.Z, to test local version
113 ## rhodecode-tools, special case, use file://PATH.tar.gz#egg=rhodecode-tools==X.Y.Z, to test local version
113 https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a#egg=rhodecode-tools==1.4.0
114 https://code.rhodecode.com/rhodecode-tools-ce/artifacts/download/0-ed54e749-2ef5-4bc7-ae7f-7900e3c2aa15.tar.gz?sha256=76f024bad3a1e55fdb3d64f13f5b77ff21a12fee699918de2110fe21effd5a3a#egg=rhodecode-tools==1.4.0
114
115
115
116
116 ## appenlight
117 ## appenlight
117 appenlight-client==0.6.26
118 appenlight-client==0.6.26
118
119
119 ## test related requirements
120 ## test related requirements
120 -r requirements_test.txt
121 -r requirements_test.txt
121
122
122 ## uncomment to add the debug libraries
123 ## uncomment to add the debug libraries
123 #-r requirements_debug.txt
124 #-r requirements_debug.txt
@@ -1,783 +1,792 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import logging
22 import logging
23 import collections
23 import collections
24
24
25 import datetime
25 import datetime
26 import formencode
26 import formencode
27 import formencode.htmlfill
27 import formencode.htmlfill
28
28
29 import rhodecode
29 import rhodecode
30 from pyramid.view import view_config
30 from pyramid.view import view_config
31 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
31 from pyramid.httpexceptions import HTTPFound, HTTPNotFound
32 from pyramid.renderers import render
32 from pyramid.renderers import render
33 from pyramid.response import Response
33 from pyramid.response import Response
34
34
35 from rhodecode.apps._base import BaseAppView
35 from rhodecode.apps._base import BaseAppView
36 from rhodecode.apps._base.navigation import navigation_list
36 from rhodecode.apps._base.navigation import navigation_list
37 from rhodecode.apps.svn_support.config_keys import generate_config
37 from rhodecode.apps.svn_support.config_keys import generate_config
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import (
39 from rhodecode.lib.auth import (
40 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
40 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
41 from rhodecode.lib.celerylib import tasks, run_task
41 from rhodecode.lib.celerylib import tasks, run_task
42 from rhodecode.lib.utils import repo2db_mapper
42 from rhodecode.lib.utils import repo2db_mapper
43 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
43 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict
44 from rhodecode.lib.index import searcher_from_config
44 from rhodecode.lib.index import searcher_from_config
45
45
46 from rhodecode.model.db import RhodeCodeUi, Repository
46 from rhodecode.model.db import RhodeCodeUi, Repository
47 from rhodecode.model.forms import (ApplicationSettingsForm,
47 from rhodecode.model.forms import (ApplicationSettingsForm,
48 ApplicationUiSettingsForm, ApplicationVisualisationForm,
48 ApplicationUiSettingsForm, ApplicationVisualisationForm,
49 LabsSettingsForm, IssueTrackerPatternsForm)
49 LabsSettingsForm, IssueTrackerPatternsForm)
50 from rhodecode.model.permission import PermissionModel
50 from rhodecode.model.permission import PermissionModel
51 from rhodecode.model.repo_group import RepoGroupModel
51 from rhodecode.model.repo_group import RepoGroupModel
52
52
53 from rhodecode.model.scm import ScmModel
53 from rhodecode.model.scm import ScmModel
54 from rhodecode.model.notification import EmailNotificationModel
54 from rhodecode.model.notification import EmailNotificationModel
55 from rhodecode.model.meta import Session
55 from rhodecode.model.meta import Session
56 from rhodecode.model.settings import (
56 from rhodecode.model.settings import (
57 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
57 IssueTrackerSettingsModel, VcsSettingsModel, SettingNotFound,
58 SettingsModel)
58 SettingsModel)
59
59
60
60
61 log = logging.getLogger(__name__)
61 log = logging.getLogger(__name__)
62
62
63
63
64 class AdminSettingsView(BaseAppView):
64 class AdminSettingsView(BaseAppView):
65
65
66 def load_default_context(self):
66 def load_default_context(self):
67 c = self._get_local_tmpl_context()
67 c = self._get_local_tmpl_context()
68 c.labs_active = str2bool(
68 c.labs_active = str2bool(
69 rhodecode.CONFIG.get('labs_settings_active', 'true'))
69 rhodecode.CONFIG.get('labs_settings_active', 'true'))
70 c.navlist = navigation_list(self.request)
70 c.navlist = navigation_list(self.request)
71
71
72 return c
72 return c
73
73
74 @classmethod
74 @classmethod
75 def _get_ui_settings(cls):
75 def _get_ui_settings(cls):
76 ret = RhodeCodeUi.query().all()
76 ret = RhodeCodeUi.query().all()
77
77
78 if not ret:
78 if not ret:
79 raise Exception('Could not get application ui settings !')
79 raise Exception('Could not get application ui settings !')
80 settings = {}
80 settings = {}
81 for each in ret:
81 for each in ret:
82 k = each.ui_key
82 k = each.ui_key
83 v = each.ui_value
83 v = each.ui_value
84 if k == '/':
84 if k == '/':
85 k = 'root_path'
85 k = 'root_path'
86
86
87 if k in ['push_ssl', 'publish', 'enabled']:
87 if k in ['push_ssl', 'publish', 'enabled']:
88 v = str2bool(v)
88 v = str2bool(v)
89
89
90 if k.find('.') != -1:
90 if k.find('.') != -1:
91 k = k.replace('.', '_')
91 k = k.replace('.', '_')
92
92
93 if each.ui_section in ['hooks', 'extensions']:
93 if each.ui_section in ['hooks', 'extensions']:
94 v = each.ui_active
94 v = each.ui_active
95
95
96 settings[each.ui_section + '_' + k] = v
96 settings[each.ui_section + '_' + k] = v
97 return settings
97 return settings
98
98
99 @classmethod
99 @classmethod
100 def _form_defaults(cls):
100 def _form_defaults(cls):
101 defaults = SettingsModel().get_all_settings()
101 defaults = SettingsModel().get_all_settings()
102 defaults.update(cls._get_ui_settings())
102 defaults.update(cls._get_ui_settings())
103
103
104 defaults.update({
104 defaults.update({
105 'new_svn_branch': '',
105 'new_svn_branch': '',
106 'new_svn_tag': '',
106 'new_svn_tag': '',
107 })
107 })
108 return defaults
108 return defaults
109
109
110 @LoginRequired()
110 @LoginRequired()
111 @HasPermissionAllDecorator('hg.admin')
111 @HasPermissionAllDecorator('hg.admin')
112 @view_config(
112 @view_config(
113 route_name='admin_settings_vcs', request_method='GET',
113 route_name='admin_settings_vcs', request_method='GET',
114 renderer='rhodecode:templates/admin/settings/settings.mako')
114 renderer='rhodecode:templates/admin/settings/settings.mako')
115 def settings_vcs(self):
115 def settings_vcs(self):
116 c = self.load_default_context()
116 c = self.load_default_context()
117 c.active = 'vcs'
117 c.active = 'vcs'
118 model = VcsSettingsModel()
118 model = VcsSettingsModel()
119 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
119 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
120 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
120 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
121
121
122 settings = self.request.registry.settings
122 settings = self.request.registry.settings
123 c.svn_proxy_generate_config = settings[generate_config]
123 c.svn_proxy_generate_config = settings[generate_config]
124
124
125 defaults = self._form_defaults()
125 defaults = self._form_defaults()
126
126
127 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
127 model.create_largeobjects_dirs_if_needed(defaults['paths_root_path'])
128
128
129 data = render('rhodecode:templates/admin/settings/settings.mako',
129 data = render('rhodecode:templates/admin/settings/settings.mako',
130 self._get_template_context(c), self.request)
130 self._get_template_context(c), self.request)
131 html = formencode.htmlfill.render(
131 html = formencode.htmlfill.render(
132 data,
132 data,
133 defaults=defaults,
133 defaults=defaults,
134 encoding="UTF-8",
134 encoding="UTF-8",
135 force_defaults=False
135 force_defaults=False
136 )
136 )
137 return Response(html)
137 return Response(html)
138
138
139 @LoginRequired()
139 @LoginRequired()
140 @HasPermissionAllDecorator('hg.admin')
140 @HasPermissionAllDecorator('hg.admin')
141 @CSRFRequired()
141 @CSRFRequired()
142 @view_config(
142 @view_config(
143 route_name='admin_settings_vcs_update', request_method='POST',
143 route_name='admin_settings_vcs_update', request_method='POST',
144 renderer='rhodecode:templates/admin/settings/settings.mako')
144 renderer='rhodecode:templates/admin/settings/settings.mako')
145 def settings_vcs_update(self):
145 def settings_vcs_update(self):
146 _ = self.request.translate
146 _ = self.request.translate
147 c = self.load_default_context()
147 c = self.load_default_context()
148 c.active = 'vcs'
148 c.active = 'vcs'
149
149
150 model = VcsSettingsModel()
150 model = VcsSettingsModel()
151 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
151 c.svn_branch_patterns = model.get_global_svn_branch_patterns()
152 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
152 c.svn_tag_patterns = model.get_global_svn_tag_patterns()
153
153
154 settings = self.request.registry.settings
154 settings = self.request.registry.settings
155 c.svn_proxy_generate_config = settings[generate_config]
155 c.svn_proxy_generate_config = settings[generate_config]
156
156
157 application_form = ApplicationUiSettingsForm(self.request.translate)()
157 application_form = ApplicationUiSettingsForm(self.request.translate)()
158
158
159 try:
159 try:
160 form_result = application_form.to_python(dict(self.request.POST))
160 form_result = application_form.to_python(dict(self.request.POST))
161 except formencode.Invalid as errors:
161 except formencode.Invalid as errors:
162 h.flash(
162 h.flash(
163 _("Some form inputs contain invalid data."),
163 _("Some form inputs contain invalid data."),
164 category='error')
164 category='error')
165 data = render('rhodecode:templates/admin/settings/settings.mako',
165 data = render('rhodecode:templates/admin/settings/settings.mako',
166 self._get_template_context(c), self.request)
166 self._get_template_context(c), self.request)
167 html = formencode.htmlfill.render(
167 html = formencode.htmlfill.render(
168 data,
168 data,
169 defaults=errors.value,
169 defaults=errors.value,
170 errors=errors.error_dict or {},
170 errors=errors.error_dict or {},
171 prefix_error=False,
171 prefix_error=False,
172 encoding="UTF-8",
172 encoding="UTF-8",
173 force_defaults=False
173 force_defaults=False
174 )
174 )
175 return Response(html)
175 return Response(html)
176
176
177 try:
177 try:
178 if c.visual.allow_repo_location_change:
178 if c.visual.allow_repo_location_change:
179 model.update_global_path_setting(form_result['paths_root_path'])
179 model.update_global_path_setting(form_result['paths_root_path'])
180
180
181 model.update_global_ssl_setting(form_result['web_push_ssl'])
181 model.update_global_ssl_setting(form_result['web_push_ssl'])
182 model.update_global_hook_settings(form_result)
182 model.update_global_hook_settings(form_result)
183
183
184 model.create_or_update_global_svn_settings(form_result)
184 model.create_or_update_global_svn_settings(form_result)
185 model.create_or_update_global_hg_settings(form_result)
185 model.create_or_update_global_hg_settings(form_result)
186 model.create_or_update_global_git_settings(form_result)
186 model.create_or_update_global_git_settings(form_result)
187 model.create_or_update_global_pr_settings(form_result)
187 model.create_or_update_global_pr_settings(form_result)
188 except Exception:
188 except Exception:
189 log.exception("Exception while updating settings")
189 log.exception("Exception while updating settings")
190 h.flash(_('Error occurred during updating '
190 h.flash(_('Error occurred during updating '
191 'application settings'), category='error')
191 'application settings'), category='error')
192 else:
192 else:
193 Session().commit()
193 Session().commit()
194 h.flash(_('Updated VCS settings'), category='success')
194 h.flash(_('Updated VCS settings'), category='success')
195 raise HTTPFound(h.route_path('admin_settings_vcs'))
195 raise HTTPFound(h.route_path('admin_settings_vcs'))
196
196
197 data = render('rhodecode:templates/admin/settings/settings.mako',
197 data = render('rhodecode:templates/admin/settings/settings.mako',
198 self._get_template_context(c), self.request)
198 self._get_template_context(c), self.request)
199 html = formencode.htmlfill.render(
199 html = formencode.htmlfill.render(
200 data,
200 data,
201 defaults=self._form_defaults(),
201 defaults=self._form_defaults(),
202 encoding="UTF-8",
202 encoding="UTF-8",
203 force_defaults=False
203 force_defaults=False
204 )
204 )
205 return Response(html)
205 return Response(html)
206
206
207 @LoginRequired()
207 @LoginRequired()
208 @HasPermissionAllDecorator('hg.admin')
208 @HasPermissionAllDecorator('hg.admin')
209 @CSRFRequired()
209 @CSRFRequired()
210 @view_config(
210 @view_config(
211 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
211 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
212 renderer='json_ext', xhr=True)
212 renderer='json_ext', xhr=True)
213 def settings_vcs_delete_svn_pattern(self):
213 def settings_vcs_delete_svn_pattern(self):
214 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
214 delete_pattern_id = self.request.POST.get('delete_svn_pattern')
215 model = VcsSettingsModel()
215 model = VcsSettingsModel()
216 try:
216 try:
217 model.delete_global_svn_pattern(delete_pattern_id)
217 model.delete_global_svn_pattern(delete_pattern_id)
218 except SettingNotFound:
218 except SettingNotFound:
219 log.exception(
219 log.exception(
220 'Failed to delete svn_pattern with id %s', delete_pattern_id)
220 'Failed to delete svn_pattern with id %s', delete_pattern_id)
221 raise HTTPNotFound()
221 raise HTTPNotFound()
222
222
223 Session().commit()
223 Session().commit()
224 return True
224 return True
225
225
226 @LoginRequired()
226 @LoginRequired()
227 @HasPermissionAllDecorator('hg.admin')
227 @HasPermissionAllDecorator('hg.admin')
228 @view_config(
228 @view_config(
229 route_name='admin_settings_mapping', request_method='GET',
229 route_name='admin_settings_mapping', request_method='GET',
230 renderer='rhodecode:templates/admin/settings/settings.mako')
230 renderer='rhodecode:templates/admin/settings/settings.mako')
231 def settings_mapping(self):
231 def settings_mapping(self):
232 c = self.load_default_context()
232 c = self.load_default_context()
233 c.active = 'mapping'
233 c.active = 'mapping'
234
234
235 data = render('rhodecode:templates/admin/settings/settings.mako',
235 data = render('rhodecode:templates/admin/settings/settings.mako',
236 self._get_template_context(c), self.request)
236 self._get_template_context(c), self.request)
237 html = formencode.htmlfill.render(
237 html = formencode.htmlfill.render(
238 data,
238 data,
239 defaults=self._form_defaults(),
239 defaults=self._form_defaults(),
240 encoding="UTF-8",
240 encoding="UTF-8",
241 force_defaults=False
241 force_defaults=False
242 )
242 )
243 return Response(html)
243 return Response(html)
244
244
245 @LoginRequired()
245 @LoginRequired()
246 @HasPermissionAllDecorator('hg.admin')
246 @HasPermissionAllDecorator('hg.admin')
247 @CSRFRequired()
247 @CSRFRequired()
248 @view_config(
248 @view_config(
249 route_name='admin_settings_mapping_update', request_method='POST',
249 route_name='admin_settings_mapping_update', request_method='POST',
250 renderer='rhodecode:templates/admin/settings/settings.mako')
250 renderer='rhodecode:templates/admin/settings/settings.mako')
251 def settings_mapping_update(self):
251 def settings_mapping_update(self):
252 _ = self.request.translate
252 _ = self.request.translate
253 c = self.load_default_context()
253 c = self.load_default_context()
254 c.active = 'mapping'
254 c.active = 'mapping'
255 rm_obsolete = self.request.POST.get('destroy', False)
255 rm_obsolete = self.request.POST.get('destroy', False)
256 invalidate_cache = self.request.POST.get('invalidate', False)
256 invalidate_cache = self.request.POST.get('invalidate', False)
257 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
257 log.debug('rescanning repo location with destroy obsolete=%s', rm_obsolete)
258
258
259 if invalidate_cache:
259 if invalidate_cache:
260 log.debug('invalidating all repositories cache')
260 log.debug('invalidating all repositories cache')
261 for repo in Repository.get_all():
261 for repo in Repository.get_all():
262 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
262 ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
263
263
264 filesystem_repos = ScmModel().repo_scan()
264 filesystem_repos = ScmModel().repo_scan()
265 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
265 added, removed = repo2db_mapper(filesystem_repos, rm_obsolete)
266 PermissionModel().trigger_permission_flush()
266 PermissionModel().trigger_permission_flush()
267
267
268 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
268 _repr = lambda l: ', '.join(map(safe_unicode, l)) or '-'
269 h.flash(_('Repositories successfully '
269 h.flash(_('Repositories successfully '
270 'rescanned added: %s ; removed: %s') %
270 'rescanned added: %s ; removed: %s') %
271 (_repr(added), _repr(removed)),
271 (_repr(added), _repr(removed)),
272 category='success')
272 category='success')
273 raise HTTPFound(h.route_path('admin_settings_mapping'))
273 raise HTTPFound(h.route_path('admin_settings_mapping'))
274
274
275 @LoginRequired()
275 @LoginRequired()
276 @HasPermissionAllDecorator('hg.admin')
276 @HasPermissionAllDecorator('hg.admin')
277 @view_config(
277 @view_config(
278 route_name='admin_settings', request_method='GET',
278 route_name='admin_settings', request_method='GET',
279 renderer='rhodecode:templates/admin/settings/settings.mako')
279 renderer='rhodecode:templates/admin/settings/settings.mako')
280 @view_config(
280 @view_config(
281 route_name='admin_settings_global', request_method='GET',
281 route_name='admin_settings_global', request_method='GET',
282 renderer='rhodecode:templates/admin/settings/settings.mako')
282 renderer='rhodecode:templates/admin/settings/settings.mako')
283 def settings_global(self):
283 def settings_global(self):
284 c = self.load_default_context()
284 c = self.load_default_context()
285 c.active = 'global'
285 c.active = 'global'
286 c.personal_repo_group_default_pattern = RepoGroupModel()\
286 c.personal_repo_group_default_pattern = RepoGroupModel()\
287 .get_personal_group_name_pattern()
287 .get_personal_group_name_pattern()
288
288
289 data = render('rhodecode:templates/admin/settings/settings.mako',
289 data = render('rhodecode:templates/admin/settings/settings.mako',
290 self._get_template_context(c), self.request)
290 self._get_template_context(c), self.request)
291 html = formencode.htmlfill.render(
291 html = formencode.htmlfill.render(
292 data,
292 data,
293 defaults=self._form_defaults(),
293 defaults=self._form_defaults(),
294 encoding="UTF-8",
294 encoding="UTF-8",
295 force_defaults=False
295 force_defaults=False
296 )
296 )
297 return Response(html)
297 return Response(html)
298
298
299 @LoginRequired()
299 @LoginRequired()
300 @HasPermissionAllDecorator('hg.admin')
300 @HasPermissionAllDecorator('hg.admin')
301 @CSRFRequired()
301 @CSRFRequired()
302 @view_config(
302 @view_config(
303 route_name='admin_settings_update', request_method='POST',
303 route_name='admin_settings_update', request_method='POST',
304 renderer='rhodecode:templates/admin/settings/settings.mako')
304 renderer='rhodecode:templates/admin/settings/settings.mako')
305 @view_config(
305 @view_config(
306 route_name='admin_settings_global_update', request_method='POST',
306 route_name='admin_settings_global_update', request_method='POST',
307 renderer='rhodecode:templates/admin/settings/settings.mako')
307 renderer='rhodecode:templates/admin/settings/settings.mako')
308 def settings_global_update(self):
308 def settings_global_update(self):
309 _ = self.request.translate
309 _ = self.request.translate
310 c = self.load_default_context()
310 c = self.load_default_context()
311 c.active = 'global'
311 c.active = 'global'
312 c.personal_repo_group_default_pattern = RepoGroupModel()\
312 c.personal_repo_group_default_pattern = RepoGroupModel()\
313 .get_personal_group_name_pattern()
313 .get_personal_group_name_pattern()
314 application_form = ApplicationSettingsForm(self.request.translate)()
314 application_form = ApplicationSettingsForm(self.request.translate)()
315 try:
315 try:
316 form_result = application_form.to_python(dict(self.request.POST))
316 form_result = application_form.to_python(dict(self.request.POST))
317 except formencode.Invalid as errors:
317 except formencode.Invalid as errors:
318 h.flash(
318 h.flash(
319 _("Some form inputs contain invalid data."),
319 _("Some form inputs contain invalid data."),
320 category='error')
320 category='error')
321 data = render('rhodecode:templates/admin/settings/settings.mako',
321 data = render('rhodecode:templates/admin/settings/settings.mako',
322 self._get_template_context(c), self.request)
322 self._get_template_context(c), self.request)
323 html = formencode.htmlfill.render(
323 html = formencode.htmlfill.render(
324 data,
324 data,
325 defaults=errors.value,
325 defaults=errors.value,
326 errors=errors.error_dict or {},
326 errors=errors.error_dict or {},
327 prefix_error=False,
327 prefix_error=False,
328 encoding="UTF-8",
328 encoding="UTF-8",
329 force_defaults=False
329 force_defaults=False
330 )
330 )
331 return Response(html)
331 return Response(html)
332
332
333 settings = [
333 settings = [
334 ('title', 'rhodecode_title', 'unicode'),
334 ('title', 'rhodecode_title', 'unicode'),
335 ('realm', 'rhodecode_realm', 'unicode'),
335 ('realm', 'rhodecode_realm', 'unicode'),
336 ('pre_code', 'rhodecode_pre_code', 'unicode'),
336 ('pre_code', 'rhodecode_pre_code', 'unicode'),
337 ('post_code', 'rhodecode_post_code', 'unicode'),
337 ('post_code', 'rhodecode_post_code', 'unicode'),
338 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
338 ('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
339 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
339 ('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
340 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
340 ('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
341 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
341 ('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
342 ]
342 ]
343 try:
343 try:
344 for setting, form_key, type_ in settings:
344 for setting, form_key, type_ in settings:
345 sett = SettingsModel().create_or_update_setting(
345 sett = SettingsModel().create_or_update_setting(
346 setting, form_result[form_key], type_)
346 setting, form_result[form_key], type_)
347 Session().add(sett)
347 Session().add(sett)
348
348
349 Session().commit()
349 Session().commit()
350 SettingsModel().invalidate_settings_cache()
350 SettingsModel().invalidate_settings_cache()
351 h.flash(_('Updated application settings'), category='success')
351 h.flash(_('Updated application settings'), category='success')
352 except Exception:
352 except Exception:
353 log.exception("Exception while updating application settings")
353 log.exception("Exception while updating application settings")
354 h.flash(
354 h.flash(
355 _('Error occurred during updating application settings'),
355 _('Error occurred during updating application settings'),
356 category='error')
356 category='error')
357
357
358 raise HTTPFound(h.route_path('admin_settings_global'))
358 raise HTTPFound(h.route_path('admin_settings_global'))
359
359
360 @LoginRequired()
360 @LoginRequired()
361 @HasPermissionAllDecorator('hg.admin')
361 @HasPermissionAllDecorator('hg.admin')
362 @view_config(
362 @view_config(
363 route_name='admin_settings_visual', request_method='GET',
363 route_name='admin_settings_visual', request_method='GET',
364 renderer='rhodecode:templates/admin/settings/settings.mako')
364 renderer='rhodecode:templates/admin/settings/settings.mako')
365 def settings_visual(self):
365 def settings_visual(self):
366 c = self.load_default_context()
366 c = self.load_default_context()
367 c.active = 'visual'
367 c.active = 'visual'
368
368
369 data = render('rhodecode:templates/admin/settings/settings.mako',
369 data = render('rhodecode:templates/admin/settings/settings.mako',
370 self._get_template_context(c), self.request)
370 self._get_template_context(c), self.request)
371 html = formencode.htmlfill.render(
371 html = formencode.htmlfill.render(
372 data,
372 data,
373 defaults=self._form_defaults(),
373 defaults=self._form_defaults(),
374 encoding="UTF-8",
374 encoding="UTF-8",
375 force_defaults=False
375 force_defaults=False
376 )
376 )
377 return Response(html)
377 return Response(html)
378
378
379 @LoginRequired()
379 @LoginRequired()
380 @HasPermissionAllDecorator('hg.admin')
380 @HasPermissionAllDecorator('hg.admin')
381 @CSRFRequired()
381 @CSRFRequired()
382 @view_config(
382 @view_config(
383 route_name='admin_settings_visual_update', request_method='POST',
383 route_name='admin_settings_visual_update', request_method='POST',
384 renderer='rhodecode:templates/admin/settings/settings.mako')
384 renderer='rhodecode:templates/admin/settings/settings.mako')
385 def settings_visual_update(self):
385 def settings_visual_update(self):
386 _ = self.request.translate
386 _ = self.request.translate
387 c = self.load_default_context()
387 c = self.load_default_context()
388 c.active = 'visual'
388 c.active = 'visual'
389 application_form = ApplicationVisualisationForm(self.request.translate)()
389 application_form = ApplicationVisualisationForm(self.request.translate)()
390 try:
390 try:
391 form_result = application_form.to_python(dict(self.request.POST))
391 form_result = application_form.to_python(dict(self.request.POST))
392 except formencode.Invalid as errors:
392 except formencode.Invalid as errors:
393 h.flash(
393 h.flash(
394 _("Some form inputs contain invalid data."),
394 _("Some form inputs contain invalid data."),
395 category='error')
395 category='error')
396 data = render('rhodecode:templates/admin/settings/settings.mako',
396 data = render('rhodecode:templates/admin/settings/settings.mako',
397 self._get_template_context(c), self.request)
397 self._get_template_context(c), self.request)
398 html = formencode.htmlfill.render(
398 html = formencode.htmlfill.render(
399 data,
399 data,
400 defaults=errors.value,
400 defaults=errors.value,
401 errors=errors.error_dict or {},
401 errors=errors.error_dict or {},
402 prefix_error=False,
402 prefix_error=False,
403 encoding="UTF-8",
403 encoding="UTF-8",
404 force_defaults=False
404 force_defaults=False
405 )
405 )
406 return Response(html)
406 return Response(html)
407
407
408 try:
408 try:
409 settings = [
409 settings = [
410 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
410 ('show_public_icon', 'rhodecode_show_public_icon', 'bool'),
411 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
411 ('show_private_icon', 'rhodecode_show_private_icon', 'bool'),
412 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
412 ('stylify_metatags', 'rhodecode_stylify_metatags', 'bool'),
413 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
413 ('repository_fields', 'rhodecode_repository_fields', 'bool'),
414 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
414 ('dashboard_items', 'rhodecode_dashboard_items', 'int'),
415 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
415 ('admin_grid_items', 'rhodecode_admin_grid_items', 'int'),
416 ('show_version', 'rhodecode_show_version', 'bool'),
416 ('show_version', 'rhodecode_show_version', 'bool'),
417 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
417 ('use_gravatar', 'rhodecode_use_gravatar', 'bool'),
418 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
418 ('markup_renderer', 'rhodecode_markup_renderer', 'unicode'),
419 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
419 ('gravatar_url', 'rhodecode_gravatar_url', 'unicode'),
420 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
420 ('clone_uri_tmpl', 'rhodecode_clone_uri_tmpl', 'unicode'),
421 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
421 ('clone_uri_ssh_tmpl', 'rhodecode_clone_uri_ssh_tmpl', 'unicode'),
422 ('support_url', 'rhodecode_support_url', 'unicode'),
422 ('support_url', 'rhodecode_support_url', 'unicode'),
423 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
423 ('show_revision_number', 'rhodecode_show_revision_number', 'bool'),
424 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
424 ('show_sha_length', 'rhodecode_show_sha_length', 'int'),
425 ]
425 ]
426 for setting, form_key, type_ in settings:
426 for setting, form_key, type_ in settings:
427 sett = SettingsModel().create_or_update_setting(
427 sett = SettingsModel().create_or_update_setting(
428 setting, form_result[form_key], type_)
428 setting, form_result[form_key], type_)
429 Session().add(sett)
429 Session().add(sett)
430
430
431 Session().commit()
431 Session().commit()
432 SettingsModel().invalidate_settings_cache()
432 SettingsModel().invalidate_settings_cache()
433 h.flash(_('Updated visualisation settings'), category='success')
433 h.flash(_('Updated visualisation settings'), category='success')
434 except Exception:
434 except Exception:
435 log.exception("Exception updating visualization settings")
435 log.exception("Exception updating visualization settings")
436 h.flash(_('Error occurred during updating '
436 h.flash(_('Error occurred during updating '
437 'visualisation settings'),
437 'visualisation settings'),
438 category='error')
438 category='error')
439
439
440 raise HTTPFound(h.route_path('admin_settings_visual'))
440 raise HTTPFound(h.route_path('admin_settings_visual'))
441
441
442 @LoginRequired()
442 @LoginRequired()
443 @HasPermissionAllDecorator('hg.admin')
443 @HasPermissionAllDecorator('hg.admin')
444 @view_config(
444 @view_config(
445 route_name='admin_settings_issuetracker', request_method='GET',
445 route_name='admin_settings_issuetracker', request_method='GET',
446 renderer='rhodecode:templates/admin/settings/settings.mako')
446 renderer='rhodecode:templates/admin/settings/settings.mako')
447 def settings_issuetracker(self):
447 def settings_issuetracker(self):
448 c = self.load_default_context()
448 c = self.load_default_context()
449 c.active = 'issuetracker'
449 c.active = 'issuetracker'
450 defaults = c.rc_config
450 defaults = c.rc_config
451
451
452 entry_key = 'rhodecode_issuetracker_pat_'
452 entry_key = 'rhodecode_issuetracker_pat_'
453
453
454 c.issuetracker_entries = {}
454 c.issuetracker_entries = {}
455 for k, v in defaults.items():
455 for k, v in defaults.items():
456 if k.startswith(entry_key):
456 if k.startswith(entry_key):
457 uid = k[len(entry_key):]
457 uid = k[len(entry_key):]
458 c.issuetracker_entries[uid] = None
458 c.issuetracker_entries[uid] = None
459
459
460 for uid in c.issuetracker_entries:
460 for uid in c.issuetracker_entries:
461 c.issuetracker_entries[uid] = AttributeDict({
461 c.issuetracker_entries[uid] = AttributeDict({
462 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
462 'pat': defaults.get('rhodecode_issuetracker_pat_' + uid),
463 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
463 'url': defaults.get('rhodecode_issuetracker_url_' + uid),
464 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
464 'pref': defaults.get('rhodecode_issuetracker_pref_' + uid),
465 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
465 'desc': defaults.get('rhodecode_issuetracker_desc_' + uid),
466 })
466 })
467
467
468 return self._get_template_context(c)
468 return self._get_template_context(c)
469
469
470 @LoginRequired()
470 @LoginRequired()
471 @HasPermissionAllDecorator('hg.admin')
471 @HasPermissionAllDecorator('hg.admin')
472 @CSRFRequired()
472 @CSRFRequired()
473 @view_config(
473 @view_config(
474 route_name='admin_settings_issuetracker_test', request_method='POST',
474 route_name='admin_settings_issuetracker_test', request_method='POST',
475 renderer='string', xhr=True)
475 renderer='string', xhr=True)
476 def settings_issuetracker_test(self):
476 def settings_issuetracker_test(self):
477 return h.urlify_commit_message(
477 error_container = []
478
479 urlified_commit = h.urlify_commit_message(
478 self.request.POST.get('test_text', ''),
480 self.request.POST.get('test_text', ''),
479 'repo_group/test_repo1')
481 'repo_group/test_repo1', error_container=error_container)
482 if error_container:
483 def converter(inp):
484 return h.html_escape(unicode(inp))
485
486 return 'ERRORS: ' + '\n'.join(map(converter, error_container))
487
488 return urlified_commit
480
489
481 @LoginRequired()
490 @LoginRequired()
482 @HasPermissionAllDecorator('hg.admin')
491 @HasPermissionAllDecorator('hg.admin')
483 @CSRFRequired()
492 @CSRFRequired()
484 @view_config(
493 @view_config(
485 route_name='admin_settings_issuetracker_update', request_method='POST',
494 route_name='admin_settings_issuetracker_update', request_method='POST',
486 renderer='rhodecode:templates/admin/settings/settings.mako')
495 renderer='rhodecode:templates/admin/settings/settings.mako')
487 def settings_issuetracker_update(self):
496 def settings_issuetracker_update(self):
488 _ = self.request.translate
497 _ = self.request.translate
489 self.load_default_context()
498 self.load_default_context()
490 settings_model = IssueTrackerSettingsModel()
499 settings_model = IssueTrackerSettingsModel()
491
500
492 try:
501 try:
493 form = IssueTrackerPatternsForm(self.request.translate)()
502 form = IssueTrackerPatternsForm(self.request.translate)()
494 data = form.to_python(self.request.POST)
503 data = form.to_python(self.request.POST)
495 except formencode.Invalid as errors:
504 except formencode.Invalid as errors:
496 log.exception('Failed to add new pattern')
505 log.exception('Failed to add new pattern')
497 error = errors
506 error = errors
498 h.flash(_('Invalid issue tracker pattern: {}'.format(error)),
507 h.flash(_('Invalid issue tracker pattern: {}'.format(error)),
499 category='error')
508 category='error')
500 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
509 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
501
510
502 if data:
511 if data:
503 for uid in data.get('delete_patterns', []):
512 for uid in data.get('delete_patterns', []):
504 settings_model.delete_entries(uid)
513 settings_model.delete_entries(uid)
505
514
506 for pattern in data.get('patterns', []):
515 for pattern in data.get('patterns', []):
507 for setting, value, type_ in pattern:
516 for setting, value, type_ in pattern:
508 sett = settings_model.create_or_update_setting(
517 sett = settings_model.create_or_update_setting(
509 setting, value, type_)
518 setting, value, type_)
510 Session().add(sett)
519 Session().add(sett)
511
520
512 Session().commit()
521 Session().commit()
513
522
514 SettingsModel().invalidate_settings_cache()
523 SettingsModel().invalidate_settings_cache()
515 h.flash(_('Updated issue tracker entries'), category='success')
524 h.flash(_('Updated issue tracker entries'), category='success')
516 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
525 raise HTTPFound(h.route_path('admin_settings_issuetracker'))
517
526
518 @LoginRequired()
527 @LoginRequired()
519 @HasPermissionAllDecorator('hg.admin')
528 @HasPermissionAllDecorator('hg.admin')
520 @CSRFRequired()
529 @CSRFRequired()
521 @view_config(
530 @view_config(
522 route_name='admin_settings_issuetracker_delete', request_method='POST',
531 route_name='admin_settings_issuetracker_delete', request_method='POST',
523 renderer='json_ext', xhr=True)
532 renderer='json_ext', xhr=True)
524 def settings_issuetracker_delete(self):
533 def settings_issuetracker_delete(self):
525 _ = self.request.translate
534 _ = self.request.translate
526 self.load_default_context()
535 self.load_default_context()
527 uid = self.request.POST.get('uid')
536 uid = self.request.POST.get('uid')
528 try:
537 try:
529 IssueTrackerSettingsModel().delete_entries(uid)
538 IssueTrackerSettingsModel().delete_entries(uid)
530 except Exception:
539 except Exception:
531 log.exception('Failed to delete issue tracker setting %s', uid)
540 log.exception('Failed to delete issue tracker setting %s', uid)
532 raise HTTPNotFound()
541 raise HTTPNotFound()
533
542
534 SettingsModel().invalidate_settings_cache()
543 SettingsModel().invalidate_settings_cache()
535 h.flash(_('Removed issue tracker entry.'), category='success')
544 h.flash(_('Removed issue tracker entry.'), category='success')
536
545
537 return {'deleted': uid}
546 return {'deleted': uid}
538
547
539 @LoginRequired()
548 @LoginRequired()
540 @HasPermissionAllDecorator('hg.admin')
549 @HasPermissionAllDecorator('hg.admin')
541 @view_config(
550 @view_config(
542 route_name='admin_settings_email', request_method='GET',
551 route_name='admin_settings_email', request_method='GET',
543 renderer='rhodecode:templates/admin/settings/settings.mako')
552 renderer='rhodecode:templates/admin/settings/settings.mako')
544 def settings_email(self):
553 def settings_email(self):
545 c = self.load_default_context()
554 c = self.load_default_context()
546 c.active = 'email'
555 c.active = 'email'
547 c.rhodecode_ini = rhodecode.CONFIG
556 c.rhodecode_ini = rhodecode.CONFIG
548
557
549 data = render('rhodecode:templates/admin/settings/settings.mako',
558 data = render('rhodecode:templates/admin/settings/settings.mako',
550 self._get_template_context(c), self.request)
559 self._get_template_context(c), self.request)
551 html = formencode.htmlfill.render(
560 html = formencode.htmlfill.render(
552 data,
561 data,
553 defaults=self._form_defaults(),
562 defaults=self._form_defaults(),
554 encoding="UTF-8",
563 encoding="UTF-8",
555 force_defaults=False
564 force_defaults=False
556 )
565 )
557 return Response(html)
566 return Response(html)
558
567
559 @LoginRequired()
568 @LoginRequired()
560 @HasPermissionAllDecorator('hg.admin')
569 @HasPermissionAllDecorator('hg.admin')
561 @CSRFRequired()
570 @CSRFRequired()
562 @view_config(
571 @view_config(
563 route_name='admin_settings_email_update', request_method='POST',
572 route_name='admin_settings_email_update', request_method='POST',
564 renderer='rhodecode:templates/admin/settings/settings.mako')
573 renderer='rhodecode:templates/admin/settings/settings.mako')
565 def settings_email_update(self):
574 def settings_email_update(self):
566 _ = self.request.translate
575 _ = self.request.translate
567 c = self.load_default_context()
576 c = self.load_default_context()
568 c.active = 'email'
577 c.active = 'email'
569
578
570 test_email = self.request.POST.get('test_email')
579 test_email = self.request.POST.get('test_email')
571
580
572 if not test_email:
581 if not test_email:
573 h.flash(_('Please enter email address'), category='error')
582 h.flash(_('Please enter email address'), category='error')
574 raise HTTPFound(h.route_path('admin_settings_email'))
583 raise HTTPFound(h.route_path('admin_settings_email'))
575
584
576 email_kwargs = {
585 email_kwargs = {
577 'date': datetime.datetime.now(),
586 'date': datetime.datetime.now(),
578 'user': self._rhodecode_db_user
587 'user': self._rhodecode_db_user
579 }
588 }
580
589
581 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
590 (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email(
582 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
591 EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs)
583
592
584 recipients = [test_email] if test_email else None
593 recipients = [test_email] if test_email else None
585
594
586 run_task(tasks.send_email, recipients, subject,
595 run_task(tasks.send_email, recipients, subject,
587 email_body_plaintext, email_body)
596 email_body_plaintext, email_body)
588
597
589 h.flash(_('Send email task created'), category='success')
598 h.flash(_('Send email task created'), category='success')
590 raise HTTPFound(h.route_path('admin_settings_email'))
599 raise HTTPFound(h.route_path('admin_settings_email'))
591
600
592 @LoginRequired()
601 @LoginRequired()
593 @HasPermissionAllDecorator('hg.admin')
602 @HasPermissionAllDecorator('hg.admin')
594 @view_config(
603 @view_config(
595 route_name='admin_settings_hooks', request_method='GET',
604 route_name='admin_settings_hooks', request_method='GET',
596 renderer='rhodecode:templates/admin/settings/settings.mako')
605 renderer='rhodecode:templates/admin/settings/settings.mako')
597 def settings_hooks(self):
606 def settings_hooks(self):
598 c = self.load_default_context()
607 c = self.load_default_context()
599 c.active = 'hooks'
608 c.active = 'hooks'
600
609
601 model = SettingsModel()
610 model = SettingsModel()
602 c.hooks = model.get_builtin_hooks()
611 c.hooks = model.get_builtin_hooks()
603 c.custom_hooks = model.get_custom_hooks()
612 c.custom_hooks = model.get_custom_hooks()
604
613
605 data = render('rhodecode:templates/admin/settings/settings.mako',
614 data = render('rhodecode:templates/admin/settings/settings.mako',
606 self._get_template_context(c), self.request)
615 self._get_template_context(c), self.request)
607 html = formencode.htmlfill.render(
616 html = formencode.htmlfill.render(
608 data,
617 data,
609 defaults=self._form_defaults(),
618 defaults=self._form_defaults(),
610 encoding="UTF-8",
619 encoding="UTF-8",
611 force_defaults=False
620 force_defaults=False
612 )
621 )
613 return Response(html)
622 return Response(html)
614
623
615 @LoginRequired()
624 @LoginRequired()
616 @HasPermissionAllDecorator('hg.admin')
625 @HasPermissionAllDecorator('hg.admin')
617 @CSRFRequired()
626 @CSRFRequired()
618 @view_config(
627 @view_config(
619 route_name='admin_settings_hooks_update', request_method='POST',
628 route_name='admin_settings_hooks_update', request_method='POST',
620 renderer='rhodecode:templates/admin/settings/settings.mako')
629 renderer='rhodecode:templates/admin/settings/settings.mako')
621 @view_config(
630 @view_config(
622 route_name='admin_settings_hooks_delete', request_method='POST',
631 route_name='admin_settings_hooks_delete', request_method='POST',
623 renderer='rhodecode:templates/admin/settings/settings.mako')
632 renderer='rhodecode:templates/admin/settings/settings.mako')
624 def settings_hooks_update(self):
633 def settings_hooks_update(self):
625 _ = self.request.translate
634 _ = self.request.translate
626 c = self.load_default_context()
635 c = self.load_default_context()
627 c.active = 'hooks'
636 c.active = 'hooks'
628 if c.visual.allow_custom_hooks_settings:
637 if c.visual.allow_custom_hooks_settings:
629 ui_key = self.request.POST.get('new_hook_ui_key')
638 ui_key = self.request.POST.get('new_hook_ui_key')
630 ui_value = self.request.POST.get('new_hook_ui_value')
639 ui_value = self.request.POST.get('new_hook_ui_value')
631
640
632 hook_id = self.request.POST.get('hook_id')
641 hook_id = self.request.POST.get('hook_id')
633 new_hook = False
642 new_hook = False
634
643
635 model = SettingsModel()
644 model = SettingsModel()
636 try:
645 try:
637 if ui_value and ui_key:
646 if ui_value and ui_key:
638 model.create_or_update_hook(ui_key, ui_value)
647 model.create_or_update_hook(ui_key, ui_value)
639 h.flash(_('Added new hook'), category='success')
648 h.flash(_('Added new hook'), category='success')
640 new_hook = True
649 new_hook = True
641 elif hook_id:
650 elif hook_id:
642 RhodeCodeUi.delete(hook_id)
651 RhodeCodeUi.delete(hook_id)
643 Session().commit()
652 Session().commit()
644
653
645 # check for edits
654 # check for edits
646 update = False
655 update = False
647 _d = self.request.POST.dict_of_lists()
656 _d = self.request.POST.dict_of_lists()
648 for k, v in zip(_d.get('hook_ui_key', []),
657 for k, v in zip(_d.get('hook_ui_key', []),
649 _d.get('hook_ui_value_new', [])):
658 _d.get('hook_ui_value_new', [])):
650 model.create_or_update_hook(k, v)
659 model.create_or_update_hook(k, v)
651 update = True
660 update = True
652
661
653 if update and not new_hook:
662 if update and not new_hook:
654 h.flash(_('Updated hooks'), category='success')
663 h.flash(_('Updated hooks'), category='success')
655 Session().commit()
664 Session().commit()
656 except Exception:
665 except Exception:
657 log.exception("Exception during hook creation")
666 log.exception("Exception during hook creation")
658 h.flash(_('Error occurred during hook creation'),
667 h.flash(_('Error occurred during hook creation'),
659 category='error')
668 category='error')
660
669
661 raise HTTPFound(h.route_path('admin_settings_hooks'))
670 raise HTTPFound(h.route_path('admin_settings_hooks'))
662
671
663 @LoginRequired()
672 @LoginRequired()
664 @HasPermissionAllDecorator('hg.admin')
673 @HasPermissionAllDecorator('hg.admin')
665 @view_config(
674 @view_config(
666 route_name='admin_settings_search', request_method='GET',
675 route_name='admin_settings_search', request_method='GET',
667 renderer='rhodecode:templates/admin/settings/settings.mako')
676 renderer='rhodecode:templates/admin/settings/settings.mako')
668 def settings_search(self):
677 def settings_search(self):
669 c = self.load_default_context()
678 c = self.load_default_context()
670 c.active = 'search'
679 c.active = 'search'
671
680
672 c.searcher = searcher_from_config(self.request.registry.settings)
681 c.searcher = searcher_from_config(self.request.registry.settings)
673 c.statistics = c.searcher.statistics(self.request.translate)
682 c.statistics = c.searcher.statistics(self.request.translate)
674
683
675 return self._get_template_context(c)
684 return self._get_template_context(c)
676
685
677 @LoginRequired()
686 @LoginRequired()
678 @HasPermissionAllDecorator('hg.admin')
687 @HasPermissionAllDecorator('hg.admin')
679 @view_config(
688 @view_config(
680 route_name='admin_settings_automation', request_method='GET',
689 route_name='admin_settings_automation', request_method='GET',
681 renderer='rhodecode:templates/admin/settings/settings.mako')
690 renderer='rhodecode:templates/admin/settings/settings.mako')
682 def settings_automation(self):
691 def settings_automation(self):
683 c = self.load_default_context()
692 c = self.load_default_context()
684 c.active = 'automation'
693 c.active = 'automation'
685
694
686 return self._get_template_context(c)
695 return self._get_template_context(c)
687
696
688 @LoginRequired()
697 @LoginRequired()
689 @HasPermissionAllDecorator('hg.admin')
698 @HasPermissionAllDecorator('hg.admin')
690 @view_config(
699 @view_config(
691 route_name='admin_settings_labs', request_method='GET',
700 route_name='admin_settings_labs', request_method='GET',
692 renderer='rhodecode:templates/admin/settings/settings.mako')
701 renderer='rhodecode:templates/admin/settings/settings.mako')
693 def settings_labs(self):
702 def settings_labs(self):
694 c = self.load_default_context()
703 c = self.load_default_context()
695 if not c.labs_active:
704 if not c.labs_active:
696 raise HTTPFound(h.route_path('admin_settings'))
705 raise HTTPFound(h.route_path('admin_settings'))
697
706
698 c.active = 'labs'
707 c.active = 'labs'
699 c.lab_settings = _LAB_SETTINGS
708 c.lab_settings = _LAB_SETTINGS
700
709
701 data = render('rhodecode:templates/admin/settings/settings.mako',
710 data = render('rhodecode:templates/admin/settings/settings.mako',
702 self._get_template_context(c), self.request)
711 self._get_template_context(c), self.request)
703 html = formencode.htmlfill.render(
712 html = formencode.htmlfill.render(
704 data,
713 data,
705 defaults=self._form_defaults(),
714 defaults=self._form_defaults(),
706 encoding="UTF-8",
715 encoding="UTF-8",
707 force_defaults=False
716 force_defaults=False
708 )
717 )
709 return Response(html)
718 return Response(html)
710
719
711 @LoginRequired()
720 @LoginRequired()
712 @HasPermissionAllDecorator('hg.admin')
721 @HasPermissionAllDecorator('hg.admin')
713 @CSRFRequired()
722 @CSRFRequired()
714 @view_config(
723 @view_config(
715 route_name='admin_settings_labs_update', request_method='POST',
724 route_name='admin_settings_labs_update', request_method='POST',
716 renderer='rhodecode:templates/admin/settings/settings.mako')
725 renderer='rhodecode:templates/admin/settings/settings.mako')
717 def settings_labs_update(self):
726 def settings_labs_update(self):
718 _ = self.request.translate
727 _ = self.request.translate
719 c = self.load_default_context()
728 c = self.load_default_context()
720 c.active = 'labs'
729 c.active = 'labs'
721
730
722 application_form = LabsSettingsForm(self.request.translate)()
731 application_form = LabsSettingsForm(self.request.translate)()
723 try:
732 try:
724 form_result = application_form.to_python(dict(self.request.POST))
733 form_result = application_form.to_python(dict(self.request.POST))
725 except formencode.Invalid as errors:
734 except formencode.Invalid as errors:
726 h.flash(
735 h.flash(
727 _("Some form inputs contain invalid data."),
736 _("Some form inputs contain invalid data."),
728 category='error')
737 category='error')
729 data = render('rhodecode:templates/admin/settings/settings.mako',
738 data = render('rhodecode:templates/admin/settings/settings.mako',
730 self._get_template_context(c), self.request)
739 self._get_template_context(c), self.request)
731 html = formencode.htmlfill.render(
740 html = formencode.htmlfill.render(
732 data,
741 data,
733 defaults=errors.value,
742 defaults=errors.value,
734 errors=errors.error_dict or {},
743 errors=errors.error_dict or {},
735 prefix_error=False,
744 prefix_error=False,
736 encoding="UTF-8",
745 encoding="UTF-8",
737 force_defaults=False
746 force_defaults=False
738 )
747 )
739 return Response(html)
748 return Response(html)
740
749
741 try:
750 try:
742 session = Session()
751 session = Session()
743 for setting in _LAB_SETTINGS:
752 for setting in _LAB_SETTINGS:
744 setting_name = setting.key[len('rhodecode_'):]
753 setting_name = setting.key[len('rhodecode_'):]
745 sett = SettingsModel().create_or_update_setting(
754 sett = SettingsModel().create_or_update_setting(
746 setting_name, form_result[setting.key], setting.type)
755 setting_name, form_result[setting.key], setting.type)
747 session.add(sett)
756 session.add(sett)
748
757
749 except Exception:
758 except Exception:
750 log.exception('Exception while updating lab settings')
759 log.exception('Exception while updating lab settings')
751 h.flash(_('Error occurred during updating labs settings'),
760 h.flash(_('Error occurred during updating labs settings'),
752 category='error')
761 category='error')
753 else:
762 else:
754 Session().commit()
763 Session().commit()
755 SettingsModel().invalidate_settings_cache()
764 SettingsModel().invalidate_settings_cache()
756 h.flash(_('Updated Labs settings'), category='success')
765 h.flash(_('Updated Labs settings'), category='success')
757 raise HTTPFound(h.route_path('admin_settings_labs'))
766 raise HTTPFound(h.route_path('admin_settings_labs'))
758
767
759 data = render('rhodecode:templates/admin/settings/settings.mako',
768 data = render('rhodecode:templates/admin/settings/settings.mako',
760 self._get_template_context(c), self.request)
769 self._get_template_context(c), self.request)
761 html = formencode.htmlfill.render(
770 html = formencode.htmlfill.render(
762 data,
771 data,
763 defaults=self._form_defaults(),
772 defaults=self._form_defaults(),
764 encoding="UTF-8",
773 encoding="UTF-8",
765 force_defaults=False
774 force_defaults=False
766 )
775 )
767 return Response(html)
776 return Response(html)
768
777
769
778
770 # :param key: name of the setting including the 'rhodecode_' prefix
779 # :param key: name of the setting including the 'rhodecode_' prefix
771 # :param type: the RhodeCodeSetting type to use.
780 # :param type: the RhodeCodeSetting type to use.
772 # :param group: the i18ned group in which we should dispaly this setting
781 # :param group: the i18ned group in which we should dispaly this setting
773 # :param label: the i18ned label we should display for this setting
782 # :param label: the i18ned label we should display for this setting
774 # :param help: the i18ned help we should dispaly for this setting
783 # :param help: the i18ned help we should dispaly for this setting
775 LabSetting = collections.namedtuple(
784 LabSetting = collections.namedtuple(
776 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
785 'LabSetting', ('key', 'type', 'group', 'label', 'help'))
777
786
778
787
779 # This list has to be kept in sync with the form
788 # This list has to be kept in sync with the form
780 # rhodecode.model.forms.LabsSettingsForm.
789 # rhodecode.model.forms.LabsSettingsForm.
781 _LAB_SETTINGS = [
790 _LAB_SETTINGS = [
782
791
783 ]
792 ]
@@ -1,436 +1,436 b''
1 # Copyright (C) 2016-2020 RhodeCode GmbH
1 # Copyright (C) 2016-2020 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import collections
19 import collections
20 import logging
20 import logging
21 import datetime
21 import datetime
22
22
23 from rhodecode.translation import lazy_ugettext
23 from rhodecode.translation import lazy_ugettext
24 from rhodecode.model.db import User, Repository, Session
24 from rhodecode.model.db import User, Repository, Session
25 from rhodecode.events.base import RhodeCodeIntegrationEvent
25 from rhodecode.events.base import RhodeCodeIntegrationEvent
26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
27
27
28 log = logging.getLogger(__name__)
28 log = logging.getLogger(__name__)
29
29
30
30
31 def _commits_as_dict(event, commit_ids, repos):
31 def _commits_as_dict(event, commit_ids, repos):
32 """
32 """
33 Helper function to serialize commit_ids
33 Helper function to serialize commit_ids
34
34
35 :param event: class calling this method
35 :param event: class calling this method
36 :param commit_ids: commits to get
36 :param commit_ids: commits to get
37 :param repos: list of repos to check
37 :param repos: list of repos to check
38 """
38 """
39 from rhodecode.lib.utils2 import extract_mentioned_users
39 from rhodecode.lib.utils2 import extract_mentioned_users
40 from rhodecode.lib.helpers import (
40 from rhodecode.lib.helpers import (
41 urlify_commit_message, process_patterns, chop_at_smart)
41 urlify_commit_message, process_patterns, chop_at_smart)
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43
43
44 if not repos:
44 if not repos:
45 raise Exception('no repo defined')
45 raise Exception('no repo defined')
46
46
47 if not isinstance(repos, (tuple, list)):
47 if not isinstance(repos, (tuple, list)):
48 repos = [repos]
48 repos = [repos]
49
49
50 if not commit_ids:
50 if not commit_ids:
51 return []
51 return []
52
52
53 needed_commits = list(commit_ids)
53 needed_commits = list(commit_ids)
54
54
55 commits = []
55 commits = []
56 reviewers = []
56 reviewers = []
57 for repo in repos:
57 for repo in repos:
58 if not needed_commits:
58 if not needed_commits:
59 return commits # return early if we have the commits we need
59 return commits # return early if we have the commits we need
60
60
61 vcs_repo = repo.scm_instance(cache=False)
61 vcs_repo = repo.scm_instance(cache=False)
62
62
63 try:
63 try:
64 # use copy of needed_commits since we modify it while iterating
64 # use copy of needed_commits since we modify it while iterating
65 for commit_id in list(needed_commits):
65 for commit_id in list(needed_commits):
66 if commit_id.startswith('tag=>'):
66 if commit_id.startswith('tag=>'):
67 raw_id = commit_id[5:]
67 raw_id = commit_id[5:]
68 cs_data = {
68 cs_data = {
69 'raw_id': commit_id, 'short_id': commit_id,
69 'raw_id': commit_id, 'short_id': commit_id,
70 'branch': None,
70 'branch': None,
71 'git_ref_change': 'tag_add',
71 'git_ref_change': 'tag_add',
72 'message': 'Added new tag {}'.format(raw_id),
72 'message': 'Added new tag {}'.format(raw_id),
73 'author': event.actor.full_contact,
73 'author': event.actor.full_contact,
74 'date': datetime.datetime.now(),
74 'date': datetime.datetime.now(),
75 'refs': {
75 'refs': {
76 'branches': [],
76 'branches': [],
77 'bookmarks': [],
77 'bookmarks': [],
78 'tags': []
78 'tags': []
79 }
79 }
80 }
80 }
81 commits.append(cs_data)
81 commits.append(cs_data)
82
82
83 elif commit_id.startswith('delete_branch=>'):
83 elif commit_id.startswith('delete_branch=>'):
84 raw_id = commit_id[15:]
84 raw_id = commit_id[15:]
85 cs_data = {
85 cs_data = {
86 'raw_id': commit_id, 'short_id': commit_id,
86 'raw_id': commit_id, 'short_id': commit_id,
87 'branch': None,
87 'branch': None,
88 'git_ref_change': 'branch_delete',
88 'git_ref_change': 'branch_delete',
89 'message': 'Deleted branch {}'.format(raw_id),
89 'message': 'Deleted branch {}'.format(raw_id),
90 'author': event.actor.full_contact,
90 'author': event.actor.full_contact,
91 'date': datetime.datetime.now(),
91 'date': datetime.datetime.now(),
92 'refs': {
92 'refs': {
93 'branches': [],
93 'branches': [],
94 'bookmarks': [],
94 'bookmarks': [],
95 'tags': []
95 'tags': []
96 }
96 }
97 }
97 }
98 commits.append(cs_data)
98 commits.append(cs_data)
99
99
100 else:
100 else:
101 try:
101 try:
102 cs = vcs_repo.get_commit(commit_id)
102 cs = vcs_repo.get_commit(commit_id)
103 except CommitDoesNotExistError:
103 except CommitDoesNotExistError:
104 continue # maybe its in next repo
104 continue # maybe its in next repo
105
105
106 cs_data = cs.__json__()
106 cs_data = cs.__json__()
107 cs_data['refs'] = cs._get_refs()
107 cs_data['refs'] = cs._get_refs()
108
108
109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
110 cs_data['reviewers'] = reviewers
110 cs_data['reviewers'] = reviewers
111 cs_data['url'] = RepoModel().get_commit_url(
111 cs_data['url'] = RepoModel().get_commit_url(
112 repo, cs_data['raw_id'], request=event.request)
112 repo, cs_data['raw_id'], request=event.request)
113 cs_data['permalink_url'] = RepoModel().get_commit_url(
113 cs_data['permalink_url'] = RepoModel().get_commit_url(
114 repo, cs_data['raw_id'], request=event.request,
114 repo, cs_data['raw_id'], request=event.request,
115 permalink=True)
115 permalink=True)
116 urlified_message, issues_data = process_patterns(
116 urlified_message, issues_data, errors = process_patterns(
117 cs_data['message'], repo.repo_name)
117 cs_data['message'], repo.repo_name)
118 cs_data['issues'] = issues_data
118 cs_data['issues'] = issues_data
119 cs_data['message_html'] = urlify_commit_message(
119 cs_data['message_html'] = urlify_commit_message(
120 cs_data['message'], repo.repo_name)
120 cs_data['message'], repo.repo_name)
121 cs_data['message_html_title'] = chop_at_smart(
121 cs_data['message_html_title'] = chop_at_smart(
122 cs_data['message'], '\n', suffix_if_chopped='...')
122 cs_data['message'], '\n', suffix_if_chopped='...')
123 commits.append(cs_data)
123 commits.append(cs_data)
124
124
125 needed_commits.remove(commit_id)
125 needed_commits.remove(commit_id)
126
126
127 except Exception:
127 except Exception:
128 log.exception('Failed to extract commits data')
128 log.exception('Failed to extract commits data')
129 # we don't send any commits when crash happens, only full list
129 # we don't send any commits when crash happens, only full list
130 # matters we short circuit then.
130 # matters we short circuit then.
131 return []
131 return []
132
132
133 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
133 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
134 if missing_commits:
134 if missing_commits:
135 log.error('Inconsistent repository state. '
135 log.error('Inconsistent repository state. '
136 'Missing commits: %s', ', '.join(missing_commits))
136 'Missing commits: %s', ', '.join(missing_commits))
137
137
138 return commits
138 return commits
139
139
140
140
141 def _issues_as_dict(commits):
141 def _issues_as_dict(commits):
142 """ Helper function to serialize issues from commits """
142 """ Helper function to serialize issues from commits """
143 issues = {}
143 issues = {}
144 for commit in commits:
144 for commit in commits:
145 for issue in commit['issues']:
145 for issue in commit['issues']:
146 issues[issue['id']] = issue
146 issues[issue['id']] = issue
147 return issues
147 return issues
148
148
149
149
150 class RepoEvent(RhodeCodeIntegrationEvent):
150 class RepoEvent(RhodeCodeIntegrationEvent):
151 """
151 """
152 Base class for events acting on a repository.
152 Base class for events acting on a repository.
153
153
154 :param repo: a :class:`Repository` instance
154 :param repo: a :class:`Repository` instance
155 """
155 """
156
156
157 def __init__(self, repo):
157 def __init__(self, repo):
158 super(RepoEvent, self).__init__()
158 super(RepoEvent, self).__init__()
159 self.repo = repo
159 self.repo = repo
160
160
161 def as_dict(self):
161 def as_dict(self):
162 from rhodecode.model.repo import RepoModel
162 from rhodecode.model.repo import RepoModel
163 data = super(RepoEvent, self).as_dict()
163 data = super(RepoEvent, self).as_dict()
164
164
165 extra_fields = collections.OrderedDict()
165 extra_fields = collections.OrderedDict()
166 for field in self.repo.extra_fields:
166 for field in self.repo.extra_fields:
167 extra_fields[field.field_key] = field.field_value
167 extra_fields[field.field_key] = field.field_value
168
168
169 data.update({
169 data.update({
170 'repo': {
170 'repo': {
171 'repo_id': self.repo.repo_id,
171 'repo_id': self.repo.repo_id,
172 'repo_name': self.repo.repo_name,
172 'repo_name': self.repo.repo_name,
173 'repo_type': self.repo.repo_type,
173 'repo_type': self.repo.repo_type,
174 'url': RepoModel().get_url(
174 'url': RepoModel().get_url(
175 self.repo, request=self.request),
175 self.repo, request=self.request),
176 'permalink_url': RepoModel().get_url(
176 'permalink_url': RepoModel().get_url(
177 self.repo, request=self.request, permalink=True),
177 self.repo, request=self.request, permalink=True),
178 'extra_fields': extra_fields
178 'extra_fields': extra_fields
179 }
179 }
180 })
180 })
181 return data
181 return data
182
182
183
183
184 class RepoCommitCommentEvent(RepoEvent):
184 class RepoCommitCommentEvent(RepoEvent):
185 """
185 """
186 An instance of this class is emitted as an :term:`event` after a comment is made
186 An instance of this class is emitted as an :term:`event` after a comment is made
187 on repository commit.
187 on repository commit.
188 """
188 """
189
189
190 name = 'repo-commit-comment'
190 name = 'repo-commit-comment'
191 display_name = lazy_ugettext('repository commit comment')
191 display_name = lazy_ugettext('repository commit comment')
192 description = lazy_ugettext('Event triggered after a comment was made '
192 description = lazy_ugettext('Event triggered after a comment was made '
193 'on commit inside a repository')
193 'on commit inside a repository')
194
194
195 def __init__(self, repo, commit, comment):
195 def __init__(self, repo, commit, comment):
196 super(RepoCommitCommentEvent, self).__init__(repo)
196 super(RepoCommitCommentEvent, self).__init__(repo)
197 self.commit = commit
197 self.commit = commit
198 self.comment = comment
198 self.comment = comment
199
199
200 def as_dict(self):
200 def as_dict(self):
201 data = super(RepoCommitCommentEvent, self).as_dict()
201 data = super(RepoCommitCommentEvent, self).as_dict()
202 data['commit'] = {
202 data['commit'] = {
203 'commit_id': self.commit.raw_id,
203 'commit_id': self.commit.raw_id,
204 'commit_message': self.commit.message,
204 'commit_message': self.commit.message,
205 'commit_branch': self.commit.branch,
205 'commit_branch': self.commit.branch,
206 }
206 }
207
207
208 data['comment'] = {
208 data['comment'] = {
209 'comment_id': self.comment.comment_id,
209 'comment_id': self.comment.comment_id,
210 'comment_text': self.comment.text,
210 'comment_text': self.comment.text,
211 'comment_type': self.comment.comment_type,
211 'comment_type': self.comment.comment_type,
212 'comment_f_path': self.comment.f_path,
212 'comment_f_path': self.comment.f_path,
213 'comment_line_no': self.comment.line_no,
213 'comment_line_no': self.comment.line_no,
214 'comment_version': self.comment.last_version,
214 'comment_version': self.comment.last_version,
215 }
215 }
216 return data
216 return data
217
217
218
218
219 class RepoCommitCommentEditEvent(RepoEvent):
219 class RepoCommitCommentEditEvent(RepoEvent):
220 """
220 """
221 An instance of this class is emitted as an :term:`event` after a comment is edited
221 An instance of this class is emitted as an :term:`event` after a comment is edited
222 on repository commit.
222 on repository commit.
223 """
223 """
224
224
225 name = 'repo-commit-edit-comment'
225 name = 'repo-commit-edit-comment'
226 display_name = lazy_ugettext('repository commit edit comment')
226 display_name = lazy_ugettext('repository commit edit comment')
227 description = lazy_ugettext('Event triggered after a comment was edited '
227 description = lazy_ugettext('Event triggered after a comment was edited '
228 'on commit inside a repository')
228 'on commit inside a repository')
229
229
230 def __init__(self, repo, commit, comment):
230 def __init__(self, repo, commit, comment):
231 super(RepoCommitCommentEditEvent, self).__init__(repo)
231 super(RepoCommitCommentEditEvent, self).__init__(repo)
232 self.commit = commit
232 self.commit = commit
233 self.comment = comment
233 self.comment = comment
234
234
235 def as_dict(self):
235 def as_dict(self):
236 data = super(RepoCommitCommentEditEvent, self).as_dict()
236 data = super(RepoCommitCommentEditEvent, self).as_dict()
237 data['commit'] = {
237 data['commit'] = {
238 'commit_id': self.commit.raw_id,
238 'commit_id': self.commit.raw_id,
239 'commit_message': self.commit.message,
239 'commit_message': self.commit.message,
240 'commit_branch': self.commit.branch,
240 'commit_branch': self.commit.branch,
241 }
241 }
242
242
243 data['comment'] = {
243 data['comment'] = {
244 'comment_id': self.comment.comment_id,
244 'comment_id': self.comment.comment_id,
245 'comment_text': self.comment.text,
245 'comment_text': self.comment.text,
246 'comment_type': self.comment.comment_type,
246 'comment_type': self.comment.comment_type,
247 'comment_f_path': self.comment.f_path,
247 'comment_f_path': self.comment.f_path,
248 'comment_line_no': self.comment.line_no,
248 'comment_line_no': self.comment.line_no,
249 'comment_version': self.comment.last_version,
249 'comment_version': self.comment.last_version,
250 }
250 }
251 return data
251 return data
252
252
253
253
254 class RepoPreCreateEvent(RepoEvent):
254 class RepoPreCreateEvent(RepoEvent):
255 """
255 """
256 An instance of this class is emitted as an :term:`event` before a repo is
256 An instance of this class is emitted as an :term:`event` before a repo is
257 created.
257 created.
258 """
258 """
259 name = 'repo-pre-create'
259 name = 'repo-pre-create'
260 display_name = lazy_ugettext('repository pre create')
260 display_name = lazy_ugettext('repository pre create')
261 description = lazy_ugettext('Event triggered before repository is created')
261 description = lazy_ugettext('Event triggered before repository is created')
262
262
263
263
264 class RepoCreateEvent(RepoEvent):
264 class RepoCreateEvent(RepoEvent):
265 """
265 """
266 An instance of this class is emitted as an :term:`event` whenever a repo is
266 An instance of this class is emitted as an :term:`event` whenever a repo is
267 created.
267 created.
268 """
268 """
269 name = 'repo-create'
269 name = 'repo-create'
270 display_name = lazy_ugettext('repository created')
270 display_name = lazy_ugettext('repository created')
271 description = lazy_ugettext('Event triggered after repository was created')
271 description = lazy_ugettext('Event triggered after repository was created')
272
272
273
273
274 class RepoPreDeleteEvent(RepoEvent):
274 class RepoPreDeleteEvent(RepoEvent):
275 """
275 """
276 An instance of this class is emitted as an :term:`event` whenever a repo is
276 An instance of this class is emitted as an :term:`event` whenever a repo is
277 created.
277 created.
278 """
278 """
279 name = 'repo-pre-delete'
279 name = 'repo-pre-delete'
280 display_name = lazy_ugettext('repository pre delete')
280 display_name = lazy_ugettext('repository pre delete')
281 description = lazy_ugettext('Event triggered before a repository is deleted')
281 description = lazy_ugettext('Event triggered before a repository is deleted')
282
282
283
283
284 class RepoDeleteEvent(RepoEvent):
284 class RepoDeleteEvent(RepoEvent):
285 """
285 """
286 An instance of this class is emitted as an :term:`event` whenever a repo is
286 An instance of this class is emitted as an :term:`event` whenever a repo is
287 created.
287 created.
288 """
288 """
289 name = 'repo-delete'
289 name = 'repo-delete'
290 display_name = lazy_ugettext('repository deleted')
290 display_name = lazy_ugettext('repository deleted')
291 description = lazy_ugettext('Event triggered after repository was deleted')
291 description = lazy_ugettext('Event triggered after repository was deleted')
292
292
293
293
294 class RepoVCSEvent(RepoEvent):
294 class RepoVCSEvent(RepoEvent):
295 """
295 """
296 Base class for events triggered by the VCS
296 Base class for events triggered by the VCS
297 """
297 """
298 def __init__(self, repo_name, extras):
298 def __init__(self, repo_name, extras):
299 self.repo = Repository.get_by_repo_name(repo_name)
299 self.repo = Repository.get_by_repo_name(repo_name)
300 if not self.repo:
300 if not self.repo:
301 raise Exception('repo by this name %s does not exist' % repo_name)
301 raise Exception('repo by this name %s does not exist' % repo_name)
302 self.extras = extras
302 self.extras = extras
303 super(RepoVCSEvent, self).__init__(self.repo)
303 super(RepoVCSEvent, self).__init__(self.repo)
304
304
305 @property
305 @property
306 def actor(self):
306 def actor(self):
307 if self.extras.get('username'):
307 if self.extras.get('username'):
308 return User.get_by_username(self.extras['username'])
308 return User.get_by_username(self.extras['username'])
309
309
310 @property
310 @property
311 def actor_ip(self):
311 def actor_ip(self):
312 if self.extras.get('ip'):
312 if self.extras.get('ip'):
313 return self.extras['ip']
313 return self.extras['ip']
314
314
315 @property
315 @property
316 def server_url(self):
316 def server_url(self):
317 if self.extras.get('server_url'):
317 if self.extras.get('server_url'):
318 return self.extras['server_url']
318 return self.extras['server_url']
319
319
320 @property
320 @property
321 def request(self):
321 def request(self):
322 return self.extras.get('request') or self.get_request()
322 return self.extras.get('request') or self.get_request()
323
323
324
324
325 class RepoPrePullEvent(RepoVCSEvent):
325 class RepoPrePullEvent(RepoVCSEvent):
326 """
326 """
327 An instance of this class is emitted as an :term:`event` before commits
327 An instance of this class is emitted as an :term:`event` before commits
328 are pulled from a repo.
328 are pulled from a repo.
329 """
329 """
330 name = 'repo-pre-pull'
330 name = 'repo-pre-pull'
331 display_name = lazy_ugettext('repository pre pull')
331 display_name = lazy_ugettext('repository pre pull')
332 description = lazy_ugettext('Event triggered before repository code is pulled')
332 description = lazy_ugettext('Event triggered before repository code is pulled')
333
333
334
334
335 class RepoPullEvent(RepoVCSEvent):
335 class RepoPullEvent(RepoVCSEvent):
336 """
336 """
337 An instance of this class is emitted as an :term:`event` after commits
337 An instance of this class is emitted as an :term:`event` after commits
338 are pulled from a repo.
338 are pulled from a repo.
339 """
339 """
340 name = 'repo-pull'
340 name = 'repo-pull'
341 display_name = lazy_ugettext('repository pull')
341 display_name = lazy_ugettext('repository pull')
342 description = lazy_ugettext('Event triggered after repository code was pulled')
342 description = lazy_ugettext('Event triggered after repository code was pulled')
343
343
344
344
345 class RepoPrePushEvent(RepoVCSEvent):
345 class RepoPrePushEvent(RepoVCSEvent):
346 """
346 """
347 An instance of this class is emitted as an :term:`event` before commits
347 An instance of this class is emitted as an :term:`event` before commits
348 are pushed to a repo.
348 are pushed to a repo.
349 """
349 """
350 name = 'repo-pre-push'
350 name = 'repo-pre-push'
351 display_name = lazy_ugettext('repository pre push')
351 display_name = lazy_ugettext('repository pre push')
352 description = lazy_ugettext('Event triggered before the code is '
352 description = lazy_ugettext('Event triggered before the code is '
353 'pushed to a repository')
353 'pushed to a repository')
354
354
355
355
356 class RepoPushEvent(RepoVCSEvent):
356 class RepoPushEvent(RepoVCSEvent):
357 """
357 """
358 An instance of this class is emitted as an :term:`event` after commits
358 An instance of this class is emitted as an :term:`event` after commits
359 are pushed to a repo.
359 are pushed to a repo.
360
360
361 :param extras: (optional) dict of data from proxied VCS actions
361 :param extras: (optional) dict of data from proxied VCS actions
362 """
362 """
363 name = 'repo-push'
363 name = 'repo-push'
364 display_name = lazy_ugettext('repository push')
364 display_name = lazy_ugettext('repository push')
365 description = lazy_ugettext('Event triggered after the code was '
365 description = lazy_ugettext('Event triggered after the code was '
366 'pushed to a repository')
366 'pushed to a repository')
367
367
368 def __init__(self, repo_name, pushed_commit_ids, extras):
368 def __init__(self, repo_name, pushed_commit_ids, extras):
369 super(RepoPushEvent, self).__init__(repo_name, extras)
369 super(RepoPushEvent, self).__init__(repo_name, extras)
370 self.pushed_commit_ids = pushed_commit_ids
370 self.pushed_commit_ids = pushed_commit_ids
371 self.new_refs = extras.new_refs
371 self.new_refs = extras.new_refs
372
372
373 def as_dict(self):
373 def as_dict(self):
374 data = super(RepoPushEvent, self).as_dict()
374 data = super(RepoPushEvent, self).as_dict()
375
375
376 def branch_url(branch_name):
376 def branch_url(branch_name):
377 return '{}/changelog?branch={}'.format(
377 return '{}/changelog?branch={}'.format(
378 data['repo']['url'], branch_name)
378 data['repo']['url'], branch_name)
379
379
380 def tag_url(tag_name):
380 def tag_url(tag_name):
381 return '{}/files/{}/'.format(
381 return '{}/files/{}/'.format(
382 data['repo']['url'], tag_name)
382 data['repo']['url'], tag_name)
383
383
384 commits = _commits_as_dict(
384 commits = _commits_as_dict(
385 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
385 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
386
386
387 last_branch = None
387 last_branch = None
388 for commit in reversed(commits):
388 for commit in reversed(commits):
389 commit['branch'] = commit['branch'] or last_branch
389 commit['branch'] = commit['branch'] or last_branch
390 last_branch = commit['branch']
390 last_branch = commit['branch']
391 issues = _issues_as_dict(commits)
391 issues = _issues_as_dict(commits)
392
392
393 branches = set()
393 branches = set()
394 tags = set()
394 tags = set()
395 for commit in commits:
395 for commit in commits:
396 if commit['refs']['tags']:
396 if commit['refs']['tags']:
397 for tag in commit['refs']['tags']:
397 for tag in commit['refs']['tags']:
398 tags.add(tag)
398 tags.add(tag)
399 if commit['branch']:
399 if commit['branch']:
400 branches.add(commit['branch'])
400 branches.add(commit['branch'])
401
401
402 # maybe we have branches in new_refs ?
402 # maybe we have branches in new_refs ?
403 try:
403 try:
404 branches = branches.union(set(self.new_refs['branches']))
404 branches = branches.union(set(self.new_refs['branches']))
405 except Exception:
405 except Exception:
406 pass
406 pass
407
407
408 branches = [
408 branches = [
409 {
409 {
410 'name': branch,
410 'name': branch,
411 'url': branch_url(branch)
411 'url': branch_url(branch)
412 }
412 }
413 for branch in branches
413 for branch in branches
414 ]
414 ]
415
415
416 # maybe we have branches in new_refs ?
416 # maybe we have branches in new_refs ?
417 try:
417 try:
418 tags = tags.union(set(self.new_refs['tags']))
418 tags = tags.union(set(self.new_refs['tags']))
419 except Exception:
419 except Exception:
420 pass
420 pass
421
421
422 tags = [
422 tags = [
423 {
423 {
424 'name': tag,
424 'name': tag,
425 'url': tag_url(tag)
425 'url': tag_url(tag)
426 }
426 }
427 for tag in tags
427 for tag in tags
428 ]
428 ]
429
429
430 data['push'] = {
430 data['push'] = {
431 'commits': commits,
431 'commits': commits,
432 'issues': issues,
432 'issues': issues,
433 'branches': branches,
433 'branches': branches,
434 'tags': tags,
434 'tags': tags,
435 }
435 }
436 return data
436 return data
@@ -1,2106 +1,2113 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Helper functions
22 Helper functions
23
23
24 Consists of functions to typically be used within templates, but also
24 Consists of functions to typically be used within templates, but also
25 available to Controllers. This module is available to both as 'h'.
25 available to Controllers. This module is available to both as 'h'.
26 """
26 """
27 import base64
27 import base64
28
28
29 import os
29 import os
30 import random
30 import random
31 import hashlib
31 import hashlib
32 import StringIO
32 import StringIO
33 import textwrap
33 import textwrap
34 import urllib
34 import urllib
35 import math
35 import math
36 import logging
36 import logging
37 import re
37 import re
38 import time
38 import time
39 import string
39 import string
40 import hashlib
40 import hashlib
41 import regex
41 from collections import OrderedDict
42 from collections import OrderedDict
42
43
43 import pygments
44 import pygments
44 import itertools
45 import itertools
45 import fnmatch
46 import fnmatch
46 import bleach
47 import bleach
47
48
48 from pyramid import compat
49 from pyramid import compat
49 from datetime import datetime
50 from datetime import datetime
50 from functools import partial
51 from functools import partial
51 from pygments.formatters.html import HtmlFormatter
52 from pygments.formatters.html import HtmlFormatter
52 from pygments.lexers import (
53 from pygments.lexers import (
53 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
54 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
54
55
55 from pyramid.threadlocal import get_current_request
56 from pyramid.threadlocal import get_current_request
56 from tempita import looper
57 from tempita import looper
57 from webhelpers2.html import literal, HTML, escape
58 from webhelpers2.html import literal, HTML, escape
58 from webhelpers2.html._autolink import _auto_link_urls
59 from webhelpers2.html._autolink import _auto_link_urls
59 from webhelpers2.html.tools import (
60 from webhelpers2.html.tools import (
60 button_to, highlight, js_obfuscate, strip_links, strip_tags)
61 button_to, highlight, js_obfuscate, strip_links, strip_tags)
61
62
62 from webhelpers2.text import (
63 from webhelpers2.text import (
63 chop_at, collapse, convert_accented_entities,
64 chop_at, collapse, convert_accented_entities,
64 convert_misc_entities, lchop, plural, rchop, remove_formatting,
65 convert_misc_entities, lchop, plural, rchop, remove_formatting,
65 replace_whitespace, urlify, truncate, wrap_paragraphs)
66 replace_whitespace, urlify, truncate, wrap_paragraphs)
66 from webhelpers2.date import time_ago_in_words
67 from webhelpers2.date import time_ago_in_words
67
68
68 from webhelpers2.html.tags import (
69 from webhelpers2.html.tags import (
69 _input, NotGiven, _make_safe_id_component as safeid,
70 _input, NotGiven, _make_safe_id_component as safeid,
70 form as insecure_form,
71 form as insecure_form,
71 auto_discovery_link, checkbox, end_form, file,
72 auto_discovery_link, checkbox, end_form, file,
72 hidden, image, javascript_link, link_to, link_to_if, link_to_unless, ol,
73 hidden, image, javascript_link, link_to, link_to_if, link_to_unless, ol,
73 select as raw_select, stylesheet_link, submit, text, password, textarea,
74 select as raw_select, stylesheet_link, submit, text, password, textarea,
74 ul, radio, Options)
75 ul, radio, Options)
75
76
76 from webhelpers2.number import format_byte_size
77 from webhelpers2.number import format_byte_size
77
78
78 from rhodecode.lib.action_parser import action_parser
79 from rhodecode.lib.action_parser import action_parser
79 from rhodecode.lib.pagination import Page, RepoPage, SqlPage
80 from rhodecode.lib.pagination import Page, RepoPage, SqlPage
80 from rhodecode.lib.ext_json import json
81 from rhodecode.lib.ext_json import json
81 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
82 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
82 from rhodecode.lib.utils2 import (
83 from rhodecode.lib.utils2 import (
83 str2bool, safe_unicode, safe_str,
84 str2bool, safe_unicode, safe_str,
84 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime,
85 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime,
85 AttributeDict, safe_int, md5, md5_safe, get_host_info)
86 AttributeDict, safe_int, md5, md5_safe, get_host_info)
86 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
87 from rhodecode.lib.markup_renderer import MarkupRenderer, relative_links
87 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
88 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
88 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
89 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
89 from rhodecode.lib.vcs.conf.settings import ARCHIVE_SPECS
90 from rhodecode.lib.vcs.conf.settings import ARCHIVE_SPECS
90 from rhodecode.lib.index.search_utils import get_matching_line_offsets
91 from rhodecode.lib.index.search_utils import get_matching_line_offsets
91 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
92 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
92 from rhodecode.model.changeset_status import ChangesetStatusModel
93 from rhodecode.model.changeset_status import ChangesetStatusModel
93 from rhodecode.model.db import Permission, User, Repository, UserApiKeys, FileStore
94 from rhodecode.model.db import Permission, User, Repository, UserApiKeys, FileStore
94 from rhodecode.model.repo_group import RepoGroupModel
95 from rhodecode.model.repo_group import RepoGroupModel
95 from rhodecode.model.settings import IssueTrackerSettingsModel
96 from rhodecode.model.settings import IssueTrackerSettingsModel
96
97
97
98
98 log = logging.getLogger(__name__)
99 log = logging.getLogger(__name__)
99
100
100
101
101 DEFAULT_USER = User.DEFAULT_USER
102 DEFAULT_USER = User.DEFAULT_USER
102 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
103 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
103
104
104
105
105 def asset(path, ver=None, **kwargs):
106 def asset(path, ver=None, **kwargs):
106 """
107 """
107 Helper to generate a static asset file path for rhodecode assets
108 Helper to generate a static asset file path for rhodecode assets
108
109
109 eg. h.asset('images/image.png', ver='3923')
110 eg. h.asset('images/image.png', ver='3923')
110
111
111 :param path: path of asset
112 :param path: path of asset
112 :param ver: optional version query param to append as ?ver=
113 :param ver: optional version query param to append as ?ver=
113 """
114 """
114 request = get_current_request()
115 request = get_current_request()
115 query = {}
116 query = {}
116 query.update(kwargs)
117 query.update(kwargs)
117 if ver:
118 if ver:
118 query = {'ver': ver}
119 query = {'ver': ver}
119 return request.static_path(
120 return request.static_path(
120 'rhodecode:public/{}'.format(path), _query=query)
121 'rhodecode:public/{}'.format(path), _query=query)
121
122
122
123
123 default_html_escape_table = {
124 default_html_escape_table = {
124 ord('&'): u'&amp;',
125 ord('&'): u'&amp;',
125 ord('<'): u'&lt;',
126 ord('<'): u'&lt;',
126 ord('>'): u'&gt;',
127 ord('>'): u'&gt;',
127 ord('"'): u'&quot;',
128 ord('"'): u'&quot;',
128 ord("'"): u'&#39;',
129 ord("'"): u'&#39;',
129 }
130 }
130
131
131
132
132 def html_escape(text, html_escape_table=default_html_escape_table):
133 def html_escape(text, html_escape_table=default_html_escape_table):
133 """Produce entities within text."""
134 """Produce entities within text."""
134 return text.translate(html_escape_table)
135 return text.translate(html_escape_table)
135
136
136
137
137 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
138 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
138 """
139 """
139 Truncate string ``s`` at the first occurrence of ``sub``.
140 Truncate string ``s`` at the first occurrence of ``sub``.
140
141
141 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
142 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
142 """
143 """
143 suffix_if_chopped = suffix_if_chopped or ''
144 suffix_if_chopped = suffix_if_chopped or ''
144 pos = s.find(sub)
145 pos = s.find(sub)
145 if pos == -1:
146 if pos == -1:
146 return s
147 return s
147
148
148 if inclusive:
149 if inclusive:
149 pos += len(sub)
150 pos += len(sub)
150
151
151 chopped = s[:pos]
152 chopped = s[:pos]
152 left = s[pos:].strip()
153 left = s[pos:].strip()
153
154
154 if left and suffix_if_chopped:
155 if left and suffix_if_chopped:
155 chopped += suffix_if_chopped
156 chopped += suffix_if_chopped
156
157
157 return chopped
158 return chopped
158
159
159
160
160 def shorter(text, size=20, prefix=False):
161 def shorter(text, size=20, prefix=False):
161 postfix = '...'
162 postfix = '...'
162 if len(text) > size:
163 if len(text) > size:
163 if prefix:
164 if prefix:
164 # shorten in front
165 # shorten in front
165 return postfix + text[-(size - len(postfix)):]
166 return postfix + text[-(size - len(postfix)):]
166 else:
167 else:
167 return text[:size - len(postfix)] + postfix
168 return text[:size - len(postfix)] + postfix
168 return text
169 return text
169
170
170
171
171 def reset(name, value=None, id=NotGiven, type="reset", **attrs):
172 def reset(name, value=None, id=NotGiven, type="reset", **attrs):
172 """
173 """
173 Reset button
174 Reset button
174 """
175 """
175 return _input(type, name, value, id, attrs)
176 return _input(type, name, value, id, attrs)
176
177
177
178
178 def select(name, selected_values, options, id=NotGiven, **attrs):
179 def select(name, selected_values, options, id=NotGiven, **attrs):
179
180
180 if isinstance(options, (list, tuple)):
181 if isinstance(options, (list, tuple)):
181 options_iter = options
182 options_iter = options
182 # Handle old value,label lists ... where value also can be value,label lists
183 # Handle old value,label lists ... where value also can be value,label lists
183 options = Options()
184 options = Options()
184 for opt in options_iter:
185 for opt in options_iter:
185 if isinstance(opt, tuple) and len(opt) == 2:
186 if isinstance(opt, tuple) and len(opt) == 2:
186 value, label = opt
187 value, label = opt
187 elif isinstance(opt, basestring):
188 elif isinstance(opt, basestring):
188 value = label = opt
189 value = label = opt
189 else:
190 else:
190 raise ValueError('invalid select option type %r' % type(opt))
191 raise ValueError('invalid select option type %r' % type(opt))
191
192
192 if isinstance(value, (list, tuple)):
193 if isinstance(value, (list, tuple)):
193 option_group = options.add_optgroup(label)
194 option_group = options.add_optgroup(label)
194 for opt2 in value:
195 for opt2 in value:
195 if isinstance(opt2, tuple) and len(opt2) == 2:
196 if isinstance(opt2, tuple) and len(opt2) == 2:
196 group_value, group_label = opt2
197 group_value, group_label = opt2
197 elif isinstance(opt2, basestring):
198 elif isinstance(opt2, basestring):
198 group_value = group_label = opt2
199 group_value = group_label = opt2
199 else:
200 else:
200 raise ValueError('invalid select option type %r' % type(opt2))
201 raise ValueError('invalid select option type %r' % type(opt2))
201
202
202 option_group.add_option(group_label, group_value)
203 option_group.add_option(group_label, group_value)
203 else:
204 else:
204 options.add_option(label, value)
205 options.add_option(label, value)
205
206
206 return raw_select(name, selected_values, options, id=id, **attrs)
207 return raw_select(name, selected_values, options, id=id, **attrs)
207
208
208
209
209 def branding(name, length=40):
210 def branding(name, length=40):
210 return truncate(name, length, indicator="")
211 return truncate(name, length, indicator="")
211
212
212
213
213 def FID(raw_id, path):
214 def FID(raw_id, path):
214 """
215 """
215 Creates a unique ID for filenode based on it's hash of path and commit
216 Creates a unique ID for filenode based on it's hash of path and commit
216 it's safe to use in urls
217 it's safe to use in urls
217
218
218 :param raw_id:
219 :param raw_id:
219 :param path:
220 :param path:
220 """
221 """
221
222
222 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
223 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
223
224
224
225
225 class _GetError(object):
226 class _GetError(object):
226 """Get error from form_errors, and represent it as span wrapped error
227 """Get error from form_errors, and represent it as span wrapped error
227 message
228 message
228
229
229 :param field_name: field to fetch errors for
230 :param field_name: field to fetch errors for
230 :param form_errors: form errors dict
231 :param form_errors: form errors dict
231 """
232 """
232
233
233 def __call__(self, field_name, form_errors):
234 def __call__(self, field_name, form_errors):
234 tmpl = """<span class="error_msg">%s</span>"""
235 tmpl = """<span class="error_msg">%s</span>"""
235 if form_errors and field_name in form_errors:
236 if form_errors and field_name in form_errors:
236 return literal(tmpl % form_errors.get(field_name))
237 return literal(tmpl % form_errors.get(field_name))
237
238
238
239
239 get_error = _GetError()
240 get_error = _GetError()
240
241
241
242
242 class _ToolTip(object):
243 class _ToolTip(object):
243
244
244 def __call__(self, tooltip_title, trim_at=50):
245 def __call__(self, tooltip_title, trim_at=50):
245 """
246 """
246 Special function just to wrap our text into nice formatted
247 Special function just to wrap our text into nice formatted
247 autowrapped text
248 autowrapped text
248
249
249 :param tooltip_title:
250 :param tooltip_title:
250 """
251 """
251 tooltip_title = escape(tooltip_title)
252 tooltip_title = escape(tooltip_title)
252 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
253 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
253 return tooltip_title
254 return tooltip_title
254
255
255
256
256 tooltip = _ToolTip()
257 tooltip = _ToolTip()
257
258
258 files_icon = u'<i class="file-breadcrumb-copy tooltip icon-clipboard clipboard-action" data-clipboard-text="{}" title="Copy file path"></i>'
259 files_icon = u'<i class="file-breadcrumb-copy tooltip icon-clipboard clipboard-action" data-clipboard-text="{}" title="Copy file path"></i>'
259
260
260
261
261 def files_breadcrumbs(repo_name, repo_type, commit_id, file_path, landing_ref_name=None, at_ref=None,
262 def files_breadcrumbs(repo_name, repo_type, commit_id, file_path, landing_ref_name=None, at_ref=None,
262 limit_items=False, linkify_last_item=False, hide_last_item=False,
263 limit_items=False, linkify_last_item=False, hide_last_item=False,
263 copy_path_icon=True):
264 copy_path_icon=True):
264 if isinstance(file_path, str):
265 if isinstance(file_path, str):
265 file_path = safe_unicode(file_path)
266 file_path = safe_unicode(file_path)
266
267
267 if at_ref:
268 if at_ref:
268 route_qry = {'at': at_ref}
269 route_qry = {'at': at_ref}
269 default_landing_ref = at_ref or landing_ref_name or commit_id
270 default_landing_ref = at_ref or landing_ref_name or commit_id
270 else:
271 else:
271 route_qry = None
272 route_qry = None
272 default_landing_ref = commit_id
273 default_landing_ref = commit_id
273
274
274 # first segment is a `HOME` link to repo files root location
275 # first segment is a `HOME` link to repo files root location
275 root_name = literal(u'<i class="icon-home"></i>')
276 root_name = literal(u'<i class="icon-home"></i>')
276
277
277 url_segments = [
278 url_segments = [
278 link_to(
279 link_to(
279 root_name,
280 root_name,
280 repo_files_by_ref_url(
281 repo_files_by_ref_url(
281 repo_name,
282 repo_name,
282 repo_type,
283 repo_type,
283 f_path=None, # None here is a special case for SVN repos,
284 f_path=None, # None here is a special case for SVN repos,
284 # that won't prefix with a ref
285 # that won't prefix with a ref
285 ref_name=default_landing_ref,
286 ref_name=default_landing_ref,
286 commit_id=commit_id,
287 commit_id=commit_id,
287 query=route_qry
288 query=route_qry
288 )
289 )
289 )]
290 )]
290
291
291 path_segments = file_path.split('/')
292 path_segments = file_path.split('/')
292 last_cnt = len(path_segments) - 1
293 last_cnt = len(path_segments) - 1
293 for cnt, segment in enumerate(path_segments):
294 for cnt, segment in enumerate(path_segments):
294 if not segment:
295 if not segment:
295 continue
296 continue
296 segment_html = escape(segment)
297 segment_html = escape(segment)
297
298
298 last_item = cnt == last_cnt
299 last_item = cnt == last_cnt
299
300
300 if last_item and hide_last_item:
301 if last_item and hide_last_item:
301 # iterate over and hide last element
302 # iterate over and hide last element
302 continue
303 continue
303
304
304 if last_item and linkify_last_item is False:
305 if last_item and linkify_last_item is False:
305 # plain version
306 # plain version
306 url_segments.append(segment_html)
307 url_segments.append(segment_html)
307 else:
308 else:
308 url_segments.append(
309 url_segments.append(
309 link_to(
310 link_to(
310 segment_html,
311 segment_html,
311 repo_files_by_ref_url(
312 repo_files_by_ref_url(
312 repo_name,
313 repo_name,
313 repo_type,
314 repo_type,
314 f_path='/'.join(path_segments[:cnt + 1]),
315 f_path='/'.join(path_segments[:cnt + 1]),
315 ref_name=default_landing_ref,
316 ref_name=default_landing_ref,
316 commit_id=commit_id,
317 commit_id=commit_id,
317 query=route_qry
318 query=route_qry
318 ),
319 ),
319 ))
320 ))
320
321
321 limited_url_segments = url_segments[:1] + ['...'] + url_segments[-5:]
322 limited_url_segments = url_segments[:1] + ['...'] + url_segments[-5:]
322 if limit_items and len(limited_url_segments) < len(url_segments):
323 if limit_items and len(limited_url_segments) < len(url_segments):
323 url_segments = limited_url_segments
324 url_segments = limited_url_segments
324
325
325 full_path = file_path
326 full_path = file_path
326 if copy_path_icon:
327 if copy_path_icon:
327 icon = files_icon.format(escape(full_path))
328 icon = files_icon.format(escape(full_path))
328 else:
329 else:
329 icon = ''
330 icon = ''
330
331
331 if file_path == '':
332 if file_path == '':
332 return root_name
333 return root_name
333 else:
334 else:
334 return literal(' / '.join(url_segments) + icon)
335 return literal(' / '.join(url_segments) + icon)
335
336
336
337
337 def files_url_data(request):
338 def files_url_data(request):
338 matchdict = request.matchdict
339 matchdict = request.matchdict
339
340
340 if 'f_path' not in matchdict:
341 if 'f_path' not in matchdict:
341 matchdict['f_path'] = ''
342 matchdict['f_path'] = ''
342
343
343 if 'commit_id' not in matchdict:
344 if 'commit_id' not in matchdict:
344 matchdict['commit_id'] = 'tip'
345 matchdict['commit_id'] = 'tip'
345
346
346 return json.dumps(matchdict)
347 return json.dumps(matchdict)
347
348
348
349
349 def repo_files_by_ref_url(db_repo_name, db_repo_type, f_path, ref_name, commit_id, query=None, ):
350 def repo_files_by_ref_url(db_repo_name, db_repo_type, f_path, ref_name, commit_id, query=None, ):
350 _is_svn = is_svn(db_repo_type)
351 _is_svn = is_svn(db_repo_type)
351 final_f_path = f_path
352 final_f_path = f_path
352
353
353 if _is_svn:
354 if _is_svn:
354 """
355 """
355 For SVN the ref_name cannot be used as a commit_id, it needs to be prefixed with
356 For SVN the ref_name cannot be used as a commit_id, it needs to be prefixed with
356 actually commit_id followed by the ref_name. This should be done only in case
357 actually commit_id followed by the ref_name. This should be done only in case
357 This is a initial landing url, without additional paths.
358 This is a initial landing url, without additional paths.
358
359
359 like: /1000/tags/1.0.0/?at=tags/1.0.0
360 like: /1000/tags/1.0.0/?at=tags/1.0.0
360 """
361 """
361
362
362 if ref_name and ref_name != 'tip':
363 if ref_name and ref_name != 'tip':
363 # NOTE(marcink): for svn the ref_name is actually the stored path, so we prefix it
364 # NOTE(marcink): for svn the ref_name is actually the stored path, so we prefix it
364 # for SVN we only do this magic prefix if it's root, .eg landing revision
365 # for SVN we only do this magic prefix if it's root, .eg landing revision
365 # of files link. If we are in the tree we don't need this since we traverse the url
366 # of files link. If we are in the tree we don't need this since we traverse the url
366 # that has everything stored
367 # that has everything stored
367 if f_path in ['', '/']:
368 if f_path in ['', '/']:
368 final_f_path = '/'.join([ref_name, f_path])
369 final_f_path = '/'.join([ref_name, f_path])
369
370
370 # SVN always needs a commit_id explicitly, without a named REF
371 # SVN always needs a commit_id explicitly, without a named REF
371 default_commit_id = commit_id
372 default_commit_id = commit_id
372 else:
373 else:
373 """
374 """
374 For git and mercurial we construct a new URL using the names instead of commit_id
375 For git and mercurial we construct a new URL using the names instead of commit_id
375 like: /master/some_path?at=master
376 like: /master/some_path?at=master
376 """
377 """
377 # We currently do not support branches with slashes
378 # We currently do not support branches with slashes
378 if '/' in ref_name:
379 if '/' in ref_name:
379 default_commit_id = commit_id
380 default_commit_id = commit_id
380 else:
381 else:
381 default_commit_id = ref_name
382 default_commit_id = ref_name
382
383
383 # sometimes we pass f_path as None, to indicate explicit no prefix,
384 # sometimes we pass f_path as None, to indicate explicit no prefix,
384 # we translate it to string to not have None
385 # we translate it to string to not have None
385 final_f_path = final_f_path or ''
386 final_f_path = final_f_path or ''
386
387
387 files_url = route_path(
388 files_url = route_path(
388 'repo_files',
389 'repo_files',
389 repo_name=db_repo_name,
390 repo_name=db_repo_name,
390 commit_id=default_commit_id,
391 commit_id=default_commit_id,
391 f_path=final_f_path,
392 f_path=final_f_path,
392 _query=query
393 _query=query
393 )
394 )
394 return files_url
395 return files_url
395
396
396
397
397 def code_highlight(code, lexer, formatter, use_hl_filter=False):
398 def code_highlight(code, lexer, formatter, use_hl_filter=False):
398 """
399 """
399 Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
400 Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
400
401
401 If ``outfile`` is given and a valid file object (an object
402 If ``outfile`` is given and a valid file object (an object
402 with a ``write`` method), the result will be written to it, otherwise
403 with a ``write`` method), the result will be written to it, otherwise
403 it is returned as a string.
404 it is returned as a string.
404 """
405 """
405 if use_hl_filter:
406 if use_hl_filter:
406 # add HL filter
407 # add HL filter
407 from rhodecode.lib.index import search_utils
408 from rhodecode.lib.index import search_utils
408 lexer.add_filter(search_utils.ElasticSearchHLFilter())
409 lexer.add_filter(search_utils.ElasticSearchHLFilter())
409 return pygments.format(pygments.lex(code, lexer), formatter)
410 return pygments.format(pygments.lex(code, lexer), formatter)
410
411
411
412
412 class CodeHtmlFormatter(HtmlFormatter):
413 class CodeHtmlFormatter(HtmlFormatter):
413 """
414 """
414 My code Html Formatter for source codes
415 My code Html Formatter for source codes
415 """
416 """
416
417
417 def wrap(self, source, outfile):
418 def wrap(self, source, outfile):
418 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
419 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
419
420
420 def _wrap_code(self, source):
421 def _wrap_code(self, source):
421 for cnt, it in enumerate(source):
422 for cnt, it in enumerate(source):
422 i, t = it
423 i, t = it
423 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
424 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
424 yield i, t
425 yield i, t
425
426
426 def _wrap_tablelinenos(self, inner):
427 def _wrap_tablelinenos(self, inner):
427 dummyoutfile = StringIO.StringIO()
428 dummyoutfile = StringIO.StringIO()
428 lncount = 0
429 lncount = 0
429 for t, line in inner:
430 for t, line in inner:
430 if t:
431 if t:
431 lncount += 1
432 lncount += 1
432 dummyoutfile.write(line)
433 dummyoutfile.write(line)
433
434
434 fl = self.linenostart
435 fl = self.linenostart
435 mw = len(str(lncount + fl - 1))
436 mw = len(str(lncount + fl - 1))
436 sp = self.linenospecial
437 sp = self.linenospecial
437 st = self.linenostep
438 st = self.linenostep
438 la = self.lineanchors
439 la = self.lineanchors
439 aln = self.anchorlinenos
440 aln = self.anchorlinenos
440 nocls = self.noclasses
441 nocls = self.noclasses
441 if sp:
442 if sp:
442 lines = []
443 lines = []
443
444
444 for i in range(fl, fl + lncount):
445 for i in range(fl, fl + lncount):
445 if i % st == 0:
446 if i % st == 0:
446 if i % sp == 0:
447 if i % sp == 0:
447 if aln:
448 if aln:
448 lines.append('<a href="#%s%d" class="special">%*d</a>' %
449 lines.append('<a href="#%s%d" class="special">%*d</a>' %
449 (la, i, mw, i))
450 (la, i, mw, i))
450 else:
451 else:
451 lines.append('<span class="special">%*d</span>' % (mw, i))
452 lines.append('<span class="special">%*d</span>' % (mw, i))
452 else:
453 else:
453 if aln:
454 if aln:
454 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
455 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
455 else:
456 else:
456 lines.append('%*d' % (mw, i))
457 lines.append('%*d' % (mw, i))
457 else:
458 else:
458 lines.append('')
459 lines.append('')
459 ls = '\n'.join(lines)
460 ls = '\n'.join(lines)
460 else:
461 else:
461 lines = []
462 lines = []
462 for i in range(fl, fl + lncount):
463 for i in range(fl, fl + lncount):
463 if i % st == 0:
464 if i % st == 0:
464 if aln:
465 if aln:
465 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
466 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
466 else:
467 else:
467 lines.append('%*d' % (mw, i))
468 lines.append('%*d' % (mw, i))
468 else:
469 else:
469 lines.append('')
470 lines.append('')
470 ls = '\n'.join(lines)
471 ls = '\n'.join(lines)
471
472
472 # in case you wonder about the seemingly redundant <div> here: since the
473 # in case you wonder about the seemingly redundant <div> here: since the
473 # content in the other cell also is wrapped in a div, some browsers in
474 # content in the other cell also is wrapped in a div, some browsers in
474 # some configurations seem to mess up the formatting...
475 # some configurations seem to mess up the formatting...
475 if nocls:
476 if nocls:
476 yield 0, ('<table class="%stable">' % self.cssclass +
477 yield 0, ('<table class="%stable">' % self.cssclass +
477 '<tr><td><div class="linenodiv" '
478 '<tr><td><div class="linenodiv" '
478 'style="background-color: #f0f0f0; padding-right: 10px">'
479 'style="background-color: #f0f0f0; padding-right: 10px">'
479 '<pre style="line-height: 125%">' +
480 '<pre style="line-height: 125%">' +
480 ls + '</pre></div></td><td id="hlcode" class="code">')
481 ls + '</pre></div></td><td id="hlcode" class="code">')
481 else:
482 else:
482 yield 0, ('<table class="%stable">' % self.cssclass +
483 yield 0, ('<table class="%stable">' % self.cssclass +
483 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
484 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
484 ls + '</pre></div></td><td id="hlcode" class="code">')
485 ls + '</pre></div></td><td id="hlcode" class="code">')
485 yield 0, dummyoutfile.getvalue()
486 yield 0, dummyoutfile.getvalue()
486 yield 0, '</td></tr></table>'
487 yield 0, '</td></tr></table>'
487
488
488
489
489 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
490 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
490 def __init__(self, **kw):
491 def __init__(self, **kw):
491 # only show these line numbers if set
492 # only show these line numbers if set
492 self.only_lines = kw.pop('only_line_numbers', [])
493 self.only_lines = kw.pop('only_line_numbers', [])
493 self.query_terms = kw.pop('query_terms', [])
494 self.query_terms = kw.pop('query_terms', [])
494 self.max_lines = kw.pop('max_lines', 5)
495 self.max_lines = kw.pop('max_lines', 5)
495 self.line_context = kw.pop('line_context', 3)
496 self.line_context = kw.pop('line_context', 3)
496 self.url = kw.pop('url', None)
497 self.url = kw.pop('url', None)
497
498
498 super(CodeHtmlFormatter, self).__init__(**kw)
499 super(CodeHtmlFormatter, self).__init__(**kw)
499
500
500 def _wrap_code(self, source):
501 def _wrap_code(self, source):
501 for cnt, it in enumerate(source):
502 for cnt, it in enumerate(source):
502 i, t = it
503 i, t = it
503 t = '<pre>%s</pre>' % t
504 t = '<pre>%s</pre>' % t
504 yield i, t
505 yield i, t
505
506
506 def _wrap_tablelinenos(self, inner):
507 def _wrap_tablelinenos(self, inner):
507 yield 0, '<table class="code-highlight %stable">' % self.cssclass
508 yield 0, '<table class="code-highlight %stable">' % self.cssclass
508
509
509 last_shown_line_number = 0
510 last_shown_line_number = 0
510 current_line_number = 1
511 current_line_number = 1
511
512
512 for t, line in inner:
513 for t, line in inner:
513 if not t:
514 if not t:
514 yield t, line
515 yield t, line
515 continue
516 continue
516
517
517 if current_line_number in self.only_lines:
518 if current_line_number in self.only_lines:
518 if last_shown_line_number + 1 != current_line_number:
519 if last_shown_line_number + 1 != current_line_number:
519 yield 0, '<tr>'
520 yield 0, '<tr>'
520 yield 0, '<td class="line">...</td>'
521 yield 0, '<td class="line">...</td>'
521 yield 0, '<td id="hlcode" class="code"></td>'
522 yield 0, '<td id="hlcode" class="code"></td>'
522 yield 0, '</tr>'
523 yield 0, '</tr>'
523
524
524 yield 0, '<tr>'
525 yield 0, '<tr>'
525 if self.url:
526 if self.url:
526 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
527 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
527 self.url, current_line_number, current_line_number)
528 self.url, current_line_number, current_line_number)
528 else:
529 else:
529 yield 0, '<td class="line"><a href="">%i</a></td>' % (
530 yield 0, '<td class="line"><a href="">%i</a></td>' % (
530 current_line_number)
531 current_line_number)
531 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
532 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
532 yield 0, '</tr>'
533 yield 0, '</tr>'
533
534
534 last_shown_line_number = current_line_number
535 last_shown_line_number = current_line_number
535
536
536 current_line_number += 1
537 current_line_number += 1
537
538
538 yield 0, '</table>'
539 yield 0, '</table>'
539
540
540
541
541 def hsv_to_rgb(h, s, v):
542 def hsv_to_rgb(h, s, v):
542 """ Convert hsv color values to rgb """
543 """ Convert hsv color values to rgb """
543
544
544 if s == 0.0:
545 if s == 0.0:
545 return v, v, v
546 return v, v, v
546 i = int(h * 6.0) # XXX assume int() truncates!
547 i = int(h * 6.0) # XXX assume int() truncates!
547 f = (h * 6.0) - i
548 f = (h * 6.0) - i
548 p = v * (1.0 - s)
549 p = v * (1.0 - s)
549 q = v * (1.0 - s * f)
550 q = v * (1.0 - s * f)
550 t = v * (1.0 - s * (1.0 - f))
551 t = v * (1.0 - s * (1.0 - f))
551 i = i % 6
552 i = i % 6
552 if i == 0:
553 if i == 0:
553 return v, t, p
554 return v, t, p
554 if i == 1:
555 if i == 1:
555 return q, v, p
556 return q, v, p
556 if i == 2:
557 if i == 2:
557 return p, v, t
558 return p, v, t
558 if i == 3:
559 if i == 3:
559 return p, q, v
560 return p, q, v
560 if i == 4:
561 if i == 4:
561 return t, p, v
562 return t, p, v
562 if i == 5:
563 if i == 5:
563 return v, p, q
564 return v, p, q
564
565
565
566
566 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
567 def unique_color_generator(n=10000, saturation=0.10, lightness=0.95):
567 """
568 """
568 Generator for getting n of evenly distributed colors using
569 Generator for getting n of evenly distributed colors using
569 hsv color and golden ratio. It always return same order of colors
570 hsv color and golden ratio. It always return same order of colors
570
571
571 :param n: number of colors to generate
572 :param n: number of colors to generate
572 :param saturation: saturation of returned colors
573 :param saturation: saturation of returned colors
573 :param lightness: lightness of returned colors
574 :param lightness: lightness of returned colors
574 :returns: RGB tuple
575 :returns: RGB tuple
575 """
576 """
576
577
577 golden_ratio = 0.618033988749895
578 golden_ratio = 0.618033988749895
578 h = 0.22717784590367374
579 h = 0.22717784590367374
579
580
580 for _ in xrange(n):
581 for _ in xrange(n):
581 h += golden_ratio
582 h += golden_ratio
582 h %= 1
583 h %= 1
583 HSV_tuple = [h, saturation, lightness]
584 HSV_tuple = [h, saturation, lightness]
584 RGB_tuple = hsv_to_rgb(*HSV_tuple)
585 RGB_tuple = hsv_to_rgb(*HSV_tuple)
585 yield map(lambda x: str(int(x * 256)), RGB_tuple)
586 yield map(lambda x: str(int(x * 256)), RGB_tuple)
586
587
587
588
588 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
589 def color_hasher(n=10000, saturation=0.10, lightness=0.95):
589 """
590 """
590 Returns a function which when called with an argument returns a unique
591 Returns a function which when called with an argument returns a unique
591 color for that argument, eg.
592 color for that argument, eg.
592
593
593 :param n: number of colors to generate
594 :param n: number of colors to generate
594 :param saturation: saturation of returned colors
595 :param saturation: saturation of returned colors
595 :param lightness: lightness of returned colors
596 :param lightness: lightness of returned colors
596 :returns: css RGB string
597 :returns: css RGB string
597
598
598 >>> color_hash = color_hasher()
599 >>> color_hash = color_hasher()
599 >>> color_hash('hello')
600 >>> color_hash('hello')
600 'rgb(34, 12, 59)'
601 'rgb(34, 12, 59)'
601 >>> color_hash('hello')
602 >>> color_hash('hello')
602 'rgb(34, 12, 59)'
603 'rgb(34, 12, 59)'
603 >>> color_hash('other')
604 >>> color_hash('other')
604 'rgb(90, 224, 159)'
605 'rgb(90, 224, 159)'
605 """
606 """
606
607
607 color_dict = {}
608 color_dict = {}
608 cgenerator = unique_color_generator(
609 cgenerator = unique_color_generator(
609 saturation=saturation, lightness=lightness)
610 saturation=saturation, lightness=lightness)
610
611
611 def get_color_string(thing):
612 def get_color_string(thing):
612 if thing in color_dict:
613 if thing in color_dict:
613 col = color_dict[thing]
614 col = color_dict[thing]
614 else:
615 else:
615 col = color_dict[thing] = cgenerator.next()
616 col = color_dict[thing] = cgenerator.next()
616 return "rgb(%s)" % (', '.join(col))
617 return "rgb(%s)" % (', '.join(col))
617
618
618 return get_color_string
619 return get_color_string
619
620
620
621
621 def get_lexer_safe(mimetype=None, filepath=None):
622 def get_lexer_safe(mimetype=None, filepath=None):
622 """
623 """
623 Tries to return a relevant pygments lexer using mimetype/filepath name,
624 Tries to return a relevant pygments lexer using mimetype/filepath name,
624 defaulting to plain text if none could be found
625 defaulting to plain text if none could be found
625 """
626 """
626 lexer = None
627 lexer = None
627 try:
628 try:
628 if mimetype:
629 if mimetype:
629 lexer = get_lexer_for_mimetype(mimetype)
630 lexer = get_lexer_for_mimetype(mimetype)
630 if not lexer:
631 if not lexer:
631 lexer = get_lexer_for_filename(filepath)
632 lexer = get_lexer_for_filename(filepath)
632 except pygments.util.ClassNotFound:
633 except pygments.util.ClassNotFound:
633 pass
634 pass
634
635
635 if not lexer:
636 if not lexer:
636 lexer = get_lexer_by_name('text')
637 lexer = get_lexer_by_name('text')
637
638
638 return lexer
639 return lexer
639
640
640
641
641 def get_lexer_for_filenode(filenode):
642 def get_lexer_for_filenode(filenode):
642 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
643 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
643 return lexer
644 return lexer
644
645
645
646
646 def pygmentize(filenode, **kwargs):
647 def pygmentize(filenode, **kwargs):
647 """
648 """
648 pygmentize function using pygments
649 pygmentize function using pygments
649
650
650 :param filenode:
651 :param filenode:
651 """
652 """
652 lexer = get_lexer_for_filenode(filenode)
653 lexer = get_lexer_for_filenode(filenode)
653 return literal(code_highlight(filenode.content, lexer,
654 return literal(code_highlight(filenode.content, lexer,
654 CodeHtmlFormatter(**kwargs)))
655 CodeHtmlFormatter(**kwargs)))
655
656
656
657
657 def is_following_repo(repo_name, user_id):
658 def is_following_repo(repo_name, user_id):
658 from rhodecode.model.scm import ScmModel
659 from rhodecode.model.scm import ScmModel
659 return ScmModel().is_following_repo(repo_name, user_id)
660 return ScmModel().is_following_repo(repo_name, user_id)
660
661
661
662
662 class _Message(object):
663 class _Message(object):
663 """A message returned by ``Flash.pop_messages()``.
664 """A message returned by ``Flash.pop_messages()``.
664
665
665 Converting the message to a string returns the message text. Instances
666 Converting the message to a string returns the message text. Instances
666 also have the following attributes:
667 also have the following attributes:
667
668
668 * ``message``: the message text.
669 * ``message``: the message text.
669 * ``category``: the category specified when the message was created.
670 * ``category``: the category specified when the message was created.
670 """
671 """
671
672
672 def __init__(self, category, message, sub_data=None):
673 def __init__(self, category, message, sub_data=None):
673 self.category = category
674 self.category = category
674 self.message = message
675 self.message = message
675 self.sub_data = sub_data or {}
676 self.sub_data = sub_data or {}
676
677
677 def __str__(self):
678 def __str__(self):
678 return self.message
679 return self.message
679
680
680 __unicode__ = __str__
681 __unicode__ = __str__
681
682
682 def __html__(self):
683 def __html__(self):
683 return escape(safe_unicode(self.message))
684 return escape(safe_unicode(self.message))
684
685
685
686
686 class Flash(object):
687 class Flash(object):
687 # List of allowed categories. If None, allow any category.
688 # List of allowed categories. If None, allow any category.
688 categories = ["warning", "notice", "error", "success"]
689 categories = ["warning", "notice", "error", "success"]
689
690
690 # Default category if none is specified.
691 # Default category if none is specified.
691 default_category = "notice"
692 default_category = "notice"
692
693
693 def __init__(self, session_key="flash", categories=None,
694 def __init__(self, session_key="flash", categories=None,
694 default_category=None):
695 default_category=None):
695 """
696 """
696 Instantiate a ``Flash`` object.
697 Instantiate a ``Flash`` object.
697
698
698 ``session_key`` is the key to save the messages under in the user's
699 ``session_key`` is the key to save the messages under in the user's
699 session.
700 session.
700
701
701 ``categories`` is an optional list which overrides the default list
702 ``categories`` is an optional list which overrides the default list
702 of categories.
703 of categories.
703
704
704 ``default_category`` overrides the default category used for messages
705 ``default_category`` overrides the default category used for messages
705 when none is specified.
706 when none is specified.
706 """
707 """
707 self.session_key = session_key
708 self.session_key = session_key
708 if categories is not None:
709 if categories is not None:
709 self.categories = categories
710 self.categories = categories
710 if default_category is not None:
711 if default_category is not None:
711 self.default_category = default_category
712 self.default_category = default_category
712 if self.categories and self.default_category not in self.categories:
713 if self.categories and self.default_category not in self.categories:
713 raise ValueError(
714 raise ValueError(
714 "unrecognized default category %r" % (self.default_category,))
715 "unrecognized default category %r" % (self.default_category,))
715
716
716 def pop_messages(self, session=None, request=None):
717 def pop_messages(self, session=None, request=None):
717 """
718 """
718 Return all accumulated messages and delete them from the session.
719 Return all accumulated messages and delete them from the session.
719
720
720 The return value is a list of ``Message`` objects.
721 The return value is a list of ``Message`` objects.
721 """
722 """
722 messages = []
723 messages = []
723
724
724 if not session:
725 if not session:
725 if not request:
726 if not request:
726 request = get_current_request()
727 request = get_current_request()
727 session = request.session
728 session = request.session
728
729
729 # Pop the 'old' pylons flash messages. They are tuples of the form
730 # Pop the 'old' pylons flash messages. They are tuples of the form
730 # (category, message)
731 # (category, message)
731 for cat, msg in session.pop(self.session_key, []):
732 for cat, msg in session.pop(self.session_key, []):
732 messages.append(_Message(cat, msg))
733 messages.append(_Message(cat, msg))
733
734
734 # Pop the 'new' pyramid flash messages for each category as list
735 # Pop the 'new' pyramid flash messages for each category as list
735 # of strings.
736 # of strings.
736 for cat in self.categories:
737 for cat in self.categories:
737 for msg in session.pop_flash(queue=cat):
738 for msg in session.pop_flash(queue=cat):
738 sub_data = {}
739 sub_data = {}
739 if hasattr(msg, 'rsplit'):
740 if hasattr(msg, 'rsplit'):
740 flash_data = msg.rsplit('|DELIM|', 1)
741 flash_data = msg.rsplit('|DELIM|', 1)
741 org_message = flash_data[0]
742 org_message = flash_data[0]
742 if len(flash_data) > 1:
743 if len(flash_data) > 1:
743 sub_data = json.loads(flash_data[1])
744 sub_data = json.loads(flash_data[1])
744 else:
745 else:
745 org_message = msg
746 org_message = msg
746
747
747 messages.append(_Message(cat, org_message, sub_data=sub_data))
748 messages.append(_Message(cat, org_message, sub_data=sub_data))
748
749
749 # Map messages from the default queue to the 'notice' category.
750 # Map messages from the default queue to the 'notice' category.
750 for msg in session.pop_flash():
751 for msg in session.pop_flash():
751 messages.append(_Message('notice', msg))
752 messages.append(_Message('notice', msg))
752
753
753 session.save()
754 session.save()
754 return messages
755 return messages
755
756
756 def json_alerts(self, session=None, request=None):
757 def json_alerts(self, session=None, request=None):
757 payloads = []
758 payloads = []
758 messages = flash.pop_messages(session=session, request=request) or []
759 messages = flash.pop_messages(session=session, request=request) or []
759 for message in messages:
760 for message in messages:
760 payloads.append({
761 payloads.append({
761 'message': {
762 'message': {
762 'message': u'{}'.format(message.message),
763 'message': u'{}'.format(message.message),
763 'level': message.category,
764 'level': message.category,
764 'force': True,
765 'force': True,
765 'subdata': message.sub_data
766 'subdata': message.sub_data
766 }
767 }
767 })
768 })
768 return json.dumps(payloads)
769 return json.dumps(payloads)
769
770
770 def __call__(self, message, category=None, ignore_duplicate=True,
771 def __call__(self, message, category=None, ignore_duplicate=True,
771 session=None, request=None):
772 session=None, request=None):
772
773
773 if not session:
774 if not session:
774 if not request:
775 if not request:
775 request = get_current_request()
776 request = get_current_request()
776 session = request.session
777 session = request.session
777
778
778 session.flash(
779 session.flash(
779 message, queue=category, allow_duplicate=not ignore_duplicate)
780 message, queue=category, allow_duplicate=not ignore_duplicate)
780
781
781
782
782 flash = Flash()
783 flash = Flash()
783
784
784 #==============================================================================
785 #==============================================================================
785 # SCM FILTERS available via h.
786 # SCM FILTERS available via h.
786 #==============================================================================
787 #==============================================================================
787 from rhodecode.lib.vcs.utils import author_name, author_email
788 from rhodecode.lib.vcs.utils import author_name, author_email
788 from rhodecode.lib.utils2 import age, age_from_seconds
789 from rhodecode.lib.utils2 import age, age_from_seconds
789 from rhodecode.model.db import User, ChangesetStatus
790 from rhodecode.model.db import User, ChangesetStatus
790
791
791
792
792 email = author_email
793 email = author_email
793
794
794
795
795 def capitalize(raw_text):
796 def capitalize(raw_text):
796 return raw_text.capitalize()
797 return raw_text.capitalize()
797
798
798
799
799 def short_id(long_id):
800 def short_id(long_id):
800 return long_id[:12]
801 return long_id[:12]
801
802
802
803
803 def hide_credentials(url):
804 def hide_credentials(url):
804 from rhodecode.lib.utils2 import credentials_filter
805 from rhodecode.lib.utils2 import credentials_filter
805 return credentials_filter(url)
806 return credentials_filter(url)
806
807
807
808
808 import pytz
809 import pytz
809 import tzlocal
810 import tzlocal
810 local_timezone = tzlocal.get_localzone()
811 local_timezone = tzlocal.get_localzone()
811
812
812
813
813 def get_timezone(datetime_iso, time_is_local=False):
814 def get_timezone(datetime_iso, time_is_local=False):
814 tzinfo = '+00:00'
815 tzinfo = '+00:00'
815
816
816 # detect if we have a timezone info, otherwise, add it
817 # detect if we have a timezone info, otherwise, add it
817 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
818 if time_is_local and isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
818 force_timezone = os.environ.get('RC_TIMEZONE', '')
819 force_timezone = os.environ.get('RC_TIMEZONE', '')
819 if force_timezone:
820 if force_timezone:
820 force_timezone = pytz.timezone(force_timezone)
821 force_timezone = pytz.timezone(force_timezone)
821 timezone = force_timezone or local_timezone
822 timezone = force_timezone or local_timezone
822 offset = timezone.localize(datetime_iso).strftime('%z')
823 offset = timezone.localize(datetime_iso).strftime('%z')
823 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
824 tzinfo = '{}:{}'.format(offset[:-2], offset[-2:])
824 return tzinfo
825 return tzinfo
825
826
826
827
827 def age_component(datetime_iso, value=None, time_is_local=False, tooltip=True):
828 def age_component(datetime_iso, value=None, time_is_local=False, tooltip=True):
828 title = value or format_date(datetime_iso)
829 title = value or format_date(datetime_iso)
829 tzinfo = get_timezone(datetime_iso, time_is_local=time_is_local)
830 tzinfo = get_timezone(datetime_iso, time_is_local=time_is_local)
830
831
831 return literal(
832 return literal(
832 '<time class="timeago {cls}" title="{tt_title}" datetime="{dt}{tzinfo}">{title}</time>'.format(
833 '<time class="timeago {cls}" title="{tt_title}" datetime="{dt}{tzinfo}">{title}</time>'.format(
833 cls='tooltip' if tooltip else '',
834 cls='tooltip' if tooltip else '',
834 tt_title=('{title}{tzinfo}'.format(title=title, tzinfo=tzinfo)) if tooltip else '',
835 tt_title=('{title}{tzinfo}'.format(title=title, tzinfo=tzinfo)) if tooltip else '',
835 title=title, dt=datetime_iso, tzinfo=tzinfo
836 title=title, dt=datetime_iso, tzinfo=tzinfo
836 ))
837 ))
837
838
838
839
839 def _shorten_commit_id(commit_id, commit_len=None):
840 def _shorten_commit_id(commit_id, commit_len=None):
840 if commit_len is None:
841 if commit_len is None:
841 request = get_current_request()
842 request = get_current_request()
842 commit_len = request.call_context.visual.show_sha_length
843 commit_len = request.call_context.visual.show_sha_length
843 return commit_id[:commit_len]
844 return commit_id[:commit_len]
844
845
845
846
846 def show_id(commit, show_idx=None, commit_len=None):
847 def show_id(commit, show_idx=None, commit_len=None):
847 """
848 """
848 Configurable function that shows ID
849 Configurable function that shows ID
849 by default it's r123:fffeeefffeee
850 by default it's r123:fffeeefffeee
850
851
851 :param commit: commit instance
852 :param commit: commit instance
852 """
853 """
853 if show_idx is None:
854 if show_idx is None:
854 request = get_current_request()
855 request = get_current_request()
855 show_idx = request.call_context.visual.show_revision_number
856 show_idx = request.call_context.visual.show_revision_number
856
857
857 raw_id = _shorten_commit_id(commit.raw_id, commit_len=commit_len)
858 raw_id = _shorten_commit_id(commit.raw_id, commit_len=commit_len)
858 if show_idx:
859 if show_idx:
859 return 'r%s:%s' % (commit.idx, raw_id)
860 return 'r%s:%s' % (commit.idx, raw_id)
860 else:
861 else:
861 return '%s' % (raw_id, )
862 return '%s' % (raw_id, )
862
863
863
864
864 def format_date(date):
865 def format_date(date):
865 """
866 """
866 use a standardized formatting for dates used in RhodeCode
867 use a standardized formatting for dates used in RhodeCode
867
868
868 :param date: date/datetime object
869 :param date: date/datetime object
869 :return: formatted date
870 :return: formatted date
870 """
871 """
871
872
872 if date:
873 if date:
873 _fmt = "%a, %d %b %Y %H:%M:%S"
874 _fmt = "%a, %d %b %Y %H:%M:%S"
874 return safe_unicode(date.strftime(_fmt))
875 return safe_unicode(date.strftime(_fmt))
875
876
876 return u""
877 return u""
877
878
878
879
879 class _RepoChecker(object):
880 class _RepoChecker(object):
880
881
881 def __init__(self, backend_alias):
882 def __init__(self, backend_alias):
882 self._backend_alias = backend_alias
883 self._backend_alias = backend_alias
883
884
884 def __call__(self, repository):
885 def __call__(self, repository):
885 if hasattr(repository, 'alias'):
886 if hasattr(repository, 'alias'):
886 _type = repository.alias
887 _type = repository.alias
887 elif hasattr(repository, 'repo_type'):
888 elif hasattr(repository, 'repo_type'):
888 _type = repository.repo_type
889 _type = repository.repo_type
889 else:
890 else:
890 _type = repository
891 _type = repository
891 return _type == self._backend_alias
892 return _type == self._backend_alias
892
893
893
894
894 is_git = _RepoChecker('git')
895 is_git = _RepoChecker('git')
895 is_hg = _RepoChecker('hg')
896 is_hg = _RepoChecker('hg')
896 is_svn = _RepoChecker('svn')
897 is_svn = _RepoChecker('svn')
897
898
898
899
899 def get_repo_type_by_name(repo_name):
900 def get_repo_type_by_name(repo_name):
900 repo = Repository.get_by_repo_name(repo_name)
901 repo = Repository.get_by_repo_name(repo_name)
901 if repo:
902 if repo:
902 return repo.repo_type
903 return repo.repo_type
903
904
904
905
905 def is_svn_without_proxy(repository):
906 def is_svn_without_proxy(repository):
906 if is_svn(repository):
907 if is_svn(repository):
907 from rhodecode.model.settings import VcsSettingsModel
908 from rhodecode.model.settings import VcsSettingsModel
908 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
909 conf = VcsSettingsModel().get_ui_settings_as_config_obj()
909 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
910 return not str2bool(conf.get('vcs_svn_proxy', 'http_requests_enabled'))
910 return False
911 return False
911
912
912
913
913 def discover_user(author):
914 def discover_user(author):
914 """
915 """
915 Tries to discover RhodeCode User based on the author string. Author string
916 Tries to discover RhodeCode User based on the author string. Author string
916 is typically `FirstName LastName <email@address.com>`
917 is typically `FirstName LastName <email@address.com>`
917 """
918 """
918
919
919 # if author is already an instance use it for extraction
920 # if author is already an instance use it for extraction
920 if isinstance(author, User):
921 if isinstance(author, User):
921 return author
922 return author
922
923
923 # Valid email in the attribute passed, see if they're in the system
924 # Valid email in the attribute passed, see if they're in the system
924 _email = author_email(author)
925 _email = author_email(author)
925 if _email != '':
926 if _email != '':
926 user = User.get_by_email(_email, case_insensitive=True, cache=True)
927 user = User.get_by_email(_email, case_insensitive=True, cache=True)
927 if user is not None:
928 if user is not None:
928 return user
929 return user
929
930
930 # Maybe it's a username, we try to extract it and fetch by username ?
931 # Maybe it's a username, we try to extract it and fetch by username ?
931 _author = author_name(author)
932 _author = author_name(author)
932 user = User.get_by_username(_author, case_insensitive=True, cache=True)
933 user = User.get_by_username(_author, case_insensitive=True, cache=True)
933 if user is not None:
934 if user is not None:
934 return user
935 return user
935
936
936 return None
937 return None
937
938
938
939
939 def email_or_none(author):
940 def email_or_none(author):
940 # extract email from the commit string
941 # extract email from the commit string
941 _email = author_email(author)
942 _email = author_email(author)
942
943
943 # If we have an email, use it, otherwise
944 # If we have an email, use it, otherwise
944 # see if it contains a username we can get an email from
945 # see if it contains a username we can get an email from
945 if _email != '':
946 if _email != '':
946 return _email
947 return _email
947 else:
948 else:
948 user = User.get_by_username(
949 user = User.get_by_username(
949 author_name(author), case_insensitive=True, cache=True)
950 author_name(author), case_insensitive=True, cache=True)
950
951
951 if user is not None:
952 if user is not None:
952 return user.email
953 return user.email
953
954
954 # No valid email, not a valid user in the system, none!
955 # No valid email, not a valid user in the system, none!
955 return None
956 return None
956
957
957
958
958 def link_to_user(author, length=0, **kwargs):
959 def link_to_user(author, length=0, **kwargs):
959 user = discover_user(author)
960 user = discover_user(author)
960 # user can be None, but if we have it already it means we can re-use it
961 # user can be None, but if we have it already it means we can re-use it
961 # in the person() function, so we save 1 intensive-query
962 # in the person() function, so we save 1 intensive-query
962 if user:
963 if user:
963 author = user
964 author = user
964
965
965 display_person = person(author, 'username_or_name_or_email')
966 display_person = person(author, 'username_or_name_or_email')
966 if length:
967 if length:
967 display_person = shorter(display_person, length)
968 display_person = shorter(display_person, length)
968
969
969 if user and user.username != user.DEFAULT_USER:
970 if user and user.username != user.DEFAULT_USER:
970 return link_to(
971 return link_to(
971 escape(display_person),
972 escape(display_person),
972 route_path('user_profile', username=user.username),
973 route_path('user_profile', username=user.username),
973 **kwargs)
974 **kwargs)
974 else:
975 else:
975 return escape(display_person)
976 return escape(display_person)
976
977
977
978
978 def link_to_group(users_group_name, **kwargs):
979 def link_to_group(users_group_name, **kwargs):
979 return link_to(
980 return link_to(
980 escape(users_group_name),
981 escape(users_group_name),
981 route_path('user_group_profile', user_group_name=users_group_name),
982 route_path('user_group_profile', user_group_name=users_group_name),
982 **kwargs)
983 **kwargs)
983
984
984
985
985 def person(author, show_attr="username_and_name"):
986 def person(author, show_attr="username_and_name"):
986 user = discover_user(author)
987 user = discover_user(author)
987 if user:
988 if user:
988 return getattr(user, show_attr)
989 return getattr(user, show_attr)
989 else:
990 else:
990 _author = author_name(author)
991 _author = author_name(author)
991 _email = email(author)
992 _email = email(author)
992 return _author or _email
993 return _author or _email
993
994
994
995
995 def author_string(email):
996 def author_string(email):
996 if email:
997 if email:
997 user = User.get_by_email(email, case_insensitive=True, cache=True)
998 user = User.get_by_email(email, case_insensitive=True, cache=True)
998 if user:
999 if user:
999 if user.first_name or user.last_name:
1000 if user.first_name or user.last_name:
1000 return '%s %s &lt;%s&gt;' % (
1001 return '%s %s &lt;%s&gt;' % (
1001 user.first_name, user.last_name, email)
1002 user.first_name, user.last_name, email)
1002 else:
1003 else:
1003 return email
1004 return email
1004 else:
1005 else:
1005 return email
1006 return email
1006 else:
1007 else:
1007 return None
1008 return None
1008
1009
1009
1010
1010 def person_by_id(id_, show_attr="username_and_name"):
1011 def person_by_id(id_, show_attr="username_and_name"):
1011 # attr to return from fetched user
1012 # attr to return from fetched user
1012 person_getter = lambda usr: getattr(usr, show_attr)
1013 person_getter = lambda usr: getattr(usr, show_attr)
1013
1014
1014 #maybe it's an ID ?
1015 #maybe it's an ID ?
1015 if str(id_).isdigit() or isinstance(id_, int):
1016 if str(id_).isdigit() or isinstance(id_, int):
1016 id_ = int(id_)
1017 id_ = int(id_)
1017 user = User.get(id_)
1018 user = User.get(id_)
1018 if user is not None:
1019 if user is not None:
1019 return person_getter(user)
1020 return person_getter(user)
1020 return id_
1021 return id_
1021
1022
1022
1023
1023 def gravatar_with_user(request, author, show_disabled=False, tooltip=False):
1024 def gravatar_with_user(request, author, show_disabled=False, tooltip=False):
1024 _render = request.get_partial_renderer('rhodecode:templates/base/base.mako')
1025 _render = request.get_partial_renderer('rhodecode:templates/base/base.mako')
1025 return _render('gravatar_with_user', author, show_disabled=show_disabled, tooltip=tooltip)
1026 return _render('gravatar_with_user', author, show_disabled=show_disabled, tooltip=tooltip)
1026
1027
1027
1028
1028 tags_paterns = OrderedDict((
1029 tags_paterns = OrderedDict((
1029 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
1030 ('lang', (re.compile(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+\.]*)\]'),
1030 '<div class="metatag" tag="lang">\\2</div>')),
1031 '<div class="metatag" tag="lang">\\2</div>')),
1031
1032
1032 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
1033 ('see', (re.compile(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
1033 '<div class="metatag" tag="see">see: \\1 </div>')),
1034 '<div class="metatag" tag="see">see: \\1 </div>')),
1034
1035
1035 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
1036 ('url', (re.compile(r'\[url\ \=\&gt;\ \[([a-zA-Z0-9\ \.\-\_]+)\]\((http://|https://|/)(.*?)\)\]'),
1036 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
1037 '<div class="metatag" tag="url"> <a href="\\2\\3">\\1</a> </div>')),
1037
1038
1038 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
1039 ('license', (re.compile(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]'),
1039 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
1040 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>')),
1040
1041
1041 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
1042 ('ref', (re.compile(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]'),
1042 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
1043 '<div class="metatag" tag="ref \\1">\\1: <a href="/\\2">\\2</a></div>')),
1043
1044
1044 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
1045 ('state', (re.compile(r'\[(stable|featured|stale|dead|dev|deprecated)\]'),
1045 '<div class="metatag" tag="state \\1">\\1</div>')),
1046 '<div class="metatag" tag="state \\1">\\1</div>')),
1046
1047
1047 # label in grey
1048 # label in grey
1048 ('label', (re.compile(r'\[([a-z]+)\]'),
1049 ('label', (re.compile(r'\[([a-z]+)\]'),
1049 '<div class="metatag" tag="label">\\1</div>')),
1050 '<div class="metatag" tag="label">\\1</div>')),
1050
1051
1051 # generic catch all in grey
1052 # generic catch all in grey
1052 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
1053 ('generic', (re.compile(r'\[([a-zA-Z0-9\.\-\_]+)\]'),
1053 '<div class="metatag" tag="generic">\\1</div>')),
1054 '<div class="metatag" tag="generic">\\1</div>')),
1054 ))
1055 ))
1055
1056
1056
1057
1057 def extract_metatags(value):
1058 def extract_metatags(value):
1058 """
1059 """
1059 Extract supported meta-tags from given text value
1060 Extract supported meta-tags from given text value
1060 """
1061 """
1061 tags = []
1062 tags = []
1062 if not value:
1063 if not value:
1063 return tags, ''
1064 return tags, ''
1064
1065
1065 for key, val in tags_paterns.items():
1066 for key, val in tags_paterns.items():
1066 pat, replace_html = val
1067 pat, replace_html = val
1067 tags.extend([(key, x.group()) for x in pat.finditer(value)])
1068 tags.extend([(key, x.group()) for x in pat.finditer(value)])
1068 value = pat.sub('', value)
1069 value = pat.sub('', value)
1069
1070
1070 return tags, value
1071 return tags, value
1071
1072
1072
1073
1073 def style_metatag(tag_type, value):
1074 def style_metatag(tag_type, value):
1074 """
1075 """
1075 converts tags from value into html equivalent
1076 converts tags from value into html equivalent
1076 """
1077 """
1077 if not value:
1078 if not value:
1078 return ''
1079 return ''
1079
1080
1080 html_value = value
1081 html_value = value
1081 tag_data = tags_paterns.get(tag_type)
1082 tag_data = tags_paterns.get(tag_type)
1082 if tag_data:
1083 if tag_data:
1083 pat, replace_html = tag_data
1084 pat, replace_html = tag_data
1084 # convert to plain `unicode` instead of a markup tag to be used in
1085 # convert to plain `unicode` instead of a markup tag to be used in
1085 # regex expressions. safe_unicode doesn't work here
1086 # regex expressions. safe_unicode doesn't work here
1086 html_value = pat.sub(replace_html, unicode(value))
1087 html_value = pat.sub(replace_html, unicode(value))
1087
1088
1088 return html_value
1089 return html_value
1089
1090
1090
1091
1091 def bool2icon(value, show_at_false=True):
1092 def bool2icon(value, show_at_false=True):
1092 """
1093 """
1093 Returns boolean value of a given value, represented as html element with
1094 Returns boolean value of a given value, represented as html element with
1094 classes that will represent icons
1095 classes that will represent icons
1095
1096
1096 :param value: given value to convert to html node
1097 :param value: given value to convert to html node
1097 """
1098 """
1098
1099
1099 if value: # does bool conversion
1100 if value: # does bool conversion
1100 return HTML.tag('i', class_="icon-true", title='True')
1101 return HTML.tag('i', class_="icon-true", title='True')
1101 else: # not true as bool
1102 else: # not true as bool
1102 if show_at_false:
1103 if show_at_false:
1103 return HTML.tag('i', class_="icon-false", title='False')
1104 return HTML.tag('i', class_="icon-false", title='False')
1104 return HTML.tag('i')
1105 return HTML.tag('i')
1105
1106
1106 #==============================================================================
1107 #==============================================================================
1107 # PERMS
1108 # PERMS
1108 #==============================================================================
1109 #==============================================================================
1109 from rhodecode.lib.auth import (
1110 from rhodecode.lib.auth import (
1110 HasPermissionAny, HasPermissionAll,
1111 HasPermissionAny, HasPermissionAll,
1111 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll,
1112 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll,
1112 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token,
1113 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token,
1113 csrf_token_key, AuthUser)
1114 csrf_token_key, AuthUser)
1114
1115
1115
1116
1116 #==============================================================================
1117 #==============================================================================
1117 # GRAVATAR URL
1118 # GRAVATAR URL
1118 #==============================================================================
1119 #==============================================================================
1119 class InitialsGravatar(object):
1120 class InitialsGravatar(object):
1120 def __init__(self, email_address, first_name, last_name, size=30,
1121 def __init__(self, email_address, first_name, last_name, size=30,
1121 background=None, text_color='#fff'):
1122 background=None, text_color='#fff'):
1122 self.size = size
1123 self.size = size
1123 self.first_name = first_name
1124 self.first_name = first_name
1124 self.last_name = last_name
1125 self.last_name = last_name
1125 self.email_address = email_address
1126 self.email_address = email_address
1126 self.background = background or self.str2color(email_address)
1127 self.background = background or self.str2color(email_address)
1127 self.text_color = text_color
1128 self.text_color = text_color
1128
1129
1129 def get_color_bank(self):
1130 def get_color_bank(self):
1130 """
1131 """
1131 returns a predefined list of colors that gravatars can use.
1132 returns a predefined list of colors that gravatars can use.
1132 Those are randomized distinct colors that guarantee readability and
1133 Those are randomized distinct colors that guarantee readability and
1133 uniqueness.
1134 uniqueness.
1134
1135
1135 generated with: http://phrogz.net/css/distinct-colors.html
1136 generated with: http://phrogz.net/css/distinct-colors.html
1136 """
1137 """
1137 return [
1138 return [
1138 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
1139 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
1139 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
1140 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
1140 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
1141 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
1141 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
1142 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
1142 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1143 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
1143 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1144 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
1144 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1145 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
1145 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1146 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
1146 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1147 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
1147 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1148 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
1148 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1149 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
1149 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1150 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
1150 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1151 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
1151 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1152 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
1152 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1153 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
1153 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1154 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
1154 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1155 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
1155 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1156 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
1156 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1157 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
1157 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1158 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
1158 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1159 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
1159 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1160 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
1160 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1161 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
1161 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1162 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
1162 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1163 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
1163 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1164 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
1164 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1165 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
1165 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1166 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
1166 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1167 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
1167 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1168 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
1168 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1169 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
1169 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1170 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
1170 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1171 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
1171 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1172 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
1172 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1173 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
1173 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1174 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
1174 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1175 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
1175 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1176 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1176 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1177 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1177 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1178 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1178 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1179 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1179 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1180 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1180 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1181 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1181 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1182 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1182 '#4f8c46', '#368dd9', '#5c0073'
1183 '#4f8c46', '#368dd9', '#5c0073'
1183 ]
1184 ]
1184
1185
1185 def rgb_to_hex_color(self, rgb_tuple):
1186 def rgb_to_hex_color(self, rgb_tuple):
1186 """
1187 """
1187 Converts an rgb_tuple passed to an hex color.
1188 Converts an rgb_tuple passed to an hex color.
1188
1189
1189 :param rgb_tuple: tuple with 3 ints represents rgb color space
1190 :param rgb_tuple: tuple with 3 ints represents rgb color space
1190 """
1191 """
1191 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1192 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1192
1193
1193 def email_to_int_list(self, email_str):
1194 def email_to_int_list(self, email_str):
1194 """
1195 """
1195 Get every byte of the hex digest value of email and turn it to integer.
1196 Get every byte of the hex digest value of email and turn it to integer.
1196 It's going to be always between 0-255
1197 It's going to be always between 0-255
1197 """
1198 """
1198 digest = md5_safe(email_str.lower())
1199 digest = md5_safe(email_str.lower())
1199 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1200 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1200
1201
1201 def pick_color_bank_index(self, email_str, color_bank):
1202 def pick_color_bank_index(self, email_str, color_bank):
1202 return self.email_to_int_list(email_str)[0] % len(color_bank)
1203 return self.email_to_int_list(email_str)[0] % len(color_bank)
1203
1204
1204 def str2color(self, email_str):
1205 def str2color(self, email_str):
1205 """
1206 """
1206 Tries to map in a stable algorithm an email to color
1207 Tries to map in a stable algorithm an email to color
1207
1208
1208 :param email_str:
1209 :param email_str:
1209 """
1210 """
1210 color_bank = self.get_color_bank()
1211 color_bank = self.get_color_bank()
1211 # pick position (module it's length so we always find it in the
1212 # pick position (module it's length so we always find it in the
1212 # bank even if it's smaller than 256 values
1213 # bank even if it's smaller than 256 values
1213 pos = self.pick_color_bank_index(email_str, color_bank)
1214 pos = self.pick_color_bank_index(email_str, color_bank)
1214 return color_bank[pos]
1215 return color_bank[pos]
1215
1216
1216 def normalize_email(self, email_address):
1217 def normalize_email(self, email_address):
1217 import unicodedata
1218 import unicodedata
1218 # default host used to fill in the fake/missing email
1219 # default host used to fill in the fake/missing email
1219 default_host = u'localhost'
1220 default_host = u'localhost'
1220
1221
1221 if not email_address:
1222 if not email_address:
1222 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1223 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1223
1224
1224 email_address = safe_unicode(email_address)
1225 email_address = safe_unicode(email_address)
1225
1226
1226 if u'@' not in email_address:
1227 if u'@' not in email_address:
1227 email_address = u'%s@%s' % (email_address, default_host)
1228 email_address = u'%s@%s' % (email_address, default_host)
1228
1229
1229 if email_address.endswith(u'@'):
1230 if email_address.endswith(u'@'):
1230 email_address = u'%s%s' % (email_address, default_host)
1231 email_address = u'%s%s' % (email_address, default_host)
1231
1232
1232 email_address = unicodedata.normalize('NFKD', email_address)\
1233 email_address = unicodedata.normalize('NFKD', email_address)\
1233 .encode('ascii', 'ignore')
1234 .encode('ascii', 'ignore')
1234 return email_address
1235 return email_address
1235
1236
1236 def get_initials(self):
1237 def get_initials(self):
1237 """
1238 """
1238 Returns 2 letter initials calculated based on the input.
1239 Returns 2 letter initials calculated based on the input.
1239 The algorithm picks first given email address, and takes first letter
1240 The algorithm picks first given email address, and takes first letter
1240 of part before @, and then the first letter of server name. In case
1241 of part before @, and then the first letter of server name. In case
1241 the part before @ is in a format of `somestring.somestring2` it replaces
1242 the part before @ is in a format of `somestring.somestring2` it replaces
1242 the server letter with first letter of somestring2
1243 the server letter with first letter of somestring2
1243
1244
1244 In case function was initialized with both first and lastname, this
1245 In case function was initialized with both first and lastname, this
1245 overrides the extraction from email by first letter of the first and
1246 overrides the extraction from email by first letter of the first and
1246 last name. We add special logic to that functionality, In case Full name
1247 last name. We add special logic to that functionality, In case Full name
1247 is compound, like Guido Von Rossum, we use last part of the last name
1248 is compound, like Guido Von Rossum, we use last part of the last name
1248 (Von Rossum) picking `R`.
1249 (Von Rossum) picking `R`.
1249
1250
1250 Function also normalizes the non-ascii characters to they ascii
1251 Function also normalizes the non-ascii characters to they ascii
1251 representation, eg Δ„ => A
1252 representation, eg Δ„ => A
1252 """
1253 """
1253 import unicodedata
1254 import unicodedata
1254 # replace non-ascii to ascii
1255 # replace non-ascii to ascii
1255 first_name = unicodedata.normalize(
1256 first_name = unicodedata.normalize(
1256 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1257 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1257 last_name = unicodedata.normalize(
1258 last_name = unicodedata.normalize(
1258 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1259 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1259
1260
1260 # do NFKD encoding, and also make sure email has proper format
1261 # do NFKD encoding, and also make sure email has proper format
1261 email_address = self.normalize_email(self.email_address)
1262 email_address = self.normalize_email(self.email_address)
1262
1263
1263 # first push the email initials
1264 # first push the email initials
1264 prefix, server = email_address.split('@', 1)
1265 prefix, server = email_address.split('@', 1)
1265
1266
1266 # check if prefix is maybe a 'first_name.last_name' syntax
1267 # check if prefix is maybe a 'first_name.last_name' syntax
1267 _dot_split = prefix.rsplit('.', 1)
1268 _dot_split = prefix.rsplit('.', 1)
1268 if len(_dot_split) == 2 and _dot_split[1]:
1269 if len(_dot_split) == 2 and _dot_split[1]:
1269 initials = [_dot_split[0][0], _dot_split[1][0]]
1270 initials = [_dot_split[0][0], _dot_split[1][0]]
1270 else:
1271 else:
1271 initials = [prefix[0], server[0]]
1272 initials = [prefix[0], server[0]]
1272
1273
1273 # then try to replace either first_name or last_name
1274 # then try to replace either first_name or last_name
1274 fn_letter = (first_name or " ")[0].strip()
1275 fn_letter = (first_name or " ")[0].strip()
1275 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1276 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1276
1277
1277 if fn_letter:
1278 if fn_letter:
1278 initials[0] = fn_letter
1279 initials[0] = fn_letter
1279
1280
1280 if ln_letter:
1281 if ln_letter:
1281 initials[1] = ln_letter
1282 initials[1] = ln_letter
1282
1283
1283 return ''.join(initials).upper()
1284 return ''.join(initials).upper()
1284
1285
1285 def get_img_data_by_type(self, font_family, img_type):
1286 def get_img_data_by_type(self, font_family, img_type):
1286 default_user = """
1287 default_user = """
1287 <svg xmlns="http://www.w3.org/2000/svg"
1288 <svg xmlns="http://www.w3.org/2000/svg"
1288 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1289 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1289 viewBox="-15 -10 439.165 429.164"
1290 viewBox="-15 -10 439.165 429.164"
1290
1291
1291 xml:space="preserve"
1292 xml:space="preserve"
1292 style="background:{background};" >
1293 style="background:{background};" >
1293
1294
1294 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1295 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1295 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1296 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1296 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1297 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1297 168.596,153.916,216.671,
1298 168.596,153.916,216.671,
1298 204.583,216.671z" fill="{text_color}"/>
1299 204.583,216.671z" fill="{text_color}"/>
1299 <path d="M407.164,374.717L360.88,
1300 <path d="M407.164,374.717L360.88,
1300 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1301 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1301 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1302 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1302 15.366-44.203,23.488-69.076,23.488c-24.877,
1303 15.366-44.203,23.488-69.076,23.488c-24.877,
1303 0-48.762-8.122-69.078-23.488
1304 0-48.762-8.122-69.078-23.488
1304 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1305 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1305 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1306 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1306 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1307 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1307 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1308 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1308 19.402-10.527 C409.699,390.129,
1309 19.402-10.527 C409.699,390.129,
1309 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1310 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1310 </svg>""".format(
1311 </svg>""".format(
1311 size=self.size,
1312 size=self.size,
1312 background='#979797', # @grey4
1313 background='#979797', # @grey4
1313 text_color=self.text_color,
1314 text_color=self.text_color,
1314 font_family=font_family)
1315 font_family=font_family)
1315
1316
1316 return {
1317 return {
1317 "default_user": default_user
1318 "default_user": default_user
1318 }[img_type]
1319 }[img_type]
1319
1320
1320 def get_img_data(self, svg_type=None):
1321 def get_img_data(self, svg_type=None):
1321 """
1322 """
1322 generates the svg metadata for image
1323 generates the svg metadata for image
1323 """
1324 """
1324 fonts = [
1325 fonts = [
1325 '-apple-system',
1326 '-apple-system',
1326 'BlinkMacSystemFont',
1327 'BlinkMacSystemFont',
1327 'Segoe UI',
1328 'Segoe UI',
1328 'Roboto',
1329 'Roboto',
1329 'Oxygen-Sans',
1330 'Oxygen-Sans',
1330 'Ubuntu',
1331 'Ubuntu',
1331 'Cantarell',
1332 'Cantarell',
1332 'Helvetica Neue',
1333 'Helvetica Neue',
1333 'sans-serif'
1334 'sans-serif'
1334 ]
1335 ]
1335 font_family = ','.join(fonts)
1336 font_family = ','.join(fonts)
1336 if svg_type:
1337 if svg_type:
1337 return self.get_img_data_by_type(font_family, svg_type)
1338 return self.get_img_data_by_type(font_family, svg_type)
1338
1339
1339 initials = self.get_initials()
1340 initials = self.get_initials()
1340 img_data = """
1341 img_data = """
1341 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1342 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1342 width="{size}" height="{size}"
1343 width="{size}" height="{size}"
1343 style="width: 100%; height: 100%; background-color: {background}"
1344 style="width: 100%; height: 100%; background-color: {background}"
1344 viewBox="0 0 {size} {size}">
1345 viewBox="0 0 {size} {size}">
1345 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1346 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1346 pointer-events="auto" fill="{text_color}"
1347 pointer-events="auto" fill="{text_color}"
1347 font-family="{font_family}"
1348 font-family="{font_family}"
1348 style="font-weight: 400; font-size: {f_size}px;">{text}
1349 style="font-weight: 400; font-size: {f_size}px;">{text}
1349 </text>
1350 </text>
1350 </svg>""".format(
1351 </svg>""".format(
1351 size=self.size,
1352 size=self.size,
1352 f_size=self.size/2.05, # scale the text inside the box nicely
1353 f_size=self.size/2.05, # scale the text inside the box nicely
1353 background=self.background,
1354 background=self.background,
1354 text_color=self.text_color,
1355 text_color=self.text_color,
1355 text=initials.upper(),
1356 text=initials.upper(),
1356 font_family=font_family)
1357 font_family=font_family)
1357
1358
1358 return img_data
1359 return img_data
1359
1360
1360 def generate_svg(self, svg_type=None):
1361 def generate_svg(self, svg_type=None):
1361 img_data = self.get_img_data(svg_type)
1362 img_data = self.get_img_data(svg_type)
1362 return "data:image/svg+xml;base64,%s" % base64.b64encode(img_data)
1363 return "data:image/svg+xml;base64,%s" % base64.b64encode(img_data)
1363
1364
1364
1365
1365 def initials_gravatar(request, email_address, first_name, last_name, size=30, store_on_disk=False):
1366 def initials_gravatar(request, email_address, first_name, last_name, size=30, store_on_disk=False):
1366
1367
1367 svg_type = None
1368 svg_type = None
1368 if email_address == User.DEFAULT_USER_EMAIL:
1369 if email_address == User.DEFAULT_USER_EMAIL:
1369 svg_type = 'default_user'
1370 svg_type = 'default_user'
1370
1371
1371 klass = InitialsGravatar(email_address, first_name, last_name, size)
1372 klass = InitialsGravatar(email_address, first_name, last_name, size)
1372
1373
1373 if store_on_disk:
1374 if store_on_disk:
1374 from rhodecode.apps.file_store import utils as store_utils
1375 from rhodecode.apps.file_store import utils as store_utils
1375 from rhodecode.apps.file_store.exceptions import FileNotAllowedException, \
1376 from rhodecode.apps.file_store.exceptions import FileNotAllowedException, \
1376 FileOverSizeException
1377 FileOverSizeException
1377 from rhodecode.model.db import Session
1378 from rhodecode.model.db import Session
1378
1379
1379 image_key = md5_safe(email_address.lower()
1380 image_key = md5_safe(email_address.lower()
1380 + first_name.lower() + last_name.lower())
1381 + first_name.lower() + last_name.lower())
1381
1382
1382 storage = store_utils.get_file_storage(request.registry.settings)
1383 storage = store_utils.get_file_storage(request.registry.settings)
1383 filename = '{}.svg'.format(image_key)
1384 filename = '{}.svg'.format(image_key)
1384 subdir = 'gravatars'
1385 subdir = 'gravatars'
1385 # since final name has a counter, we apply the 0
1386 # since final name has a counter, we apply the 0
1386 uid = storage.apply_counter(0, store_utils.uid_filename(filename, randomized=False))
1387 uid = storage.apply_counter(0, store_utils.uid_filename(filename, randomized=False))
1387 store_uid = os.path.join(subdir, uid)
1388 store_uid = os.path.join(subdir, uid)
1388
1389
1389 db_entry = FileStore.get_by_store_uid(store_uid)
1390 db_entry = FileStore.get_by_store_uid(store_uid)
1390 if db_entry:
1391 if db_entry:
1391 return request.route_path('download_file', fid=store_uid)
1392 return request.route_path('download_file', fid=store_uid)
1392
1393
1393 img_data = klass.get_img_data(svg_type=svg_type)
1394 img_data = klass.get_img_data(svg_type=svg_type)
1394 img_file = store_utils.bytes_to_file_obj(img_data)
1395 img_file = store_utils.bytes_to_file_obj(img_data)
1395
1396
1396 try:
1397 try:
1397 store_uid, metadata = storage.save_file(
1398 store_uid, metadata = storage.save_file(
1398 img_file, filename, directory=subdir,
1399 img_file, filename, directory=subdir,
1399 extensions=['.svg'], randomized_name=False)
1400 extensions=['.svg'], randomized_name=False)
1400 except (FileNotAllowedException, FileOverSizeException):
1401 except (FileNotAllowedException, FileOverSizeException):
1401 raise
1402 raise
1402
1403
1403 try:
1404 try:
1404 entry = FileStore.create(
1405 entry = FileStore.create(
1405 file_uid=store_uid, filename=metadata["filename"],
1406 file_uid=store_uid, filename=metadata["filename"],
1406 file_hash=metadata["sha256"], file_size=metadata["size"],
1407 file_hash=metadata["sha256"], file_size=metadata["size"],
1407 file_display_name=filename,
1408 file_display_name=filename,
1408 file_description=u'user gravatar `{}`'.format(safe_unicode(filename)),
1409 file_description=u'user gravatar `{}`'.format(safe_unicode(filename)),
1409 hidden=True, check_acl=False, user_id=1
1410 hidden=True, check_acl=False, user_id=1
1410 )
1411 )
1411 Session().add(entry)
1412 Session().add(entry)
1412 Session().commit()
1413 Session().commit()
1413 log.debug('Stored upload in DB as %s', entry)
1414 log.debug('Stored upload in DB as %s', entry)
1414 except Exception:
1415 except Exception:
1415 raise
1416 raise
1416
1417
1417 return request.route_path('download_file', fid=store_uid)
1418 return request.route_path('download_file', fid=store_uid)
1418
1419
1419 else:
1420 else:
1420 return klass.generate_svg(svg_type=svg_type)
1421 return klass.generate_svg(svg_type=svg_type)
1421
1422
1422
1423
1423 def gravatar_external(request, gravatar_url_tmpl, email_address, size=30):
1424 def gravatar_external(request, gravatar_url_tmpl, email_address, size=30):
1424 return safe_str(gravatar_url_tmpl)\
1425 return safe_str(gravatar_url_tmpl)\
1425 .replace('{email}', email_address) \
1426 .replace('{email}', email_address) \
1426 .replace('{md5email}', md5_safe(email_address.lower())) \
1427 .replace('{md5email}', md5_safe(email_address.lower())) \
1427 .replace('{netloc}', request.host) \
1428 .replace('{netloc}', request.host) \
1428 .replace('{scheme}', request.scheme) \
1429 .replace('{scheme}', request.scheme) \
1429 .replace('{size}', safe_str(size))
1430 .replace('{size}', safe_str(size))
1430
1431
1431
1432
1432 def gravatar_url(email_address, size=30, request=None):
1433 def gravatar_url(email_address, size=30, request=None):
1433 request = request or get_current_request()
1434 request = request or get_current_request()
1434 _use_gravatar = request.call_context.visual.use_gravatar
1435 _use_gravatar = request.call_context.visual.use_gravatar
1435
1436
1436 email_address = email_address or User.DEFAULT_USER_EMAIL
1437 email_address = email_address or User.DEFAULT_USER_EMAIL
1437 if isinstance(email_address, unicode):
1438 if isinstance(email_address, unicode):
1438 # hashlib crashes on unicode items
1439 # hashlib crashes on unicode items
1439 email_address = safe_str(email_address)
1440 email_address = safe_str(email_address)
1440
1441
1441 # empty email or default user
1442 # empty email or default user
1442 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1443 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1443 return initials_gravatar(request, User.DEFAULT_USER_EMAIL, '', '', size=size)
1444 return initials_gravatar(request, User.DEFAULT_USER_EMAIL, '', '', size=size)
1444
1445
1445 if _use_gravatar:
1446 if _use_gravatar:
1446 gravatar_url_tmpl = request.call_context.visual.gravatar_url \
1447 gravatar_url_tmpl = request.call_context.visual.gravatar_url \
1447 or User.DEFAULT_GRAVATAR_URL
1448 or User.DEFAULT_GRAVATAR_URL
1448 return gravatar_external(request, gravatar_url_tmpl, email_address, size=size)
1449 return gravatar_external(request, gravatar_url_tmpl, email_address, size=size)
1449
1450
1450 else:
1451 else:
1451 return initials_gravatar(request, email_address, '', '', size=size)
1452 return initials_gravatar(request, email_address, '', '', size=size)
1452
1453
1453
1454
1454 def breadcrumb_repo_link(repo):
1455 def breadcrumb_repo_link(repo):
1455 """
1456 """
1456 Makes a breadcrumbs path link to repo
1457 Makes a breadcrumbs path link to repo
1457
1458
1458 ex::
1459 ex::
1459 group >> subgroup >> repo
1460 group >> subgroup >> repo
1460
1461
1461 :param repo: a Repository instance
1462 :param repo: a Repository instance
1462 """
1463 """
1463
1464
1464 path = [
1465 path = [
1465 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name),
1466 link_to(group.name, route_path('repo_group_home', repo_group_name=group.group_name),
1466 title='last change:{}'.format(format_date(group.last_commit_change)))
1467 title='last change:{}'.format(format_date(group.last_commit_change)))
1467 for group in repo.groups_with_parents
1468 for group in repo.groups_with_parents
1468 ] + [
1469 ] + [
1469 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name),
1470 link_to(repo.just_name, route_path('repo_summary', repo_name=repo.repo_name),
1470 title='last change:{}'.format(format_date(repo.last_commit_change)))
1471 title='last change:{}'.format(format_date(repo.last_commit_change)))
1471 ]
1472 ]
1472
1473
1473 return literal(' &raquo; '.join(path))
1474 return literal(' &raquo; '.join(path))
1474
1475
1475
1476
1476 def breadcrumb_repo_group_link(repo_group):
1477 def breadcrumb_repo_group_link(repo_group):
1477 """
1478 """
1478 Makes a breadcrumbs path link to repo
1479 Makes a breadcrumbs path link to repo
1479
1480
1480 ex::
1481 ex::
1481 group >> subgroup
1482 group >> subgroup
1482
1483
1483 :param repo_group: a Repository Group instance
1484 :param repo_group: a Repository Group instance
1484 """
1485 """
1485
1486
1486 path = [
1487 path = [
1487 link_to(group.name,
1488 link_to(group.name,
1488 route_path('repo_group_home', repo_group_name=group.group_name),
1489 route_path('repo_group_home', repo_group_name=group.group_name),
1489 title='last change:{}'.format(format_date(group.last_commit_change)))
1490 title='last change:{}'.format(format_date(group.last_commit_change)))
1490 for group in repo_group.parents
1491 for group in repo_group.parents
1491 ] + [
1492 ] + [
1492 link_to(repo_group.name,
1493 link_to(repo_group.name,
1493 route_path('repo_group_home', repo_group_name=repo_group.group_name),
1494 route_path('repo_group_home', repo_group_name=repo_group.group_name),
1494 title='last change:{}'.format(format_date(repo_group.last_commit_change)))
1495 title='last change:{}'.format(format_date(repo_group.last_commit_change)))
1495 ]
1496 ]
1496
1497
1497 return literal(' &raquo; '.join(path))
1498 return literal(' &raquo; '.join(path))
1498
1499
1499
1500
1500 def format_byte_size_binary(file_size):
1501 def format_byte_size_binary(file_size):
1501 """
1502 """
1502 Formats file/folder sizes to standard.
1503 Formats file/folder sizes to standard.
1503 """
1504 """
1504 if file_size is None:
1505 if file_size is None:
1505 file_size = 0
1506 file_size = 0
1506
1507
1507 formatted_size = format_byte_size(file_size, binary=True)
1508 formatted_size = format_byte_size(file_size, binary=True)
1508 return formatted_size
1509 return formatted_size
1509
1510
1510
1511
1511 def urlify_text(text_, safe=True, **href_attrs):
1512 def urlify_text(text_, safe=True, **href_attrs):
1512 """
1513 """
1513 Extract urls from text and make html links out of them
1514 Extract urls from text and make html links out of them
1514 """
1515 """
1515
1516
1516 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1517 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1517 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1518 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1518
1519
1519 def url_func(match_obj):
1520 def url_func(match_obj):
1520 url_full = match_obj.groups()[0]
1521 url_full = match_obj.groups()[0]
1521 a_options = dict(href_attrs)
1522 a_options = dict(href_attrs)
1522 a_options['href'] = url_full
1523 a_options['href'] = url_full
1523 a_text = url_full
1524 a_text = url_full
1524 return HTML.tag("a", a_text, **a_options)
1525 return HTML.tag("a", a_text, **a_options)
1525
1526
1526 _new_text = url_pat.sub(url_func, text_)
1527 _new_text = url_pat.sub(url_func, text_)
1527
1528
1528 if safe:
1529 if safe:
1529 return literal(_new_text)
1530 return literal(_new_text)
1530 return _new_text
1531 return _new_text
1531
1532
1532
1533
1533 def urlify_commits(text_, repo_name):
1534 def urlify_commits(text_, repo_name):
1534 """
1535 """
1535 Extract commit ids from text and make link from them
1536 Extract commit ids from text and make link from them
1536
1537
1537 :param text_:
1538 :param text_:
1538 :param repo_name: repo name to build the URL with
1539 :param repo_name: repo name to build the URL with
1539 """
1540 """
1540
1541
1541 url_pat = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1542 url_pat = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1542
1543
1543 def url_func(match_obj):
1544 def url_func(match_obj):
1544 commit_id = match_obj.groups()[1]
1545 commit_id = match_obj.groups()[1]
1545 pref = match_obj.groups()[0]
1546 pref = match_obj.groups()[0]
1546 suf = match_obj.groups()[2]
1547 suf = match_obj.groups()[2]
1547
1548
1548 tmpl = (
1549 tmpl = (
1549 '%(pref)s<a class="tooltip-hovercard %(cls)s" href="%(url)s" data-hovercard-alt="%(hovercard_alt)s" data-hovercard-url="%(hovercard_url)s">'
1550 '%(pref)s<a class="tooltip-hovercard %(cls)s" href="%(url)s" data-hovercard-alt="%(hovercard_alt)s" data-hovercard-url="%(hovercard_url)s">'
1550 '%(commit_id)s</a>%(suf)s'
1551 '%(commit_id)s</a>%(suf)s'
1551 )
1552 )
1552 return tmpl % {
1553 return tmpl % {
1553 'pref': pref,
1554 'pref': pref,
1554 'cls': 'revision-link',
1555 'cls': 'revision-link',
1555 'url': route_url(
1556 'url': route_url(
1556 'repo_commit', repo_name=repo_name, commit_id=commit_id),
1557 'repo_commit', repo_name=repo_name, commit_id=commit_id),
1557 'commit_id': commit_id,
1558 'commit_id': commit_id,
1558 'suf': suf,
1559 'suf': suf,
1559 'hovercard_alt': 'Commit: {}'.format(commit_id),
1560 'hovercard_alt': 'Commit: {}'.format(commit_id),
1560 'hovercard_url': route_url(
1561 'hovercard_url': route_url(
1561 'hovercard_repo_commit', repo_name=repo_name, commit_id=commit_id)
1562 'hovercard_repo_commit', repo_name=repo_name, commit_id=commit_id)
1562 }
1563 }
1563
1564
1564 new_text = url_pat.sub(url_func, text_)
1565 new_text = url_pat.sub(url_func, text_)
1565
1566
1566 return new_text
1567 return new_text
1567
1568
1568
1569
1569 def _process_url_func(match_obj, repo_name, uid, entry,
1570 def _process_url_func(match_obj, repo_name, uid, entry,
1570 return_raw_data=False, link_format='html'):
1571 return_raw_data=False, link_format='html'):
1571 pref = ''
1572 pref = ''
1572 if match_obj.group().startswith(' '):
1573 if match_obj.group().startswith(' '):
1573 pref = ' '
1574 pref = ' '
1574
1575
1575 issue_id = ''.join(match_obj.groups())
1576 issue_id = ''.join(match_obj.groups())
1576
1577
1577 if link_format == 'html':
1578 if link_format == 'html':
1578 tmpl = (
1579 tmpl = (
1579 '%(pref)s<a class="tooltip %(cls)s" href="%(url)s" title="%(title)s">'
1580 '%(pref)s<a class="tooltip %(cls)s" href="%(url)s" title="%(title)s">'
1580 '%(issue-prefix)s%(id-repr)s'
1581 '%(issue-prefix)s%(id-repr)s'
1581 '</a>')
1582 '</a>')
1582 elif link_format == 'html+hovercard':
1583 elif link_format == 'html+hovercard':
1583 tmpl = (
1584 tmpl = (
1584 '%(pref)s<a class="tooltip-hovercard %(cls)s" href="%(url)s" data-hovercard-url="%(hovercard_url)s">'
1585 '%(pref)s<a class="tooltip-hovercard %(cls)s" href="%(url)s" data-hovercard-url="%(hovercard_url)s">'
1585 '%(issue-prefix)s%(id-repr)s'
1586 '%(issue-prefix)s%(id-repr)s'
1586 '</a>')
1587 '</a>')
1587 elif link_format in ['rst', 'rst+hovercard']:
1588 elif link_format in ['rst', 'rst+hovercard']:
1588 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1589 tmpl = '`%(issue-prefix)s%(id-repr)s <%(url)s>`_'
1589 elif link_format in ['markdown', 'markdown+hovercard']:
1590 elif link_format in ['markdown', 'markdown+hovercard']:
1590 tmpl = '[%(pref)s%(issue-prefix)s%(id-repr)s](%(url)s)'
1591 tmpl = '[%(pref)s%(issue-prefix)s%(id-repr)s](%(url)s)'
1591 else:
1592 else:
1592 raise ValueError('Bad link_format:{}'.format(link_format))
1593 raise ValueError('Bad link_format:{}'.format(link_format))
1593
1594
1594 (repo_name_cleaned,
1595 (repo_name_cleaned,
1595 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(repo_name)
1596 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(repo_name)
1596
1597
1597 # variables replacement
1598 # variables replacement
1598 named_vars = {
1599 named_vars = {
1599 'id': issue_id,
1600 'id': issue_id,
1600 'repo': repo_name,
1601 'repo': repo_name,
1601 'repo_name': repo_name_cleaned,
1602 'repo_name': repo_name_cleaned,
1602 'group_name': parent_group_name,
1603 'group_name': parent_group_name,
1603 # set dummy keys so we always have them
1604 # set dummy keys so we always have them
1604 'hostname': '',
1605 'hostname': '',
1605 'netloc': '',
1606 'netloc': '',
1606 'scheme': ''
1607 'scheme': ''
1607 }
1608 }
1608
1609
1609 request = get_current_request()
1610 request = get_current_request()
1610 if request:
1611 if request:
1611 # exposes, hostname, netloc, scheme
1612 # exposes, hostname, netloc, scheme
1612 host_data = get_host_info(request)
1613 host_data = get_host_info(request)
1613 named_vars.update(host_data)
1614 named_vars.update(host_data)
1614
1615
1615 # named regex variables
1616 # named regex variables
1616 named_vars.update(match_obj.groupdict())
1617 named_vars.update(match_obj.groupdict())
1617 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1618 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1618 desc = string.Template(escape(entry['desc'])).safe_substitute(**named_vars)
1619 desc = string.Template(escape(entry['desc'])).safe_substitute(**named_vars)
1619 hovercard_url = string.Template(entry.get('hovercard_url', '')).safe_substitute(**named_vars)
1620 hovercard_url = string.Template(entry.get('hovercard_url', '')).safe_substitute(**named_vars)
1620
1621
1621 def quote_cleaner(input_str):
1622 def quote_cleaner(input_str):
1622 """Remove quotes as it's HTML"""
1623 """Remove quotes as it's HTML"""
1623 return input_str.replace('"', '')
1624 return input_str.replace('"', '')
1624
1625
1625 data = {
1626 data = {
1626 'pref': pref,
1627 'pref': pref,
1627 'cls': quote_cleaner('issue-tracker-link'),
1628 'cls': quote_cleaner('issue-tracker-link'),
1628 'url': quote_cleaner(_url),
1629 'url': quote_cleaner(_url),
1629 'id-repr': issue_id,
1630 'id-repr': issue_id,
1630 'issue-prefix': entry['pref'],
1631 'issue-prefix': entry['pref'],
1631 'serv': entry['url'],
1632 'serv': entry['url'],
1632 'title': bleach.clean(desc, strip=True),
1633 'title': bleach.clean(desc, strip=True),
1633 'hovercard_url': hovercard_url
1634 'hovercard_url': hovercard_url
1634 }
1635 }
1635
1636
1636 if return_raw_data:
1637 if return_raw_data:
1637 return {
1638 return {
1638 'id': issue_id,
1639 'id': issue_id,
1639 'url': _url
1640 'url': _url
1640 }
1641 }
1641 return tmpl % data
1642 return tmpl % data
1642
1643
1643
1644
1644 def get_active_pattern_entries(repo_name):
1645 def get_active_pattern_entries(repo_name):
1645 repo = None
1646 repo = None
1646 if repo_name:
1647 if repo_name:
1647 # Retrieving repo_name to avoid invalid repo_name to explode on
1648 # Retrieving repo_name to avoid invalid repo_name to explode on
1648 # IssueTrackerSettingsModel but still passing invalid name further down
1649 # IssueTrackerSettingsModel but still passing invalid name further down
1649 repo = Repository.get_by_repo_name(repo_name, cache=True)
1650 repo = Repository.get_by_repo_name(repo_name, cache=True)
1650
1651
1651 settings_model = IssueTrackerSettingsModel(repo=repo)
1652 settings_model = IssueTrackerSettingsModel(repo=repo)
1652 active_entries = settings_model.get_settings(cache=True)
1653 active_entries = settings_model.get_settings(cache=True)
1653 return active_entries
1654 return active_entries
1654
1655
1655
1656
1656 pr_pattern_re = re.compile(r'(?:(?:^!)|(?: !))(\d+)')
1657 pr_pattern_re = regex.compile(r'(?:(?:^!)|(?: !))(\d+)')
1657
1658
1658 allowed_link_formats = [
1659 allowed_link_formats = [
1659 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard']
1660 'html', 'rst', 'markdown', 'html+hovercard', 'rst+hovercard', 'markdown+hovercard']
1660
1661
1661
1662
1662 def process_patterns(text_string, repo_name, link_format='html', active_entries=None):
1663 def process_patterns(text_string, repo_name, link_format='html', active_entries=None):
1663
1664
1664 if link_format not in allowed_link_formats:
1665 if link_format not in allowed_link_formats:
1665 raise ValueError('Link format can be only one of:{} got {}'.format(
1666 raise ValueError('Link format can be only one of:{} got {}'.format(
1666 allowed_link_formats, link_format))
1667 allowed_link_formats, link_format))
1667
1668
1668 if active_entries is None:
1669 if active_entries is None:
1669 log.debug('Fetch active issue tracker patterns for repo: %s', repo_name)
1670 log.debug('Fetch active issue tracker patterns for repo: %s', repo_name)
1670 active_entries = get_active_pattern_entries(repo_name)
1671 active_entries = get_active_pattern_entries(repo_name)
1671
1672
1672 issues_data = []
1673 issues_data = []
1674 errors = []
1673 new_text = text_string
1675 new_text = text_string
1674
1676
1675 log.debug('Got %s entries to process', len(active_entries))
1677 log.debug('Got %s entries to process', len(active_entries))
1676 for uid, entry in active_entries.items():
1678 for uid, entry in active_entries.items():
1677 log.debug('found issue tracker entry with uid %s', uid)
1679 log.debug('found issue tracker entry with uid %s', uid)
1678
1680
1679 if not (entry['pat'] and entry['url']):
1681 if not (entry['pat'] and entry['url']):
1680 log.debug('skipping due to missing data')
1682 log.debug('skipping due to missing data')
1681 continue
1683 continue
1682
1684
1683 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1685 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s',
1684 uid, entry['pat'], entry['url'], entry['pref'])
1686 uid, entry['pat'], entry['url'], entry['pref'])
1685
1687
1686 if entry.get('pat_compiled'):
1688 if entry.get('pat_compiled'):
1687 pattern = entry['pat_compiled']
1689 pattern = entry['pat_compiled']
1688 else:
1690 else:
1689 try:
1691 try:
1690 pattern = re.compile(r'%s' % entry['pat'])
1692 pattern = regex.compile(r'%s' % entry['pat'])
1691 except re.error:
1693 except regex.error as e:
1692 log.exception('issue tracker pattern: `%s` failed to compile', entry['pat'])
1694 regex_err = ValueError('{}:{}'.format(entry['pat'], e))
1695 log.exception('issue tracker pattern: `%s` failed to compile', regex_err)
1696 errors.append(regex_err)
1693 continue
1697 continue
1694
1698
1695 data_func = partial(
1699 data_func = partial(
1696 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1700 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1697 return_raw_data=True)
1701 return_raw_data=True)
1698
1702
1699 for match_obj in pattern.finditer(text_string):
1703 for match_obj in pattern.finditer(text_string):
1700 issues_data.append(data_func(match_obj))
1704 issues_data.append(data_func(match_obj))
1701
1705
1702 url_func = partial(
1706 url_func = partial(
1703 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1707 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1704 link_format=link_format)
1708 link_format=link_format)
1705
1709
1706 new_text = pattern.sub(url_func, new_text)
1710 new_text = pattern.sub(url_func, new_text)
1707 log.debug('processed prefix:uid `%s`', uid)
1711 log.debug('processed prefix:uid `%s`', uid)
1708
1712
1709 # finally use global replace, eg !123 -> pr-link, those will not catch
1713 # finally use global replace, eg !123 -> pr-link, those will not catch
1710 # if already similar pattern exists
1714 # if already similar pattern exists
1711 server_url = '${scheme}://${netloc}'
1715 server_url = '${scheme}://${netloc}'
1712 pr_entry = {
1716 pr_entry = {
1713 'pref': '!',
1717 'pref': '!',
1714 'url': server_url + '/_admin/pull-requests/${id}',
1718 'url': server_url + '/_admin/pull-requests/${id}',
1715 'desc': 'Pull Request !${id}',
1719 'desc': 'Pull Request !${id}',
1716 'hovercard_url': server_url + '/_hovercard/pull_request/${id}'
1720 'hovercard_url': server_url + '/_hovercard/pull_request/${id}'
1717 }
1721 }
1718 pr_url_func = partial(
1722 pr_url_func = partial(
1719 _process_url_func, repo_name=repo_name, entry=pr_entry, uid=None,
1723 _process_url_func, repo_name=repo_name, entry=pr_entry, uid=None,
1720 link_format=link_format+'+hovercard')
1724 link_format=link_format+'+hovercard')
1721 new_text = pr_pattern_re.sub(pr_url_func, new_text)
1725 new_text = pr_pattern_re.sub(pr_url_func, new_text)
1722 log.debug('processed !pr pattern')
1726 log.debug('processed !pr pattern')
1723
1727
1724 return new_text, issues_data
1728 return new_text, issues_data, errors
1725
1729
1726
1730
1727 def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None,
1731 def urlify_commit_message(commit_text, repository=None, active_pattern_entries=None,
1728 issues_container=None):
1732 issues_container=None, error_container=None):
1729 """
1733 """
1730 Parses given text message and makes proper links.
1734 Parses given text message and makes proper links.
1731 issues are linked to given issue-server, and rest is a commit link
1735 issues are linked to given issue-server, and rest is a commit link
1732 """
1736 """
1733
1737
1734 def escaper(_text):
1738 def escaper(_text):
1735 return _text.replace('<', '&lt;').replace('>', '&gt;')
1739 return _text.replace('<', '&lt;').replace('>', '&gt;')
1736
1740
1737 new_text = escaper(commit_text)
1741 new_text = escaper(commit_text)
1738
1742
1739 # extract http/https links and make them real urls
1743 # extract http/https links and make them real urls
1740 new_text = urlify_text(new_text, safe=False)
1744 new_text = urlify_text(new_text, safe=False)
1741
1745
1742 # urlify commits - extract commit ids and make link out of them, if we have
1746 # urlify commits - extract commit ids and make link out of them, if we have
1743 # the scope of repository present.
1747 # the scope of repository present.
1744 if repository:
1748 if repository:
1745 new_text = urlify_commits(new_text, repository)
1749 new_text = urlify_commits(new_text, repository)
1746
1750
1747 # process issue tracker patterns
1751 # process issue tracker patterns
1748 new_text, issues = process_patterns(new_text, repository or '',
1752 new_text, issues, errors = process_patterns(
1749 active_entries=active_pattern_entries)
1753 new_text, repository or '', active_entries=active_pattern_entries)
1750
1754
1751 if issues_container is not None:
1755 if issues_container is not None:
1752 issues_container.extend(issues)
1756 issues_container.extend(issues)
1753
1757
1758 if error_container is not None:
1759 error_container.extend(errors)
1760
1754 return literal(new_text)
1761 return literal(new_text)
1755
1762
1756
1763
1757 def render_binary(repo_name, file_obj):
1764 def render_binary(repo_name, file_obj):
1758 """
1765 """
1759 Choose how to render a binary file
1766 Choose how to render a binary file
1760 """
1767 """
1761
1768
1762 # unicode
1769 # unicode
1763 filename = file_obj.name
1770 filename = file_obj.name
1764
1771
1765 # images
1772 # images
1766 for ext in ['*.png', '*.jpeg', '*.jpg', '*.ico', '*.gif']:
1773 for ext in ['*.png', '*.jpeg', '*.jpg', '*.ico', '*.gif']:
1767 if fnmatch.fnmatch(filename, pat=ext):
1774 if fnmatch.fnmatch(filename, pat=ext):
1768 src = route_path(
1775 src = route_path(
1769 'repo_file_raw', repo_name=repo_name,
1776 'repo_file_raw', repo_name=repo_name,
1770 commit_id=file_obj.commit.raw_id,
1777 commit_id=file_obj.commit.raw_id,
1771 f_path=file_obj.path)
1778 f_path=file_obj.path)
1772
1779
1773 return literal(
1780 return literal(
1774 '<img class="rendered-binary" alt="rendered-image" src="{}">'.format(src))
1781 '<img class="rendered-binary" alt="rendered-image" src="{}">'.format(src))
1775
1782
1776
1783
1777 def renderer_from_filename(filename, exclude=None):
1784 def renderer_from_filename(filename, exclude=None):
1778 """
1785 """
1779 choose a renderer based on filename, this works only for text based files
1786 choose a renderer based on filename, this works only for text based files
1780 """
1787 """
1781
1788
1782 # ipython
1789 # ipython
1783 for ext in ['*.ipynb']:
1790 for ext in ['*.ipynb']:
1784 if fnmatch.fnmatch(filename, pat=ext):
1791 if fnmatch.fnmatch(filename, pat=ext):
1785 return 'jupyter'
1792 return 'jupyter'
1786
1793
1787 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1794 is_markup = MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1788 if is_markup:
1795 if is_markup:
1789 return is_markup
1796 return is_markup
1790 return None
1797 return None
1791
1798
1792
1799
1793 def render(source, renderer='rst', mentions=False, relative_urls=None,
1800 def render(source, renderer='rst', mentions=False, relative_urls=None,
1794 repo_name=None, active_pattern_entries=None, issues_container=None):
1801 repo_name=None, active_pattern_entries=None, issues_container=None):
1795
1802
1796 def maybe_convert_relative_links(html_source):
1803 def maybe_convert_relative_links(html_source):
1797 if relative_urls:
1804 if relative_urls:
1798 return relative_links(html_source, relative_urls)
1805 return relative_links(html_source, relative_urls)
1799 return html_source
1806 return html_source
1800
1807
1801 if renderer == 'plain':
1808 if renderer == 'plain':
1802 return literal(
1809 return literal(
1803 MarkupRenderer.plain(source, leading_newline=False))
1810 MarkupRenderer.plain(source, leading_newline=False))
1804
1811
1805 elif renderer == 'rst':
1812 elif renderer == 'rst':
1806 if repo_name:
1813 if repo_name:
1807 # process patterns on comments if we pass in repo name
1814 # process patterns on comments if we pass in repo name
1808 source, issues = process_patterns(
1815 source, issues, errors = process_patterns(
1809 source, repo_name, link_format='rst',
1816 source, repo_name, link_format='rst',
1810 active_entries=active_pattern_entries)
1817 active_entries=active_pattern_entries)
1811 if issues_container is not None:
1818 if issues_container is not None:
1812 issues_container.extend(issues)
1819 issues_container.extend(issues)
1813
1820
1814 return literal(
1821 return literal(
1815 '<div class="rst-block">%s</div>' %
1822 '<div class="rst-block">%s</div>' %
1816 maybe_convert_relative_links(
1823 maybe_convert_relative_links(
1817 MarkupRenderer.rst(source, mentions=mentions)))
1824 MarkupRenderer.rst(source, mentions=mentions)))
1818
1825
1819 elif renderer == 'markdown':
1826 elif renderer == 'markdown':
1820 if repo_name:
1827 if repo_name:
1821 # process patterns on comments if we pass in repo name
1828 # process patterns on comments if we pass in repo name
1822 source, issues = process_patterns(
1829 source, issues, errors = process_patterns(
1823 source, repo_name, link_format='markdown',
1830 source, repo_name, link_format='markdown',
1824 active_entries=active_pattern_entries)
1831 active_entries=active_pattern_entries)
1825 if issues_container is not None:
1832 if issues_container is not None:
1826 issues_container.extend(issues)
1833 issues_container.extend(issues)
1827
1834
1828 return literal(
1835 return literal(
1829 '<div class="markdown-block">%s</div>' %
1836 '<div class="markdown-block">%s</div>' %
1830 maybe_convert_relative_links(
1837 maybe_convert_relative_links(
1831 MarkupRenderer.markdown(source, flavored=True,
1838 MarkupRenderer.markdown(source, flavored=True,
1832 mentions=mentions)))
1839 mentions=mentions)))
1833
1840
1834 elif renderer == 'jupyter':
1841 elif renderer == 'jupyter':
1835 return literal(
1842 return literal(
1836 '<div class="ipynb">%s</div>' %
1843 '<div class="ipynb">%s</div>' %
1837 maybe_convert_relative_links(
1844 maybe_convert_relative_links(
1838 MarkupRenderer.jupyter(source)))
1845 MarkupRenderer.jupyter(source)))
1839
1846
1840 # None means just show the file-source
1847 # None means just show the file-source
1841 return None
1848 return None
1842
1849
1843
1850
1844 def commit_status(repo, commit_id):
1851 def commit_status(repo, commit_id):
1845 return ChangesetStatusModel().get_status(repo, commit_id)
1852 return ChangesetStatusModel().get_status(repo, commit_id)
1846
1853
1847
1854
1848 def commit_status_lbl(commit_status):
1855 def commit_status_lbl(commit_status):
1849 return dict(ChangesetStatus.STATUSES).get(commit_status)
1856 return dict(ChangesetStatus.STATUSES).get(commit_status)
1850
1857
1851
1858
1852 def commit_time(repo_name, commit_id):
1859 def commit_time(repo_name, commit_id):
1853 repo = Repository.get_by_repo_name(repo_name)
1860 repo = Repository.get_by_repo_name(repo_name)
1854 commit = repo.get_commit(commit_id=commit_id)
1861 commit = repo.get_commit(commit_id=commit_id)
1855 return commit.date
1862 return commit.date
1856
1863
1857
1864
1858 def get_permission_name(key):
1865 def get_permission_name(key):
1859 return dict(Permission.PERMS).get(key)
1866 return dict(Permission.PERMS).get(key)
1860
1867
1861
1868
1862 def journal_filter_help(request):
1869 def journal_filter_help(request):
1863 _ = request.translate
1870 _ = request.translate
1864 from rhodecode.lib.audit_logger import ACTIONS
1871 from rhodecode.lib.audit_logger import ACTIONS
1865 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1872 actions = '\n'.join(textwrap.wrap(', '.join(sorted(ACTIONS.keys())), 80))
1866
1873
1867 return _(
1874 return _(
1868 'Example filter terms:\n' +
1875 'Example filter terms:\n' +
1869 ' repository:vcs\n' +
1876 ' repository:vcs\n' +
1870 ' username:marcin\n' +
1877 ' username:marcin\n' +
1871 ' username:(NOT marcin)\n' +
1878 ' username:(NOT marcin)\n' +
1872 ' action:*push*\n' +
1879 ' action:*push*\n' +
1873 ' ip:127.0.0.1\n' +
1880 ' ip:127.0.0.1\n' +
1874 ' date:20120101\n' +
1881 ' date:20120101\n' +
1875 ' date:[20120101100000 TO 20120102]\n' +
1882 ' date:[20120101100000 TO 20120102]\n' +
1876 '\n' +
1883 '\n' +
1877 'Actions: {actions}\n' +
1884 'Actions: {actions}\n' +
1878 '\n' +
1885 '\n' +
1879 'Generate wildcards using \'*\' character:\n' +
1886 'Generate wildcards using \'*\' character:\n' +
1880 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1887 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1881 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1888 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1882 '\n' +
1889 '\n' +
1883 'Optional AND / OR operators in queries\n' +
1890 'Optional AND / OR operators in queries\n' +
1884 ' "repository:vcs OR repository:test"\n' +
1891 ' "repository:vcs OR repository:test"\n' +
1885 ' "username:test AND repository:test*"\n'
1892 ' "username:test AND repository:test*"\n'
1886 ).format(actions=actions)
1893 ).format(actions=actions)
1887
1894
1888
1895
1889 def not_mapped_error(repo_name):
1896 def not_mapped_error(repo_name):
1890 from rhodecode.translation import _
1897 from rhodecode.translation import _
1891 flash(_('%s repository is not mapped to db perhaps'
1898 flash(_('%s repository is not mapped to db perhaps'
1892 ' it was created or renamed from the filesystem'
1899 ' it was created or renamed from the filesystem'
1893 ' please run the application again'
1900 ' please run the application again'
1894 ' in order to rescan repositories') % repo_name, category='error')
1901 ' in order to rescan repositories') % repo_name, category='error')
1895
1902
1896
1903
1897 def ip_range(ip_addr):
1904 def ip_range(ip_addr):
1898 from rhodecode.model.db import UserIpMap
1905 from rhodecode.model.db import UserIpMap
1899 s, e = UserIpMap._get_ip_range(ip_addr)
1906 s, e = UserIpMap._get_ip_range(ip_addr)
1900 return '%s - %s' % (s, e)
1907 return '%s - %s' % (s, e)
1901
1908
1902
1909
1903 def form(url, method='post', needs_csrf_token=True, **attrs):
1910 def form(url, method='post', needs_csrf_token=True, **attrs):
1904 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1911 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1905 if method.lower() != 'get' and needs_csrf_token:
1912 if method.lower() != 'get' and needs_csrf_token:
1906 raise Exception(
1913 raise Exception(
1907 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1914 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1908 'CSRF token. If the endpoint does not require such token you can ' +
1915 'CSRF token. If the endpoint does not require such token you can ' +
1909 'explicitly set the parameter needs_csrf_token to false.')
1916 'explicitly set the parameter needs_csrf_token to false.')
1910
1917
1911 return insecure_form(url, method=method, **attrs)
1918 return insecure_form(url, method=method, **attrs)
1912
1919
1913
1920
1914 def secure_form(form_url, method="POST", multipart=False, **attrs):
1921 def secure_form(form_url, method="POST", multipart=False, **attrs):
1915 """Start a form tag that points the action to an url. This
1922 """Start a form tag that points the action to an url. This
1916 form tag will also include the hidden field containing
1923 form tag will also include the hidden field containing
1917 the auth token.
1924 the auth token.
1918
1925
1919 The url options should be given either as a string, or as a
1926 The url options should be given either as a string, or as a
1920 ``url()`` function. The method for the form defaults to POST.
1927 ``url()`` function. The method for the form defaults to POST.
1921
1928
1922 Options:
1929 Options:
1923
1930
1924 ``multipart``
1931 ``multipart``
1925 If set to True, the enctype is set to "multipart/form-data".
1932 If set to True, the enctype is set to "multipart/form-data".
1926 ``method``
1933 ``method``
1927 The method to use when submitting the form, usually either
1934 The method to use when submitting the form, usually either
1928 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1935 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1929 hidden input with name _method is added to simulate the verb
1936 hidden input with name _method is added to simulate the verb
1930 over POST.
1937 over POST.
1931
1938
1932 """
1939 """
1933
1940
1934 if 'request' in attrs:
1941 if 'request' in attrs:
1935 session = attrs['request'].session
1942 session = attrs['request'].session
1936 del attrs['request']
1943 del attrs['request']
1937 else:
1944 else:
1938 raise ValueError(
1945 raise ValueError(
1939 'Calling this form requires request= to be passed as argument')
1946 'Calling this form requires request= to be passed as argument')
1940
1947
1941 _form = insecure_form(form_url, method, multipart, **attrs)
1948 _form = insecure_form(form_url, method, multipart, **attrs)
1942 token = literal(
1949 token = literal(
1943 '<input type="hidden" name="{}" value="{}">'.format(
1950 '<input type="hidden" name="{}" value="{}">'.format(
1944 csrf_token_key, get_csrf_token(session)))
1951 csrf_token_key, get_csrf_token(session)))
1945
1952
1946 return literal("%s\n%s" % (_form, token))
1953 return literal("%s\n%s" % (_form, token))
1947
1954
1948
1955
1949 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1956 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1950 select_html = select(name, selected, options, **attrs)
1957 select_html = select(name, selected, options, **attrs)
1951
1958
1952 select2 = """
1959 select2 = """
1953 <script>
1960 <script>
1954 $(document).ready(function() {
1961 $(document).ready(function() {
1955 $('#%s').select2({
1962 $('#%s').select2({
1956 containerCssClass: 'drop-menu %s',
1963 containerCssClass: 'drop-menu %s',
1957 dropdownCssClass: 'drop-menu-dropdown',
1964 dropdownCssClass: 'drop-menu-dropdown',
1958 dropdownAutoWidth: true%s
1965 dropdownAutoWidth: true%s
1959 });
1966 });
1960 });
1967 });
1961 </script>
1968 </script>
1962 """
1969 """
1963
1970
1964 filter_option = """,
1971 filter_option = """,
1965 minimumResultsForSearch: -1
1972 minimumResultsForSearch: -1
1966 """
1973 """
1967 input_id = attrs.get('id') or name
1974 input_id = attrs.get('id') or name
1968 extra_classes = ' '.join(attrs.pop('extra_classes', []))
1975 extra_classes = ' '.join(attrs.pop('extra_classes', []))
1969 filter_enabled = "" if enable_filter else filter_option
1976 filter_enabled = "" if enable_filter else filter_option
1970 select_script = literal(select2 % (input_id, extra_classes, filter_enabled))
1977 select_script = literal(select2 % (input_id, extra_classes, filter_enabled))
1971
1978
1972 return literal(select_html+select_script)
1979 return literal(select_html+select_script)
1973
1980
1974
1981
1975 def get_visual_attr(tmpl_context_var, attr_name):
1982 def get_visual_attr(tmpl_context_var, attr_name):
1976 """
1983 """
1977 A safe way to get a variable from visual variable of template context
1984 A safe way to get a variable from visual variable of template context
1978
1985
1979 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1986 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1980 :param attr_name: name of the attribute we fetch from the c.visual
1987 :param attr_name: name of the attribute we fetch from the c.visual
1981 """
1988 """
1982 visual = getattr(tmpl_context_var, 'visual', None)
1989 visual = getattr(tmpl_context_var, 'visual', None)
1983 if not visual:
1990 if not visual:
1984 return
1991 return
1985 else:
1992 else:
1986 return getattr(visual, attr_name, None)
1993 return getattr(visual, attr_name, None)
1987
1994
1988
1995
1989 def get_last_path_part(file_node):
1996 def get_last_path_part(file_node):
1990 if not file_node.path:
1997 if not file_node.path:
1991 return u'/'
1998 return u'/'
1992
1999
1993 path = safe_unicode(file_node.path.split('/')[-1])
2000 path = safe_unicode(file_node.path.split('/')[-1])
1994 return u'../' + path
2001 return u'../' + path
1995
2002
1996
2003
1997 def route_url(*args, **kwargs):
2004 def route_url(*args, **kwargs):
1998 """
2005 """
1999 Wrapper around pyramids `route_url` (fully qualified url) function.
2006 Wrapper around pyramids `route_url` (fully qualified url) function.
2000 """
2007 """
2001 req = get_current_request()
2008 req = get_current_request()
2002 return req.route_url(*args, **kwargs)
2009 return req.route_url(*args, **kwargs)
2003
2010
2004
2011
2005 def route_path(*args, **kwargs):
2012 def route_path(*args, **kwargs):
2006 """
2013 """
2007 Wrapper around pyramids `route_path` function.
2014 Wrapper around pyramids `route_path` function.
2008 """
2015 """
2009 req = get_current_request()
2016 req = get_current_request()
2010 return req.route_path(*args, **kwargs)
2017 return req.route_path(*args, **kwargs)
2011
2018
2012
2019
2013 def route_path_or_none(*args, **kwargs):
2020 def route_path_or_none(*args, **kwargs):
2014 try:
2021 try:
2015 return route_path(*args, **kwargs)
2022 return route_path(*args, **kwargs)
2016 except KeyError:
2023 except KeyError:
2017 return None
2024 return None
2018
2025
2019
2026
2020 def current_route_path(request, **kw):
2027 def current_route_path(request, **kw):
2021 new_args = request.GET.mixed()
2028 new_args = request.GET.mixed()
2022 new_args.update(kw)
2029 new_args.update(kw)
2023 return request.current_route_path(_query=new_args)
2030 return request.current_route_path(_query=new_args)
2024
2031
2025
2032
2026 def curl_api_example(method, args):
2033 def curl_api_example(method, args):
2027 args_json = json.dumps(OrderedDict([
2034 args_json = json.dumps(OrderedDict([
2028 ('id', 1),
2035 ('id', 1),
2029 ('auth_token', 'SECRET'),
2036 ('auth_token', 'SECRET'),
2030 ('method', method),
2037 ('method', method),
2031 ('args', args)
2038 ('args', args)
2032 ]))
2039 ]))
2033
2040
2034 return "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{args_json}'".format(
2041 return "curl {api_url} -X POST -H 'content-type:text/plain' --data-binary '{args_json}'".format(
2035 api_url=route_url('apiv2'),
2042 api_url=route_url('apiv2'),
2036 args_json=args_json
2043 args_json=args_json
2037 )
2044 )
2038
2045
2039
2046
2040 def api_call_example(method, args):
2047 def api_call_example(method, args):
2041 """
2048 """
2042 Generates an API call example via CURL
2049 Generates an API call example via CURL
2043 """
2050 """
2044 curl_call = curl_api_example(method, args)
2051 curl_call = curl_api_example(method, args)
2045
2052
2046 return literal(
2053 return literal(
2047 curl_call +
2054 curl_call +
2048 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2055 "<br/><br/>SECRET can be found in <a href=\"{token_url}\">auth-tokens</a> page, "
2049 "and needs to be of `api calls` role."
2056 "and needs to be of `api calls` role."
2050 .format(token_url=route_url('my_account_auth_tokens')))
2057 .format(token_url=route_url('my_account_auth_tokens')))
2051
2058
2052
2059
2053 def notification_description(notification, request):
2060 def notification_description(notification, request):
2054 """
2061 """
2055 Generate notification human readable description based on notification type
2062 Generate notification human readable description based on notification type
2056 """
2063 """
2057 from rhodecode.model.notification import NotificationModel
2064 from rhodecode.model.notification import NotificationModel
2058 return NotificationModel().make_description(
2065 return NotificationModel().make_description(
2059 notification, translate=request.translate)
2066 notification, translate=request.translate)
2060
2067
2061
2068
2062 def go_import_header(request, db_repo=None):
2069 def go_import_header(request, db_repo=None):
2063 """
2070 """
2064 Creates a header for go-import functionality in Go Lang
2071 Creates a header for go-import functionality in Go Lang
2065 """
2072 """
2066
2073
2067 if not db_repo:
2074 if not db_repo:
2068 return
2075 return
2069 if 'go-get' not in request.GET:
2076 if 'go-get' not in request.GET:
2070 return
2077 return
2071
2078
2072 clone_url = db_repo.clone_url()
2079 clone_url = db_repo.clone_url()
2073 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2080 prefix = re.split(r'^https?:\/\/', clone_url)[-1]
2074 # we have a repo and go-get flag,
2081 # we have a repo and go-get flag,
2075 return literal('<meta name="go-import" content="{} {} {}">'.format(
2082 return literal('<meta name="go-import" content="{} {} {}">'.format(
2076 prefix, db_repo.repo_type, clone_url))
2083 prefix, db_repo.repo_type, clone_url))
2077
2084
2078
2085
2079 def reviewer_as_json(*args, **kwargs):
2086 def reviewer_as_json(*args, **kwargs):
2080 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2087 from rhodecode.apps.repository.utils import reviewer_as_json as _reviewer_as_json
2081 return _reviewer_as_json(*args, **kwargs)
2088 return _reviewer_as_json(*args, **kwargs)
2082
2089
2083
2090
2084 def get_repo_view_type(request):
2091 def get_repo_view_type(request):
2085 route_name = request.matched_route.name
2092 route_name = request.matched_route.name
2086 route_to_view_type = {
2093 route_to_view_type = {
2087 'repo_changelog': 'commits',
2094 'repo_changelog': 'commits',
2088 'repo_commits': 'commits',
2095 'repo_commits': 'commits',
2089 'repo_files': 'files',
2096 'repo_files': 'files',
2090 'repo_summary': 'summary',
2097 'repo_summary': 'summary',
2091 'repo_commit': 'commit'
2098 'repo_commit': 'commit'
2092 }
2099 }
2093
2100
2094 return route_to_view_type.get(route_name)
2101 return route_to_view_type.get(route_name)
2095
2102
2096
2103
2097 def is_active(menu_entry, selected):
2104 def is_active(menu_entry, selected):
2098 """
2105 """
2099 Returns active class for selecting menus in templates
2106 Returns active class for selecting menus in templates
2100 <li class=${h.is_active('settings', current_active)}></li>
2107 <li class=${h.is_active('settings', current_active)}></li>
2101 """
2108 """
2102 if not isinstance(menu_entry, list):
2109 if not isinstance(menu_entry, list):
2103 menu_entry = [menu_entry]
2110 menu_entry = [menu_entry]
2104
2111
2105 if selected in menu_entry:
2112 if selected in menu_entry:
2106 return "active"
2113 return "active"
@@ -1,321 +1,328 b''
1 ## snippet for displaying issue tracker settings
1 ## snippet for displaying issue tracker settings
2 ## usage:
2 ## usage:
3 ## <%namespace name="its" file="/base/issue_tracker_settings.mako"/>
3 ## <%namespace name="its" file="/base/issue_tracker_settings.mako"/>
4 ## ${its.issue_tracker_settings_table(patterns, form_url, delete_url)}
4 ## ${its.issue_tracker_settings_table(patterns, form_url, delete_url)}
5 ## ${its.issue_tracker_settings_test(test_url)}
5 ## ${its.issue_tracker_settings_test(test_url)}
6
6
7 <%def name="issue_tracker_settings_table(patterns, form_url, delete_url)">
7 <%def name="issue_tracker_settings_table(patterns, form_url, delete_url)">
8 <%
8 <%
9 # Name/desc, pattern, issue prefix
9 # Name/desc, pattern, issue prefix
10 examples = [
10 examples = [
11 (
11 (
12 ' ',
12 ' ',
13 ' ',
13 ' ',
14 ' ',
14 ' ',
15 ' '
15 ' '
16 ),
16 ),
17
17
18 (
18 (
19 'Redmine',
19 'Tickets with #123 (Redmine etc)',
20 '(^#|\s#)(?P<issue_id>\d+)',
20 '(?<![a-zA-Z0-9_/]{1,10}-?)(#)(?P<issue_id>\d+)',
21 'https://myissueserver.com/${repo}/issue/${issue_id}',
21 'https://myissueserver.com/${repo}/issue/${issue_id}',
22 ''
22 ''
23 ),
23 ),
24
24
25 (
25 (
26 'Redmine - Alternative',
26 'Redmine - Alternative',
27 '(?:issue-)(\d+)',
27 '(?:issue-)(\d+)',
28 'https://myissueserver.com/redmine/issue/${id}',
28 'https://myissueserver.com/redmine/issue/${id}',
29 ''
29 ''
30 ),
30 ),
31
31
32 (
32 (
33 'Redmine - Wiki',
33 'Redmine - Wiki',
34 '(?:wiki-)([a-zA-Z0-9]+)',
34 '(?:wiki-)([a-zA-Z0-9]+)',
35 'http://example.org/projects/${repo_name}/wiki/${id}',
35 'http://example.org/projects/${repo_name}/wiki/${id}',
36 'wiki-'
36 'wiki-'
37 ),
37 ),
38
38
39 (
39 (
40 'JIRA - All tickets',
40 'JIRA - All tickets',
41 '(^|\s\w+-\d+)',
41 # official JIRA ticket pattern
42 'https://myjira.com/browse/${id}',
42 '(?<![a-zA-Z0-9_/#]-?)(?P<issue_id>[A-Z]{1,6}-(?:[1-9][0-9]{0,7}))',
43 'https://myjira.com/browse/${issue_id}',
43 ''
44 ''
44 ),
45 ),
45
46
46 (
47 (
47 'JIRA - Project (JRA)',
48 'JIRA - Single project (JRA-XXXXXXXX)',
48 '(?:(^|\s)(?P<issue_id>(?:JRA-|JRA-)(?:\d+)))',
49 '(?<![a-zA-Z0-9_/#]-?)(?P<issue_id>JRA-(?:[1-9][0-9]{0,7}))',
49 'https://myjira.com/${issue_id}',
50 'https://myjira.com/${issue_id}',
50 ''
51 ''
51 ),
52 ),
52
53
53 (
54 (
54 'Confluence WIKI',
55 'Confluence WIKI',
55 '(?:conf-)([A-Z0-9]+)',
56 '(?:conf-)([A-Z0-9]+)',
56 'https://example.atlassian.net/display/wiki/${id}/${repo_name}',
57 'https://example.atlassian.net/display/wiki/${id}/${repo_name}',
57 'CONF-',
58 'CONF-',
58 ),
59 ),
59
60
60 (
61 (
61 'Pivotal Tracker',
62 'Pivotal Tracker',
62 '(?:pivot-)(?P<project_id>\d+)-(?P<story>\d+)',
63 '(?:pivot-)(?P<project_id>\d+)-(?P<story>\d+)',
63 'https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}',
64 'https://www.pivotaltracker.com/s/projects/${project_id}/stories/${story}',
64 'PIV-',
65 'PIV-',
65 ),
66 ),
66
67
67 (
68 (
68 'Trello',
69 'Trello',
69 '(?:trello-)(?P<card_id>[a-zA-Z0-9]+)',
70 '(?:trello-)(?P<card_id>[a-zA-Z0-9]+)',
70 'https://trello.com/example.com/${card_id}',
71 'https://trello.com/example.com/${card_id}',
71 'TRELLO-',
72 'TRELLO-',
72 ),
73 ),
73 ]
74 ]
74 %>
75 %>
75
76
76 <table class="rctable issuetracker">
77 <table class="rctable issuetracker">
77 <tr>
78 <tr>
78 <th>${_('Description')}</th>
79 <th>${_('Description')}</th>
79 <th>${_('Pattern')}</th>
80 <th>${_('Pattern')}</th>
80 <th>${_('Url')}</th>
81 <th>${_('Url')}</th>
81 <th>${_('Extra Prefix')}</th>
82 <th>${_('Extra Prefix')}</th>
82 <th ></th>
83 <th ></th>
83 </tr>
84 </tr>
84 % for name, pat, url, pref in examples:
85 % for name, pat, url, pref in examples:
85 <tr class="it-examples" style="${'' if loop.index == 0 else 'display:none'}">
86 <tr class="it-examples" style="${'' if loop.index == 0 else 'display:none'}">
86 <td class="td-issue-tracker-name issue-tracker-example">${name}</td>
87 <td class="td-issue-tracker-name issue-tracker-example">${name}</td>
87 <td class="td-regex issue-tracker-example">${pat}</td>
88 <td class="td-regex issue-tracker-example">${pat}</td>
88 <td class="td-url issue-tracker-example">${url}</td>
89 <td class="td-url issue-tracker-example">${url}</td>
89 <td class="td-prefix issue-tracker-example">${pref}</td>
90 <td class="td-prefix issue-tracker-example">${pref}</td>
90 <td>
91 <td>
91 % if loop.index == 0:
92 % if loop.index == 0:
92 <a href="#showMore" onclick="$('.it-examples').toggle(); return false">${_('show examples')}</a>
93 <a href="#showMore" onclick="$('.it-examples').toggle(); return false">${_('show examples')}</a>
93 % else:
94 % else:
94 <a href="#copyToInput" onclick="copyToInput(this, '${h.json.dumps(name)}', '${h.json.dumps(pat)}', '${h.json.dumps(url)}', '${h.json.dumps(pref)}'); return false">copy to input</a>
95 <a href="#copyToInput" onclick="copyToInput(this, '${h.json.dumps(name)}', '${h.json.dumps(pat)}', '${h.json.dumps(url)}', '${h.json.dumps(pref)}'); return false">copy to input</a>
95 % endif
96 % endif
96 </td>
97 </td>
97 </tr>
98 </tr>
98 % endfor
99 % endfor
99
100
100 %for uid, entry in patterns:
101 %for uid, entry in patterns:
101 <tr id="entry_${uid}">
102 <tr id="entry_${uid}">
102 <td class="td-issue-tracker-name issuetracker_desc">
103 <td class="td-issue-tracker-name issuetracker_desc">
103 <span class="entry">
104 <span class="entry">
104 ${entry.desc}
105 ${entry.desc}
105 </span>
106 </span>
106 <span class="edit">
107 <span class="edit">
107 ${h.text('new_pattern_description_'+uid, class_='medium-inline', value=entry.desc or '')}
108 ${h.text('new_pattern_description_'+uid, class_='medium-inline', value=entry.desc or '')}
108 </span>
109 </span>
109 </td>
110 </td>
110 <td class="td-issue-tracker-regex issuetracker_pat">
111 <td class="td-issue-tracker-regex issuetracker_pat">
111 <span class="entry">
112 <span class="entry">
112 ${entry.pat}
113 ${entry.pat}
113 </span>
114 </span>
114 <span class="edit">
115 <span class="edit">
115 ${h.text('new_pattern_pattern_'+uid, class_='medium-inline', value=entry.pat or '')}
116 ${h.text('new_pattern_pattern_'+uid, class_='medium-inline', value=entry.pat or '')}
116 </span>
117 </span>
117 </td>
118 </td>
118 <td class="td-url issuetracker_url">
119 <td class="td-url issuetracker_url">
119 <span class="entry">
120 <span class="entry">
120 ${entry.url}
121 ${entry.url}
121 </span>
122 </span>
122 <span class="edit">
123 <span class="edit">
123 ${h.text('new_pattern_url_'+uid, class_='medium-inline', value=entry.url or '')}
124 ${h.text('new_pattern_url_'+uid, class_='medium-inline', value=entry.url or '')}
124 </span>
125 </span>
125 </td>
126 </td>
126 <td class="td-prefix issuetracker_pref">
127 <td class="td-prefix issuetracker_pref">
127 <span class="entry">
128 <span class="entry">
128 ${entry.pref}
129 ${entry.pref}
129 </span>
130 </span>
130 <span class="edit">
131 <span class="edit">
131 ${h.text('new_pattern_prefix_'+uid, class_='medium-inline', value=entry.pref or '')}
132 ${h.text('new_pattern_prefix_'+uid, class_='medium-inline', value=entry.pref or '')}
132 </span>
133 </span>
133 </td>
134 </td>
134 <td class="td-action">
135 <td class="td-action">
135 <div class="grid_edit">
136 <div class="grid_edit">
136 <span class="entry">
137 <span class="entry">
137 <a class="edit_issuetracker_entry" href="">${_('Edit')}</a>
138 <a class="edit_issuetracker_entry" href="">${_('Edit')}</a>
138 </span>
139 </span>
139 <span class="edit">
140 <span class="edit">
140 <input id="uid_${uid}" name="uid" type="hidden" value="${uid}">
141 <input id="uid_${uid}" name="uid" type="hidden" value="${uid}">
141 </span>
142 </span>
142 </div>
143 </div>
143 <div class="grid_delete">
144 <div class="grid_delete">
144 <span class="entry">
145 <span class="entry">
145 <a class="btn btn-link btn-danger delete_issuetracker_entry" data-desc="${entry.desc}" data-uid="${uid}">
146 <a class="btn btn-link btn-danger delete_issuetracker_entry" data-desc="${entry.desc}" data-uid="${uid}">
146 ${_('Delete')}
147 ${_('Delete')}
147 </a>
148 </a>
148 </span>
149 </span>
149 <span class="edit">
150 <span class="edit">
150 <a class="btn btn-link btn-danger edit_issuetracker_cancel" data-uid="${uid}">${_('Cancel')}</a>
151 <a class="btn btn-link btn-danger edit_issuetracker_cancel" data-uid="${uid}">${_('Cancel')}</a>
151 </span>
152 </span>
152 </div>
153 </div>
153 </td>
154 </td>
154 </tr>
155 </tr>
155 %endfor
156 %endfor
156 <tr id="last-row"></tr>
157 <tr id="last-row"></tr>
157 </table>
158 </table>
158 <p>
159 <p>
159 <a id="add_pattern" class="link">
160 <a id="add_pattern" class="link">
160 ${_('Add new')}
161 ${_('Add new')}
161 </a>
162 </a>
162 </p>
163 </p>
163
164
164 <script type="text/javascript">
165 <script type="text/javascript">
165 var newEntryLabel = $('label[for="new_entry"]');
166 var newEntryLabel = $('label[for="new_entry"]');
166
167
167 var resetEntry = function() {
168 var resetEntry = function() {
168 newEntryLabel.text("${_('New Entry')}:");
169 newEntryLabel.text("${_('New Entry')}:");
169 };
170 };
170
171
171 var delete_pattern = function(entry) {
172 var delete_pattern = function(entry) {
172 if (confirm("${_('Confirm to remove this pattern:')} "+$(entry).data('desc'))) {
173 if (confirm("${_('Confirm to remove this pattern:')} "+$(entry).data('desc'))) {
173 $.ajax({
174 $.ajax({
174 type: "POST",
175 type: "POST",
175 url: "${delete_url}",
176 url: "${delete_url}",
176 data: {
177 data: {
177 'csrf_token': CSRF_TOKEN,
178 'csrf_token': CSRF_TOKEN,
178 'uid':$(entry).data('uid')
179 'uid':$(entry).data('uid')
179 },
180 },
180 success: function(){
181 success: function(){
181 window.location.reload();
182 window.location.reload();
182 },
183 },
183 error: function(data, textStatus, errorThrown){
184 error: function(data, textStatus, errorThrown){
184 alert("Error while deleting entry.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(entry)[0].url));
185 alert("Error while deleting entry.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(entry)[0].url));
185 }
186 }
186 });
187 });
187 }
188 }
188 };
189 };
189
190
190 $('.delete_issuetracker_entry').on('click', function(e){
191 $('.delete_issuetracker_entry').on('click', function(e){
191 e.preventDefault();
192 e.preventDefault();
192 delete_pattern(this);
193 delete_pattern(this);
193 });
194 });
194
195
195 $('.edit_issuetracker_entry').on('click', function(e){
196 $('.edit_issuetracker_entry').on('click', function(e){
196 e.preventDefault();
197 e.preventDefault();
197 $(this).parents('tr').addClass('editopen');
198 $(this).parents('tr').addClass('editopen');
198 });
199 });
199
200
200 $('.edit_issuetracker_cancel').on('click', function(e){
201 $('.edit_issuetracker_cancel').on('click', function(e){
201 e.preventDefault();
202 e.preventDefault();
202 $(this).parents('tr').removeClass('editopen');
203 $(this).parents('tr').removeClass('editopen');
203 // Reset to original value
204 // Reset to original value
204 var uid = $(this).data('uid');
205 var uid = $(this).data('uid');
205 $('#'+uid+' input').each(function(e) {
206 $('#'+uid+' input').each(function(e) {
206 this.value = this.defaultValue;
207 this.value = this.defaultValue;
207 });
208 });
208 });
209 });
209
210
210 $('input#reset').on('click', function(e) {
211 $('input#reset').on('click', function(e) {
211 resetEntry();
212 resetEntry();
212 });
213 });
213
214
214 $('#add_pattern').on('click', function(e) {
215 $('#add_pattern').on('click', function(e) {
215 addNewPatternInput();
216 addNewPatternInput();
216 });
217 });
217
218
218 var copied = false;
219 var copied = false;
219 copyToInput = function (elem, name, pat, url, pref) {
220 copyToInput = function (elem, name, pat, url, pref) {
220 if (copied === false) {
221 if (copied === false) {
221 addNewPatternInput();
222 addNewPatternInput();
222 copied = true;
223 copied = true;
223 }
224 }
224 $(elem).hide();
225 $(elem).hide();
225 var load = function(text){
226 var load = function(text){
226 return text.replace(/["]/g, "")
227 return text.replace(/["]/g, "")
227 };
228 };
228 $('#description_1').val(load(name));
229 $('#description_1').val(load(name));
229 $('#pattern_1').val(load(pat));
230 $('#pattern_1').val(load(pat));
230 $('#url_1').val(load(url));
231 $('#url_1').val(load(url));
231 $('#prefix_1').val(load(pref));
232 $('#prefix_1').val(load(pref));
232
233
233 }
234 }
234
235
235 </script>
236 </script>
236 </%def>
237 </%def>
237
238
238 <%def name="issue_tracker_new_row()">
239 <%def name="issue_tracker_new_row()">
239 <table id="add-row-tmpl" style="display: none;">
240 <table id="add-row-tmpl" style="display: none;">
240 <tbody>
241 <tbody>
241 <tr class="new_pattern">
242 <tr class="new_pattern">
242 <td class="td-issue-tracker-name issuetracker_desc">
243 <td class="td-issue-tracker-name issuetracker_desc">
243 <span class="entry">
244 <span class="entry">
244 <input class="medium-inline" id="description_##UUID##" name="new_pattern_description_##UUID##" value="##DESCRIPTION##" type="text">
245 <input class="medium-inline" id="description_##UUID##" name="new_pattern_description_##UUID##" value="##DESCRIPTION##" type="text">
245 </span>
246 </span>
246 </td>
247 </td>
247 <td class="td-issue-tracker-regex issuetracker_pat">
248 <td class="td-issue-tracker-regex issuetracker_pat">
248 <span class="entry">
249 <span class="entry">
249 <input class="medium-inline" id="pattern_##UUID##" name="new_pattern_pattern_##UUID##" placeholder="Pattern"
250 <input class="medium-inline" id="pattern_##UUID##" name="new_pattern_pattern_##UUID##" placeholder="Pattern"
250 value="##PATTERN##" type="text">
251 value="##PATTERN##" type="text">
251 </span>
252 </span>
252 </td>
253 </td>
253 <td class="td-url issuetracker_url">
254 <td class="td-url issuetracker_url">
254 <span class="entry">
255 <span class="entry">
255 <input class="medium-inline" id="url_##UUID##" name="new_pattern_url_##UUID##" placeholder="Url" value="##URL##" type="text">
256 <input class="medium-inline" id="url_##UUID##" name="new_pattern_url_##UUID##" placeholder="Url" value="##URL##" type="text">
256 </span>
257 </span>
257 </td>
258 </td>
258 <td class="td-prefix issuetracker_pref">
259 <td class="td-prefix issuetracker_pref">
259 <span class="entry">
260 <span class="entry">
260 <input class="medium-inline" id="prefix_##UUID##" name="new_pattern_prefix_##UUID##" placeholder="Prefix" value="##PREFIX##" type="text">
261 <input class="medium-inline" id="prefix_##UUID##" name="new_pattern_prefix_##UUID##" placeholder="Prefix" value="##PREFIX##" type="text">
261 </span>
262 </span>
262 </td>
263 </td>
263 <td class="td-action">
264 <td class="td-action">
264 </td>
265 </td>
265 <input id="uid_##UUID##" name="uid_##UUID##" type="hidden" value="">
266 <input id="uid_##UUID##" name="uid_##UUID##" type="hidden" value="">
266 </tr>
267 </tr>
267 </tbody>
268 </tbody>
268 </table>
269 </table>
269 </%def>
270 </%def>
270
271
271 <%def name="issue_tracker_settings_test(test_url)">
272 <%def name="issue_tracker_settings_test(test_url)">
272 <div class="form-vertical">
273 <div class="form-vertical">
273 <div class="fields">
274 <div class="fields">
274 <div class="field">
275 <div class="field">
275 <div class='textarea-full'>
276 <div class='textarea-full'>
276 <textarea id="test_pattern_data" rows="12">
277 <textarea id="test_pattern_data" rows="12">
277 This is an example text for testing issue tracker patterns.
278 This is an example text for testing issue tracker patterns.
278 This commit fixes ticket #451 and ticket #910.
279 This commit fixes ticket #451 and ticket #910, reference for JRA-401.
279 Following tickets will get mentioned:
280 The following tickets will get mentioned:
280 #123
281 #123
281 #456
282 #456 and PROJ-101
282 JRA-123
283 JRA-123 and #123
283 JRA-456
284 PROJ-456
284 Open a pull request !101 to contribute !
285
286 [my artifact](http://something.com/JRA-1234-build.zip)
287
288 - #1001
289 - JRA-998
290
291 Open a pull request !101 to contribute!
285 Added tag v1.3.0 for commit 0f3b629be725
292 Added tag v1.3.0 for commit 0f3b629be725
286
293
287 Add a test pattern here and hit preview to see the link.
294 Add a test pattern here and hit preview to see the link.
288 </textarea>
295 </textarea>
289 </div>
296 </div>
290 </div>
297 </div>
291 </div>
298 </div>
292 <div class="test_pattern_preview">
299 <div class="test_pattern_preview">
293 <div id="test_pattern" class="btn btn-small" >${_('Preview')}</div>
300 <div id="test_pattern" class="btn btn-small" >${_('Preview')}</div>
294 <p>${_('Test Pattern Preview')}</p>
301 <p>${_('Test Pattern Preview')}</p>
295 <div id="test_pattern_result" style="white-space: pre-wrap"></div>
302 <div id="test_pattern_result" style="white-space: pre-wrap"></div>
296 </div>
303 </div>
297 </div>
304 </div>
298
305
299 <script type="text/javascript">
306 <script type="text/javascript">
300 $('#test_pattern').on('click', function(e) {
307 $('#test_pattern').on('click', function(e) {
301 $.ajax({
308 $.ajax({
302 type: "POST",
309 type: "POST",
303 url: "${test_url}",
310 url: "${test_url}",
304 data: {
311 data: {
305 'test_text': $('#test_pattern_data').val(),
312 'test_text': $('#test_pattern_data').val(),
306 'csrf_token': CSRF_TOKEN
313 'csrf_token': CSRF_TOKEN
307 },
314 },
308 success: function(data){
315 success: function(data){
309 $('#test_pattern_result').html(data);
316 $('#test_pattern_result').html(data);
310 tooltipActivate();
317 tooltipActivate();
311 },
318 },
312 error: function(jqXHR, textStatus, errorThrown){
319 error: function(jqXHR, textStatus, errorThrown){
313 $('#test_pattern_result').html('Error: ' + errorThrown);
320 $('#test_pattern_result').html('Error: ' + errorThrown);
314 }
321 }
315 });
322 });
316 $('#test_pattern_result').show();
323 $('#test_pattern_result').show();
317 });
324 });
318 </script>
325 </script>
319 </%def>
326 </%def>
320
327
321
328
@@ -1,241 +1,241 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import copy
21 import copy
22 import mock
22 import mock
23 import pytest
23 import pytest
24
24
25 from rhodecode.lib import helpers
25 from rhodecode.lib import helpers
26 from rhodecode.lib.utils2 import AttributeDict
26 from rhodecode.lib.utils2 import AttributeDict
27 from rhodecode.model.settings import IssueTrackerSettingsModel
27 from rhodecode.model.settings import IssueTrackerSettingsModel
28 from rhodecode.tests import no_newline_id_generator
28 from rhodecode.tests import no_newline_id_generator
29
29
30
30
31 @pytest.mark.parametrize('url, expected_url', [
31 @pytest.mark.parametrize('url, expected_url', [
32 ('http://rc.com', '<a href="http://rc.com">http://rc.com</a>'),
32 ('http://rc.com', '<a href="http://rc.com">http://rc.com</a>'),
33 ('http://rc.com/test', '<a href="http://rc.com/test">http://rc.com/test</a>'),
33 ('http://rc.com/test', '<a href="http://rc.com/test">http://rc.com/test</a>'),
34 ('http://rc.com/!foo', '<a href="http://rc.com/!foo">http://rc.com/!foo</a>'),
34 ('http://rc.com/!foo', '<a href="http://rc.com/!foo">http://rc.com/!foo</a>'),
35 ('http://rc.com/&foo', '<a href="http://rc.com/&amp;foo">http://rc.com/&amp;foo</a>'),
35 ('http://rc.com/&foo', '<a href="http://rc.com/&amp;foo">http://rc.com/&amp;foo</a>'),
36 ('http://rc.com/?foo-1&bar=1', '<a href="http://rc.com/?foo-1&amp;bar=1">http://rc.com/?foo-1&amp;bar=1</a>'),
36 ('http://rc.com/?foo-1&bar=1', '<a href="http://rc.com/?foo-1&amp;bar=1">http://rc.com/?foo-1&amp;bar=1</a>'),
37 ('http://rc.com?foo-1&bar=1', '<a href="http://rc.com?foo-1&amp;bar=1">http://rc.com?foo-1&amp;bar=1</a>'),
37 ('http://rc.com?foo-1&bar=1', '<a href="http://rc.com?foo-1&amp;bar=1">http://rc.com?foo-1&amp;bar=1</a>'),
38 ('http://rc.com/#foo', '<a href="http://rc.com/#foo">http://rc.com/#foo</a>'),
38 ('http://rc.com/#foo', '<a href="http://rc.com/#foo">http://rc.com/#foo</a>'),
39 ('http://rc.com/@foo', '<a href="http://rc.com/@foo">http://rc.com/@foo</a>'),
39 ('http://rc.com/@foo', '<a href="http://rc.com/@foo">http://rc.com/@foo</a>'),
40 ])
40 ])
41 def test_urlify_text(url, expected_url):
41 def test_urlify_text(url, expected_url):
42 assert helpers.urlify_text(url) == expected_url
42 assert helpers.urlify_text(url) == expected_url
43
43
44
44
45 @pytest.mark.parametrize('repo_name, commit_id, path, expected_result', [
45 @pytest.mark.parametrize('repo_name, commit_id, path, expected_result', [
46 # Simple case 1
46 # Simple case 1
47 ('repo', 'commit', 'a/b',
47 ('repo', 'commit', 'a/b',
48 '<a href="/repo/files/commit/"><i class="icon-home"></i></a>'
48 '<a href="/repo/files/commit/"><i class="icon-home"></i></a>'
49 ' / '
49 ' / '
50 '<a href="/repo/files/commit/a">a</a>'
50 '<a href="/repo/files/commit/a">a</a>'
51 ' / '
51 ' / '
52 'b'),
52 'b'),
53
53
54 # Simple case
54 # Simple case
55 ('rX<X', 'cX<X', 'pX<X/aX<X/bX<X',
55 ('rX<X', 'cX<X', 'pX<X/aX<X/bX<X',
56 '<a href="/rX%3CX/files/cX%3CX/"><i class="icon-home"></i></a>'
56 '<a href="/rX%3CX/files/cX%3CX/"><i class="icon-home"></i></a>'
57 ' / '
57 ' / '
58 '<a href="/rX%3CX/files/cX%3CX/pX%3CX">pX&lt;X</a>'
58 '<a href="/rX%3CX/files/cX%3CX/pX%3CX">pX&lt;X</a>'
59 ' / '
59 ' / '
60 '<a href="/rX%3CX/files/cX%3CX/pX%3CX/aX%3CX">aX&lt;X</a>'
60 '<a href="/rX%3CX/files/cX%3CX/pX%3CX/aX%3CX">aX&lt;X</a>'
61 ' / '
61 ' / '
62 'bX&lt;X'),
62 'bX&lt;X'),
63
63
64 # Path with only one segment
64 # Path with only one segment
65 ('rX<X', 'cX<X', 'pX<X',
65 ('rX<X', 'cX<X', 'pX<X',
66 '<a href="/rX%3CX/files/cX%3CX/"><i class="icon-home"></i></a>'
66 '<a href="/rX%3CX/files/cX%3CX/"><i class="icon-home"></i></a>'
67 ' / '
67 ' / '
68 'pX&lt;X'),
68 'pX&lt;X'),
69
69
70 # Empty path
70 # Empty path
71 ('rX<X', 'cX<X', '',
71 ('rX<X', 'cX<X', '',
72 '<i class="icon-home"></i>'),
72 '<i class="icon-home"></i>'),
73
73
74 # simple quote
74 # simple quote
75 ('rX"X', 'cX"X', 'pX"X/aX"X/bX"X',
75 ('rX"X', 'cX"X', 'pX"X/aX"X/bX"X',
76 '<a href="/rX%22X/files/cX%22X/"><i class="icon-home"></i></a>'
76 '<a href="/rX%22X/files/cX%22X/"><i class="icon-home"></i></a>'
77 ' / '
77 ' / '
78 '<a href="/rX%22X/files/cX%22X/pX%22X">pX&#34;X</a>'
78 '<a href="/rX%22X/files/cX%22X/pX%22X">pX&#34;X</a>'
79 ' / '
79 ' / '
80 '<a href="/rX%22X/files/cX%22X/pX%22X/aX%22X">aX&#34;X</a>'
80 '<a href="/rX%22X/files/cX%22X/pX%22X/aX%22X">aX&#34;X</a>'
81 ' / '
81 ' / '
82 'bX&#34;X'),
82 'bX&#34;X'),
83
83
84 ], ids=['simple1', 'simple2', 'one_segment', 'empty_path', 'simple_quote'])
84 ], ids=['simple1', 'simple2', 'one_segment', 'empty_path', 'simple_quote'])
85 def test_files_breadcrumbs_xss(repo_name, commit_id, path, app, expected_result):
85 def test_files_breadcrumbs_xss(repo_name, commit_id, path, app, expected_result):
86 result = helpers.files_breadcrumbs(repo_name, 'hg', commit_id, path)
86 result = helpers.files_breadcrumbs(repo_name, 'hg', commit_id, path)
87 # Expect it to encode all path fragments properly. This is important
87 # Expect it to encode all path fragments properly. This is important
88 # because it returns an instance of `literal`.
88 # because it returns an instance of `literal`.
89 if path != '':
89 if path != '':
90 expected_result = expected_result + helpers.files_icon.format(helpers.escape(path))
90 expected_result = expected_result + helpers.files_icon.format(helpers.escape(path))
91 assert result == expected_result
91 assert result == expected_result
92
92
93
93
94 def test_format_binary():
94 def test_format_binary():
95 assert helpers.format_byte_size_binary(298489462784) == '278.0 GiB'
95 assert helpers.format_byte_size_binary(298489462784) == '278.0 GiB'
96
96
97
97
98 @pytest.mark.parametrize('text_string, pattern, expected', [
98 @pytest.mark.parametrize('text_string, pattern, expected', [
99 ('No issue here', '(?:#)(?P<issue_id>\d+)', []),
99 ('No issue here', '(?:#)(?P<issue_id>\d+)', []),
100 ('Fix #42', '(?:#)(?P<issue_id>\d+)',
100 ('Fix #42', '(?:#)(?P<issue_id>\d+)',
101 [{'url': 'http://r.io/{repo}/i/42', 'id': '42'}]),
101 [{'url': 'http://r.io/{repo}/i/42', 'id': '42'}]),
102 ('Fix #42, #53', '(?:#)(?P<issue_id>\d+)', [
102 ('Fix #42, #53', '(?:#)(?P<issue_id>\d+)', [
103 {'url': 'http://r.io/{repo}/i/42', 'id': '42'},
103 {'url': 'http://r.io/{repo}/i/42', 'id': '42'},
104 {'url': 'http://r.io/{repo}/i/53', 'id': '53'}]),
104 {'url': 'http://r.io/{repo}/i/53', 'id': '53'}]),
105 ('Fix #42', '(?:#)?<issue_id>\d+)', []), # Broken regex
105 ('Fix #42', '(?:#)?<issue_id>\d+)', []), # Broken regex
106 ])
106 ])
107 def test_extract_issues(backend, text_string, pattern, expected):
107 def test_extract_issues(backend, text_string, pattern, expected):
108 repo = backend.create_repo()
108 repo = backend.create_repo()
109 config = {
109 config = {
110 '123': {
110 '123': {
111 'uid': '123',
111 'uid': '123',
112 'pat': pattern,
112 'pat': pattern,
113 'url': 'http://r.io/${repo}/i/${issue_id}',
113 'url': 'http://r.io/${repo}/i/${issue_id}',
114 'pref': '#',
114 'pref': '#',
115 'desc': 'Test Pattern'
115 'desc': 'Test Pattern'
116 }
116 }
117 }
117 }
118
118
119 def get_settings_mock(self, cache=True):
119 def get_settings_mock(self, cache=True):
120 return config
120 return config
121
121
122 with mock.patch.object(IssueTrackerSettingsModel,
122 with mock.patch.object(IssueTrackerSettingsModel,
123 'get_settings', get_settings_mock):
123 'get_settings', get_settings_mock):
124 text, issues = helpers.process_patterns(text_string, repo.repo_name)
124 text, issues, errors = helpers.process_patterns(text_string, repo.repo_name)
125
125
126 expected = copy.deepcopy(expected)
126 expected = copy.deepcopy(expected)
127 for item in expected:
127 for item in expected:
128 item['url'] = item['url'].format(repo=repo.repo_name)
128 item['url'] = item['url'].format(repo=repo.repo_name)
129
129
130 assert issues == expected
130 assert issues == expected
131
131
132
132
133 @pytest.mark.parametrize('text_string, pattern, link_format, expected_text', [
133 @pytest.mark.parametrize('text_string, pattern, link_format, expected_text', [
134 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'html',
134 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'html',
135 'Fix <a class="tooltip issue-tracker-link" href="http://r.io/{repo}/i/42" title="Test Pattern">#42</a>'),
135 'Fix <a class="tooltip issue-tracker-link" href="http://r.io/{repo}/i/42" title="Test Pattern">#42</a>'),
136
136
137 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'markdown',
137 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'markdown',
138 'Fix [#42](http://r.io/{repo}/i/42)'),
138 'Fix [#42](http://r.io/{repo}/i/42)'),
139
139
140 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'rst',
140 ('Fix #42', '(?:#)(?P<issue_id>\d+)', 'rst',
141 'Fix `#42 <http://r.io/{repo}/i/42>`_'),
141 'Fix `#42 <http://r.io/{repo}/i/42>`_'),
142
142
143 ('Fix #42', '(?:#)?<issue_id>\d+)', 'html',
143 ('Fix #42', '(?:#)?<issue_id>\d+)', 'html',
144 'Fix #42'), # Broken regex
144 'Fix #42'), # Broken regex
145 ])
145 ])
146 def test_process_patterns_repo(backend, text_string, pattern, expected_text, link_format):
146 def test_process_patterns_repo(backend, text_string, pattern, expected_text, link_format):
147 repo = backend.create_repo()
147 repo = backend.create_repo()
148
148
149 def get_settings_mock(self, cache=True):
149 def get_settings_mock(self, cache=True):
150 return {
150 return {
151 '123': {
151 '123': {
152 'uid': '123',
152 'uid': '123',
153 'pat': pattern,
153 'pat': pattern,
154 'url': 'http://r.io/${repo}/i/${issue_id}',
154 'url': 'http://r.io/${repo}/i/${issue_id}',
155 'pref': '#',
155 'pref': '#',
156 'desc': 'Test Pattern'
156 'desc': 'Test Pattern'
157 }
157 }
158 }
158 }
159
159
160 with mock.patch.object(IssueTrackerSettingsModel,
160 with mock.patch.object(IssueTrackerSettingsModel,
161 'get_settings', get_settings_mock):
161 'get_settings', get_settings_mock):
162 processed_text, issues = helpers.process_patterns(
162 processed_text, issues, error = helpers.process_patterns(
163 text_string, repo.repo_name, link_format)
163 text_string, repo.repo_name, link_format)
164
164
165 assert processed_text == expected_text.format(repo=repo.repo_name)
165 assert processed_text == expected_text.format(repo=repo.repo_name)
166
166
167
167
168 @pytest.mark.parametrize('text_string, pattern, expected_text', [
168 @pytest.mark.parametrize('text_string, pattern, expected_text', [
169 ('Fix #42', '(?:#)(?P<issue_id>\d+)',
169 ('Fix #42', '(?:#)(?P<issue_id>\d+)',
170 'Fix <a class="tooltip issue-tracker-link" href="http://r.io/i/42" title="Test Pattern">#42</a>'),
170 'Fix <a class="tooltip issue-tracker-link" href="http://r.io/i/42" title="Test Pattern">#42</a>'),
171 ('Fix #42', '(?:#)?<issue_id>\d+)',
171 ('Fix #42', '(?:#)?<issue_id>\d+)',
172 'Fix #42'), # Broken regex
172 'Fix #42'), # Broken regex
173 ])
173 ])
174 def test_process_patterns_no_repo(text_string, pattern, expected_text):
174 def test_process_patterns_no_repo(text_string, pattern, expected_text):
175
175
176 def get_settings_mock(self, cache=True):
176 def get_settings_mock(self, cache=True):
177 return {
177 return {
178 '123': {
178 '123': {
179 'uid': '123',
179 'uid': '123',
180 'pat': pattern,
180 'pat': pattern,
181 'url': 'http://r.io/i/${issue_id}',
181 'url': 'http://r.io/i/${issue_id}',
182 'pref': '#',
182 'pref': '#',
183 'desc': 'Test Pattern'
183 'desc': 'Test Pattern'
184 }
184 }
185 }
185 }
186
186
187 with mock.patch.object(IssueTrackerSettingsModel,
187 with mock.patch.object(IssueTrackerSettingsModel,
188 'get_global_settings', get_settings_mock):
188 'get_global_settings', get_settings_mock):
189 processed_text, issues = helpers.process_patterns(
189 processed_text, issues, errors = helpers.process_patterns(
190 text_string, '')
190 text_string, '')
191
191
192 assert processed_text == expected_text
192 assert processed_text == expected_text
193
193
194
194
195 def test_process_patterns_non_existent_repo_name(backend):
195 def test_process_patterns_non_existent_repo_name(backend):
196 text_string = 'Fix #42'
196 text_string = 'Fix #42'
197 pattern = '(?:#)(?P<issue_id>\d+)'
197 pattern = '(?:#)(?P<issue_id>\d+)'
198 expected_text = ('Fix <a class="tooltip issue-tracker-link" '
198 expected_text = ('Fix <a class="tooltip issue-tracker-link" '
199 'href="http://r.io/do-not-exist/i/42" title="Test Pattern">#42</a>')
199 'href="http://r.io/do-not-exist/i/42" title="Test Pattern">#42</a>')
200
200
201 def get_settings_mock(self, cache=True):
201 def get_settings_mock(self, cache=True):
202 return {
202 return {
203 '123': {
203 '123': {
204 'uid': '123',
204 'uid': '123',
205 'pat': pattern,
205 'pat': pattern,
206 'url': 'http://r.io/${repo}/i/${issue_id}',
206 'url': 'http://r.io/${repo}/i/${issue_id}',
207 'pref': '#',
207 'pref': '#',
208 'desc': 'Test Pattern'
208 'desc': 'Test Pattern'
209 }
209 }
210 }
210 }
211
211
212 with mock.patch.object(IssueTrackerSettingsModel,
212 with mock.patch.object(IssueTrackerSettingsModel,
213 'get_global_settings', get_settings_mock):
213 'get_global_settings', get_settings_mock):
214 processed_text, issues = helpers.process_patterns(
214 processed_text, issues, errors = helpers.process_patterns(
215 text_string, 'do-not-exist')
215 text_string, 'do-not-exist')
216
216
217 assert processed_text == expected_text
217 assert processed_text == expected_text
218
218
219
219
220 def test_get_visual_attr(baseapp):
220 def test_get_visual_attr(baseapp):
221 from rhodecode.apps._base import TemplateArgs
221 from rhodecode.apps._base import TemplateArgs
222 c = TemplateArgs()
222 c = TemplateArgs()
223 assert None is helpers.get_visual_attr(c, 'fakse')
223 assert None is helpers.get_visual_attr(c, 'fakse')
224
224
225 # emulate the c.visual behaviour
225 # emulate the c.visual behaviour
226 c.visual = AttributeDict({})
226 c.visual = AttributeDict({})
227 assert None is helpers.get_visual_attr(c, 'some_var')
227 assert None is helpers.get_visual_attr(c, 'some_var')
228
228
229 c.visual.some_var = 'foobar'
229 c.visual.some_var = 'foobar'
230 assert 'foobar' == helpers.get_visual_attr(c, 'some_var')
230 assert 'foobar' == helpers.get_visual_attr(c, 'some_var')
231
231
232
232
233 @pytest.mark.parametrize('test_text, inclusive, expected_text', [
233 @pytest.mark.parametrize('test_text, inclusive, expected_text', [
234 ('just a string', False, 'just a string'),
234 ('just a string', False, 'just a string'),
235 ('just a string\n', False, 'just a string'),
235 ('just a string\n', False, 'just a string'),
236 ('just a string\n next line', False, 'just a string...'),
236 ('just a string\n next line', False, 'just a string...'),
237 ('just a string\n next line', True, 'just a string\n...'),
237 ('just a string\n next line', True, 'just a string\n...'),
238 ], ids=no_newline_id_generator)
238 ], ids=no_newline_id_generator)
239 def test_chop_at(test_text, inclusive, expected_text):
239 def test_chop_at(test_text, inclusive, expected_text):
240 assert helpers.chop_at_smart(
240 assert helpers.chop_at_smart(
241 test_text, '\n', inclusive, '...') == expected_text
241 test_text, '\n', inclusive, '...') == expected_text
General Comments 0
You need to be logged in to leave comments. Login now