pyscriptc 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. pyscriptc/__init__.py +3 -0
  2. pyscriptc/__main__.py +3 -0
  3. pyscriptc/_posthog_token.py +1 -0
  4. pyscriptc/builtins.py +156 -0
  5. pyscriptc/canonical.py +167 -0
  6. pyscriptc/check.py +49 -0
  7. pyscriptc/cli.py +271 -0
  8. pyscriptc/coverage.py +388 -0
  9. pyscriptc/debug.py +120 -0
  10. pyscriptc/diagnostics.py +179 -0
  11. pyscriptc/errors.py +56 -0
  12. pyscriptc/ir.py +365 -0
  13. pyscriptc/llvm.py +2129 -0
  14. pyscriptc/log.py +127 -0
  15. pyscriptc/lower/__init__.py +1071 -0
  16. pyscriptc/lower/_calls.py +1499 -0
  17. pyscriptc/lower/_classes.py +969 -0
  18. pyscriptc/lower/_core.py +301 -0
  19. pyscriptc/lower/_expr.py +886 -0
  20. pyscriptc/lower/_stdlib.py +491 -0
  21. pyscriptc/lower/_stdlib_shared.py +93 -0
  22. pyscriptc/lower/_stmt.py +1173 -0
  23. pyscriptc/package.py +249 -0
  24. pyscriptc/restlower.py +1008 -0
  25. pyscriptc/runtime/ps_argv.c +28 -0
  26. pyscriptc/runtime/ps_b64.c +168 -0
  27. pyscriptc/runtime/ps_coll.c +133 -0
  28. pyscriptc/runtime/ps_dt.c +388 -0
  29. pyscriptc/runtime/ps_hash.c +411 -0
  30. pyscriptc/runtime/ps_help.c +219 -0
  31. pyscriptc/runtime/ps_hmac.c +120 -0
  32. pyscriptc/runtime/ps_io.c +198 -0
  33. pyscriptc/runtime/ps_island.c +272 -0
  34. pyscriptc/runtime/ps_json.c +402 -0
  35. pyscriptc/runtime/ps_mix.c +47 -0
  36. pyscriptc/runtime/ps_more.c +1089 -0
  37. pyscriptc/runtime/ps_osmore.c +447 -0
  38. pyscriptc/runtime/ps_path.c +547 -0
  39. pyscriptc/runtime/ps_re.c +1102 -0
  40. pyscriptc/runtime/ps_rt.c +1175 -0
  41. pyscriptc/runtime/ps_rt.h +189 -0
  42. pyscriptc/runtime/ps_struct.c +291 -0
  43. pyscriptc/runtime/ps_time.c +207 -0
  44. pyscriptc/runtime/ps_unicode.c +1521 -0
  45. pyscriptc/runtime/ps_url.c +327 -0
  46. pyscriptc/stdlib_queue.py +191 -0
  47. pyscriptc/stdmore.py +1596 -0
  48. pyscriptc/telemetry.py +219 -0
  49. pyscriptc-0.1.0.dist-info/METADATA +187 -0
  50. pyscriptc-0.1.0.dist-info/RECORD +54 -0
  51. pyscriptc-0.1.0.dist-info/WHEEL +5 -0
  52. pyscriptc-0.1.0.dist-info/entry_points.txt +2 -0
  53. pyscriptc-0.1.0.dist-info/licenses/LICENSE +201 -0
  54. pyscriptc-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,327 @@
