From 611077359f865ef963d5ca51f458bb48100c27fd Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 17 Aug 2020 16:06:32 +0800 Subject: [PATCH 01/22] add test --- create-with-arg.py | 40 ++++++++++++++++++++++++++++++++++++++++ test/args_kwargs.py | 13 +++++++++++++ 2 files changed, 53 insertions(+) create mode 100755 create-with-arg.py create mode 100644 test/args_kwargs.py diff --git a/create-with-arg.py b/create-with-arg.py new file mode 100755 index 0000000..be1d006 --- /dev/null +++ b/create-with-arg.py @@ -0,0 +1,40 @@ +import sys,os + +print(sys.argv) + + +def main(): + l = sys.argv[1].split("/") + alist = [ + [ + l[-1].upper(), + l[-1], + ','+sys.argv[2] if len(sys.argv)>=3 else '' + ] + ] + dirName = '/'.join(l[:-1]) + # Create target directory & all intermediate directories if don't exists + try: + print("Directory " , dirName , " Created ") + os.makedirs(dirName) + except FileExistsError: + print("Directory " , dirName , " already exists") + for item in alist: + f = open(sys.argv[1] + ".py", "w+") + # for i in range(10): + # f.write("This is line %d\r\n" % (i+1)) + content = """ +import unittest{2} +class TDD_{0}(unittest.TestCase): + def test_{1}(self): + +if __name__ == '__main__': + unittest.main() + + """ + f.write(content.format(item[0], item[1],item[2])) + f.close() + + +if __name__ == "__main__": + main() diff --git a/test/args_kwargs.py b/test/args_kwargs.py new file mode 100644 index 0000000..77dfddf --- /dev/null +++ b/test/args_kwargs.py @@ -0,0 +1,13 @@ + +import unittest +class TDD_ARGS_KWARGS(unittest.TestCase): + def test_args_kwargs(self): + def test_var_args(f_arg, *argv): + return f_arg,*argv + + arg=test_var_args('yasoob', 'python', 'eggs', 'test') + self.assertEqual(arg,('yasoob', 'python', 'eggs', 'test')) +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 69b9313ea661c05ae747f0cdb6660d0f6340b7a1 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 17 Aug 2020 17:05:17 +0800 Subject: [PATCH 02/22] *args **kwargs --- test/args_kwargs.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/test/args_kwargs.py b/test/args_kwargs.py index 77dfddf..391101c 100644 --- a/test/args_kwargs.py +++ b/test/args_kwargs.py @@ -1,13 +1,40 @@ - import unittest class TDD_ARGS_KWARGS(unittest.TestCase): def test_args_kwargs(self): def test_var_args(f_arg, *argv): return f_arg,*argv - arg=test_var_args('yasoob', 'python', 'eggs', 'test') - self.assertEqual(arg,('yasoob', 'python', 'eggs', 'test')) + self.assertEqual(arg, ('yasoob', 'python', 'eggs', 'test')) + def test_kwargs(self): + def greet_me(**kwargs): + l=[] + for key, value in kwargs.items(): + l.append("{0} = {1}".format(key, value)) + return l + self.assertEqual(greet_me(name="yasoob"),['name = yasoob']) + def test_call(self): + def test_args_kwargs(arg1, arg2, arg3): + return (arg1, arg2, arg3) + # first with *args + args = ("two", 3, 5) + self.assertIsInstance(args,tuple) + t=test_args_kwargs(*args) + self.assertEqual(t,args) + # now with **kwargs: + kwargs = {"arg3": 3, "arg2": "two", "arg1": 5} + self.assertIsInstance(kwargs,dict) + t1=test_args_kwargs(**kwargs) + self.assertCountEqual(t1, tuple(kwargs.values())) + t2=test_args_kwargs('two', *(3,), **{'arg3': 5}) + self.assertCountEqual(t2,args) + self.assertRaises(SyntaxError, lambda: eval("test_args_kwargs('two', **{'arg3': 5}, *(3,))")) + def test_monkey_patching(self): + class someclass(): + pass + def get_info(self, *args): + return "Test data" + someclass.get_info = get_info + ins = someclass() + self.assertEqual(ins.get_info(),'Test data') if __name__ == '__main__': unittest.main() - - \ No newline at end of file From bc0839a8b4d6901b6a75e0442d7949e2e77a7ee0 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 17 Aug 2020 20:02:05 +0800 Subject: [PATCH 03/22] debugging --- test/debugging.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/debugging.py diff --git a/test/debugging.py b/test/debugging.py new file mode 100644 index 0000000..dfdc695 --- /dev/null +++ b/test/debugging.py @@ -0,0 +1,21 @@ + +import unittest +class TDD_DEBUGGING(unittest.TestCase): + def test_stop_execution(self): + import subprocess + # subprocess.run(["ls", "-l"]) + subprocess.run("python3 -m pdb test/args_kwargs.py", shell=True) + def test_debugging(self): + + import pdb +# Set 'Whether to run code in integrated terminal' if in vscode. https://stackoverflow.com/a/54879495/2630686 + def make_bread(): + pdb.set_trace() + # Press letter c to continue when terminal focused + return "I don't have time" + + self.assertEqual(make_bread(),"I don't have time") +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 0f57409952e2b075b95d79e6f46cce8603a705b6 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 18 Aug 2020 08:22:33 +0800 Subject: [PATCH 04/22] generator --- .vscode/.ropeproject/config.py | 114 +++++++++++++++++++++++++++++++++ .vscode/settings.json | 3 + test/generators.py | 46 +++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 .vscode/.ropeproject/config.py create mode 100644 .vscode/settings.json create mode 100644 test/generators.py diff --git a/.vscode/.ropeproject/config.py b/.vscode/.ropeproject/config.py new file mode 100644 index 0000000..dee2d1a --- /dev/null +++ b/.vscode/.ropeproject/config.py @@ -0,0 +1,114 @@ +# The default ``config.py`` +# flake8: noqa + + +def set_prefs(prefs): + """This function is called before opening the project""" + + # Specify which files and folders to ignore in the project. + # Changes to ignored resources are not added to the history and + # VCSs. Also they are not returned in `Project.get_files()`. + # Note that ``?`` and ``*`` match all characters but slashes. + # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' + # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' + # '.svn': matches 'pkg/.svn' and all of its children + # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' + # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' + prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', + '.hg', '.svn', '_svn', '.git', '.tox'] + + # Specifies which files should be considered python files. It is + # useful when you have scripts inside your project. Only files + # ending with ``.py`` are considered to be python files by + # default. + # prefs['python_files'] = ['*.py'] + + # Custom source folders: By default rope searches the project + # for finding source folders (folders that should be searched + # for finding modules). You can add paths to that list. Note + # that rope guesses project source folders correctly most of the + # time; use this if you have any problems. + # The folders should be relative to project root and use '/' for + # separating folders regardless of the platform rope is running on. + # 'src/my_source_folder' for instance. + # prefs.add('source_folders', 'src') + + # You can extend python path for looking up modules + # prefs.add('python_path', '~/python/') + + # Should rope save object information or not. + prefs['save_objectdb'] = True + prefs['compress_objectdb'] = False + + # If `True`, rope analyzes each module when it is being saved. + prefs['automatic_soa'] = True + # The depth of calls to follow in static object analysis + prefs['soa_followed_calls'] = 0 + + # If `False` when running modules or unit tests "dynamic object + # analysis" is turned off. This makes them much faster. + prefs['perform_doa'] = True + + # Rope can check the validity of its object DB when running. + prefs['validate_objectdb'] = True + + # How many undos to hold? + prefs['max_history_items'] = 32 + + # Shows whether to save history across sessions. + prefs['save_history'] = True + prefs['compress_history'] = False + + # Set the number spaces used for indenting. According to + # :PEP:`8`, it is best to use 4 spaces. Since most of rope's + # unit-tests use 4 spaces it is more reliable, too. + prefs['indent_size'] = 4 + + # Builtin and c-extension modules that are allowed to be imported + # and inspected by rope. + prefs['extension_modules'] = [] + + # Add all standard c-extensions to extension_modules list. + prefs['import_dynload_stdmods'] = True + + # If `True` modules with syntax errors are considered to be empty. + # The default value is `False`; When `False` syntax errors raise + # `rope.base.exceptions.ModuleSyntaxError` exception. + prefs['ignore_syntax_errors'] = False + + # If `True`, rope ignores unresolvable imports. Otherwise, they + # appear in the importing namespace. + prefs['ignore_bad_imports'] = False + + # If `True`, rope will insert new module imports as + # `from import ` by default. + prefs['prefer_module_from_imports'] = False + + # If `True`, rope will transform a comma list of imports into + # multiple separate import statements when organizing + # imports. + prefs['split_imports'] = False + + # If `True`, rope will remove all top-level import statements and + # reinsert them at the top of the module when making changes. + prefs['pull_imports_to_top'] = True + + # If `True`, rope will sort imports alphabetically by module name instead + # of alphabetically by import statement, with from imports after normal + # imports. + prefs['sort_imports_alphabetically'] = False + + # Location of implementation of + # rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general + # case, you don't have to change this value, unless you're an rope expert. + # Change this value to inject you own implementations of interfaces + # listed in module rope.base.oi.type_hinting.providers.interfaces + # For example, you can add you own providers for Django Models, or disable + # the search type-hinting in a class hierarchy, etc. + prefs['type_hinting_factory'] = ( + 'rope.base.oi.type_hinting.factory.default_type_hinting_factory') + + +def project_opened(project): + """This function is called after opening the project""" + # Do whatever you like here! diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d5d660b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "restructuredtext.confPath": "${workspaceFolder}" +} \ No newline at end of file diff --git a/test/generators.py b/test/generators.py new file mode 100644 index 0000000..a83a0cc --- /dev/null +++ b/test/generators.py @@ -0,0 +1,46 @@ +import unittest +class TDD_GENERATORS(unittest.TestCase): + def test_generators(self): + def generator_function(): + for i in range(10): + yield i + l=[] + for item in generator_function(): + l.append(item) + self.assertEqual(l, list(range(10))) + def test_large_sets(self): + # generator version + def fibon(n): + a = b = 1 + for i in range(n): + yield a + a, b = b, a + b + g=fibon(1) + self.assertEqual(next(g),1) + self.assertRaises(StopIteration,lambda:next(g)) + g=fibon(4) + self.assertEqual(next(g),1) + self.assertEqual(next(g),1) + self.assertEqual(next(g),2) + self.assertEqual(next(g),3) + self.assertRaises(StopIteration,lambda:next(g)) + def test_next(self): + def generator_function(): + for i in range(3): + yield i + gen = generator_function() + self.assertEqual(next(gen),0) + self.assertEqual(next(gen),1) + self.assertEqual(next(gen),2) + self.assertRaises(StopIteration,lambda:next(gen)) + def test_err(self): + int_var = 1779 + self.assertRaises(TypeError,lambda:next(int_var)) + self.assertRaises(TypeError,lambda:iter(int_var)) + my_string = "Yasoob" + self.assertRaises(TypeError, lambda: next(my_string)) + my_iter = iter(my_string) + self.assertEqual(next(my_iter),'Y') + self.assertEqual(next(my_iter),'a') +if __name__ == '__main__': + unittest.main() From dcceecb94d5425aed02772babf070bef346266b6 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 18 Aug 2020 09:39:52 +0800 Subject: [PATCH 05/22] map filter reduce --- test/map_filter_reduce.py | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/map_filter_reduce.py diff --git a/test/map_filter_reduce.py b/test/map_filter_reduce.py new file mode 100644 index 0000000..5dc1e05 --- /dev/null +++ b/test/map_filter_reduce.py @@ -0,0 +1,41 @@ + +import unittest +class TDD_MAP_FILTER_REDUCE(unittest.TestCase): + def test_map_filter_reduce(self): + items = [1, 2, 3, 4, 5] + squared = [] + for i in items: + squared.append(i ** 2) + self.assertEqual(squared,[1,4,9,16,25]) + squared1 = list(map(lambda x: x**2, items)) + self.assertEqual(squared, squared1) + def multiply(x): + return (x*x) + def add(x): + return (x+x) + + funcs = [multiply, add] + value=[] + for i in range(5): + value .append( list(map(lambda x: x(i), funcs))) + self.assertEqual(value,[[0,0],[1,2],[4,4],[9,6],[16,8]]) + def test_filter(self): + number_list = range(-5, 5) + less_than_zero = list(filter(lambda x: x < 0, number_list)) + self.assertEqual(less_than_zero,[-5,-4,-3,-2,-1]) + def test_reduce(self): + product = 1 + list = [1, 2, 3, 4] + for num in list: + product=product * num + self.assertEqual(product, 24) + from functools import reduce + product1 = reduce((lambda x, y: x * y), [1, 2, 3, 4]) + self.assertEqual(product1,24) + product1 = reduce((lambda x, y: x * y), [ 3, 4]) + self.assertEqual(product1,12) + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From d1a37879efefbf61a8d89fec1d341d8e2a6ed229 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 18 Aug 2020 11:16:05 +0800 Subject: [PATCH 06/22] set data structure --- test/set_data_structure.py | 31 +++++++++++++++++++++++++++++++ test/ternary_operators.py | 9 +++++++++ 2 files changed, 40 insertions(+) create mode 100644 test/set_data_structure.py create mode 100644 test/ternary_operators.py diff --git a/test/set_data_structure.py b/test/set_data_structure.py new file mode 100644 index 0000000..00ad4af --- /dev/null +++ b/test/set_data_structure.py @@ -0,0 +1,31 @@ + +import unittest +class TDD_DATA_STRUCTURE(unittest.TestCase): + def test_set_data_structure(self): + some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n'] + + duplicates = [] + for value in some_list: + if some_list.count(value) > 1: + if value not in duplicates: + duplicates.append(value) + + self.assertEqual(duplicates, ['b', 'n']) + duplicates1 = list(set([x for x in some_list if some_list.count(x) > 1])) + self.assertCountEqual(duplicates1,duplicates) + def test_intersection(self): + valid = set(['yellow', 'red', 'blue', 'green', 'black']) + input_set = set(['red', 'brown']) + self.assertEqual(input_set.intersection(valid),{'red'}) + def test_difference(self): + valid = set(['yellow', 'red', 'blue', 'green', 'black']) + input_set = set(['red', 'brown']) + self.assertEqual(input_set.difference(valid),{'brown'}) + self.assertEqual(valid.difference(input_set),{'yellow','blue','green','black'}) + a_set = {'red', 'blue', 'green'} + self.assertIsInstance(a_set,set) + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file diff --git a/test/ternary_operators.py b/test/ternary_operators.py new file mode 100644 index 0000000..75288c9 --- /dev/null +++ b/test/ternary_operators.py @@ -0,0 +1,9 @@ + +import unittest +class TDD_TERNARY_OPERATORS(unittest.TestCase): + def test_ternary_operators(self): + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From c603b1e218772442fef88a4eaa662c2119b0867d Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 18 Aug 2020 15:35:13 +0800 Subject: [PATCH 07/22] decorators --- .vscode/.ropeproject/objectdb | Bin 0 -> 6 bytes .vscode/launch.json | 15 +++ func2.log | 25 ++++ out.log | 37 ++++++ out2.log | 17 +++ test/decorators.py | 225 ++++++++++++++++++++++++++++++++++ test/ternary_operators.py | 25 +++- 7 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 .vscode/.ropeproject/objectdb create mode 100644 .vscode/launch.json create mode 100644 func2.log create mode 100644 out.log create mode 100644 out2.log create mode 100644 test/decorators.py diff --git a/.vscode/.ropeproject/objectdb b/.vscode/.ropeproject/objectdb new file mode 100644 index 0000000000000000000000000000000000000000..0a47446c0ad231c193bdd44ff327ba2ab28bf3d8 GIT binary patch literal 6 NcmZo*sx4&D0{{kv0iOT> literal 0 HcmV?d00001 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..17e15f2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/func2.log b/func2.log new file mode 100644 index 0000000..74ffc75 --- /dev/null +++ b/func2.log @@ -0,0 +1,25 @@ +myfunc2 was called +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 +myfunc2 diff --git a/out.log b/out.log new file mode 100644 index 0000000..04de490 --- /dev/null +++ b/out.log @@ -0,0 +1,37 @@ +myfunc1 was called +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 +myfunc1 diff --git a/out2.log b/out2.log new file mode 100644 index 0000000..79c6a0b --- /dev/null +++ b/out2.log @@ -0,0 +1,17 @@ +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called +myfunc1 was called diff --git a/test/decorators.py b/test/decorators.py new file mode 100644 index 0000000..349bee4 --- /dev/null +++ b/test/decorators.py @@ -0,0 +1,225 @@ +import unittest,re +from functools import wraps +class TDD_DECORATORS(unittest.TestCase): + def test_decorators(self): + def hi(name="yasoob"): + return "hi " + name + self.assertEqual(hi(), 'hi yasoob') + # We can even assign a function to a variable like + greet = hi + self.assertEqual(greet, hi) + # We are not using parentheses here because we are not calling the function hi + # instead we are just putting it into the greet variable. Let's try to run this + self.assertEqual(greet(), 'hi yasoob') + # output: 'hi yasoob' + # Let's see what happens if we delete the old hi function! + del hi + self.assertRaises(NameError, lambda: hi()) + self.assertEqual(greet(), 'hi yasoob') + def test_inline_function(self): + def hi(name="yasoob"): + l = [] + l.append("hi() function start") + def greet(): + return "greet() function" + def welcome(): + return "welcome() function" + l.append(greet()) + l.append(welcome()) + l.append("hi() function end") + return l + self.assertEqual(' -> '.join(hi()), + 'hi() function start -> greet() function -> welcome() function -> hi() function end' + ) + # This shows that whenever you call hi(), greet() and welcome() + # are also called. However the greet() and welcome() functions + # are not available outside the hi() function e.g: + self.assertRaises(NameError, lambda: greet) + def test_return_inline_function(self): + def hi(name="yasoob"): + def greet(): + return "now you are in the greet() function" + def welcome(): + return "now you are in the welcome() function" + if name == "yasoob": + return greet + else: + return welcome + a = hi() + self.assertTrue(callable(a)) + # This clearly shows that `a` now points to the greet() function in hi() + # Now try this + self.assertEqual(a(), "now you are in the greet() function") + def test_give_argument(self): + def hi(): + return "hi yasoob!" + def doSomethingBeforeHi(func): + return ("I am doing some boring work before executing hi() ")+(func()) + self.assertEqual(doSomethingBeforeHi( + hi), "I am doing some boring work before executing hi() hi yasoob!") + def test_decorator(self): + def a_new_decorator(a_func): + def wrapTheFunction(): + l = [] + l.append("before executing a_func()") + l.append(a_func()) + l.append("after executing a_func()") + return l + return wrapTheFunction + def a_function_requiring_decoration(): + return ("needs some decoration") + self.assertEqual(a_function_requiring_decoration(), + 'needs some decoration') + a_function_requiring_decoration1 = a_new_decorator( + a_function_requiring_decoration) + s = 'before executing a_func() -> needs some decoration -> after executing a_func()' + self.assertEqual(' -> '.join(a_function_requiring_decoration1()), s) + @a_new_decorator + def a_function_requiring_decoration2(): + """Hey you! Decorate me!""" + return("needs some decoration") + self.assertEqual(' -> '.join(a_function_requiring_decoration2()),s) + # the @a_new_decorator is just a short way of saying: + a_function_requiring_decoration3 = a_new_decorator(a_function_requiring_decoration) + self.assertEqual(' -> '.join(a_function_requiring_decoration3()), s) + self.assertEqual(a_function_requiring_decoration.__name__,'a_function_requiring_decoration') + self.assertEqual(a_function_requiring_decoration3.__name__, 'wrapTheFunction') + def test_wraps(self): + def a_new_decorator(a_func): + @wraps(a_func) + def wrapTheFunction(): + l = [] + l.append("before executing a_func()") + l.append(a_func()) + l.append("after executing a_func()") + return l + return wrapTheFunction + @a_new_decorator + def a_function_requiring_decoration(): + """Hey yo! Decorate me!""" + print("needs some decoration") + self.assertEqual(a_function_requiring_decoration.__name__,'a_function_requiring_decoration') + def test_outer_variable(self): + def decorator_name(f): + @wraps(f) + def decorated(*args, **kwargs): + if not can_run: + return "Function will not run" + return f(*args, **kwargs) + return decorated + @decorator_name + def func(): + return("Function is running") + can_run = True + self.assertEqual(func(),"Function is running") + can_run = False + self.assertEqual(func(),"Function will not run") + def test_authorization(self): + class request(): + class Auth(): + username='' + password = '' + authorization = Auth + def authenticate(): + return 5 + def check_auth(name,pwd): + return False + def requires_auth(f): + @wraps(f) + def decorated(*args, **kwargs): + auth = request.authorization + n=0 + if not auth or not check_auth(auth.username, auth.password): + n=authenticate() + return f(n=n,*args, **kwargs) + return decorated + d = requires_auth(lambda x, y,three,n: n+x + y+three)(1, 2,three=6) + self.assertEqual(d, 5 + 1 + 2 + 6) + def test_logging(self): + def logit(func): + @wraps(func) + def with_logging(*args, **kwargs): + self.assertEqual(func.__name__ , 'addition_func') + return func(5,*args, **kwargs) + return with_logging + @logit + def addition_func(x,y): + """Do some math.""" + return x + y + result = addition_func(4) + self.assertEqual(result,4+5) + def test_nesting_decorator(self): + def logit(logfile='out.log'): + def logging_decorator(func): + @wraps(func) + def wrapped_function(*args, **kwargs): + log_string = func.__name__ + self.assertRegex(log_string,'myfunc1|myfunc2') + # Open the logfile and append + with open(logfile, 'a') as opened_file: + # Now we log to the specified logfile + opened_file.write(log_string + '\n') + return func(logfile,*args, **kwargs) + return wrapped_function + return logging_decorator + + @logit() + def myfunc1(fileName): + return fileName + + self.assertEqual(myfunc1(),'out.log') + # Output: myfunc1 was called + # A file called out.log now exists, with the above string + + @logit(logfile='func2.log') + def myfunc2(fileName): + return fileName + + self.assertEqual(myfunc2(),'func2.log') + def test_decorator_classes(self): + class logit(object): + + _logfile = 'out.log' + + def __init__(self, func): + self.func = func + + def __call__(self, *args): + log_string = self.func.__name__ + " was called" + # Open the logfile and append + with open(self._logfile, 'a') as opened_file: + # Now we log to the specified logfile + opened_file.write(log_string + '\n') + # Now, send a notification + self.notify() + + # return base func + return self.func(log_string,*args) + + + + def notify(self): + # logit only logs, no more + pass + logit._logfile = 'out2.log' # if change log file + @logit + def myfunc1(s): + return s + + self.assertEqual(myfunc1(),'myfunc1 was called') + class email_logit(logit): + ''' + A logit implementation for sending emails to admins + when the function is called. + ''' + def __init__(self, email='admin@myproject.com', *args, **kwargs): + self.email = email + super(email_logit, self).__init__(*args, **kwargs) + + def notify(self): + # Send an email to self.email + # Will not be implemented here + return self.email + self.assertEqual(email_logit(func=lambda x:x).notify(),'admin@myproject.com') +if __name__ == '__main__': + unittest.main() diff --git a/test/ternary_operators.py b/test/ternary_operators.py index 75288c9..39d3de6 100644 --- a/test/ternary_operators.py +++ b/test/ternary_operators.py @@ -2,7 +2,30 @@ import unittest class TDD_TERNARY_OPERATORS(unittest.TestCase): def test_ternary_operators(self): - + is_nice = True + state = "nice" if is_nice else "not nice" + self.assertEqual(state,'nice') + def test_bool(self): + nice = True + personality = ("mean", "nice")[nice] + self.assertEqual(personality,'nice') + personality1 = ( "nice","mean")[nice] + self.assertEqual(personality1, 'mean') + condition = True + self.assertEqual(2 if condition else 1/0,2) + self.assertRaises(ZeroDivisionError,lambda:(1/0, 2)[condition]) + def test_shorthand_ternary(self): + self.assertTrue(True or "Some") + self.assertEqual(False or "Some",'Some') + output = None + msg = output or "No data returned" + self.assertEqual(msg,'No data returned') + def test_default_parameter(self): + def my_function(real_name, optional_display_name=None): + optional_display_name = optional_display_name or real_name + return (optional_display_name) + self.assertEqual(my_function("John"),'John') + self.assertEqual(my_function("Mike", "anonymous123"),'anonymous123') if __name__ == '__main__': unittest.main() From 9200c8b0b4eea12eae2c6d4598e55dedc6e31e5e Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 18 Aug 2020 20:21:54 +0800 Subject: [PATCH 08/22] global --- test/global_return.py | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/global_return.py diff --git a/test/global_return.py b/test/global_return.py new file mode 100644 index 0000000..acddb09 --- /dev/null +++ b/test/global_return.py @@ -0,0 +1,58 @@ +import unittest +class TDD_GLOBAL_RETURN(unittest.TestCase): + def test_global_return(self): + def add(value1, value2): + result=value1 + value2 + return result + add(3, 5) + self.assertRaises(NameError,lambda:result) + result = add(3, 5) + self.assertEqual(result, 8) + def add(value1,value2): + global result1 + result1 = value1 + value2 + add(3,5) + self.assertEqual(result1,8) + def test_multiple_return(self): + def profile(): + global name + global age + name = "Danny" + age = 30 + profile() + self.assertEqual(name,'Danny') + self.assertEqual(age,30) + def profile(): + name = "Danny" + age = 30 + return (name, age) + profile_data = profile() + self.assertEqual(profile_data[0],'Danny') + self.assertEqual(profile_data[1],30) + def profile(): + name = "Danny" + age = 30 + return name, age + profile_name, profile_age = profile() + self.assertEqual(profile_data[0],'Danny') + self.assertEqual(profile_data[1],30) + def test_namedtuple(self): + from collections import namedtuple + def profile(): + Person = namedtuple('Person', 'name age') + return Person(name="Danny", age=31) + # Use as namedtuple + p = profile() + self.assertIsInstance(p, object) + self.assertEqual(p.name,'Danny') + self.assertEqual(p.age,31) + # Use as plain tuple + p = profile() + self.assertEqual(p[0],'Danny') + self.assertEqual(p[1],31) + # Unpack it immediatly + name, age = profile() + self.assertEqual(name,'Danny') + self.assertEqual(age,31) +if __name__ == '__main__': + unittest.main() From c849f552a4e3fce12ca972fe8945d09743eb083a Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 20 Aug 2020 15:51:17 +0800 Subject: [PATCH 09/22] virtual environment --- test/Virtual_Environment.py | 11 ++++++ test/mutation.py | 26 ++++++++++++++ test/slots.py | 67 +++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 test/Virtual_Environment.py create mode 100644 test/mutation.py create mode 100644 test/slots.py diff --git a/test/Virtual_Environment.py b/test/Virtual_Environment.py new file mode 100644 index 0000000..1c640c8 --- /dev/null +++ b/test/Virtual_Environment.py @@ -0,0 +1,11 @@ + +import unittest +class TDD_VIRTUAL_ENVIRONMENT(unittest.TestCase): + def test_Virtual_Environment(self): + import subprocess + # subprocess.run(["ls", "-l"]) + subprocess.run("pip install virtualenv", shell=True) +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file diff --git a/test/mutation.py b/test/mutation.py new file mode 100644 index 0000000..cc382fd --- /dev/null +++ b/test/mutation.py @@ -0,0 +1,26 @@ +import unittest +class TDD_MUTATION(unittest.TestCase): + def test_mutation(self): + foo = ['hi'] + self.assertEqual(foo,['hi']) + bar = foo + bar += ['bye'] + self.assertEqual(foo,['hi','bye']) + def test_never_default_mutable(self): + def add_to(num, target=[]): + target.append(num) + return target + + self.assertEqual(add_to(1),[1]) + self.assertEqual(add_to(2),[1,2]) + self.assertEqual(add_to(3),[1,2,3]) + def add_to(element, target=None): + if target is None: + target = [] + target.append(element) + return target + self.assertEqual(add_to(1),[1]) + self.assertEqual(add_to(2),[2]) + self.assertEqual(add_to(3),[3]) +if __name__ == '__main__': + unittest.main() diff --git a/test/slots.py b/test/slots.py new file mode 100644 index 0000000..6b5c60f --- /dev/null +++ b/test/slots.py @@ -0,0 +1,67 @@ + +import unittest +class TDD_SLOTS(unittest.TestCase): + def test_slots(self): + class MyClass(object): + def __init__(self, name, identifier): + self.name = name + self.identifier = identifier + self.set_up() + def set_up(self): + pass + class MyClass1(object): + # reduce the burden on your RAM + __slots__ = ['name', 'identifier'] + def __init__(self, name, identifier): + self.name = name + self.identifier = identifier + self.set_up() + def set_up(self): + pass + self.assertEqual(MyClass('n','i').identifier,'i') + self.assertEqual(MyClass1('n', 'i').identifier, 'i') + def test_memory_usuage(self): + # Python 3.4.3 (default, Jun 6 2015, 13:32:34) + # Type "copyright", "credits" or "license" for more information. + + # IPython 4.0.0 -- An enhanced Interactive Python. + # ? -> Introduction and overview of IPython's features. + # %quickref -> Quick reference. + # help -> Python's own help system. + # object? -> Details about 'object', use 'object??' for extra details. + + # In [1]: import ipython_memory_usage.ipython_memory_usage as imu + + # In [2]: imu.start_watching_memory() + # In [2] used 0.0000 MiB RAM in 5.31s, peaked 0.00 MiB above current, total RAM usage 15.57 MiB + + # In [3]: %cat slots.py + class MyClass(object): + __slots__ = ['name', 'identifier'] + def __init__(self, name, identifier): + self.name = name + self.identifier = identifier + + num = 1024*256 + x = [MyClass(1,1) for i in range(num)] + # In [3] used 0.2305 MiB RAM in 0.12s, peaked 0.00 MiB above current, total RAM usage 15.80 MiB + + # In [4]: from slots import * + # In [4] used 9.3008 MiB RAM in 0.72s, peaked 0.00 MiB above current, total RAM usage 25.10 MiB + + # In [5]: %cat noslots.py + class MyClass(object): + def __init__(self, name, identifier): + self.name = name + self.identifier = identifier + + num = 1024*256 + x = [MyClass(1,1) for i in range(num)] + # In [5] used 0.1758 MiB RAM in 0.12s, peaked 0.00 MiB above current, total RAM usage 25.28 MiB + + # In [6]: from noslots import * + # In [6] used 22.6680 MiB RAM in 0.80s, peaked 0.00 MiB above current, total RAM usage 47.95 MiB +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 89790bf54d562eb149925ed71884b80b0bd5c68f Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 20 Aug 2020 22:13:33 +0800 Subject: [PATCH 10/22] collections --- test/collections.py | 124 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 test/collections.py diff --git a/test/collections.py b/test/collections.py new file mode 100644 index 0000000..ff7cbef --- /dev/null +++ b/test/collections.py @@ -0,0 +1,124 @@ +import unittest,json +from collections import defaultdict,OrderedDict,Counter,deque,namedtuple +from collections.abc import Iterable +from enum import Enum +class TDD_COLLECTIONS(unittest.TestCase): + def test_collections(self): + colours = ( + ('Yasoob', 'Yellow'), + ('Ali', 'Blue'), + ('Arham', 'Green'), + ('Ali', 'Black'), + ('Yasoob', 'Red'), + ('Ahmed', 'Silver'), + ) + favourite_colours = defaultdict(list) + for name, colour in colours: + favourite_colours[name].append(colour) + self.assertIsInstance(favourite_colours, defaultdict) + self.assertIsInstance(favourite_colours, dict) + self.assertEqual(favourite_colours['Yasoob'],['Yellow','Red']) + self.assertEqual(favourite_colours['Ahmed'],['Silver']) + def test_keyerror_solution(self): + some_dict = {} + self.assertRaises(KeyError,lambda:some_dict['colours']['favourite'] ) + tree = lambda: defaultdict(tree) + some_dict = tree() + some_dict['colours']['favourite'] = "yellow" + self.assertEqual(json.dumps(some_dict),'{"colours": {"favourite": "yellow"}}') + def test_OrderedDict(self): + l=[("Red", 198),( "Green", 170),( "Blue", 160)] + colours = OrderedDict(l) + l1=[] + for key, value in colours.items(): + l1.append((key, value)) + self.assertEqual(l1,l) + def test_Counter(self): + colours = ( + ('Yasoob', 'Yellow'), + ('Ali', 'Blue'), + ('Arham', 'Green'), + ('Ali', 'Black'), + ('Yasoob', 'Red'), + ('Ahmed', 'Silver'), + ) + favs = Counter(name for name, colour in colours) + favs1 = Counter(name for colour,name in colours) + self.assertIsInstance(favs, Counter) + self.assertIsInstance(favs, dict) + self.assertEqual(favs,{'Yasoob':2,'Ali':2,'Arham':1,'Ahmed':1}) + self.assertEqual(favs1,{'Yellow': 1, 'Blue': 1, 'Green': 1, 'Black': 1, 'Red': 1, 'Silver': 1}) + line_count=[] + with open('test/ternary_operators.py', 'rb') as f: + line_count .append( Counter(f)) + self.assertIsInstance(line_count[0],dict) + def test_deque(self): + d = deque() + d.append('1') + d.append('2') + d.append('3') + self.assertIsInstance(d,deque) + self.assertEqual(d,deque(['1','2','3'])) + self.assertEqual(len(d),3) + self.assertEqual(d[0],'1') + self.assertEqual(d[-1], '3') + d = deque(range(5)) + self.assertEqual(len(d),5) + self.assertEqual(d.popleft(),0) + self.assertEqual(d.pop(),4) + self.assertEqual(d, deque([1, 2, 3])) + d = deque([0, 1, 2, 3, 5], maxlen=5) + self.assertEqual(len(d),5) + d.extend([6]) + self.assertEqual(len(d), 5) + self.assertIsNone(d.append(4)) + self.assertEqual(len(d), 5) + d = deque([1,2,3,4,5]) + d.extendleft([0]) + d.extend([6,7,8]) + self.assertEqual(d,deque([0,1,2,3,4,5,6,7,8])) + def test_namedtuple(self): + man = ('Ali', 30) + self.assertEqual(man[0],'Ali') + Animal = namedtuple('Animal', 'name age type') + perry = Animal(name="perry", age=31, type="cat") + self.assertIsInstance(perry,Animal) + self.assertIsInstance(perry,tuple) + self.assertEqual(perry.name,'perry') + Animal = namedtuple('Animal', 'name age type') + perry = Animal(name="perry", age=31, type="cat") + def setPerry(): + perry.age = 42 + self.assertRaises(AttributeError,setPerry) + self.assertEqual(perry[0],'perry') + self.assertIsInstance(perry._asdict(),dict) + self.assertEqual(perry._asdict(), {'name': 'perry', 'age': 31, 'type': 'cat'}) + def test_Enum(self): + class Species(Enum): + cat = 1 + dog = 2 + horse = 3 + aardvark = 4 + butterfly = 5 + owl = 6 + platypus = 7 + dragon = 8 + unicorn = 9 + # But we don't really care about age, so we can use an alias. + kitten = 1 + puppy = 2 + Animal = namedtuple('Animal', 'name age type') + perry = Animal(name="Perry", age=31, type=Species.cat) + drogon = Animal(name="Drogon", age=4, type=Species.dragon) + tom = Animal(name="Tom", age=75, type=Species.cat) + charlie = Animal(name="Charlie", age=2, type=Species.kitten) + self.assertEqual(charlie.type, Species.cat) + self.assertEqual(charlie.type, Species['cat']) + self.assertEqual(charlie.type, Species(1)) + self.assertEqual(charlie.type, Species.kitten) + self.assertEqual(charlie.type, tom.type) + def test_iterable(self): + m = map(lambda x: x, []) + self.assertIsInstance(m,Iterable) +if __name__ == '__main__': + unittest.main() From b6689272b43a96ed6963333e20283e5c4ea6fb88 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 20 Aug 2020 22:24:47 +0800 Subject: [PATCH 11/22] enumerate --- test/Enumerate.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/Enumerate.py diff --git a/test/Enumerate.py b/test/Enumerate.py new file mode 100644 index 0000000..75e5be4 --- /dev/null +++ b/test/Enumerate.py @@ -0,0 +1,15 @@ + +import unittest +class TDD_ENUMERATE(unittest.TestCase): + def test_Enumerate(self): + my_list = ['apple', 'banana', 'grapes', 'pear'] + d={} + for counter, value in enumerate(my_list): + d[counter] = value + self.assertEqual(d,{0: 'apple', 1: 'banana', 2: 'grapes', 3: 'pear'}) + counter_list = list(enumerate(my_list, 1)) + self.assertEqual(counter_list,[(1, 'apple'), (2, 'banana'), (3, 'grapes'), (4, 'pear')]) +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 4b679c04e196b13d91f0485cf90f009951477e1d Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 09:04:03 +0800 Subject: [PATCH 12/22] object introspection --- test/Object_introspection.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 test/Object_introspection.py diff --git a/test/Object_introspection.py b/test/Object_introspection.py new file mode 100644 index 0000000..2959a51 --- /dev/null +++ b/test/Object_introspection.py @@ -0,0 +1,23 @@ +import unittest +class TDD_OBJECT_INTROSPECTION(unittest.TestCase): + def test_Object_introspection(self): + my_list = [1, 2, 3] + d=dir(my_list) + # print(d) + self.assertIsInstance(d, list) + self.assertTrue('copy' in d) + def test_type_id(self): + self.assertEqual(type(''),str) + self.assertIsInstance('',str) + self.assertEqual(type([]),list) + self.assertEqual(type({}),dict) + self.assertEqual(type(dict),type) + self.assertEqual(type(3),int) + name = "Yasoob" + self.assertIsInstance(id(name),int) + def test_inspect(self): + import inspect + self.assertIsInstance(inspect.getmembers(str),list) + self.assertIsInstance(inspect.getmembers(str)[0],tuple) +if __name__ == '__main__': + unittest.main() From 6002bc1c6787d35f0df9dbfd9836691175af2472 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 11:14:36 +0800 Subject: [PATCH 13/22] comprehensions --- test/comprehensions.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/comprehensions.py diff --git a/test/comprehensions.py b/test/comprehensions.py new file mode 100644 index 0000000..d38db38 --- /dev/null +++ b/test/comprehensions.py @@ -0,0 +1,37 @@ +from collections.abc import Iterable +import unittest +class TDD_COMPREHENSIONS(unittest.TestCase): + def test_comprehensions(self): + multiples = [i for i in range(30) if i % 3 == 0] + self.assertEqual(multiples,[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]) + squared = [] + for x in range(10): + squared.append(x**2) + self.assertEqual(squared, [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]) + squared1=[x**2 for x in range(10)] + self.assertEqual(squared,squared1) + def test_dict(self): + mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} + + mcase_frequency = { + k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) + for k in mcase.keys() + } + self.assertEqual(mcase_frequency,{'a':17,'b':34,'z':3}) + self.assertEqual({v: k for k, v in mcase.items()},{10:'a',34:'b',7:'A',3:'Z'}) + def test_set(self): + squared = {x**2 for x in [1, 1, 2]} + self.assertEqual(squared,{1,1,4}) + def test_generator(self): + multiples_gen = (i for i in range(10) if i % 3 == 0) + self.assertIsInstance(multiples_gen, Iterable) + l=[] + for x in multiples_gen: + l.append(x) + self.assertEqual([0,3,6,9],l) + self.assertEqual(list(multiples_gen),[]) + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From f9d52bcb6a8a2385826afb42c096530bfa139297 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 13:16:11 +0800 Subject: [PATCH 14/22] classes --- test/Classes.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++ test/Exceptions.py | 55 ++++++++++++++++++++++++++++++ test/lambdas.py | 9 +++++ 3 files changed, 147 insertions(+) create mode 100644 test/Classes.py create mode 100644 test/Exceptions.py create mode 100644 test/lambdas.py diff --git a/test/Classes.py b/test/Classes.py new file mode 100644 index 0000000..0ec984d --- /dev/null +++ b/test/Classes.py @@ -0,0 +1,83 @@ +import unittest +class TDD_CLASSES(unittest.TestCase): + def test_Classes(self): + class Cal(object): + # pi is a class variable + pi = 3.142 + def __init__(self, radius): + # self.radius is an instance variable + self.radius = radius + def area(self): + return self.pi * (self.radius ** 2) + a = Cal(32) + self.assertEqual(a.area(),Cal.pi*a.radius**2) + self.assertEqual(a.pi,3.142) + a.pi = 43 + self.assertEqual(a.pi,43) + b = Cal(44) + self.assertEqual(b.area(),3.142*44**2) + self.assertEqual(b.pi,3.142) + b.pi = 50 + self.assertEqual(b.pi,50) + def test_mutable_class_var(self): + class SuperClass(object): + superpowers = [] + def __init__(self, name): + self.name = name + def add_superpower(self, power): + self.superpowers.append(power) + foo = SuperClass('foo') + bar = SuperClass('bar') + self.assertEqual(foo.name,'foo') + self.assertEqual(bar.name,'bar') + self.assertEqual(bar.superpowers,[]) + foo.add_superpower('fly') + self.assertEqual(bar.superpowers,['fly']) + self.assertEqual(bar.superpowers,foo.superpowers) + def test_new_style_class(self): + class OldClass(): + def __init__(self): + pass + class NewClass(object): + def __init__(self): + pass + old = OldClass() + new = NewClass() + self.assertIsInstance(old,object) + self.assertIsInstance(new,object) + def test_magic_methods(self): + class GetTest(object): + def __init__(self,i=0): + self.i=i+1 + def another_method(self): + self.i+=1 + a = GetTest() + self.assertEqual(a.i,1) + a.another_method() + self.assertEqual(a.i,2) + class GetTest(object): + def __init__(self, name): + self.greet=('Greetings!! {0}'.format(name)) + def another_method(self): + print('I am another method which is not' + ' automatically called') + a = GetTest('yasoob') + self.assertEqual(a.greet,'Greetings!! yasoob') + # Try creating an instance without the name arguments + self.assertRaises(TypeError, lambda: GetTest()) + self.assertRaises(TypeError,lambda:a['name']) + def test_getitem(self): + class GetTest(object): + def __init__(self): + self.info = { + 'name':'Yasoob', + 'country':'Pakistan', + 'number':12345812 + } + def __getitem__(self,i): + return self.info[i] + foo = GetTest() + self.assertEqual(foo['name'],'Yasoob') + self.assertEqual(foo['number'],12345812) +if __name__ == '__main__': + unittest.main() diff --git a/test/Exceptions.py b/test/Exceptions.py new file mode 100644 index 0000000..06ada4d --- /dev/null +++ b/test/Exceptions.py @@ -0,0 +1,55 @@ + +import unittest +class TDD_EXCEPTIONS(unittest.TestCase): + def test_Exceptions(self): + try: + file = open('test.txt', 'rb') + except IOError as e: + pass + # print('An IOError occurred. {}'.format(e.args[-1])) + self.assertRaises(IOError, lambda: open('test.txt', 'rb')) + def test_Handling_multiple_exceptions(self): + try: + file = open('test.txt', 'rb') + except (IOError, EOFError) as e: + # print("An error occurred. {}".format(e.args[-1])) + pass + try: + file = open('test.txt', 'rb') + except EOFError as e: + # print("An EOF error occurred.") + raise e + except IOError as e: + # print("An error occurred.") + pass + try: + file = open('test.txt', 'rb') + except Exception as e: + self.assertRaises(FileNotFoundError,lambda:(_ for _ in ()).throw(e)) + def test_finally(self): + try: + i=0 + file = open('test.txt', 'rb') + except IOError as e: + # print('An IOError occurred. {}'.format(e.args[-1])) + i+=1 + finally: + self.assertEqual(i,1) + def test_try_else_clause(self): + try: + print('I am sure no exception is going to occur!') + i=0 + except Exception: + print('exception') + else: + # any code that should only run if no exception occurs in the try, + # but for which exceptions should NOT be caught + print('This would only run if no exception occurs. And an error here ' + 'would NOT be caught.') + i+=1 + finally: + self.assertEqual(i,1) +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file diff --git a/test/lambdas.py b/test/lambdas.py new file mode 100644 index 0000000..b14d4af --- /dev/null +++ b/test/lambdas.py @@ -0,0 +1,9 @@ + +import unittest +class TDD_LAMBDAS(unittest.TestCase): + def test_lambdas(self): + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From ce4a2b8906f609a0b6961c2e9ec6538cd069e6dd Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 15:01:16 +0800 Subject: [PATCH 15/22] one liners --- test/file.json | 1 + test/lambdas.py | 16 ++++++++++++---- test/my_script.py | 0 test/one_liners.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 test/file.json create mode 100644 test/my_script.py create mode 100644 test/one_liners.py diff --git a/test/file.json b/test/file.json new file mode 100644 index 0000000..217a463 --- /dev/null +++ b/test/file.json @@ -0,0 +1 @@ +{"name":"val"} \ No newline at end of file diff --git a/test/lambdas.py b/test/lambdas.py index b14d4af..1f83b7f 100644 --- a/test/lambdas.py +++ b/test/lambdas.py @@ -1,9 +1,17 @@ - import unittest class TDD_LAMBDAS(unittest.TestCase): def test_lambdas(self): - + add = lambda x, y: x + y + self.assertEqual(add(3, 5),8) + a = [(1, 2), (4, 1), (9, 10), (13, -3)] + a.sort(key=lambda x: x[1]) + self.assertEqual(a, [(13, -3), (4, 1), (1, 2), (9, 10)]) + list1 = [2,1, 3] + list2=[7,5,6,4] + data = zip(list1, list2) + data = sorted(data) + list1, list2 = map(lambda t: list(t), zip(*data)) + self.assertEqual(list1,[1,2,3]) + self.assertEqual(list2,[5,7,6]) if __name__ == '__main__': unittest.main() - - \ No newline at end of file diff --git a/test/my_script.py b/test/my_script.py new file mode 100644 index 0000000..e69de29 diff --git a/test/one_liners.py b/test/one_liners.py new file mode 100644 index 0000000..dd21e11 --- /dev/null +++ b/test/one_liners.py @@ -0,0 +1,48 @@ +from pprint import pprint +import unittest +import subprocess +import itertools + + +class TDD_ONE_LINERS(unittest.TestCase): + def test_server(self): + pass + # subprocess.run('python3 -m http.server', shell=True) + + def test_json(self): + subprocess.run('cat test/file.json | python -m json.tool', shell=True) + + def test_profiling(self): + subprocess.run('python3 -m cProfile test/my_script.py', shell=True) + + def test_csv_to_json(self): + pass + # subprocess.run('python3 -c "import csv,json;print json.dumps(list(csv.reader(open(\'test/csv_file.csv\'))))"',shell=True) + + def test_one_liners(self): + my_dict = {'name': 'Yasoob', 'age': 'undefined', + 'personality': 'awesome'} + # print(dir(my_dict)) + pprint(dir(my_dict)) + + def test_list_flattening(self): + a_list = [[1, 2], [3, 4], [5, 6]] + self.assertEqual(list(itertools.chain.from_iterable(a_list)), [ + 1, 2, 3, 4, 5, 6]) + self.assertEqual(list(itertools.chain(*a_list)), [1, 2, 3, 4, 5, 6]) + + def test_constructors(self): + class A(object): + def __init__(self, a, b, c, d, e, f): + self.__dict__.update( + {k: v for k, v in locals().items() if k != 'self'}) + ins = A('a', 'b', 'c', 'd', 'e', 'f') + p = ins.__dict__ + self.assertEqual(p, { + 'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd', 'e': 'e', 'f': 'f'}) + self.assertEqual(p['a'], 'a') + self.assertEqual(ins.a,'a') + + +if __name__ == '__main__': + unittest.main() From 96f04704e8e92df682b616da25e93e80309f1939 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 21:48:51 +0800 Subject: [PATCH 16/22] for else --- test/for_else.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/for_else.py diff --git a/test/for_else.py b/test/for_else.py new file mode 100644 index 0000000..d79acf4 --- /dev/null +++ b/test/for_else.py @@ -0,0 +1,33 @@ + +import unittest +class TDD_FOR_ELSE(unittest.TestCase): + def test_for_else(self): + fruits = ['apple', 'banana', 'mango'] + l=[] + for fruit in fruits: + l.append(fruit.capitalize()) + self.assertEqual(l,['Apple','Banana','Mango']) + def test_else_clause(self): + container = [] + not_found_in_container=lambda x:self.assertEqual(x,[]) + for item in container: + if search_something(item): + # Found it! + process(item) + break + else: + # Didn't find anything.. + not_found_in_container(container) + prime=[] + for n in range(2, 10): + for x in range(2, n): + if n % x == 0: + break + else: + # loop fell through without finding a factor + prime.append(n) + self.assertEqual(prime,[2,3,5,7]) +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 48174a5c500efc6e06ed2627dd002bffbfb89eab Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 22:00:47 +0800 Subject: [PATCH 17/22] c --- test/add.c | 12 ++++++++++++ test/adder.so | Bin 0 -> 4232 bytes test/c_extensions.py | 24 ++++++++++++++++++++++++ test/example.c | 18 ++++++++++++++++++ test/example.i | 14 ++++++++++++++ test/open.py | 9 +++++++++ 6 files changed, 77 insertions(+) create mode 100644 test/add.c create mode 100755 test/adder.so create mode 100644 test/c_extensions.py create mode 100644 test/example.c create mode 100644 test/example.i create mode 100644 test/open.py diff --git a/test/add.c b/test/add.c new file mode 100644 index 0000000..879afbf --- /dev/null +++ b/test/add.c @@ -0,0 +1,12 @@ +//sample C file to add 2 numbers - int and floats + +int add_int(int, int); +float add_float(float, float); + +int add_int(int num1, int num2){ + return num1 + num2; +} + +float add_float(float num1, float num2){ + return num1 + num2; +} \ No newline at end of file diff --git a/test/adder.so b/test/adder.so new file mode 100755 index 0000000000000000000000000000000000000000..45a27c10048358a022327b16317cb2b4ea5d1e23 GIT binary patch literal 4232 zcmeHK&r2Io5S~qJ><`PvOKqu`;Gx(eiHL`yhnC`kVk-p|ytGflCNxE(BpcL2!GooS zQrQ2)UiudlDhQtXR}^}vAb1H9O26;z+h)nZyYL3SH}kzWZ)V=?UgqcJ+24KzU`?~HV z`$?))v$j*M`Kns0Y~i3c-d7WE&RimoYe~k5ZN8JfO1+$4T<~V+(Phiq61CD zau>!Ja34tSuls(vUTCmXEu$j)6EV3;BQN8zcE+3l=eJrj`*&c!29iQwBAGvVewFK?2B6JaBr~3R0)>+P3;(010AuM|dxx#z<33wO}#V0qQPaI>^l=@*8a zw}#DQlbZ7t=jADA;>gUtv^k#*VD8FBlN(sqAQ4AlG*xm-Qq@`@LzRuK^+1Nxaz28) zVNUyCIUmVulet_J5}F*GcgdNbat{Dysao=)<40k&$ut=FeANh=B~`) +double My_variable = 3.0; + +int fact(int n) { + if (n <= 1) return 1; + else return n*fact(n-1); +} + +int my_mod(int x, int y) { + return (x%y); +} + +char *get_time() +{ + time_t ltime; + time(<ime); + return ctime(<ime); +} \ No newline at end of file diff --git a/test/example.i b/test/example.i new file mode 100644 index 0000000..d923c4b --- /dev/null +++ b/test/example.i @@ -0,0 +1,14 @@ +/* example.i */ + %module example + %{ + /* Put header files here or function declarations like below */ + extern double My_variable; + extern int fact(int n); + extern int my_mod(int x, int y); + extern char *get_time(); + %} + + extern double My_variable; + extern int fact(int n); + extern int my_mod(int x, int y); + extern char *get_time(); \ No newline at end of file diff --git a/test/open.py b/test/open.py new file mode 100644 index 0000000..c6cfcbc --- /dev/null +++ b/test/open.py @@ -0,0 +1,9 @@ + +import unittest +class TDD_OPEN(unittest.TestCase): + def test_open(self): + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 7b8d13ac080c2e31b86c828e063395b88615170b Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 22:15:53 +0800 Subject: [PATCH 18/22] open --- .DS_Store | Bin 0 -> 6148 bytes test/open.py | 22 ++++++++++++++++++++++ test/photo.jpg | Bin 0 -> 28573 bytes test/summary.txt | 1 + test/targeting_python.py | 9 +++++++++ 5 files changed, 32 insertions(+) create mode 100644 .DS_Store create mode 100644 test/photo.jpg create mode 100644 test/summary.txt create mode 100644 test/targeting_python.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d4a1542547efde59accd066044709c6b016bdddf GIT binary patch literal 6148 zcmeHK%}T>S5ZE2QMD#|25Q~lb{&UgFiJP!A3$N$+kU|Lhu260KNM2 z9_mB*BHo?Z-HKAZiKxuL>^D0*Gu!>P>}DBbyw(in7_%5-1}I|5gys{$anwF3X%8aD z8h$%J_v6%u{!3ppIesGpxOZhHSjciF-tV7(9!I&TR-bukpgcGn;Q6L(-VX_{FtuWcjHa!t$2N=AYrZEI4+w=FLuwA#tSJOmz zQ4(gdo~m)UA0j$j>bZvJUXDk&qo|DBcgzfZwW+Oqoc7< z2qPd|r2?u{uAdlOrGwwragN49p-N|5&J1<*%v`@vxSSpQwhU+7QAjN@Kn#3jU_f;( zy#Lp~e*b?=q8>3o4E!qwczMlTtHF}=-P*S}ylZXH6HpY4D-^z^fFZA9h{daT0#pk4 YZ8QKKjfFz+fY674q=6b@;71vF1#c^14*&oF literal 0 HcmV?d00001 diff --git a/test/open.py b/test/open.py index c6cfcbc..17af790 100644 --- a/test/open.py +++ b/test/open.py @@ -2,7 +2,29 @@ import unittest class TDD_OPEN(unittest.TestCase): def test_open(self): + with open('test/photo.jpg', 'rb') as f: + jpgdata = f.read() + self.assertIsInstance(jpgdata,bytes) + f.close() + def test_io(self): + import io + with open('test/photo.jpg', 'rb') as inf: + jpgdata = inf.read() + + if jpgdata.startswith(b'\xff\xd8'): + text = u'This is a JPEG file (%d bytes long)\n' + else: + text = u'This is a random file (%d bytes long)\n' + + with io.open('test/summary.txt', 'w', encoding='utf-8') as outf: + outf.write(text % len(jpgdata)) + inf.close() + outf.close() + f=open('test/summary.txt') + data = f.read() + self.assertEqual(data,'This is a JPEG file (28573 bytes long)\n') + f.close() if __name__ == '__main__': unittest.main() diff --git a/test/photo.jpg b/test/photo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..db8ceffbb2373b750d4ff021eedb05f19b63502b GIT binary patch literal 28573 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�sguzG$sWz@4_PBG)Ll^K226p(r_KZz^SB!>ry`!uSH*M3s+QK7K{ zAe^(eq3wo^H}%Q)vlAg6wtD0Gbx4D2N~DB|F4HBU^O5b#Oi%>o@Xn|2Y8H|nxxfdJM@-0jy%Y@F%} z{O|b_6+`gLTM&)1NnR$E5y6mL6%7mtrWV*pHP$oS zd;G3E`u6~kc*pnsla?6WtF@DIli4n*^uU+QA*%k}$@r?8hR2O>y3}rOttV_PD5v!& znnvT{d}Nr9$H2o5UI*beOtzO^Sp4h~C+R5-Oe2L~CFKG}-Z}?Fd6S*IN
EFU|Q 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%0D-C~rLACyX?I|j#
    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 literal 0 HcmV?d00001 diff --git a/test/summary.txt b/test/summary.txt new file mode 100644 index 0000000..1255b3b --- /dev/null +++ b/test/summary.txt @@ -0,0 +1 @@ +This is a JPEG file (28573 bytes long) diff --git a/test/targeting_python.py b/test/targeting_python.py new file mode 100644 index 0000000..efc178e --- /dev/null +++ b/test/targeting_python.py @@ -0,0 +1,9 @@ + +import unittest +class TDD_TARGETING_PYTHON(unittest.TestCase): + def test_targeting_python(self): + +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file From 378c0801a623c7402472c10c78dcbf32fc2c39b8 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 22:30:42 +0800 Subject: [PATCH 19/22] compatible --- test/targeting_python.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/targeting_python.py b/test/targeting_python.py index efc178e..bf9d355 100644 --- a/test/targeting_python.py +++ b/test/targeting_python.py @@ -1,9 +1,19 @@ - +from __future__ import print_function +# from future.builtins.disabled import * import unittest class TDD_TARGETING_PYTHON(unittest.TestCase): def test_targeting_python(self): - + print + # Output: + self.assertTrue(callable(print)) + def test_compatible(self): + try: + import urllib.request as urllib_request # for Python 3 + print('??') + except ImportError: + import urllib2 as urllib_request # for Python 2 + print(urllib_request) + def test_Obsolete_Python2_builtins(self): + self.assertRaises(NameError,lambda:apply()) if __name__ == '__main__': unittest.main() - - \ No newline at end of file From 896e0dbc72f02573b85a52ee6f85f4f226a83ce4 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 22:48:38 +0800 Subject: [PATCH 20/22] coroutines --- test/Coroutines.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/Coroutines.py diff --git a/test/Coroutines.py b/test/Coroutines.py new file mode 100644 index 0000000..b25f312 --- /dev/null +++ b/test/Coroutines.py @@ -0,0 +1,30 @@ + +import unittest +class TDD_COROUTINES(unittest.TestCase): + def test_Coroutines(self): + def fib(n): + a, b = 0, 1 + while a Date: Fri, 21 Aug 2020 23:05:55 +0800 Subject: [PATCH 21/22] function caching --- test/function_caching.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/function_caching.py diff --git a/test/function_caching.py b/test/function_caching.py new file mode 100644 index 0000000..41a87ef --- /dev/null +++ b/test/function_caching.py @@ -0,0 +1,33 @@ +from functools import wraps +import unittest +class TDD_FUNCTION_CACHING(unittest.TestCase): + def test_function_caching(self): + from functools import lru_cache + @lru_cache(maxsize=32) + def fib(n): + if n < 2: + return n + return fib(n-1) + fib(n-2) + l=([fib(n) for n in range(10)]) + self.assertEqual(l, [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]) + fib.cache_clear() + self.assertEqual(l, [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]) + def test_python2_plus(self): + def memoize(function): + memo = {} + @wraps(function) + def wrapper(*args): + try: + return memo[args] + except KeyError: + rv = function(*args) + memo[args] = rv + return rv + return wrapper + @memoize + def fibonacci(n): + if n < 2: return n + return fibonacci(n - 1) + fibonacci(n - 2) + self.assertEqual(fibonacci(25),75025) +if __name__ == '__main__': + unittest.main() From f8514139bf578989944c2f4693958aceff9dcb82 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Aug 2020 23:27:41 +0800 Subject: [PATCH 22/22] context manager --- some_file | 1 + test/context_managers.py | 54 ++++++++++++++++++++++++++++++++++++++++ test/demo.txt | 0 test/some_file | 1 + 4 files changed, 56 insertions(+) create mode 100644 some_file create mode 100644 test/context_managers.py create mode 100644 test/demo.txt create mode 100644 test/some_file diff --git a/some_file b/some_file new file mode 100644 index 0000000..22875c8 --- /dev/null +++ b/some_file @@ -0,0 +1 @@ +Hola! \ No newline at end of file diff --git a/test/context_managers.py b/test/context_managers.py new file mode 100644 index 0000000..5d42118 --- /dev/null +++ b/test/context_managers.py @@ -0,0 +1,54 @@ + +import unittest,io +class TDD_CONTEXT_MANAGERS(unittest.TestCase): + def test_context_managers(self): + with open('test/some_file', 'w') as opened_file: + opened_file.write('Hola!') + opened_file.close() + f = open('test/some_file') + data = f.read() + self.assertEqual(data,'Hola!') + f.close() + file = open('some_file', 'w') + try: + file.write('Hola!') + self.assertRaises(io.UnsupportedOperation, file.read) + finally: + file.close() + def test_manager_class(self): + this=self + class File(object): + def __init__(self, file_name, method): + self.file_obj = open(file_name, method) + def __enter__(self): + return self.file_obj + def __exit__(self, type, value, traceback): + this.assertEqual(self.file_obj.name,'test/demo.txt') + type and this.assertTrue(type is AttributeError) + self.file_obj.close() + return True + with File('test/demo.txt', 'w') as opened_file: + opened_file.write('Hola!') + with File('test/demo.txt', 'w') as opened_file: + opened_file.undefined_function('Hola!') + def test_manager_generator(self): + from contextlib import contextmanager + + @contextmanager + def open_file(name): + f = open(name, 'w') + try: + yield f + finally: + f.close() + with open_file('test/some_file') as f: + f.write('hola!') + f.close() + f=open('test/some_file') + data = f.read() + self.assertEqual(data, 'hola!') + f.close() +if __name__ == '__main__': + unittest.main() + + \ No newline at end of file diff --git a/test/demo.txt b/test/demo.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/some_file b/test/some_file new file mode 100644 index 0000000..0d5acab --- /dev/null +++ b/test/some_file @@ -0,0 +1 @@ +hola! \ No newline at end of file