Skip to main content
added 1 character in body
Source Link
Peilonrayz
  • 44.6k
  • 7
  • 80
  • 158

Other commandcommands left for you to implement

Other command left for you to implement

Other commands left for you to implement

Source Link
Peilonrayz
  • 44.6k
  • 7
  • 80
  • 158

The first thing I notice with your code is that the code is a very long global script. To resolve this I'd start by moving your code into functions.

The actual calculations could be as simple as say:

def add(arg1, arg2):
    print(float(arg1) + float(arg2))

To then get the help information we could add a docstring.

def add(arg1, arg2):
    """
    Add:
     Description: Adds 2 numbers
     Syntax: add [num1] [num2]
    """
    print(float(arg1) + float(arg2))

We can get both the docstring and the output of the operation with Python. To get the docstring to be nicely formatted we can use textwrap.dedent.

>>> add("10", "5")
15.0
>>> import textwrap
>>> textwrap.dedent(add.__doc__.strip("\n"))
Add:
 Description: Adds 2 numbers
 Syntax: add [num1] [num2]

To then reduce the amount of lines of code we can bundle all these functions into a dictionary. And just index the dictionary to get a specific function.

COMMANDS = {
    "add": add,
    "sub": sub,
    # ...
}

fn = COMMANDS["add"]
fn("10", "5")
15.0

Whilst you can build the dictionary and execute the commands yourself, you could instead subclass cmd.Cmd. You will need to change the functions slightly to only take a string as input, and prefix do_ to any commands available to the commandline.

import cmd


class PyCMD(cmd.Cmd):
    intro = 'Welcome to pyCMD, user\nStarting command line, use "help" for help'
    prompt = ": "

    def do_add(self, arg):
        """
        Add:
         Description: Adds 2 numbers
         Syntax: add [num1] [num2]
        """
        arg1, arg2 = arg.split()
        print(float(arg1) + float(arg2))

PyCMD().cmdloop()
Welcome to pyCMD, user
Starting command line, use "help" for help
: help

Documented commands (type help <topic>):
========================================
add  help

: help add

        Add:
         Description: Adds 2 numbers
         Syntax: add [num1] [num2]
        
: add 10 5
15.0

The help is clearly a bit on the broken side. To fix this we can change the docstring after the function.

class PyCMD(cmd.Cmd):
    def do_add(self, arg):
        # ...

    do_add.__doc__ = textwrap.dedent(do_add.__doc__.rstrip(" ").strip("\n"))

This is a bit ugly and doing this for each function would be horrible. So we can create a function to do this.

def clean_doc(fn):
    fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))


class PyCMD(cmd.Cmd):
    def do_add(self, arg):
        # ...

    clean_doc(do_add)

This is still a bit on the ugly side so we can use @ to do this for us. This is called a decorator. This makes sense because we're decorating how __doc__ is seen. Note that we changed clean_doc to return fn.

def clean_doc(fn):
    fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))
    return fn


class PyCMD(cmd.Cmd):
    @clean_doc
    def do_add(self, arg):
        # ...

We can add another function like clean_doc, but this time make it a closure if you want to easily add your validation of two arguments.

import functools


def command(fn):
    @functools.wraps(fn)
    def wrapper(self, arg):
        args = [token for token in arg.split()]
        try:
            arg1, arg2 = args
        except ValueError:
            print('Too many or too little args, 2 args required, if you want to not use an arg, use a "."')
        else:
            return fn(self, arg1, arg2)
    return wrapper


class PyCMD(cmd.Cmd):
    @command
    @clean_doc
    def do_add(self, arg1, arg2):
        """
        Add:
         Description: Adds 2 numbers
         Syntax: add [num1] [num2]
        """
        print(float(arg1) + float(arg2))

import cmd
import textwrap
import functools


def command(fn):
    @functools.wraps(fn)
    def wrapper(self, arg):
        try:
            arg1, arg2 = arg.split()
        except ValueError:
            print('Too many or too little args, 2 args required, if you want to not use an arg, use a "."')
        else:
            return fn(self, arg1, arg2)
    return wrapper


def clean_doc(fn):
    fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))
    return fn


class PyCMD(cmd.Cmd):
    intro = 'Welcome to pyCMD, user\nStarting command line, use "help" for help'
    prompt = ": "

    @command
    @clean_doc
    def do_add(self, arg1, arg2):
        """
        Add:
         Description: Adds 2 numbers
         Syntax: add [num1] [num2]
        """
        print(float(arg1) + float(arg2))


PyCMD().cmdloop()
Welcome to pyCMD, user
Starting command line, use "help" for help
: help

Documented commands (type help <topic>):
========================================
add  help

: help add
Add:
 Description: Adds 2 numbers
 Syntax: add [num1] [num2]
: add 10 5
15.0

Other command left for you to implement