22# CodeWriter21
33
44import re as _re
5+ import sys as _sys
56import logging as _logging
67from types import MethodType as _MethodType
7- from typing import (Union as _Union , Literal as _Literal , Mapping ,
8+ from typing import (Any , List , Union as _Union , Literal as _Literal , Mapping ,
89 Callable as _Callable , Optional as _Optional , Sequence as _Sequence )
910from getpass import getpass as _getpass
1011from logging import raiseExceptions as _raiseExceptions
@@ -40,7 +41,7 @@ def __init__(
4041 handlers = [handlers ]
4142 else :
4243 raise TypeError (
43- " handlers must be a list of logging.Handler objects"
44+ ' handlers must be a list of logging.Handler objects'
4445 )
4546 for handler in handlers :
4647 self .addHandler (handler )
@@ -61,7 +62,7 @@ def log(self, level: int, *msg, args: tuple = (), end='\n', **kwargs):
6162 msg = ' ' .join ([str (m ) for m in msg ]) + end
6263 if not isinstance (level , int ):
6364 if _raiseExceptions :
64- raise TypeError (" level must be an integer" )
65+ raise TypeError (' level must be an integer' )
6566 return
6667 if self .isEnabledFor (level ):
6768 self ._log (level , msg , args , ** kwargs )
@@ -161,19 +162,22 @@ def input(self, *msg, args: tuple = (), end='', **kwargs):
161162 """Log 'msg % args'.
162163
163164 To pass exception information, use the keyword argument exc_info with a true
164- value, e.g .
165+ value.
165166
167+ Usage example:
166168 age = logger.input("Enter your age: ")
167169 """
168170 msg = ' ' .join ([str (m ) for m in msg ]) + end
169171 self ._log (INPUT , msg , args , ** kwargs )
170172 return input ()
171173
172174 def getpass (self , * msg , args : tuple = (), end = '' , ** kwargs ):
173- """
174-
175+ """Takes a password input from the user.
175176
176- :return:
177+ :param msg: The message to display to the user.
178+ :param args: The arguments to pass to the message.
179+ :param end: The ending character to append to the message.
180+ :return: The password.
177181 """
178182 msg = ' ' .join ([str (m ) for m in msg ]) + end
179183 self ._log (self .level if self .level >= NOTSET else NOTSET , msg , args , ** kwargs )
@@ -213,7 +217,7 @@ def add_level(
213217 self ,
214218 level : int ,
215219 name : str ,
216- errors : _Literal [" raise" , " ignore" , " handle" , " force" ] = " raise"
220+ errors : _Literal [' raise' , ' ignore' , ' handle' , ' force' ] = ' raise'
217221 ) -> str :
218222 """Adds a new method to the logger with a specific level and name.
219223
@@ -276,7 +280,7 @@ def log_for_level(self, *msg, args: tuple = (), end='\n', **kwargs):
276280 def add_levels (
277281 self ,
278282 level_names : Mapping [int , str ],
279- errors : _Literal [" raise" , " ignore" , " handle" , " force" ] = " raise"
283+ errors : _Literal [' raise' , ' ignore' , ' handle' , ' force' ] = ' raise'
280284 ) -> None :
281285 """Adds new methods to the logger with specific levels and names.
282286
@@ -287,6 +291,67 @@ def add_levels(
287291 for level , name in level_names .items ():
288292 self .add_level (level , name , errors )
289293
294+ def __lshift__ (self , obj ):
295+ """Prints the object to the output stream.
296+ This operator is meant to make the Logger object be usable in a
297+ std::cout-like way.
298+
299+ :param obj: The object to print.
300+ :return: The Logger object.
301+ """
302+ logger = self
303+ found = 0
304+ while logger :
305+ for handler in logger .handlers :
306+ if (isinstance (handler , _logging .StreamHandler )
307+ and hasattr (handler .stream , 'write' )
308+ and hasattr (handler .stream , 'flush' )):
309+ found = found + 1
310+ handler .stream .write (str (obj ))
311+ handler .stream .flush ()
312+ if not logger .propagate :
313+ break
314+ logger = logger .parent
315+ if found == 0 :
316+ _sys .stderr .write (
317+ f"No handlers could be found for logger \" { self .name } \" \n "
318+ )
319+ return self
320+
321+ def __rshift__ (self , obj : List [Any ]):
322+ """A way of receiving input from the stdin.
323+ This operator is meant to make a std::cin-like operation possible in Python.
324+
325+ :param obj: The object to redirect the output to.
326+ :return: The Logger object.
327+ """
328+ n = len (obj ) - 1
329+ if n >= 0 :
330+ data = []
331+ while n >= 0 :
332+ tmp = _sys .stdin .readline ()[:- 1 ].split (maxsplit = n )
333+ data .extend (tmp )
334+ n -= len (tmp )
335+ tmp = []
336+ for i , item in enumerate (data ):
337+ if obj [i ] is None :
338+ tmp .append (item )
339+ elif isinstance (obj [i ], type ):
340+ try :
341+ tmp .append (obj [i ](item ))
342+ except ValueError :
343+ tmp .append (obj [i ]())
344+ else :
345+ try :
346+ tmp .append (obj [i ].__class__ (item ))
347+ except ValueError :
348+ tmp .append (obj [i ])
349+ obj [:] = tmp
350+ else :
351+ obj [:] = _sys .stdin .readline ()[:- 1 ].split ()
352+
353+ return self
354+
290355
291356def _add_one (name : str ) -> str :
292357 """Add one to the end of a string.
0 commit comments