'Attempt at an IRC client.'
# standard libs
+from pathlib import Path
from queue import SimpleQueue
from sys import argv, exit as sys_exit
# non-standard libs
if __name__ == '__main__':
- if len(argv) == 1:
- main_loop(Terminal, ClientTui)
- elif len(argv) == 2 and argv[1] == 'test':
- for path in PATH_TESTS.iterdir():
- if path.parts[-1].endswith('.toml'):
- continue
- print(f'running test: {path}')
- main_loop(TestTerminal, TestingClientTui.on_file(path))
- print('(success!)')
- else:
- print(f'unrecognized argument(s): {argv[1:]}')
+ class _HandledException(BaseException):
+ 'To fail with only passed message rather than stack listing'
+
+ try:
+ _ARG_TEST = 'test'
+ _ARG_TEST_SEP = ':'
+ if len(argv) == 1:
+ main_loop(Terminal, ClientTui)
+ elif len(argv) == 2\
+ and (argv[1] == _ARG_TEST
+ or argv[1].startswith(_ARG_TEST + _ARG_TEST_SEP)):
+ _EXT_TEST = '.test'
+ collected_paths: list[Path] = []
+ candidates = [path for path in PATH_TESTS.iterdir()
+ if path.parts[-1].endswith(_EXT_TEST)]
+ _ARG_TEST_ALL = '*'
+ selector = (_ARG_TEST_ALL if argv[1] == _ARG_TEST
+ else argv[1].split(_ARG_TEST_SEP, maxsplit=1)[1])
+ if selector == '':
+ collected_paths = [path for path in candidates
+ if not path.parts[-1].startswith('_')]
+ elif selector == _ARG_TEST_ALL:
+ collected_paths = candidates[:]
+ else:
+ collected_paths = [path for path in candidates
+ if path.parts[-1].startswith(selector)]
+ if not collected_paths:
+ raise _HandledException(
+ f'no test files in {PATH_TESTS} matching [{selector}]')
+ for path in collected_paths:
+ print(f'running test: {path}')
+ main_loop(TestTerminal, TestingClientTui.on_file(path))
+ print('(success!)')
+ else:
+ raise _HandledException(f'unrecognized argument(s): {argv[1:]}')
+ except _HandledException as e:
+ print(e)
sys_exit(1)
--- /dev/null
+> /connect foo.bar.baz foo:bar baz:foobarbazquux
+| isupport-clear-in
+1 .$ isupport cleared
+1 .$ isupport:CHANTYPES set to: [#&]
+1 .$ isupport:PREFIX set to: [(ov)@+]
+1 .$ isupport:USERLEN set to: [10]
+| isupport-clear-out
+1 .$ caps cleared
+1 .$ users cleared
+1 .$ channels cleared
+, .$ DISCONNECTED
+1 .$ hostname set to: [foo.bar.baz]
+1 .$ port set to: [-1]
+1 .$ nick_wanted set to: [foo]
+1 .$ user_wanted set to: [foobarbazquux]
+1 .$ realname set to: [baz]
+1 .$ password set to: [bar]
+1 .$ port set to: [6697]
+| conn0-in
+1 .$ connection_state set to: [connecting]
+1 .$ connection_state set to: [connected]
+| conn0-out
+, .$ CONNECTED
+| conn1-in
+1 .> CAP LS :302
+1 .> USER foobarbazquux 0 * :baz
+1 .> NICK :foo
+
+# ensure we PONG properly
+:0:1 .< PING :?
+1 .> PONG :?
+| conn1-out
+
+# ping on timeout, go on as normal if PONG received
+| trigger-ping-in
+<0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
+1 .> PING :what's up?
+| trigger-ping-out
+:0:1 .< :*.?.net PONG *.?.net :what's up?
+:0:1 .< :*.?.net NOTICE * :*** Looking up your ident...
+2 .< *** [ server] *** Looking up your ident...
+
+# another timeout instead of pong? disconnect
+| full-timeout-in
+repeat trigger-ping-in trigger-ping-out
+<0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
+1 .$ connection_state set to: [broken: no timely PONG from server]
+repeat isupport-clear-in isupport-clear-out
+1 .$ connection_state set to: []
+2 .$ DISCONNECTED
+| full-timeout-out
+
+# on (automatic!) re-connect, ensure timer cleared, so won't trigger already on 1st timeout
+| conn2-in
+1 .!$ will retry connecting in 1 seconds
+repeat conn0-in conn0-out
+2 .$ CONNECTED
+repeat conn1-in conn1-out
+| conn2-out
+repeat full-timeout-in full-timeout-out
+
+# after proof that a full double-timeout was necessary, we again automatically re-connect before our /quit gets processed …
+repeat conn2-in conn2-out
+
+> /quit
+0 .<
+++ /dev/null
-> /connect foo.bar.baz foo:bar baz:foobarbazquux
-| isupport-clear-in
-1 .$ isupport cleared
-1 .$ isupport:CHANTYPES set to: [#&]
-1 .$ isupport:PREFIX set to: [(ov)@+]
-1 .$ isupport:USERLEN set to: [10]
-| isupport-clear-out
-1 .$ caps cleared
-1 .$ users cleared
-1 .$ channels cleared
-, .$ DISCONNECTED
-1 .$ hostname set to: [foo.bar.baz]
-1 .$ port set to: [-1]
-1 .$ nick_wanted set to: [foo]
-1 .$ user_wanted set to: [foobarbazquux]
-1 .$ realname set to: [baz]
-1 .$ password set to: [bar]
-1 .$ port set to: [6697]
-| conn0-in
-1 .$ connection_state set to: [connecting]
-1 .$ connection_state set to: [connected]
-| conn0-out
-, .$ CONNECTED
-| conn1-in
-1 .> CAP LS :302
-1 .> USER foobarbazquux 0 * :baz
-1 .> NICK :foo
-
-# ensure we PONG properly
-:0:1 .< PING :?
-1 .> PONG :?
-| conn1-out
-
-# ping on timeout, go on as normal if PONG received
-| trigger-ping-in
-<0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .> PING :what's up?
-| trigger-ping-out
-:0:1 .< :*.?.net PONG *.?.net :what's up?
-:0:1 .< :*.?.net NOTICE * :*** Looking up your ident...
-2 .< *** [ server] *** Looking up your ident...
-
-# another timeout instead of pong? disconnect
-| full-timeout-in
-repeat trigger-ping-in trigger-ping-out
-<0 FAKE_IRC_CONN_TIMEOUT_EXCEPTION
-1 .$ connection_state set to: [broken: no timely PONG from server]
-repeat isupport-clear-in isupport-clear-out
-1 .$ connection_state set to: []
-2 .$ DISCONNECTED
-| full-timeout-out
-
-# on (automatic!) re-connect, ensure timer cleared, so won't trigger already on 1st timeout
-| conn2-in
-1 .!$ will retry connecting in 1 seconds
-repeat conn0-in conn0-out
-2 .$ CONNECTED
-repeat conn1-in conn1-out
-| conn2-out
-repeat full-timeout-in full-timeout-out
-
-# after proof that a full double-timeout was necessary, we again automatically re-connect before our /quit gets processed …
-repeat conn2-in conn2-out
-
-> /quit
-0 .<