uxuxx 1.4.0__tar.gz

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.
uxuxx-1.4.0/PKG-INFO ADDED
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: uxuxx
3
+ Version: 1.4.0
4
+ Summary: Zadachi informatiki 8 klass
5
+ Author: uxuxs82
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.8
uxuxx-1.4.0/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # uxuxx
2
+
3
+ Zadachi 8 klass
4
+
5
+ pip install uxuxx
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "uxuxx"
7
+ version = "1.4.0"
8
+ description = "Zadachi informatiki 8 klass"
9
+ requires-python = ">=3.8"
10
+ authors = [{name = "uxuxs82"}]
11
+ license = "MIT"
12
+
13
+ [project.scripts]
14
+ uxuxx = "uxuxx.cli:main"
15
+
16
+ [tool.setuptools]
17
+ package-dir = {"" = "src"}
18
+ license-files = []
19
+
20
+ [tool.setuptools.packages.find]
21
+ where = ["src"]
uxuxx-1.4.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,75 @@
1
+ import sys
2
+ from .data import TASKS
3
+ __version__ = "1.4.0"
4
+
5
+ def _best(q):
6
+ q = q.lower().strip()
7
+ words = q.split()
8
+ best = None
9
+ score = -1
10
+ for t in TASKS:
11
+ text = (t["desc"] + " " + t.get("notes", "") + " " + t["code"]).lower()
12
+ s = 10 if q in text else sum(1 for w in words if w in text)
13
+ if s > score:
14
+ score = s
15
+ best = t
16
+ return best if score > 0 else None
17
+
18
+ def _slide(sn):
19
+ for t in TASKS:
20
+ if t["slide"] == sn:
21
+ return t
22
+ return None
23
+
24
+ def _task(sn, lvl):
25
+ for t in TASKS:
26
+ if t["slide"] == sn and t["level"].lower() == lvl.lower():
27
+ return t
28
+ return None
29
+
30
+ def _handle(*args):
31
+ if not args:
32
+ print("uxuxx(1, slovo) | uxuxx(2, slayd) | uxuxx(3, slayd, uroven)")
33
+ return None
34
+ if len(args) == 1:
35
+ t = _best(str(args[0]))
36
+ elif len(args) == 2:
37
+ c = str(args[0])
38
+ v = args[1]
39
+ if c == "1":
40
+ t = _best(str(v))
41
+ elif c == "2":
42
+ t = _slide(int(v))
43
+ else:
44
+ t = _best(str(v))
45
+ elif len(args) == 3:
46
+ if str(args[0]) == "3":
47
+ t = _task(int(args[1]), str(args[2]))
48
+ else:
49
+ t = _best(" ".join(str(x) for x in args[1:]))
50
+ else:
51
+ t = _best(" ".join(str(x) for x in args))
52
+ if not t:
53
+ print("ne naideno")
54
+ return None
55
+ print(t["code"])
56
+ return t
57
+
58
+ class _Uxuxx:
59
+ def __call__(self, *a, **k):
60
+ return _handle(*a)
61
+ def search(self, q):
62
+ return _handle(1, q)
63
+ def slide(self, n):
64
+ return _handle(2, n)
65
+ def task(self, n, l):
66
+ return _handle(3, n, l)
67
+ def all(self):
68
+ for t in TASKS:
69
+ print(str(t["slide"]) + "|" + t["level"] + " " + t["desc"])
70
+ def count(self):
71
+ return len(TASKS)
72
+ def __repr__(self):
73
+ return "<uxuxx>"
74
+
75
+ sys.modules[__name__] = _Uxuxx()
@@ -0,0 +1,61 @@
1
+ import sys
2
+ from .data import TASKS
3
+
4
+ def _best(q):
5
+ q = q.lower().strip()
6
+ words = q.split()
7
+ best = None
8
+ score = -1
9
+ for t in TASKS:
10
+ text = (t["desc"] + " " + t.get("notes", "") + " " + t["code"]).lower()
11
+ s = 10 if q in text else sum(1 for w in words if w in text)
12
+ if s > score:
13
+ score = s
14
+ best = t
15
+ return best if score > 0 else None
16
+
17
+ def main(argv=None):
18
+ a = argv if argv is not None else sys.argv[1:]
19
+ if not a or a[0] in ("help", "-h", "--help"):
20
+ print("uxuxx 1 slovo poisk")
21
+ print("uxuxx 2 141 slayd")
22
+ print("uxuxx 3 141 A zadacha")
23
+ print("uxuxx 4 vse")
24
+ print("uxuxx 5 skolko")
25
+ return 0
26
+ if a[0] == "4":
27
+ for t in TASKS:
28
+ print(str(t["slide"]) + "|" + t["level"] + " " + t["desc"])
29
+ return 0
30
+ if a[0] == "5":
31
+ print(len(TASKS))
32
+ return 0
33
+ if a[0] == "2":
34
+ sn = int(a[1])
35
+ for t in TASKS:
36
+ if t["slide"] == sn:
37
+ print(t["code"])
38
+ return 0
39
+ print("net")
40
+ return 1
41
+ if a[0] == "3":
42
+ sn = int(a[1])
43
+ lvl = a[2].lower()
44
+ for t in TASKS:
45
+ if t["slide"] == sn and t["level"].lower() == lvl:
46
+ print(t["code"])
47
+ return 0
48
+ print("net")
49
+ return 1
50
+ if a[0] == "1":
51
+ t = _best(" ".join(a[1:]))
52
+ else:
53
+ t = _best(" ".join(a))
54
+ if not t:
55
+ print("ne naideno")
56
+ return 1
57
+ print(t["code"])
58
+ return 0
59
+
60
+ if __name__ == "__main__":
61
+ sys.exit(main())
@@ -0,0 +1 @@
1
+ TASKS = [{'slide': 10, 'level': 'В', 'desc': 'лесенкой Вася пошел гулять', 'notes': 'вывод print', 'code': 'print("Вася")\nprint("пошел")\nprint("гулять")'}, {'slide': 10, 'level': 'С', 'desc': 'рисунок из букв ж H z', 'notes': 'фигура', 'code': 'print(" ж")\nprint(" жжж")\nprint(" жжжжж")\nprint("жжжжжжж")\nprint(" HH HH")\nprint("HHHHHHH")\nprint(" HH HH")\nprint(" zzzzz")'}, {'slide': 25, 'level': 'А', 'desc': 'сумма трех чисел', 'notes': 'ввод', 'code': 'a=int(input())\nb=int(input())\nc=int(input())\nprint(a+b+c)'}, {'slide': 25, 'level': 'В', 'desc': 'сумма и произведение трех', 'notes': 'f-строки', 'code': 'a,b,c=map(int,input().split())\nprint(f"{a}+{b}+{c}={a+b+c}")\nprint(f"{a}*{b}*{c}={a*b*c}")'}, {'slide': 26, 'level': 'С', 'desc': 'среднее трех', 'notes': 'среднее', 'code': 'a,b,c=map(int,input().split())\nprint(f"({a}+{b}+{c})/3={(a+b+c)/3}")'}, {'slide': 36, 'level': 'А', 'desc': 'секунды в минуты и секунды', 'notes': 'деление', 'code': 't=int(input())\nprint(f"{t//60} мин. {t%60} с.")'}, {'slide': 36, 'level': 'В', 'desc': 'секунды в часы минуты секунды', 'notes': 'часы', 'code': 't=int(input())\nprint(f"{t//3600} ч. {t%3600//60} мин. {t%60} с.")'}, {'slide': 37, 'level': 'С', 'desc': 'время окончания урока', 'notes': 'школа', 'code': 'n=int(input())\ntotal=8*60+30+(n-1)*55+45\nprint(f"{total//60}-{total%60:02d}")'}, {'slide': 38, 'level': 'А1', 'desc': 'квадрат числа', 'notes': 'квадрат', 'code': 'n=int(input())\nprint(n*n)'}, {'slide': 38, 'level': 'А2', 'desc': 'последняя цифра', 'notes': 'остаток', 'code': 'n=int(input())\nprint(n%10)'}, {'slide': 38, 'level': 'А3', 'desc': 'первая цифра трехзначного', 'notes': 'сотни', 'code': 'n=int(input())\nprint(n//100)'}, {'slide': 39, 'level': 'В1', 'desc': 'вторая с конца цифра', 'notes': 'десятки', 'code': 'n=int(input())\nprint(n//10%10)'}, {'slide': 39, 'level': 'В2', 'desc': 'сумма цифр двузначного', 'notes': 'разбор', 'code': 'n=int(input())\nprint(n//10+n%10)'}, {'slide': 39, 'level': 'В3', 'desc': 'минуты секунды в секунды', 'notes': 'перевод', 'code': 'm=int(input())\ns=int(input())\nprint(m*60+s)'}, {'slide': 40, 'level': 'С1', 'desc': 'сумма цифр четырехзначного', 'notes': 'while', 'code': 'n=int(input())\ns=0\nwhile n:\n s+=n%10\n n//=10\nprint(s)'}, {'slide': 40, 'level': 'С2', 'desc': 'развернуть трехзначное', 'notes': 'наоборот', 'code': 'n=int(input())\nprint(n%10*100+n//10%10*10+n//100)'}, {'slide': 40, 'level': 'С3', 'desc': 'первые две цифры в конец', 'notes': 'перестановка', 'code': 'n=int(input())\nprint(n%100*100+n//100)'}, {'slide': 41, 'level': 'А', 'desc': 'трехзначное в столбик с последней', 'notes': 'while', 'code': 'n=int(input())\nwhile n:\n print(n%10)\n n//=10'}, {'slide': 41, 'level': 'В', 'desc': 'трехзначное в столбик с первой', 'notes': 'порядок', 'code': 'n=int(input())\nprint(n//100)\nprint(n//10%10)\nprint(n%10)'}, {'slide': 50, 'level': 'А', 'desc': 'сколько фото влезет на флешку', 'notes': 'объем', 'code': 'print(int(2048/float(input())))'}, {'slide': 51, 'level': 'В', 'desc': 'оцифровка звука размер файла', 'notes': 'звук', 'code': 'm=int(input())\nprint(int(44100*24*2*60*m/8/1024/1024)+1,"Мбайт")'}, {'slide': 52, 'level': 'С', 'desc': 'разведчики первая цифра дробной', 'notes': 'дробь', 'code': 'x=float(input())\nprint(int(((x*x)%1)*10))'}, {'slide': 57, 'level': 'А', 'desc': 'лото 5 случайных номеров', 'notes': 'random', 'code': 'from random import randint\nfor _ in range(5):\n print(randint(1,90))'}, {'slide': 57, 'level': 'В', 'desc': 'лото 5 разных номеров', 'notes': 'диапазоны', 'code': 'from random import randint\nprint(randint(1,18),randint(19,36),randint(37,54),randint(55,72),randint(73,90))'}, {'slide': 58, 'level': 'С', 'desc': 'кубик три раза число квадрат', 'notes': 'кубик', 'code': 'from random import randint\na,b,c=randint(1,6),randint(1,6),randint(1,6)\nn=a*100+b*10+c\nprint(n,n*n)'}, {'slide': 59, 'level': 'D', 'desc': 'случайное трехзначное цифры', 'notes': 'цифры', 'code': 'from random import randint\nn=randint(100,999)\nprint(n)\nprint(n//100)\nprint(n//10%10)\nprint(n%10)'}, {'slide': 74, 'level': 'А', 'desc': 'максимум минимум из двух без max', 'notes': 'без max', 'code': 'a,b=map(int,input().split())\nprint("Max",a if a>b else b)\nprint("Min",a if a<b else b)'}, {'slide': 74, 'level': 'В', 'desc': 'максимум из четырех без max', 'notes': 'из 4', 'code': 'a,b,c,d=map(int,input().split())\nM=a\nif b>M:M=b\nif c>M:M=c\nif d>M:M=d\nprint(M)'}, {'slide': 75, 'level': 'С', 'desc': 'кто из трех старше', 'notes': 'возраст', 'code': 'a=int(input())\nb=int(input())\nc=int(input())\nif a>b and a>c:print("Антон")\nelif b>a and b>c:print("Борис")\nelif c>a and c>b:print("Виктор")\nelse:print("Одного возраста")'}, {'slide': 86, 'level': 'А', 'desc': 'три роста по возрастанию', 'notes': 'сортировка', 'code': 'a,b,c=map(int,input().split())\nprint("По росту." if a<b<c else "Не по росту!")'}, {'slide': 87, 'level': 'В', 'desc': 'номер месяца время года', 'notes': 'времена', 'code': 'm=int(input())\nif m in(12,1,2):print("Зима")\nelif m in(3,4,5):print("Весна")\nelif m in(6,7,8):print("Лето")\nelif m in(9,10,11):print("Осень")\nelse:print("Ошибка")'}, {'slide': 88, 'level': 'С', 'desc': 'возраст год года лет', 'notes': 'склонение', 'code': 'n=int(input())\nif n%10==1 and n%100!=11:print(n,"год")\nelif n%10 in(2,3,4) and n%100 not in(12,13,14):print(n,"года")\nelse:print(n,"лет")'}, {'slide': 94, 'level': 'А', 'desc': 'трехзначное да нет', 'notes': 'трехзначное', 'code': 'n=abs(int(input()))\nprint("да" if 100<=n<=999 else "нет")'}, {'slide': 95, 'level': 'В', 'desc': 'трехзначное палиндром', 'notes': 'палиндром', 'code': 'n=int(input())\nprint("да" if n//100==n%10 else "нет")'}, {'slide': 96, 'level': 'С', 'desc': 'все цифры одинаковы', 'notes': 'одинаковые', 'code': 'n=int(input())\nprint("да" if n//100==n//10%10==n%10 else "нет")'}, {'slide': 108, 'level': 'А', 'desc': 'отладка сумма цифр трехзначного', 'notes': 'отладка', 'code': 'N=int(input())\nprint(N%10+N//10%10+N//100)'}, {'slide': 109, 'level': 'В', 'desc': 'сумма цифр с отрицательными', 'notes': 'abs', 'code': 'N=abs(int(input()))\nprint(N%10+N//10%10+N//100)'}, {'slide': 110, 'level': 'С', 'desc': 'наибольшее из трех отладка', 'notes': 'максимум', 'code': 'a=int(input())\nb=int(input())\nc=int(input())\nM=a\nif b>M:M=b\nif c>M:M=c\nprint(M)'}, {'slide': 118, 'level': 'А', 'desc': 'N раз вывести привет', 'notes': 'for', 'code': 'n=int(input())\nfor _ in range(n):print("Привет!")'}, {'slide': 118, 'level': 'В', 'desc': 'квадрат меньше N', 'notes': 'while', 'code': 'N=int(input())\nk=1\nwhile (k+1)**2<N:k+=1\nprint(k)'}, {'slide': 119, 'level': 'С', 'desc': 'число Фибоначчи не больше N', 'notes': 'Фибоначчи', 'code': 'N=int(input())\na,b=0,1\nwhile b<=N:a,b=b,a+b\nprint(a)'}, {'slide': 127, 'level': 'А', 'desc': 'число в троичной системе', 'notes': 'троичная', 'code': 'n=int(input())\nwhile n:print(n%3);n//=3'}, {'slide': 127, 'level': 'В', 'desc': 'сколько нулей в двоичной записи', 'notes': 'двоичная', 'code': 'n=int(input())\nk=0\nwhile n:\n if n%2==0:k+=1\n n//=2\nprint(k)'}, {'slide': 128, 'level': 'С', 'desc': 'наибольшая цифра', 'notes': 'максимум', 'code': 'n=int(input())\nM=0\nwhile n:\n d=n%10\n if d>M:M=d\n n//=10\nprint(M)'}, {'slide': 128, 'level': 'D', 'desc': 'одинаковые цифры рядом', 'notes': 'рядом', 'code': 's=input()\nprint("да" if any(s[i]==s[i+1] for i in range(len(s)-1)) else "нет")'}, {'slide': 132, 'level': 'А', 'desc': 'простые сомножители одной строкой', 'notes': 'разложение', 'code': 'n=int(input())\nd=2;parts=[]\nwhile n>1:\n if n%d==0:parts.append(str(d));n//=d\n else:d+=1\nprint("*".join(parts))'}, {'slide': 132, 'level': 'В', 'desc': 'сколько простых делителей', 'notes': 'делители', 'code': 'n=int(input())\nd=2;k=0\nwhile n>1:\n if n%d==0:k+=1;n//=d\n else:d+=1\nprint(k)'}, {'slide': 133, 'level': 'С', 'desc': 'сумма различных простых делителей', 'notes': 'различные', 'code': 'n=int(input())\nd=2;s=0;last=0\nwhile n>1:\n if n%d==0:\n if d!=last:s+=d;last=d\n n//=d\n else:d+=1\nprint(s)'}, {'slide': 133, 'level': 'D', 'desc': 'одинаковые простые делители', 'notes': 'повторы', 'code': 'n=int(input())\nd=2;last=0;f=False\nwhile n>1:\n if n%d==0:\n if d==last:f=True;break\n last=d;n//=d\n else:d+=1\nprint("да" if f else "нет")'}, {'slide': 141, 'level': 'А', 'desc': 'НОД алгоритм Евклида вычитанием', 'notes': 'НОД вычитание', 'code': 'a,b=map(int,input().split())\nA,B=a,b\nwhile a!=b:\n if a>b:a-=b\n else:b-=a\nprint(f"НОД({A},{B})={a}")'}, {'slide': 141, 'level': 'В', 'desc': 'НОД модифицированный алгоритм', 'notes': 'НОД остаток', 'code': 'a,b=map(int,input().split())\nA,B=a,b\nwhile b:a,b=b,a%b\nprint(f"НОД({A},{B})={a}")'}, {'slide': 142, 'level': 'С', 'desc': 'сравнить шаги двух алгоритмов НОД', 'notes': 'шаги', 'code': 'a,b=map(int,input().split())\nx,y=a,b;k1=0\nwhile x!=y:\n if x>y:x-=y\n else:y-=x\n k1+=1\nk2=0\nwhile b:a,b=b,a%b;k2+=1\nprint(k1,k2)'}]
@@ -0,0 +1,19 @@
1
+ import shutil
2
+
3
+ REQUIRED = ("x11vnc", "websockify")
4
+ OPTIONAL = ("Xvfb", "tigervnc")
5
+
6
+ def which(name):
7
+ return shutil.which(name)
8
+
9
+ def check_deps():
10
+ found = {}
11
+ missing = []
12
+ for name in REQUIRED + OPTIONAL:
13
+ path = which(name)
14
+ if path:
15
+ found[name] = path
16
+ else:
17
+ missing.append(name)
18
+ hard = [n for n in REQUIRED if n not in found]
19
+ return {"found": found, "missing": missing, "hard_missing": hard}
@@ -0,0 +1,24 @@
1
+ import socket
2
+
3
+ def find_free_port(start=6080, limit=200):
4
+ for port in range(start, start + limit):
5
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6
+ try:
7
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
8
+ s.bind(("127.0.0.1", port))
9
+ return port
10
+ except OSError:
11
+ pass
12
+ finally:
13
+ s.close()
14
+ return None
15
+
16
+ def local_ip():
17
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
18
+ try:
19
+ s.connect(("8.8.8.8", 53))
20
+ return s.getsockname()[0]
21
+ except OSError:
22
+ return None
23
+ finally:
24
+ s.close()
@@ -0,0 +1,97 @@
1
+ import http.server, os, shutil, subprocess, threading, time
2
+ from pathlib import Path
3
+ from .ports import find_free_port, local_ip
4
+
5
+ WEB = Path(__file__).parent / "web"
6
+
7
+ class Handler(http.server.SimpleHTTPRequestHandler):
8
+ def __init__(self, *a, **k):
9
+ super().__init__(*a, directory=str(WEB), **k)
10
+ def log_message(self, *a): pass
11
+
12
+ class Server:
13
+ def __init__(self, os_iso=None, memory=512, http_port=None, vnc_port=None):
14
+ self.os_iso = os_iso
15
+ self.memory = memory
16
+ self.http_port = http_port or find_free_port(6080)
17
+ self.vnc_port = vnc_port or find_free_port(5900)
18
+ self.procs = []
19
+ self.httpd = None
20
+
21
+ def _spawn(self, args, name):
22
+ try:
23
+ p = subprocess.Popen(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
24
+ self.procs.append((name, p))
25
+ print("start: " + name)
26
+ return True
27
+ except FileNotFoundError:
28
+ print("missing: " + name)
29
+ return False
30
+
31
+ def start(self):
32
+ print("uxuxxvnc v0.2.0")
33
+ print("http port: " + str(self.http_port))
34
+ print("vnc port: " + str(self.vnc_port))
35
+ print("")
36
+ if self.os_iso:
37
+ qemu = shutil.which("qemu-system-x86_64") or shutil.which("qemu-system-i386")
38
+ if not qemu:
39
+ print("ERROR: qemu not found.")
40
+ print("termux: pkg install qemu-system-x86-64-headless")
41
+ print("debian: apt install qemu-system-x86")
42
+ print("alpine: apk add qemu-system-x86_64")
43
+ return
44
+ if not os.path.exists(self.os_iso):
45
+ print("ERROR: iso not found: " + self.os_iso)
46
+ return
47
+ print("qemu: " + qemu)
48
+ print("iso: " + self.os_iso)
49
+ print("mem: " + str(self.memory) + "MB")
50
+ self._spawn([qemu, "-m", str(self.memory), "-smp", "1",
51
+ "-cdrom", self.os_iso, "-boot", "d",
52
+ "-vga", "std",
53
+ "-net", "nic,model=e1000", "-net", "user",
54
+ "-rtc", "base=localtime",
55
+ "-vnc", "127.0.0.1:" + str(self.vnc_port - 5900)],
56
+ "qemu")
57
+ time.sleep(2)
58
+ ws = shutil.which("websockify")
59
+ if ws:
60
+ self._spawn([ws, str(self.http_port), "127.0.0.1:" + str(self.vnc_port),
61
+ "--web", str(WEB)], "websockify")
62
+ else:
63
+ self.httpd = http.server.ThreadingHTTPServer(("127.0.0.1", self.http_port), Handler)
64
+ threading.Thread(target=self.httpd.serve_forever, daemon=True).start()
65
+ print("start: http (websockify missing)")
66
+ time.sleep(0.5)
67
+ ip = local_ip()
68
+ print("")
69
+ print("open: http://127.0.0.1:" + str(self.http_port))
70
+ if ip:
71
+ print("lan: http://" + ip + ":" + str(self.http_port))
72
+ print("ctrl+c to stop")
73
+ try:
74
+ while True:
75
+ time.sleep(1)
76
+ except KeyboardInterrupt:
77
+ pass
78
+ finally:
79
+ self.stop()
80
+
81
+ def stop(self):
82
+ print("")
83
+ print("shutting down")
84
+ if self.httpd:
85
+ self.httpd.shutdown()
86
+ for _, p in self.procs:
87
+ try:
88
+ p.terminate()
89
+ p.wait(timeout=2)
90
+ except Exception:
91
+ try: p.kill()
92
+ except Exception: pass
93
+ self.procs.clear()
94
+
95
+ def serve(os_iso=None, memory=512, http_port=None, vnc_port=None):
96
+ Server(os_iso=os_iso, memory=memory,
97
+ http_port=http_port, vnc_port=vnc_port).start()
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: uxuxx
3
+ Version: 1.4.0
4
+ Summary: Zadachi informatiki 8 klass
5
+ Author: uxuxs82
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.8
@@ -0,0 +1,14 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/uxuxx/__init__.py
4
+ src/uxuxx/cli.py
5
+ src/uxuxx/data.py
6
+ src/uxuxx/deps.py
7
+ src/uxuxx/ports.py
8
+ src/uxuxx/server.py
9
+ src/uxuxx.egg-info/PKG-INFO
10
+ src/uxuxx.egg-info/SOURCES.txt
11
+ src/uxuxx.egg-info/dependency_links.txt
12
+ src/uxuxx.egg-info/entry_points.txt
13
+ src/uxuxx.egg-info/top_level.txt
14
+ tests/test_uxuxx.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ uxuxx = uxuxx.cli:main
@@ -0,0 +1 @@
1
+ uxuxx
@@ -0,0 +1,19 @@
1
+ import uxuxx
2
+ from uxuxx import ports, deps
3
+
4
+ def test_version():
5
+ assert uxuxx.__version__ == "0.1.0"
6
+
7
+ def test_free_port():
8
+ p = ports.find_free_port(25000)
9
+ assert p is not None and 25000 <= p < 25200
10
+
11
+ def test_which_python():
12
+ assert deps.which("python3") is not None
13
+
14
+ def test_which_missing():
15
+ assert deps.which("this-does-not-exist-xyz") is None
16
+
17
+ def test_deps_shape():
18
+ d = deps.check_deps()
19
+ assert "found" in d and "missing" in d and "hard_missing" in d