1
+ /* Closed urllib.parse subset: quote, quote_plus, unquote, unquote_plus,
2
+ urlencode of dict[str, str], parse_qs (blank values dropped, separator '&'),
3
+ and urlsplit into five strings. Non-ASCII results are refused. */
4
+
5
+ #include "ps_rt.h"
6
+
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ static int ps_unreserved(unsigned char c) {
11
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '.' ||
12
+ c == '-' || c == '~';
13
+ }
14
+
15
+ static int ps_hex(unsigned char c) {
16
+ if (c >= '0' && c <= '9') {
17
+ return c - '0';
18
+ }
19
+ if (c >= 'a' && c <= 'f') {
20
+ return c - 'a' + 10;
21
+ }
22
+ if (c >= 'A' && c <= 'F') {
23
+ return c - 'A' + 10;
24
+ }
25
+ return -1;
26
+ }
27
+
28
+ static int ps_safe_has(const char *safe, int64_t sn, unsigned char c) {
29
+ for (int64_t i = 0; i < sn; i++) {
30
+ if ((unsigned char)safe[i] == c) {
31
+ return 1;
32
+ }
33
+ }
34
+ return 0;
35
+ }
36
+
37
+ static void ps_quote(int64_t n, const char *p, int64_t sn, const char *safe, int plus, PsBuf *out) {
38
+ PsGrow g;
39
+ ps_grow_init(&g);
40
+ for (int64_t i = 0; i < n; i++) {
41
+ unsigned char c = (unsigned char)p[i];
42
+ if (plus && c == ' ') {
43
+ ps_grow_byte(&g, '+');
44
+ continue;
45
+ }
46
+ if (ps_unreserved(c) || ps_safe_has(safe, sn, c)) {
47
+ ps_grow_byte(&g, c);
48
+ continue;
49
+ }
50
+ static const char *hexd = "0123456789ABCDEF";
51
+ ps_grow_byte(&g, '%');
52
+ ps_grow_byte(&g, (unsigned char)hexd[c >> 4]);
53
+ ps_grow_byte(&g, (unsigned char)hexd[c & 15]);
54
+ }
55
+ ps_grow_finish(&g, out);
56
+ }
57
+
58
+ void ps_url_quote(int64_t n, char *p, int64_t sn, char *safe, PsBuf *out) { ps_quote(n, p, sn, safe, 0, out); }
59
+
60
+ void ps_url_quote_plus(int64_t n, char *p, int64_t sn, char *safe, PsBuf *out) {
61
+ int has_space = 0;
62
+ for (int64_t i = 0; i < n; i++) {
63
+ if (p[i] == ' ') {
64
+ has_space = 1;
65
+ break;
66
+ }
67
+ }
68
+ if (!has_space) {
69
+ ps_quote(n, p, sn, safe, 0, out);
70
+ return;
71
+ }
72
+ char *wider = malloc((size_t)sn + 2);
73
+ if (wider == NULL) {
74
+ abort();
75
+ }
76
+ if (sn > 0) {
77
+ memcpy(wider, safe, (size_t)sn);
78
+ }
79
+ wider[sn] = ' ';
80
+ ps_quote(n, p, sn + 1, wider, 1, out);
81
+ free(wider);
82
+ }
83
+
84
+ static void ps_unquote(int64_t n, const char *p, int plus, PsBuf *out) {
85
+ PsGrow g;
86
+ ps_grow_init(&g);
87
+ for (int64_t i = 0; i < n; i++) {
88
+ unsigned char c = (unsigned char)p[i];
89
+ if (plus && c == '+') {
90
+ ps_grow_byte(&g, ' ');
91
+ continue;
92
+ }
93
+ if (c == '%' && i + 2 < n) {
94
+ int hi = ps_hex((unsigned char)p[i + 1]);
95
+ int lo = ps_hex((unsigned char)p[i + 2]);
96
+ if (hi >= 0 && lo >= 0) {
97
+ unsigned char decoded = (unsigned char)((hi << 4) | lo);
98
+ if (decoded > 127) {
99
+ free(g.data);
100
+ ps_raise_cstr(PS_VALUE, "non-ASCII URL escape is not lowered");
101
+ }
102
+ ps_grow_byte(&g, decoded);
103
+ i += 2;
104
+ continue;
105
+ }
106
+ }
107
+ if (c > 127) {
108
+ free(g.data);
109
+ ps_raise_cstr(PS_VALUE, "non-ASCII URL text is not lowered");
110
+ }
111
+ ps_grow_byte(&g, c);
112
+ }
113
+ ps_grow_finish(&g, out);
114
+ }
115
+
116
+ void ps_url_unquote(int64_t n, char *p, PsBuf *out) { ps_unquote(n, p, 0, out); }
117
+ void ps_url_unquote_plus(int64_t n, char *p, PsBuf *out) { ps_unquote(n, p, 1, out); }
118
+
119
+ void ps_url_encode(PsMap *m, PsBuf *out) {
120
+ PsGrow g;
121
+ ps_grow_init(&g);
122
+ for (int64_t i = 0; i < ps_map_len(m); i++) {
123
+ PsBuf key;
124
+ PsBuf val;
125
+ ps_map_key_at(m, i, &key);
126
+ ps_map_val_at(m, i, &val);
127
+ PsBuf qk;
128
+ PsBuf qv;
129
+ ps_url_quote_plus(key.len, key.data, 0, "", &qk);
130
+ ps_url_quote_plus(val.len, val.data, 0, "", &qv);
131
+ if (i > 0) {
132
+ ps_grow_byte(&g, '&');
133
+ }
134
+ ps_grow_add(&g, qk.data, qk.len);
135
+ ps_grow_byte(&g, '=');
136
+ ps_grow_add(&g, qv.data, qv.len);
137
+ free(qk.data);
138
+ free(qv.data);
139
+ }
140
+ ps_grow_finish(&g, out);
141
+ }
142
+
143
+ PsMap *ps_url_parse_qs(int64_t n, char *p) {
144
+ PsMap *m = ps_map_new(2, 16, 8, 0);
145
+ int64_t i = 0;
146
+ while (i <= n) {
147
+ int64_t start = i;
148
+ while (i < n && p[i] != '&') {
149
+ i++;
150
+ }
151
+ int64_t end = i;
152
+ int64_t eq = -1;
153
+ for (int64_t j = start; j < end; j++) {
154
+ if (p[j] == '=') {
155
+ eq = j;
156
+ break;
157
+ }
158
+ }
159
+ if (eq >= 0) {
160
+ PsBuf key;
161
+ PsBuf val;
162
+ ps_unquote(eq - start, p + start, 1, &key);
163
+ ps_unquote(end - (eq + 1), p + eq + 1, 1, &val);
164
+ if (val.len > 0) {
165
+ PsSeq *existing = NULL;
166
+ int64_t at = -1;
167
+ for (int64_t k = 0; k < ps_map_len(m); k++) {
168
+ PsBuf cur;
169
+ ps_map_key_at(m, k, &cur);
170
+ if (cur.len == key.len && (key.len == 0 || memcmp(cur.data, key.data, (size_t)key.len) == 0)) {
171
+ ps_map_val_at(m, k, &existing);
172
+ at = k;
173
+ break;
174
+ }
175
+ }
176
+ if (existing == NULL) {
177
+ existing = ps_seq_new(16, 0);
178
+ ps_seq_push(existing, &val);
179
+ ps_map_put(m, &key, &existing);
180
+ } else {
181
+ ps_seq_push(existing, &val);
182
+ free(key.data);
183
+ (void)at;
184
+ }
185
+ } else {
186
+ free(key.data);
187
+ free(val.data);
188
+ }
189
+ }
190
+ if (i >= n) {
191
+ break;
192
+ }
193
+ i++;
194
+ }
195
+ return m;
196
+ }
197
+
198
+ static int ps_scheme_char(unsigned char c) {
199
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '-' ||
200
+ c == '.';
201
+ }
202
+
203
+ static void ps_strip_url(const char *p, int64_t n, char **out, int64_t *out_n) {
204
+ int64_t i = 0;
205
+ while (i < n && (unsigned char)p[i] <= ' ') {
206
+ i++;
207
+ }
208
+ PsGrow g;
209
+ ps_grow_init(&g);
210
+ for (; i < n; i++) {
211
+ unsigned char c = (unsigned char)p[i];
212
+ if (c == '\t' || c == '\n' || c == '\r') {
213
+ continue;
214
+ }
215
+ ps_grow_byte(&g, c);
216
+ }
217
+ *out = g.data == NULL ? malloc(1) : g.data;
218
+ if (*out == NULL) {
219
+ abort();
220
+ }
221
+ if (g.data == NULL) {
222
+ (*out)[0] = '\0';
223
+ }
224
+ *out_n = g.len;
225
+ }
226
+
227
+ void ps_url_split(int64_t n, char *p, void *raw) {
228
+ char *text = NULL;
229
+ int64_t tn = 0;
230
+ ps_strip_url(p, n, &text, &tn);
231
+ PsBuf scheme;
232
+ PsBuf netloc;
233
+ PsBuf path;
234
+ PsBuf query;
235
+ PsBuf fragment;
236
+ ps_buf_copy(&scheme, "", 0);
237
+ ps_buf_copy(&netloc, "", 0);
238
+ ps_buf_copy(&query, "", 0);
239
+ ps_buf_copy(&fragment, "", 0);
240
+ int64_t colon = -1;
241
+ for (int64_t i = 0; i < tn; i++) {
242
+ if (text[i] == ':') {
243
+ colon = i;
244
+ break;
245
+ }
246
+ }
247
+ int64_t rest = 0;
248
+ if (colon > 0 && ((text[0] >= 'A' && text[0] <= 'Z') || (text[0] >= 'a' && text[0] <= 'z'))) {
249
+ int ok = 1;
250
+ for (int64_t i = 0; i < colon; i++) {
251
+ if (!ps_scheme_char((unsigned char)text[i])) {
252
+ ok = 0;
253
+ break;
254
+ }
255
+ }
256
+ if (ok) {
257
+ free(scheme.data);
258
+ ps_buf_copy(&scheme, text, colon);
259
+ for (int64_t i = 0; i < scheme.len; i++) {
260
+ if (scheme.data[i] >= 'A' && scheme.data[i] <= 'Z') {
261
+ scheme.data[i] = (char)(scheme.data[i] - 'A' + 'a');
262
+ }
263
+ }
264
+ rest = colon + 1;
265
+ }
266
+ }
267
+ const char *url = text + rest;
268
+ int64_t un = tn - rest;
269
+ if (un >= 2 && url[0] == '/' && url[1] == '/') {
270
+ int64_t delim = un;
271
+ for (int64_t i = 2; i < un; i++) {
272
+ if (url[i] == '/' || url[i] == '?' || url[i] == '#') {
273
+ delim = i;
274
+ break;
275
+ }
276
+ }
277
+ free(netloc.data);
278
+ ps_buf_copy(&netloc, url + 2, delim - 2);
279
+ int open = 0;
280
+ int close = 0;
281
+ for (int64_t i = 0; i < netloc.len; i++) {
282
+ if (netloc.data[i] == '[') {
283
+ open++;
284
+ }
285
+ if (netloc.data[i] == ']') {
286
+ close++;
287
+ }
288
+ }
289
+ if (open != close) {
290
+ free(text);
291
+ ps_raise_cstr(PS_VALUE, "invalid IPv6 URL");
292
+ }
293
+ url += delim;
294
+ un -= delim;
295
+ }
296
+ int64_t hash = -1;
297
+ for (int64_t i = 0; i < un; i++) {
298
+ if (url[i] == '#') {
299
+ hash = i;
300
+ break;
301
+ }
302
+ }
303
+ if (hash >= 0) {
304
+ free(fragment.data);
305
+ ps_buf_copy(&fragment, url + hash + 1, un - hash - 1);
306
+ un = hash;
307
+ }
308
+ int64_t q = -1;
309
+ for (int64_t i = 0; i < un; i++) {
310
+ if (url[i] == '?') {
311
+ q = i;
312
+ break;
313
+ }
314
+ }
315
+ if (q >= 0) {
316
+ free(query.data);
317
+ ps_buf_copy(&query, url + q + 1, un - q - 1);
318
+ un = q;
319
+ }
320
+ ps_buf_copy(&path, url, un);
321
+ memcpy(raw, &scheme, 16);
322
+ memcpy((char *)raw + 16, &netloc, 16);
323
+ memcpy((char *)raw + 32, &path, 16);
324
+ memcpy((char *)raw + 48, &query, 16);
325
+ memcpy((char *)raw + 64, &fragment, 16);
326
+ free(text);
327
+ }
@@ -0,0 +1,191 @@
1
+ """Closed import table, in the order the stdlib subset is lowered.
2
+
3
+ Every name in `QUEUE` has a lowered surface. Importing a module that is not
4
+ listed is refused. `typing` is intentionally absent; it stays in the checker.
5
+ A name added to `QUEUE` and left out of `LOWERED` imports cleanly and fences
6
+ with PS2101 on use.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any
12
+
13
+ # Iterative order from the top-100 import scan. Do not reorder casually:
14
+ # tests lock this sequence.
15
+ QUEUE: tuple[str, ...] = (
16
+ "math",
17
+ "re",
18
+ "json",
19
+ "urllib.parse",
20
+ "base64",
21
+ "hashlib",
22
+ "struct",
23
+ "datetime",
24
+ "time",
25
+ "collections",
26
+ "functools",
27
+ "itertools",
28
+ "operator",
29
+ "contextlib",
30
+ "os",
31
+ "posixpath",
32
+ "pathlib",
33
+ "stat",
34
+ "fnmatch",
35
+ "warnings",
36
+ "io",
37
+ "sys",
38
+ "importlib",
39
+ "inspect",
40
+ "threading",
41
+ "logging",
42
+ "asyncio",
43
+ "subprocess",
44
+ "socket",
45
+ "ssl",
46
+ "ctypes",
47
+ "string",
48
+ "bisect",
49
+ "errno",
50
+ "importlib.resources",
51
+ "hmac",
52
+ "unicodedata",
53
+ "tempfile",
54
+ "atexit",
55
+ "shutil",
56
+ "enum",
57
+ "dataclasses",
58
+ )
59
+
60
+ LOWERED: frozenset[str] = frozenset(QUEUE)
61
+
62
+ _F: dict[str, Any] = {"kind": "float"}
63
+ _I: dict[str, Any] = {"kind": "int"}
64
+ _B: dict[str, Any] = {"kind": "bool"}
65
+
66
+
67
+ def _sig(params: list[dict[str, Any]], ret: dict[str, Any], symbol: str) -> dict[str, Any]:
68
+ return {"params": params, "return": ret, "symbol": symbol, "llvm": "double" if ret["kind"] == "float" else "i64"}
69
+
70
+
71
+ # Domain checks live in ps_rt.c. The symbol is the C function LLVM calls.
72
+ MATH_FUNCTIONS: dict[str, dict[str, Any]] = {
73
+ "sqrt": _sig([_F], _F, "ps_math_sqrt"),
74
+ "fabs": _sig([_F], _F, "ps_math_fabs"),
75
+ "sin": _sig([_F], _F, "ps_math_sin"),
76
+ "cos": _sig([_F], _F, "ps_math_cos"),
77
+ "tan": _sig([_F], _F, "ps_math_tan"),
78
+ "exp": _sig([_F], _F, "ps_math_exp"),
79
+ "log": _sig([_F], _F, "ps_math_log"),
80
+ "log2": _sig([_F], _F, "ps_math_log2"),
81
+ "log10": _sig([_F], _F, "ps_math_log10"),
82
+ "hypot": _sig([_F, _F], _F, "ps_math_hypot"),
83
+ "pow": _sig([_F, _F], _F, "ps_math_pow"),
84
+ "floor": _sig([_F], _I, "ps_math_floor"),
85
+ "ceil": _sig([_F], _I, "ps_math_ceil"),
86
+ "trunc": _sig([_F], _I, "ps_math_trunc"),
87
+ "isnan": _sig([_F], _B, ""),
88
+ "isinf": _sig([_F], _B, ""),
89
+ }
90
+
91
+ # repr() of the CPython 3.14 constants. inf and nan go through float() at emit.
92
+ MATH_CONSTANTS: dict[str, str] = {
93
+ "pi": "3.141592653589793",
94
+ "e": "2.718281828459045",
95
+ "tau": "6.283185307179586",
96
+ "inf": "inf",
97
+ "nan": "nan",
98
+ }
99
+
100
+ _STR: dict[str, Any] = {"kind": "str"}
101
+ _BYTES: dict[str, Any] = {"kind": "bytes"}
102
+ _BUF: dict[str, Any] = {"kind": "buf"}
103
+ _LIST_STR: dict[str, Any] = {"kind": "list", "elem": _STR}
104
+ _HASH: dict[str, Any] = {"kind": "class", "name": "Hash"}
105
+ _PATTERN: dict[str, Any] = {"kind": "class", "name": "Pattern"}
106
+ _SPLIT: dict[str, Any] = {"kind": "class", "name": "SplitResult"}
107
+ _DICT_STR: dict[str, Any] = {"kind": "dict", "key": _STR, "value": _STR}
108
+ _QS: dict[str, Any] = {"kind": "dict", "key": _STR, "value": _LIST_STR}
109
+
110
+
111
+ def _fixed(params: list[dict[str, Any]], ret: dict[str, Any]) -> dict[str, Any]:
112
+ return {"params": params, "return": ret}
113
+
114
+
115
+ def _optional(
116
+ params: list[dict[str, Any]], ret: dict[str, Any], defaults: list[str], names: list[str] | None = None
117
+ ) -> dict[str, Any]:
118
+ spec: dict[str, Any] = {"params": params, "return": ret, "min": len(params) - len(defaults), "defaults": defaults}
119
+ if names is not None:
120
+ spec["names"] = names
121
+ return spec
122
+
123
+
124
+ # Fixed signatures for the codec wave. json and struct are checked in the
125
+ # lowerer: loads follows the annotation, and struct follows a literal format.
126
+ WAVE_FUNCTIONS: dict[str, dict[str, dict[str, Any]]] = {
127
+ "re": {
128
+ "escape": _fixed([_STR], _STR),
129
+ "findall": _fixed([_STR, _STR], _LIST_STR),
130
+ "sub": _fixed([_STR, _STR, _STR], _STR),
131
+ "split": _fixed([_STR, _STR], _LIST_STR),
132
+ "compile": _fixed([_STR], _PATTERN),
133
+ },
134
+ "base64": {
135
+ "b64encode": _fixed([_BYTES], _BYTES),
136
+ "standard_b64encode": _fixed([_BYTES], _BYTES),
137
+ "urlsafe_b64encode": _fixed([_BYTES], _BYTES),
138
+ "b64decode": _fixed([_BUF], _BYTES),
139
+ "standard_b64decode": _fixed([_BUF], _BYTES),
140
+ "urlsafe_b64decode": _fixed([_BUF], _BYTES),
141
+ },
142
+ "hashlib": {name: _fixed([_BUF], _HASH) for name in ("md5", "sha1", "sha256", "sha384", "sha512")},
143
+ "urllib.parse": {
144
+ "quote": _optional([_STR, _STR], _STR, ["/"], ["string", "safe"]),
145
+ "quote_plus": _optional([_STR, _STR], _STR, [""], ["string", "safe"]),
146
+ "unquote": _fixed([_STR], _STR),
147
+ "unquote_plus": _fixed([_STR], _STR),
148
+ "urlencode": _fixed([_DICT_STR], _STR),
149
+ "parse_qs": _fixed([_STR], _QS),
150
+ "urlsplit": _fixed([_STR], _SPLIT),
151
+ },
152
+ }
153
+
154
+ # Names that lower, but whose type is not a fixed signature.
155
+ SPECIAL_FUNCTIONS: dict[str, frozenset[str]] = {
156
+ "json": frozenset({"loads", "dumps"}),
157
+ "struct": frozenset({"pack", "unpack"}),
158
+ }
159
+
160
+
161
+ def wave_function(module: str, name: str) -> dict[str, Any] | None:
162
+ return WAVE_FUNCTIONS.get(module, {}).get(name)
163
+
164
+
165
+ def module_status(name: str) -> str | None:
166
+ """`lowered`, `queued`, or None when the import is outside the table.
167
+
168
+ A package root such as `urllib` is lowered once every queued child under
169
+ it has been lowered. A mix of lowered and still-queued children stays
170
+ queued, so a later wave can keep the parent closed without blocking the
171
+ children that already emit.
172
+ """
173
+
174
+ if name in LOWERED:
175
+ return "lowered"
176
+ if name in QUEUE:
177
+ return "queued"
178
+ children = [item for item in QUEUE if item.startswith(name + ".")]
179
+ if not children:
180
+ return None
181
+ if all(item in LOWERED for item in children):
182
+ return "lowered"
183
+ return "queued"
184
+
185
+
186
+ def queue_index(name: str) -> int:
187
+ root = name.split(".")[0]
188
+ for i, item in enumerate(QUEUE):
189
+ if item == name or item == root or item.startswith(root + "."):
190
+ return i
191
+ return -1