Merge pull request #4 from devfred78/ChangeDefaultIO

Change default behavior of TextIOConsoleWrapper
This commit is contained in:
devfred78
2022-02-19 16:45:05 +01:00
committed by GitHub
3 changed files with 170 additions and 8 deletions

View File

@@ -81,7 +81,7 @@ Those lines initalize a full HD, fullscreen display, with a background image nam
Initialize an I/O text, buffered stream with:
```python
iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="pygame_console", newline='\r\n', line_buffering=True)
iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="pygame_console")
```
Retrieve the console created "under the hoods" with this I/O stream:
@@ -106,9 +106,9 @@ while True:
if event.key == K_ESCAPE:
sys.exit() # Exit when hitting the ESCAPE key
elif event.key == K_RETURN:
print("", file=iotextstream, flush=True) # New line
print("", file=iotextstream) # New line
if event.type == TEXTINPUT: # When typing a key with a writable character...
print(event.text, end='', file=iotextstream, flush=True) # Display the character
print(event.text, end='', file=iotextstream) # Display the character
# Background display
screen_surface.blit(background_surface,(0,0))
@@ -125,7 +125,7 @@ If you wish to custom the console, you can initialize it independantly, and assi
```python
my_console = pygconsole.console.get_console(name="custom_console",width=120,height=50)
iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="custom_console", newline='\r\n', line_buffering=True)
iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="custom_console")
```
A console is identified by its name, 2 consoles with the same name are in reality the same instance of the Console class.

View File

@@ -472,7 +472,7 @@ class TextIOConsoleWrapper(io.TextIOWrapper):
#############################################################
# Initialisation
def __init__(self, console_name = "pygame_console", errors=None, newline=None, line_buffering=False, write_through=False):
def __init__(self, console_name = "pygame_console", errors=None, newline='\r\n', line_buffering=True, write_through=True):
"""
Parameters
----------
@@ -481,13 +481,23 @@ class TextIOConsoleWrapper(io.TextIOWrapper):
error: str
optional string that specifies how encoding and decoding errors are to be handled.
newline: str
controls how line endings are handled. It can be None, '', '\n', '\r', and '\r\n'.
controls how line endings are handled. It can be None, '', '\n', '\r', and '\r\n'. Default is '\r\n'.
line_buffering: bool
If True, flush() is implied when a call to write contains a newline character or a carriage return. Default is False.
If True, flush() is implied when a call to write contains a newline character or a carriage return. Default is True.
write_through: bool
If True, calls to write() are guaranteed not to be buffered. Default is False.
If True, calls to write() are guaranteed not to be buffered. Default is True.
"""
buffer = BufferedIOConsole(console_name)
# To be compliant with RawIOConsole, encoding must be utf-8.
encoding = 'utf-8'
super().__init__(buffer, encoding, errors, newline, line_buffering, write_through)
# write() needs re-implementation since the `write_through` parameter seems not to work properly (or at least not as expected)
def write(self, s):
"""
Write the string s to the stream and return the number of characters written. if the `write_through` attribute is set to True, the string is readily written to the underlying stream. Otherwise, it is held in the buffer.
"""
nb_char = super().write(s)
if self.write_through: self.flush()
return nb_char

View File

@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
"""
'io' test set : tests regarding the pygconsole.io submodule
Test 105 : Print characters typed on the keyboard, on a console initialized with the default parameters.
Test the unbuffered implementation, impliying the fact that the `flush` parameter of print() is not necessary any more.
ESCAPE Key to exit.
"""
# Standard modules
#-----------------
import sys
import os
from collections import namedtuple
import logging
# Third party modules
#--------------------
import pygame
from pygame.locals import *
from colorlog import ColoredFormatter
# Internal modules
#-----------------
if __name__ == '__main__':
sys.path.append(os.path.join(os.path.dirname(__file__),'..'))
import pygconsole
else:
from .. import pygconsole
# namedtuples
#------------
Coordinates = namedtuple("Coordinates", "x y")
Colour = namedtuple("Colour", "red green blue alpha")
# Global constants
#-----------------
RESOURCE_DIR = os.path.join(os.path.dirname(__file__),"resources") # directory where graphical resources are stored
BACKGROUND_IMAGE = os.path.join(RESOURCE_DIR,"background.jpg") # Background image
FONT = None # Font displayed outside of the console (None = default pygame font)
DISPLAY_SIZE = Coordinates(1920,1080) # screen resolution
CONSOLE_COORDINATES = Coordinates(1000,620) # upper left corner coordinates of the console
FRAMERATE = 50 # Maximum number of displaying loops per second
FONT_SIZE = 40 # size of the font displayed on the screen, but out of the console
FONT_COLOUR = Colour(255,0,0,255) # Colour of the font displayed outside of the console
TEXT_COORDINATES = Coordinates(50,50) # Coordinates of the first line of the text displayed outside of the console
TEXT_LIST = [
"Test 105: Print characters typed on the keyboard,",
"on a console initialized with the default parameters,",
"without using the 'flush' parameter in the 'print()' function.",
"ESCAPE key to exit."
]
# Dataclasses
#------------
# Classes
#--------
# Functions
#----------
# Main function
#--------------
def main():
""" Main program execution"""
# Logging initialization
formatter = ColoredFormatter(
'%(log_color)s[%(asctime)s][%(levelname)s][%(name)s]:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
reset=True,
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red,bg_white'
},
secondary_log_colors={},
style='%'
)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
log = logging.getLogger('display')
log.setLevel(logging.DEBUG)
log.addHandler(handler)
# screen initialization
pygame.init()
clock = pygame.time.Clock() # timer to control framerate
flags = FULLSCREEN|SCALED|DOUBLEBUF
screen_surface = pygame.display.set_mode(size=DISPLAY_SIZE,flags=flags)
background_surface = pygame.image.load(BACKGROUND_IMAGE)
# Font initialization
font = pygame.font.Font(FONT,FONT_SIZE)
line_space = font.get_linesize()
# console initialization
console = pygconsole.console.Console.get_console(name="pygame_console",logger = log)
# iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="pygame_console", newline='\r\n', line_buffering=True)
iotextstream = pygconsole.io.TextIOConsoleWrapper(console_name="pygame_console")
# Displaying loop
while True:
clock.tick(FRAMERATE)
# Events
for event in pygame.event.get():
if event.type == QUIT: sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
sys.exit()
elif event.key == K_RETURN:
# print("", file=iotextstream, flush=True) # New line
print("", file=iotextstream) # New line
if event.type == TEXTINPUT: # When typing a key with a writable character...
# print(event.text, end='', file=iotextstream, flush=True) # Display the character
print(event.text, end='', file=iotextstream) # Display the character
# Background display
screen_surface.blit(background_surface,(0,0))
# Text display
text_line_coordinates = TEXT_COORDINATES
for text_line in TEXT_LIST:
text_surface = font.render(text_line,True,FONT_COLOUR)
screen_surface.blit(text_surface,text_line_coordinates)
text_line_coordinates = text_line_coordinates._replace(y=text_line_coordinates.y+line_space)
# Console display
screen_surface.blit(console.surface,CONSOLE_COORDINATES)
# Screen rendering
pygame.display.flip()
# Main program,
# running only if the module is NOT imported (but directly executed)
#-------------------------------------------------------------------
if __name__ == '__main__':
main()