Note that I think I accidentally pushed the file I didn't intend here and I
will remove it later. This shouldn't be a huge deal as it was just an error
trace log. This program is definitely not very robust at this point it is just
designed to make adding tips for the tip of the day out on a tiny bit easier
for me so I don't have to type out Json manually.
Sent from my heavily encrypted iPhone.
Please disregard errors as this is a smaller device.
On Apr 1, 2016, at 11:47, commits-noreply@xxxxxxxxxxxxx wrote:
1 new commit in tip_of_the_day:
https://bitbucket.org/nvdaaddonteam/tip_of_the_day/commits/5e62732fb648/ ;
Changeset: 5e62732fb648 Branch: master User: derekriemer Date: 2016-04-01
17:47:29+00:00 Summary: basic command line program to make adding tips more
sane. Uses my easy ui framework.
Affected #: 5 files
diff --git a/a.txt b/a.txt deleted file mode 100644 index f971240..0000000
--- a/a.txt +++ /dev/null @@ -1,113 +0,0 @@ -EEEEEE
-======================================================================
-ERROR: test_app_exists (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
-======================================================================
-ERROR: test_app_is_correct (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
-======================================================================
-ERROR: test_get_invalid_tip_name_is_None (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
-======================================================================
-ERROR: test_iterateTips (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
-======================================================================
-ERROR: test_malformedJson (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
-======================================================================
-ERROR: test_non_existant_file (test_TipsReader.TipsTester)
-----------------------------------------------------------------------
-Traceback (most recent call last):
File “C:\Users\derek_2\Google Drive\tip_of_the_day\tests\test_TipsReader.py”,
line 11, in setUp
self.t1 = Tips(os.path.join(os.path.dirname(__file__), “assetts”, "t1.json"))
File “globalPlugins\tipsReader.py”, line 13, in _init_
self.tipsDict = j = json.load(tipsFile)
File “C:\Python27\lib\json\__init__.py”, line 290, in load
**kw)
File “C:\Python27\lib\json\__init__.py”, line 338, in loads
return _default_decoder.decode(s)
File “C:\Python27\lib\json\decoder.py”, line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “C:\Python27\lib\json\decoder.py”, line 382, in raw_decode
obj, end = self.scan_once(s, idx)
-ValueError: Expecting property name: line 14 column 13 (char 341) –
----------------------------------------------------------------------- -Ran
6 tests in 0.015s – -FAILED (errors=6)
diff --git a/easy_ui/__init__.py b/easy_ui/__init__.py new file mode 100644
index 0000000..6424e6d --- /dev/null +++ b/easy_ui/__init__.py @@ -0,0 +1,90
@@ +from _future_ import print_function +from genericValidators import *
+from sys import version + +#monkeypatch python 2's stupid builtin input
function to replace it with something safe. +if version[0] == “2”: +
input = raw_input + + + +class Ui: + def initialize_menu(self): +
print("{options:^40}\n\n".format(options="options:")) +
print("{index:<10}{item:>10}".format(item="exit", index=0)) + + for index,
item in enumerate(self.funcDict.keys()): +
print("{index:<10}{item:>10}".format(item=item, index=index+1)) +
self.max=len(list(self.funcDict.keys())) + + def getraw_input(self): +
while True: + try: + self.choice=int(input("enter your choice")) + if
self.choice>self.max or self.choice < 0: + raise ValueError(&q uot;Value
too large") + break + except KeyboardInterrupt as
e: + exit() + except ValueError as e: +
if str(e)=="Value too large": + print("item not in the menu.") +
else: + print("That was a bad option you gave me.\nEnter one of the numbers
above.") + self.initialize_menu() + continue + if 0 == self.choice: +
print("Good Bye, Exiting program.") + exit() + + + def callIt(self): +
option=list(self.funcDict.values())[self.choice-1] # get the 3-toople. + #an
option is a toople of the function, and then a toople of 2-tooples with items
in the form of (type, prompt) + args=[] + for theType, toPrint in
option[1:]: + while True: + print("{:^20}".format(toPrint)) +
#types provided by the class to make life easier. + #This is a map of
genaric types, or miscellaneous types, and their respective built-in helper.
If the python type is the same as the builtin type to map on then just put
the s ame thing on both sides of the mapping. + #To get at the actual
type that we should have, a self.validated variable should be provided with
what we want to actually give the function. See the YesNo typeclass for an
example. + inMap = False # if it is in the map we set this to True. +
self.validators.update({ + bool : YesNo, + TrueBool : TrueBool + } ) + if
theType in self.validators: + inMap = True + theOldType = theType + theType
= self.validators[theOldType] + try: + that = theType(str(input())) + if
inMap: + args.append(that.validated) + else: + args.append(that) +
break + except ValueError: + print("{:^20}".format("bad option? Try
entering that again.")) + option[0](*args) #call it with our just
built list of arguements. + + + def __init__(self, funcDict, validators = {},
once = True): + self.funcDict=funcDict + self.validators = validators +
loop=True + while loop: + self.initializ e_menu() + loop=once +
self.getraw_input() + self.callIt() #choice is passed in on self.choice
so we don't need to send it in here. + + + + + + + + + +
diff --git a/easy_ui/genericValidators.py b/easy_ui/genericValidators.py new
file mode 100644 index 0000000..1ffe48b --- /dev/null +++
b/easy_ui/genericValidators.py @@ -0,0 +1,40 @@ +class
GenericValueMap(object): + """A generic user input validator. To
implement your own custom behavior for validating user input before functions
get called, you should subclass this as it handles some things with the ui
manager. """ + def __init__(self, n): + """ The user need not worry
about the details of the constructor. If you wish to write your own
constructor, the burden of correctly interfacing with the ui manager is up to
you. """ + if self._validate(n): + return + else: #Erronious
input. + raise ValueError("Bad option") + + def _validate(self,
n): + """ This function receives an input n (of type str) which is
unsanitized and unvalidated. The job of the validator is to set
self.validated to n' whe re n' is the value (in python) that should be passed
to the callable by the ui manager. + @n: String of raw user input. +
@returns: True/false. True on success of setting self.validated, and False on
failure. Note that False represents user error. + """ + raise
NotImplementedError + + +class YesNo(GenericValueMap): + def _validate(self,
n): + n=n.lower() + if n=="y" or n=="yes": + self.validated =
True + elif n=="n" or n=="no": + self.validated = False + else: + return
False #Error on the users part. + return True #success. + +class
TrueBool(GenericValueMap): #A boolean like on a test. + def _validate(self,
n): + n = n.lower() + if n == “true”: + self.validated = True +
return True + elif n == “false”: + self.validated = False +
return True + else: + return False +
diff --git a/tip_creator.py b/tip_creator.py new file mode 100644 index
0000000..cc94c75 --- /dev/null +++ b/tip_creator.py @@ -0,0 +1,51 @@ +import
collections +import json +import easy_ui + +def save(): + with
open("tips.json", “w”) as f: + json.dump(tips, f, separators = (",", " :
“), indent=4) + +def list(): + for i in tips["tips"].keys(): + print i
+ + +def add(title, level, description): + if title in tips["tips"]: +
print “you already added this tip.” + return + tip = {} + if
level not in xrange(1,7): + print “bad level.” + return +
tip["level”] = [ + ["beginner"], + ["intermediate"], + ["advanced"],
+ ["beginner", “intermediate"], + ["intermediate”, “advanced"], +
["beginner”, “intermediate”, “advanced”] + ][level-1] +
tip["description"] = descripti on + tips["tips"][title] = tip + +ui = { +
“List Tips” : ( + list, + ), + “Add a Tip” : ( + add, +
(str, “Type your Title",), + (int, “1 for beginner, 2 for
intermediate, 3 for advanced, 4 for beginner and intermediate, 5 for
intermediate and advanced, or 6 for all three.",), + (str, "the tip, \n
makes a new line.",), + ), + "Save” : ( + save, + ) +} + +with
open("tips.json”) as tipsFile: + tips = json.load(tipsFile,
object_pairs_hook=collections.OrderedDict) +easy_ui.Ui(ui) #runs the ui
asking the user what they want. +
diff --git a/tips.json b/tips.json index 54929ed..888f81b 100644 ---
a/tips.json +++ b/tips.json @@ -1,14 +1,38 @@
{
"type" : "app",
“appname” : “winword”,
+ “appname” : “None”,
"tips" : {
“using word”: {
“level” : ["beginner"],
“description”: “fish”
+ “The NVDA Key” : { + “description” : “The NVDA key is either the insert,
extended insert, or caps lock key.\nTo use the NVDA key, you should configure
NVDA to use a key. By default, the NVDA key is set to the two insert keys.
The key that is long and skinny on the number pad is the insert key. Also,
the extended insert key is probably towards the top row of keys. To set your
NVDA keys, open the keyboard settings dialog with the NVDA key and the letter
n, and then find keyboard settings in the general settings menu.” + “level” :
[ + “beginner”, + “intermediate”, + “advanced” + ],
},
“words famous gripe” : {
“level” : ["beginner"],
“description” : “bad”
+ “Accessing the NVDA Menu.” : { + “level” : [ + “beginner”, +
“intermediate”, + “advanced” + ], + “description” : “To access the NVDA menu,
you should be able to press the NVDA key, and the letter N at the same time.”
+ }, + “Getting help” : { + “description” : “To find help, use the NVDA key
and N (open the NVDA menu), then go to help. There is a users guide and quick
key reference sheet.”, + “level” : [ + “beginner”, + “intermediate”, +
“advanced” + ] + }, + “Preferences” : { + “description” : “To customize NVDA,
use the NVDA key and N to open the NVDA menu, and then open the preferenc es
sub-menu. Then press enter on the preferences you want to change and make the
changes.”, + “level” : [ + “beginner”, + “intermediate”, + “advanced” + ]
}
}
}
\ No newline at end of file
Repository URL: https://bitbucket.org/nvdaaddonteam/tip_of_the_day/
—
This is a commit notification from bitbucket.org. You are receiving this
because you have the service enabled, addressing the recipient of this email.