# -*- coding: utf-8 -*- """ @author: Edward Middleton-Smith """ import openpyscad as ops # , Union, Difference import numpy as np from typing import Optional, List, Union from prettytable import PrettyTable from enum import Enum from pydantic import BaseModel, Field, ValidationError, validate_arguments, validator from abc import ABC, abstractmethod # from color import Color # from termcolor import colored # from colorama import init, Fore, Style import webcolors from builtins import staticmethod import os import string import pandas as pd # init() class BaseStyle(ABC): """ @abstractmethod def minimum(): pass @abstractmethod def maximum(): pass """ @abstractmethod def get_defaults(): pass @abstractmethod def get_list_headings(): pass @abstractmethod def as_row(self): pass def input_from_console(cls): # pass options = cls.get_defaults() count_options = len(options) table_output = PrettyTable() table_output.field_names = ['index'] + cls.get_list_headings() # ['index', 'name', 'dot spacing', 'block height', 'character spacing', 'base height', 'dot height', 'dot bottom radius', 'dot top radius'] for index_option in range(count_options): option = options[index_option] table_output.add_row([index_option + 1] + option.as_row()) print() print("Please select product dimensions configuration from below :") print(table_output) while True: option = str(input("Product dimensions configuration (by index):")) print(option + " selected") if option == "#!ERRORCODE!#": exit for index_option in range(count_options): if option == str(index_option + 1): # option == options[index_option].name or return options[index_option] """ @abstractmethod # @staticmethod def get_classname(self): "" stack = inspect.stack() return stack[2][0].f_locals["__qualname__"] "" return self.__class__.__name__ """ def input_many_from_console(cls): selected = [] print(f'Inputting many {cls.__name__} objects') print() while True: try: count_inputs = int(input(f'Quantity of {cls.__name__} objects to enter:')) except: continue for index_input in range(count_inputs): print(f'Inputting {cls.__name__} object {index_input + 1}') selected_new = cls.input_from_console(cls) selected.append(selected_new) break return selected class Colour_Field(str): def __new__(cls, value: Union[str, int, tuple]): try: # colour = colored('', value) # colour = colour.split(Style.RESET_ALL)[0] try: hex_code = webcolors.normalize_hex(value) return str.__new__(cls, hex_code) except: hex_code = webcolors.name_to_hex(value) return str.__new__(cls, hex_code) except ValueError: raise ValidationError(f"Invalid colour value: {value}") @classmethod def __get_pydantic_core_schema__(cls, handler): return { 'type': 'str', } class Colour_Theme_Character_Braille(BaseModel, BaseStyle): # ATTRIBUTE DECLARATION name: str colour_top: Colour_Field colour_base: Colour_Field def __init__(self, name, colour_top, colour_base): super().__init__(name=name, colour_top=colour_top, colour_base=colour_base) """ # METHODS def __new__(cls, name, coltop, colbase, openscad_colours): # FUNCTION # Initialise class object # ARGUMENTS # str name - user reference to colour theme # str coltop - a valid openSCAD colour e.g. '#010101' # str colbase - a valid openSCAD colour e.g. 'blue' # list[str] openscad_colours # ARGUMENT VALIDATION _m = 'export_colour_theme.__new__' v_arg_type = 'class attribute' av.val_str(name, 'name', _m, 1, v_arg_type = v_arg_type) av.val_list(openscad_colours, 'openscad_colours', _m, "", 1, v_arg_type = v_arg_type) if not validate_openscad_colour(coltop, openscad_colours): raise ValueError(f"Invalid export_colour_theme attribute coltop. Type = {str(type(coltop))}. Value = {coltop}") if not validate_openscad_colour(colbase, openscad_colours): raise ValueError(f"Invalid export_colour_theme attribute colbase. Type = {str(type(colbase))}. Value = {colbase}") # RETURNS return super(export_colour_theme, cls).__new__(cls) def __init__(self, name, coltop, colbase, openscad_colours): # FUNCTION # Initialise class object # ARGUMENTS # str name - user reference to colour theme # str coltop - a valid openSCAD colour e.g. '#010101' # str colbase - a valid openSCAD colour e.g. 'blue' # list[str] openscad_colours # redundant in this function - used for argument validation # ARGUMENT VALIDATION # see __new__() # ATTRIBUTE INSTANTIATION self.name = name self.top = coltop self.base = colbase """ def __repr__(self): # FUNCTION # Convert object to str representation # RETURNS return f"name = {self.name}, colour top = {self.colour_top}, colour base = {self.colour_base}" # , openscad_colours = {self.openscad_colours} def as_dict(self): # FUNCTION # Convert object attribute, value pairs to dictionary representation # RETURNS return {'name': self.name, 'colour top': self.colour_top, 'colour base': self.colour_base} # , 'openscad_colours': self.openscad_colours def as_row(self): # FUNCTION # Convert object values to list representation # RETURNS return [self.name, self.colour_top, self.colour_base] # , 'openscad_colours': self.openscad_colours def get_defaults(): # openscad_colours = get_openscad_colours() colour_themes = [] colour_themes.append(Colour_Theme_Character_Braille("Blue", "#337AFF", "#337AFF")) #, openscad_colours)) colour_themes.append(Colour_Theme_Character_Braille("Purple", "#8E44AD", "#8E44AD")) #, openscad_colours)) colour_themes.append(Colour_Theme_Character_Braille("Red", "#F7322F", "#F7322F")) #, openscad_colours)) colour_themes.append(Colour_Theme_Character_Braille("Black", "Black", "#17202A")) #, openscad_colours)) colour_themes.append(Colour_Theme_Character_Braille("White", "White", "White")) #, openscad_colours)) return colour_themes # , columns=['Name', 'Colour Top', 'Colour base']) # Colour_Theme_Character_Braille.__name__]) # colour_themes def get_defaults_DataFrame(): return pd.DataFrame(data={Colour_Theme_Character_Braille.__name__: Colour_Theme_Character_Braille.get_defaults()}) # , columns=['Name', 'Colour Top', 'Colour base']) # Colour_Theme_Character_Braille.__name__]) # colour_themes def get_default(): colours_default = Colour_Theme_Character_Braille.get_defaults_DataFrame() return colours_default[Colour_Theme_Character_Braille.__name__].apply(lambda x: x if x.name == 'Blue' else None).dropna()[0] """ def input_from_console(): colour_themes = Colour_Theme_Character_Braille.get_defaults() count_colours = len(colour_themes) colour_table = PrettyTable() colour_table.field_names = ['index', 'name', 'colour top', 'colour base'] for col_i in range(count_colours): colour_table.add_row([col_i + 1] + colour_themes[col_i].as_row()) print() print("Please select colour theme from below:") print(colour_table) while True: colour_input = input("Colour theme (name or index): ") print(str(colour_input) + " selected") if colour_input == "#!ERRORCODE!#": exit for i_colour in range(count_colours): if colour_input == colour_themes[i_colour].name: return colour_themes[i_colour] """ def get_list_headings(): return ['name', 'colour top', 'colour base']