diff --git a/config.json b/config.json index 9d4a1bdbfe7..0df3cae7ec6 100644 --- a/config.json +++ b/config.json @@ -1089,6 +1089,16 @@ "trees" ] }, + { + "uuid": "3a2a947a-01b3-1e80-e32b-de1756fd88365adf12e", + "slug": "error-handling", + "core": false, + "unlocked_by": null, + "difficulty": 3, + "topics": [ + "exception_handling" + ] + }, { "uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd", "slug": "accumulate", diff --git a/exercises/error-handling/README.md b/exercises/error-handling/README.md new file mode 100644 index 00000000000..94adb62aea0 --- /dev/null +++ b/exercises/error-handling/README.md @@ -0,0 +1,23 @@ +# Error Handling + +Implement various kinds of error handling and resource management. + +An important point of programming is how to handle errors and close +resources even if errors occur. + +This exercise requires you to handle various errors. Because error handling +is rather programming language specific you'll have to refer to the tests +for your track to see what's exactly required. + +### Submitting Exercises + +Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/` directory. + +For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit /python/bob/bob.py`. + + +For more detailed information about running tests, code style and linting, +please see the [help page](http://exercism.io/languages/python). + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/exercises/error-handling/error_handling.py b/exercises/error-handling/error_handling.py new file mode 100644 index 00000000000..f34ccee1cf0 --- /dev/null +++ b/exercises/error-handling/error_handling.py @@ -0,0 +1,14 @@ +def handle_error_by_throwing_exception(): + pass + + +def handle_error_by_returning_none(input_data): + pass + + +def handle_error_by_returning_tuple(input_data): + pass + + +def filelike_objects_are_closed_on_exception(filelike_object): + pass diff --git a/exercises/error-handling/error_handling_test.py b/exercises/error-handling/error_handling_test.py new file mode 100644 index 00000000000..b29bbfa050a --- /dev/null +++ b/exercises/error-handling/error_handling_test.py @@ -0,0 +1,66 @@ +import unittest + +import error_handling as er + + +class FileLike(object): + def __init__(self): + self.is_open = False + self.was_open = False + self.did_something = False + + def open(self): + self.was_open = False + self.is_open = True + + def close(self): + self.is_open = False + self.was_open = True + + def __enter__(self): + self.open() + return self + + def __exit__(self, *args): + self.close() + + def do_something(self): + self.did_something = True + raise Exception() + + +class ErrorHandlingTest(unittest.TestCase): + def test_throw_exception(self): + with self.assertRaises(Exception): + er.handle_error_by_throwing_exception() + + def test_return_none(self): + self.assertEqual(er.handle_error_by_returning_none('1'), 1, + 'Result of valid input should not be None') + self.assertIsNone(er.handle_error_by_returning_none('a'), + 'Result of invalid input should be None') + + def test_return_tuple(self): + successful_result, result = er.handle_error_by_returning_tuple('1') + self.assertIs(successful_result, True, + 'Valid input should be successful') + self.assertEqual(result, 1, 'Result of valid input should not be None') + + failure_result, result = er.handle_error_by_returning_tuple('a') + self.assertIs(failure_result, False, + 'Invalid input should not be successful') + + def test_filelike_objects_are_closed_on_exception(self): + filelike_object = FileLike() + with self.assertRaises(Exception): + er.filelike_objects_are_closed_on_exception(filelike_object) + self.assertIs(filelike_object.is_open, False, + 'filelike_object should be closed') + self.assertIs(filelike_object.was_open, True, + 'filelike_object should have been opened') + self.assertIs(filelike_object.did_something, True, + 'filelike_object should call do_something()') + + +if __name__ == '__main__': + unittest.main() diff --git a/exercises/error-handling/example.py b/exercises/error-handling/example.py new file mode 100644 index 00000000000..85441148098 --- /dev/null +++ b/exercises/error-handling/example.py @@ -0,0 +1,21 @@ +def handle_error_by_throwing_exception(): + raise Exception() + + +def handle_error_by_returning_none(input_data): + try: + return int(input_data) + except ValueError: + return None + + +def handle_error_by_returning_tuple(input_data): + try: + return (True, int(input_data)) + except ValueError: + return (False, None) + + +def filelike_objects_are_closed_on_exception(filelike_object): + with filelike_object as fobj: + fobj.do_something()