Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring to improved readibility #132

Merged
merged 31 commits into from
Nov 13, 2020
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f2fad9b
Removed `Config.TRUE` and `Config.FALSE` in favor of booleans
noliveleger Nov 4, 2020
d31f583
Sort alphabetically properties of the configuration template
noliveleger Nov 4, 2020
f04ded2
Added missing default properties in configuration template
noliveleger Nov 4, 2020
1824a14
Updated unit tests to support boolean instead of "Config.TRUE" and "C…
noliveleger Nov 4, 2020
b2ec9ce
Created a utility to print frame messages
noliveleger Nov 4, 2020
9ac0271
Replaced `== True/False` with `is True/False`
noliveleger Nov 4, 2020
6d09e62
Refactored private property `__config` of `Config` to `__dict` for
noliveleger Nov 5, 2020
d00a3e1
Replaced framed message with framed_print everywhere it was missing
noliveleger Nov 5, 2020
6ae7633
fixed: bad search/replace of "config" and "config_object" in template.py
noliveleger Nov 5, 2020
8d8767a
Moved configuration upgrade code to `helpers.upgrading.Upgrading`
noliveleger Nov 5, 2020
35d5991
fixed: unit tests and wrong `Config.get_dict()` call in `Setup()` class
noliveleger Nov 5, 2020
b4da7d7
Use word kobo-install everywhere (instead of KoBoInstall)
noliveleger Nov 5, 2020
c5c2b19
Changes in `CLI` class:
noliveleger Nov 5, 2020
faaf408
Use new Yes/No method of CLI class
noliveleger Nov 5, 2020
52db145
fixed typo
noliveleger Nov 5, 2020
9175b44
Use different colors for questions and defaults (than error, warning,…
noliveleger Nov 5, 2020
0c0f5de
Display a better message when PostgreSQL settings customization fails
noliveleger Nov 5, 2020
6dda975
Revert to double-quoted string passed to shell
noliveleger Nov 5, 2020
1b2bed7
Access properties of `Config.__dict` directly if present in
noliveleger Nov 6, 2020
e61f24e
fixed: Single database name is not copied to KC database
noliveleger Nov 6, 2020
c6584e7
network.py: Wrap lines to 80 characters per line
noliveleger Nov 6, 2020
4d79677
Misc. changes
noliveleger Nov 6, 2020
0c4a69f
Added missing property to configuration template
noliveleger Nov 6, 2020
9ca27b7
fixed typo
noliveleger Nov 6, 2020
165405c
Changed default value display: force [] even if value is empty.
noliveleger Nov 6, 2020
a945dc8
fixed: PostgreSQL Backup on secondary back-end server always on when …
noliveleger Nov 6, 2020
4fc140b
fixed: mock_open always return the config template
noliveleger Nov 10, 2020
f241dc0
fixed: Setup cannot run on fresh installed
noliveleger Nov 10, 2020
092c48e
Applied requested changes for PR#132
noliveleger Nov 12, 2020
52c1c5b
Always give the possibility to see the changes in `/etc/hosts`
noliveleger Nov 12, 2020
782cf5e
Fixed: exit setup when user chooses to overwrite kobo-env
noliveleger Nov 13, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# coding: utf-8
import os
import pytest

# Python retro compatibility
try:
FileNotFoundError
except NameError:
FileNotFoundError = OSError


def clean_up():
"""
Removes files created by tests
"""
files = ['.uniqid',
'upsert_db_users']
for file_ in files:
try:
os.remove(os.path.join('/tmp', file_))
except FileNotFoundError:
pass


@pytest.fixture(scope="session", autouse=True)
def setup(request):
# Clean up before tests begin in case of orphan files.
clean_up()
request.addfinalizer(_tear_down)


def _tear_down():
clean_up()
pass
134 changes: 103 additions & 31 deletions helpers/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import sys
import re
import textwrap

PY2 = sys.version_info[0] == 2
if PY2:
Expand All @@ -14,28 +15,100 @@


class CLI(object):
NO_COLOR = '\033[0m'
COLOR_ERROR = '\033[91m'
COLOR_SUCCESS = '\033[92m'
COLOR_INFO = '\033[94m'
COLOR_WARNING = '\033[95m'

NO_COLOR = '\033[0;0m'
COLOR_ERROR = '\033[0;31m' # dark red
COLOR_SUCCESS = '\033[0;32m' # dark green
COLOR_INFO = '\033[1;34m' # blue
COLOR_WARNING = '\033[1;31m' # red
COLOR_QUESTION = '\033[1;33m' # dark yellow
COLOR_DEFAULT = '\033[1;37m' # white

EMPTY_CHARACTER = '-'

DEFAULT_CHOICES = {
'1': True,
'2': False,
}
DEFAULT_RESPONSES = dict((v, k) for k, v in DEFAULT_CHOICES.items())
joshuaberetta marked this conversation as resolved.
Show resolved Hide resolved

@classmethod
def colored_input(cls, message, color=NO_COLOR, default=None):
text = cls.get_message_with_default(message, default)
input_ = input(cls.colorize(text, color))

# User wants to delete value previously entered.
if input_ == '-':
default = ''
input_ = ''

return input_ if input_ is not None and input_ != '' else default

@classmethod
def colored_print(cls, message, color=NO_COLOR):
print(cls.colorize(message, color))

@classmethod
def colorize(cls, message, color=NO_COLOR):
return '{}{}{}'.format(color, message, cls.NO_COLOR)

@classmethod
def framed_print(cls, message, color=COLOR_WARNING, columns=70):
border = '═' * (columns - 2)
framed_message = [
'╔{}╗'.format(border),
'║ {} ║'.format(' ' * (columns - 4)),
]

if not isinstance(message, list):
paragraphs = message.split('\n')
else:
paragraphs = ''.join(message).split('\n')

for paragraph in paragraphs:
if paragraph == '':
framed_message.append(
'║ {} ║'.format(' ' * (columns - 4))
)
continue

for line in textwrap.wrap(paragraph, columns - 4):
message_length = len(line)
spacer = ' ' * (columns - 4 - message_length)
framed_message.append(
'║ {}{} ║'.format(line, spacer)
)

framed_message.append('║ {} ║'.format(' ' * (columns - 4)))
framed_message.append('╚{}╝'.format(border))
cls.colored_print('\n'.join(framed_message), color=color)

@classmethod
def get_response(cls, validators=None, default='', to_lower=True,
error_msg="Sorry, I didn't understand that!"):

use_default = False
# If not validators are provided, let's use default validation
# "Yes/No", where "Yes" equals 1, and "No" equals 2
# Example:
# Are you sure?
# 1) Yes
# 2) No
if validators is None:
use_default = True
default = cls.DEFAULT_RESPONSES[default]
validators = cls.DEFAULT_CHOICES.keys()

while True:
try:
response = cls.colored_input('', cls.COLOR_WARNING, default)
response = cls.colored_input('', cls.COLOR_QUESTION, default)

if (response.lower() in map(lambda x: x.lower(), validators) or
validators is None or
(isinstance(validators, string_type) and
validators.startswith('~') and
re.match(validators[1:], response)
)):
)):
break
else:
cls.colored_print(error_msg,
Expand All @@ -44,35 +117,23 @@ def get_response(cls, validators=None, default='', to_lower=True,
cls.colored_print("Sorry, I didn't understand that.",
cls.COLOR_ERROR)

return response.lower() if to_lower else response

@classmethod
def colored_print(cls, message, color=NO_COLOR):
print(cls.colorize(message, color))

@classmethod
def colored_input(cls, message, color=NO_COLOR, default=None):
text = cls.get_message_with_default(message, default)
input_ = input(cls.colorize(text, color))

# User wants to delete value previously entered.
if input_ == '-':
default = ''
input_ = ''

return input_ if input_ is not None and input_ != '' else default
if use_default:
return cls.DEFAULT_CHOICES[response]

@classmethod
def colorize(cls, message, color=NO_COLOR):
return '{}{}{}'.format(color, message, cls.NO_COLOR)
return response.lower() if to_lower else response

@classmethod
def get_message_with_default(cls, message, default):
message = '{} '.format(message) if message else ''
default = '{}[{}]{}: '.format(cls.COLOR_WARNING,
default,
cls.NO_COLOR) \
if default else ''

if default is None:
default = ''
else:
default = '{white}[{off}{default}{white}]{off}: '.format(
white=cls.COLOR_DEFAULT,
off=cls.NO_COLOR,
default=default
)

if message:
message = '{}: '.format(message.strip()) if not default else message
Expand Down Expand Up @@ -106,3 +167,14 @@ def run_command(cls, command, cwd=None, polling=False):
cls.colored_print('An error has occurred', CLI.COLOR_ERROR)
sys.exit(1)
return stdout

@classmethod
def yes_no_question(cls, question, default=True,
labels=['Yes', 'No']):
cls.colored_print(question, color=cls.COLOR_QUESTION)
for index, label in enumerate(labels):
cls.colored_print('\t{index}) {label}'.format(
index=index + 1,
label=label
))
return cls.get_response(default=default)
Loading