Skip to content

Commit

Permalink
Updated docs, can now specify title in dict to be passed to meny.menu…
Browse files Browse the repository at this point in the history
…, refactor
  • Loading branch information
Napam committed Oct 17, 2021
1 parent a679a58 commit a549a91
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 222 deletions.
245 changes: 126 additions & 119 deletions README.md

Large diffs are not rendered by default.

85 changes: 37 additions & 48 deletions example/cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,37 @@
Each case should be a function.
The ordering of the cases in the console interface
will be by the function names. So a() will be
first then b() etc.
will be by the function definition orders.
Name of cases in console interface will be first line of
docstring
Name of cases in menu interface will be the function names by default. One can specify alternative
titles by using the meny.case decorator
Feel free to import whatever
If you want to implement nested cases, then simply import
reuse the main function
If you want to implement nested cases, then simply reuse the main function
Example
--------
from meny import menu
then you can either create another module with the nested
cases:
# Then you can either create another module with the nested cases:
menu(consolecases_nested, title= ' Title here ').
import cases_nested
menu(cases_nested, title= ' Title here ').
or you can give a list functions:
def case3():
def subcase1():
'''docstring1'''
pass
def subcase2():
'''docstring'''
pass
menu([subcase1, subcase2], title= ' Title here ')
meny.menu([subcase1, subcase2], title= ' Title here ')
"""

from functools import wraps
from time import sleep

import meny
Expand All @@ -44,17 +42,8 @@ def subcase2():

meny.set_default_frontend("fancy")

import time
@meny.ignore
def wait(func):
@wraps(func)
def wrapper(*args, **kwargs):
func(*args, **kwargs)
time.sleep(0.5)
return wrapper

@wait
@meny.case("FizzBuzz!")

@meny.title("FizzBuzz!")
def fizzbuzz(n: int = 10, waittime: float = 0.1):
"""
When you get the urge to fizz your buzz
Expand All @@ -75,78 +64,77 @@ def fizzbuzz(n: int = 10, waittime: float = 0.1):

print(stringy)
sleep(waittime)
sleep(1)


@wait
@meny.case("Append two strings")
@meny.title("Append two strings")
def appendstrings(a: str, b: str):
print(a + b)
sleep(1)


@meny.case("A nested module menu")
@meny.title("A nested module menu")
def nestedmodulemenu():
"""
This nested menu loads cases from a module
"""
menu(cases_nested, title=" Nested! ")
meny.menu(cases_nested, title=" Nested! ")


@meny.case("Math menu")
@meny.title("Math menu")
def mathmenu():
"""
This nested menu gets the cases from a user defined list.
"""

@wait
@meny.case("Multiply two floats")
@meny.title("Multiply two floats")
def multiply(x: float, y: float):
print(x * y)
sleep(1)

@wait
@meny.case("Divide two floats")
@meny.title("Divide two floats")
def divide(x: float, y: float):
if y == 0:
print("You can't divide by zero!!!")
return

print(x / y)
sleep(1)

menu(locals(), title=" Quick maths ")
meny.menu(locals(), title=" Quick maths ")


@wait
@meny.case("Even another nested menu")
@meny.title("Even another nested menu")
def anothernested():
"""
This menu obtains the nested case functions by
sending the return value of locals() into menu()
sending the return value of locals() into meny.menu()
"""

@wait
@meny.case("Print triangle")
@meny.title("Print triangle")
def triangle():
for j in range(10):
print("*" * j)
sleep(1)


@wait
@meny.case("Print rectangle")
@meny.title("Print rectangle")
def rectangle():
for i in range(10):
print("#" * 10)
sleep(1)


@wait
@meny.case("Print list")
@meny.title("Print list")
def printlist(a: list):
print(a)
sleep(1)

menu(locals(), title=" Shapes ")
meny.menu(locals(), title=" Shapes ")

@wait
@meny.case("Programmatic arguments")
@meny.title("Programmatic arguments")
def programmatic(a, b, c, d):
print(a, b, c, 4)
sleep(1)


