mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refactored color_style() and no_style() to improve testability. Refs #23663.
This includes the following improvements: - The type of the style object is now called 'Style' rather than 'dummy'. - The new make_style() function allows generating a Style object directly from a config string. Before the only way to get a style object was through the environ and it also required that the terminal supported colors which isn't necessarily the case when testing. - The output of no_style() is now cached with @lru_cache. - The output of no_style() now has the same set of attributes as the other Style objects. Previously it allowed anything to pass through with __getattr__.
This commit is contained in:
		| @@ -5,17 +5,18 @@ Sets up the terminal color scheme. | ||||
| import os | ||||
| import sys | ||||
|  | ||||
| from django.utils import lru_cache | ||||
| from django.utils import termcolors | ||||
|  | ||||
|  | ||||
| def supports_color(): | ||||
|     """ | ||||
|     Returns True if the running system's terminal supports color, and False | ||||
|     otherwise. | ||||
|     Returns True if the running system's terminal supports color, | ||||
|     and False otherwise. | ||||
|     """ | ||||
|     plat = sys.platform | ||||
|     supported_platform = plat != 'Pocket PC' and (plat != 'win32' or | ||||
|                                                   'ANSICON' in os.environ) | ||||
|     supported_platform = plat != 'Pocket PC' and (plat != 'win32' or 'ANSICON' in os.environ) | ||||
|  | ||||
|     # isatty is not always implemented, #6223. | ||||
|     is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty() | ||||
|     if not supported_platform or not is_a_tty: | ||||
| @@ -23,34 +24,49 @@ def supports_color(): | ||||
|     return True | ||||
|  | ||||
|  | ||||
| def color_style(): | ||||
|     """Returns a Style object with the Django color scheme.""" | ||||
|     if not supports_color(): | ||||
|         style = no_style() | ||||
|     else: | ||||
|         DJANGO_COLORS = os.environ.get('DJANGO_COLORS', '') | ||||
|         color_settings = termcolors.parse_color_setting(DJANGO_COLORS) | ||||
| def make_style(config_string=''): | ||||
|     """ | ||||
|     Create a Style object from the given config_string. | ||||
|  | ||||
|     If config_string is empty django.utils.termcolors.DEFAULT_PALETTE is used. | ||||
|     """ | ||||
|     class Style(object): | ||||
|         pass | ||||
|  | ||||
|     style = Style() | ||||
|  | ||||
|     color_settings = termcolors.parse_color_setting(config_string) | ||||
|  | ||||
|     # The nocolor palette has all available roles. | ||||
|     # Use that palette as the basis for populating | ||||
|     # the palette as defined in the environment. | ||||
|     for role in termcolors.PALETTES[termcolors.NOCOLOR_PALETTE]: | ||||
|         if color_settings: | ||||
|             class dummy: | ||||
|                 pass | ||||
|             style = dummy() | ||||
|             # The nocolor palette has all available roles. | ||||
|             # Use that palette as the basis for populating | ||||
|             # the palette as defined in the environment. | ||||
|             for role in termcolors.PALETTES[termcolors.NOCOLOR_PALETTE]: | ||||
|                 format = color_settings.get(role, {}) | ||||
|                 setattr(style, role, termcolors.make_style(**format)) | ||||
|             # For backwards compatibility, | ||||
|             # set style for ERROR_OUTPUT == ERROR | ||||
|             style.ERROR_OUTPUT = style.ERROR | ||||
|             format = color_settings.get(role, {}) | ||||
|             style_func = termcolors.make_style(**format) | ||||
|         else: | ||||
|             style = no_style() | ||||
|             style_func = lambda x: x | ||||
|         setattr(style, role, style_func) | ||||
|  | ||||
|     # For backwards compatibility, | ||||
|     # set style for ERROR_OUTPUT == ERROR | ||||
|     style.ERROR_OUTPUT = style.ERROR | ||||
|  | ||||
|     return style | ||||
|  | ||||
|  | ||||
| @lru_cache.lru_cache(maxsize=None) | ||||
| def no_style(): | ||||
|     """Returns a Style object that has no colors.""" | ||||
|     class dummy: | ||||
|         def __getattr__(self, attr): | ||||
|             return lambda x: x | ||||
|     return dummy() | ||||
|     """ | ||||
|     Returns a Style object with no color scheme. | ||||
|     """ | ||||
|     return make_style('nocolor') | ||||
|  | ||||
|  | ||||
| def color_style(): | ||||
|     """ | ||||
|     Returns a Style object from the Django color scheme. | ||||
|     """ | ||||
|     if not supports_color(): | ||||
|         return no_style() | ||||
|     return make_style(os.environ.get('DJANGO_COLORS', '')) | ||||
|   | ||||
| @@ -1392,6 +1392,22 @@ class CommandTypes(AdminScriptTestCase): | ||||
|         self.assertOutput(out, "Prints the CREATE TABLE, custom SQL and CREATE INDEX SQL statements for the\ngiven model module name(s).") | ||||
|         self.assertEqual(out.count('optional arguments'), 1) | ||||
|  | ||||
|     def test_color_style(self): | ||||
|         style = color.no_style() | ||||
|         self.assertEqual(style.ERROR('Hello, world!'), 'Hello, world!') | ||||
|  | ||||
|         style = color.make_style('nocolor') | ||||
|         self.assertEqual(style.ERROR('Hello, world!'), 'Hello, world!') | ||||
|  | ||||
|         style = color.make_style('dark') | ||||
|         self.assertIn('Hello, world!', style.ERROR('Hello, world!')) | ||||
|         self.assertNotEqual(style.ERROR('Hello, world!'), 'Hello, world!') | ||||
|  | ||||
|         # Default palette has color. | ||||
|         style = color.make_style('') | ||||
|         self.assertIn('Hello, world!', style.ERROR('Hello, world!')) | ||||
|         self.assertNotEqual(style.ERROR('Hello, world!'), 'Hello, world!') | ||||
|  | ||||
|     def test_command_color(self): | ||||
|         class Command(BaseCommand): | ||||
|             requires_system_checks = False | ||||
|   | ||||
		Reference in New Issue
	
	Block a user