210 lines
8.2 KiB
Python
210 lines
8.2 KiB
Python
# -*- 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, "<class 'str'>", 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'] |