def just_function_name(arg: str = "Hello World"):
Expand All @@ -155,9 +143,10 @@ def just_function_name(arg: str = "Hello World"):
print("Press enter to return")
input()

@wait

def simple_func(a=1, b: str="2", c=3.0):
print(a, b, c)
sleep(1)


if __name__ == "__main__":
Expand Down
51 changes: 51 additions & 0 deletions example/readme_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from random import randint
from time import sleep
import meny

meny.set_default_frontend("simple")

@meny.title("FizzBuzz!")
def fizzbuzz():
for i in range(21):
stringy = ''

fizz = i % 3 == 0
buzz = i % 5 == 0

if fizz:
stringy = stringy + 'Fizz'
if buzz:
stringy = stringy + 'Buzz'
if not (fizz or buzz):
stringy = i

print(stringy)
sleep(0.1)

@meny.title("Get random integer")
def random_integer():
print(randint(0,9))
sleep(1)

def add_ints(a, b):
print(a+b)
sleep(1)

def append_strings(a, b):
print(a+b)
sleep(1)

# Type hints won't interfere with meny, and will actually be displayed when using the fancy frontend
@meny.title("Print elements and their types")
def print_types_in_list(a: list):
[print(f'Element {i}: {elem}, type: {type(elem)}') for i, elem in enumerate(a)]
sleep(1)


def programmatic_args(a, b, c, d):
print(a, b, c, d)
sleep(1)

case_args = {programmatic_args: (1, 2)}
case_kwargs = {programmatic_args: {"d": 4, "c": 3}}
meny.menu(locals(), title=' Main menu ', case_args=case_args, case_kwargs=case_kwargs)
4 changes: 2 additions & 2 deletions meny/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .menu import cng as config
from .menu import menu, Menu
from .decorators import case, ignore
from .utils import clear_screen, input_splitter, list_local_cases, set_default_frontend
from .decorators import title, ignore
from .utils import clear_screen, input_splitter, set_default_frontend
5 changes: 3 additions & 2 deletions meny/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
DEFAULT_ON_INTERRUPT = "raise"
DEFAULT_ON_BLANK = "return"
DEFAULT_FRONTEND = "auto"
_CASE_TITLE = "__case_title__"
_CASE_IGNORE = "__case_ignore__"
_CASE_TITLE = "__meny_title__"
_CASE_IGNORE = "__meny_ignore__"
_DICT_KEY = "__meny_key_from_input_dict__"
6 changes: 3 additions & 3 deletions meny/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from meny.config import _CASE_IGNORE, _CASE_TITLE


def case(title: str):
def title(title: str):
"""
Sets case title
"""
Expand All @@ -28,11 +28,11 @@ def ignore(func: FunctionType):

if __name__ == "__main__":

@case("Catdog")
@title("Catdog")
def testFunc1() -> str:
pass

@case("Catdog1")
@title("Catdog1")
def testFunc2() -> str:
pass

Expand Down
19 changes: 10 additions & 9 deletions meny/funcmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from types import FunctionType
from typing import Callable, Dict, Iterable, Optional, Tuple

from meny.config import _CASE_TITLE
from meny.config import _CASE_TITLE, _DICT_KEY


def _get_case_name(func: FunctionType) -> str:
Expand All @@ -18,13 +18,12 @@ def _get_case_name(func: FunctionType) -> str:
__wrapped__ attribute (which will be handled by using functools.wraps). Then returns case
title if set, else just function name
"""
# Unwrap in case the function is wrapped
func = unwrap(func)

if _CASE_TITLE in func.__dict__:
return func.__dict__[_CASE_TITLE]
else:
return func.__name__
funcvars = vars(unwrap(func))
return (
funcvars.get(_CASE_TITLE, False)
or funcvars.get(_DICT_KEY, False)
or func.__name__
)


def construct_funcmap(
Expand Down Expand Up @@ -61,4 +60,6 @@ def construct_funcmap(


if __name__ == "__main__":
pass
import subprocess

subprocess.call(["python3", "example/cases.py"])
Loading

0 comments on commit a549a91

Please sign in to comment.