From 0a60e6ecf1a81132055cf09d545d2394cf1b9417 Mon Sep 17 00:00:00 2001 From: Corey McCandless Date: Tue, 5 Mar 2019 08:53:18 -0500 Subject: [PATCH 01/13] remove reference to logo from README Since there is no longer a copy of the Python logo stored in this repository, remove the reference to it from the README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 81bb5a064de..a38a63b16e6 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,5 @@ If you're interested, Tim Pope even has an [entire blog post](http://tbaggery.co If you're new to Git, take a look at [this short guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md#git-basics). - -## Python icon -The Python logo is an unregistered trademark. We are using a derived logo with the permission of the Python Software Foundation. - ## License This repository uses the [MIT License](/LICENSE). From bd1e9dd7cd34871cfcad8bdd2eda24ee3800ada9 Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Thu, 7 Mar 2019 15:19:21 -0600 Subject: [PATCH 02/13] Update palindrome_products_test.py Changes two tests to assertFactorsEqual in order to allow implementations that don't use lists to pass. --- exercises/palindrome-products/palindrome_products_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/palindrome-products/palindrome_products_test.py b/exercises/palindrome-products/palindrome_products_test.py index 200ab5686dc..11ece4dc154 100644 --- a/exercises/palindrome-products/palindrome_products_test.py +++ b/exercises/palindrome-products/palindrome_products_test.py @@ -62,12 +62,12 @@ def test_largest_palindrome_from_four_digit_factors(self): def test_empty_for_smallest_palindrome_if_none_in_range(self): value, factors = smallest_palindrome(min_factor=1002, max_factor=1003) self.assertIsNone(value) - self.assertEqual(factors, []) + self.assertFactorsEqual(factors, []) def test_empty_for_largest_palindrome_if_none_in_range(self): value, factors = largest_palindrome(min_factor=15, max_factor=15) self.assertIsNone(value) - self.assertEqual(factors, []) + self.assertFactorsEqual(factors, []) def test_error_for_smallest_if_min_is_more_than_max(self): with self.assertRaisesWithMessage(ValueError): From b5f3b32673c8882476fd94a27491597bc16e2abe Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Thu, 7 Mar 2019 17:54:27 -0600 Subject: [PATCH 03/13] rest-api: update tests to v1.1.1 Fixes #1673 --- exercises/rest-api/rest_api_test.py | 52 ++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/exercises/rest-api/rest_api_test.py b/exercises/rest-api/rest_api_test.py index d98a2a72886..f6c1886cb58 100644 --- a/exercises/rest-api/rest_api_test.py +++ b/exercises/rest-api/rest_api_test.py @@ -4,7 +4,7 @@ from rest_api import RestAPI -# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.2 +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.1 class RestAPITest(unittest.TestCase): def test_no_users(self): @@ -325,6 +325,56 @@ def test_lender_owes_borrower_less_than_new_loan(self): } self.assertDictEqual(json.loads(response), expected) + def test_lender_owes_borrower_same_as_new_loan(self): + database = { + "users": [ + { + "name": "Adam", + "owes": { + "Bob": 3.0 + }, + "owed_by": {}, + "balance": -3.0 + }, + { + "name": "Bob", + "owes": {}, + "owed_by": { + "Adam": 3.0 + }, + "balance": 3.0 + } + ] + } + api = RestAPI(database) + payload = json.dumps({ + 'lender': 'Adam', + 'borrower': 'Bob', + 'amount': 3.0 + }) + response = api.post('/iou', payload) + expected = { + 'users': [ + { + "name": "Adam", + "owes": { + }, + "owed_by": { + }, + "balance": 0.0 + }, + { + "name": "Bob", + "owes": { + }, + "owed_by": { + }, + "balance": 0.0 + } + ] + } + self.assertDictEqual(json.loads(response), expected) + if __name__ == '__main__': unittest.main() From 1af5240a35fb7e6317d3663827f293d0f4095b34 Mon Sep 17 00:00:00 2001 From: Corey McCandless Date: Wed, 13 Mar 2019 10:02:30 -0400 Subject: [PATCH 04/13] retree: rename to satellite --- config.json | 2 +- exercises/{retree => satellite}/README.md | 0 exercises/{retree => satellite}/example.py | 0 exercises/{retree/retree.py => satellite/satellite.py} | 0 .../{retree/retree_test.py => satellite/satellite_test.py} | 4 ++-- 5 files changed, 3 insertions(+), 3 deletions(-) rename exercises/{retree => satellite}/README.md (100%) rename exercises/{retree => satellite}/example.py (100%) rename exercises/{retree/retree.py => satellite/satellite.py} (100%) rename exercises/{retree/retree_test.py => satellite/satellite_test.py} (96%) diff --git a/config.json b/config.json index dd10b90c1c5..98c20e0ea8d 100644 --- a/config.json +++ b/config.json @@ -1423,7 +1423,7 @@ ] }, { - "slug": "retree", + "slug": "satellite", "uuid": "18467e72-e3b0-403c-896a-ce337f96e6f7", "core": false, "unlocked_by": "markdown", diff --git a/exercises/retree/README.md b/exercises/satellite/README.md similarity index 100% rename from exercises/retree/README.md rename to exercises/satellite/README.md diff --git a/exercises/retree/example.py b/exercises/satellite/example.py similarity index 100% rename from exercises/retree/example.py rename to exercises/satellite/example.py diff --git a/exercises/retree/retree.py b/exercises/satellite/satellite.py similarity index 100% rename from exercises/retree/retree.py rename to exercises/satellite/satellite.py diff --git a/exercises/retree/retree_test.py b/exercises/satellite/satellite_test.py similarity index 96% rename from exercises/retree/retree_test.py rename to exercises/satellite/satellite_test.py index 411dfbfc0ed..9f2e550ab1a 100644 --- a/exercises/retree/retree_test.py +++ b/exercises/satellite/satellite_test.py @@ -1,11 +1,11 @@ import unittest -from retree import tree_from_traversals +from satellite import tree_from_traversals # Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 -class TwoFerTest(unittest.TestCase): +class SatelliteTest(unittest.TestCase): def test_empty_tree(self): preorder = [] inorder = [] From 5a5b038e8b02325d45084d6aa4232c23c26d31c5 Mon Sep 17 00:00:00 2001 From: ee7 <45465154+ee7@users.noreply.github.com> Date: Mon, 18 Mar 2019 14:07:08 +0100 Subject: [PATCH 05/13] resistor-colors: Implement exercise (#1718) --- config.json | 10 +++ exercises/resistor-colors/README.md | 72 +++++++++++++++++++ exercises/resistor-colors/example.py | 16 +++++ exercises/resistor-colors/resistor_colors.py | 2 + .../resistor-colors/resistor_colors_test.py | 23 ++++++ 5 files changed, 123 insertions(+) create mode 100644 exercises/resistor-colors/README.md create mode 100644 exercises/resistor-colors/example.py create mode 100644 exercises/resistor-colors/resistor_colors.py create mode 100644 exercises/resistor-colors/resistor_colors_test.py diff --git a/config.json b/config.json index 98c20e0ea8d..f80b140e3fd 100644 --- a/config.json +++ b/config.json @@ -1554,6 +1554,16 @@ "topics": [ "arrays" ] + }, + { + "slug": "resistor-colors", + "uuid": "089f06a6-0759-479c-8c00-d699525a1e22", + "core": false, + "unlocked_by": null, + "difficulty": 1, + "topics": [ + "arrays" + ] } ] } diff --git a/exercises/resistor-colors/README.md b/exercises/resistor-colors/README.md new file mode 100644 index 00000000000..aa49ca44cb0 --- /dev/null +++ b/exercises/resistor-colors/README.md @@ -0,0 +1,72 @@ +# Resistor Colors + +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. For this exercise, you need to know two things about them: + +* Each resistor has a resistance value. +* Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. +To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. Each band acts as a digit of a number. For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. + +In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. The program will take two colors as input, and output the correct number. + +The band colors are encoded as follows: + +- Black: 0 +- Brown: 1 +- Red: 2 +- Orange: 3 +- Yellow: 4 +- Green: 5 +- Blue: 6 +- Violet: 7 +- Grey: 8 +- White: 9 + + +## Exception messages + +Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to +indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not +every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include +a message. + +To raise a message with an exception, just write it as an argument to the exception type. For example, instead of +`raise Exception`, you should write: + +```python +raise Exception("Meaningful message indicating the source of the error") +``` + +## Running the tests + +To run the tests, run the appropriate command below ([why they are different](https://github.com/pytest-dev/pytest/issues/1629#issue-161422224)): + +- Python 2.7: `py.test resistor_colors_test.py` +- Python 3.4+: `pytest resistor_colors_test.py` + +Alternatively, you can tell Python to run the pytest module (allowing the same command to be used regardless of Python version): +`python -m pytest resistor_colors_test.py` + +### Common `pytest` options + +- `-v` : enable verbose output +- `-x` : stop running tests on first failure +- `--ff` : run failures from previous test before running other test cases + +For other options, see `python -m pytest -h` + +## Submitting Exercises + +Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/resistor-colors` directory. + +You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`. + +For more detailed information about running tests, code style and linting, +please see [Running the Tests](http://exercism.io/tracks/python/tests). + +## Source + +Maud de Vries, Erik Schierboom [https://github.com/exercism/problem-specifications/issues/1464](https://github.com/exercism/problem-specifications/issues/1464) + +## 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/resistor-colors/example.py b/exercises/resistor-colors/example.py new file mode 100644 index 00000000000..0f128593925 --- /dev/null +++ b/exercises/resistor-colors/example.py @@ -0,0 +1,16 @@ +COLORS = [ + 'black', + 'brown', + 'red', + 'orange', + 'yellow', + 'green', + 'blue', + 'violet', + 'grey', + 'white' +] + + +def value(colors): + return 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) diff --git a/exercises/resistor-colors/resistor_colors.py b/exercises/resistor-colors/resistor_colors.py new file mode 100644 index 00000000000..f83a1c237cb --- /dev/null +++ b/exercises/resistor-colors/resistor_colors.py @@ -0,0 +1,2 @@ +def value(colors): + pass diff --git a/exercises/resistor-colors/resistor_colors_test.py b/exercises/resistor-colors/resistor_colors_test.py new file mode 100644 index 00000000000..f3681dad4c4 --- /dev/null +++ b/exercises/resistor-colors/resistor_colors_test.py @@ -0,0 +1,23 @@ +import unittest + +from resistor_colors import value + + +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 + +class ResistorColorsTest(unittest.TestCase): + def test_brown_and_black(self): + self.assertEqual(value(['brown', 'black']), 10) + + def test_blue_and_grey(self): + self.assertEqual(value(['blue', 'grey']), 68) + + def test_yellow_and_violet(self): + self.assertEqual(value(['yellow', 'violet']), 47) + + def test_orange_and_orange(self): + self.assertEqual(value(['orange', 'orange']), 33) + + +if __name__ == '__main__': + unittest.main() From 5f5bf89abb98e97034dd553b6aacc74d7597c084 Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Mon, 25 Mar 2019 08:50:50 -0500 Subject: [PATCH 06/13] darts: Fixes FP for out of date test suite (#1731) Fixes canonical data comment to fix FP. Closes #1726 --- exercises/darts/darts_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/darts/darts_test.py b/exercises/darts/darts_test.py index 53955290986..1b359709095 100644 --- a/exercises/darts/darts_test.py +++ b/exercises/darts/darts_test.py @@ -2,7 +2,7 @@ from darts import score -# Tests adapted from 'problem-specifications//canonical-data.json' @ v1.1.0 +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0 class darts_test(unittest.TestCase): def test_dart_lands_outside_target(self): From 7574242376c0870b4527b98e7f7d406a32e0bb96 Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Mon, 25 Mar 2019 08:59:27 -0500 Subject: [PATCH 07/13] satellite: update tests to v2.0.0 (#1729) Fixes #1728 as renames were done in a different commit. --- exercises/satellite/satellite_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/satellite/satellite_test.py b/exercises/satellite/satellite_test.py index 9f2e550ab1a..196cf1c917b 100644 --- a/exercises/satellite/satellite_test.py +++ b/exercises/satellite/satellite_test.py @@ -3,7 +3,7 @@ from satellite import tree_from_traversals -# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 +# Tests adapted from `problem-specifications//canonical-data.json` @ v2.0.0 class SatelliteTest(unittest.TestCase): def test_empty_tree(self): From bf0b7f25ee0cfb5ab37af221d3eb27c72b846526 Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Mon, 25 Mar 2019 09:02:07 -0500 Subject: [PATCH 08/13] leap: update tests to v1.5.1 (#1730) Fixes #1727 --- exercises/leap/leap_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/exercises/leap/leap_test.py b/exercises/leap/leap_test.py index 73c2e43a457..f5f259d4dff 100644 --- a/exercises/leap/leap_test.py +++ b/exercises/leap/leap_test.py @@ -3,12 +3,15 @@ from leap import is_leap_year -# Tests adapted from `problem-specifications//canonical-data.json` @ v1.4.0 +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.5.1 class LeapTest(unittest.TestCase): def test_year_not_divisible_by_4(self): self.assertIs(is_leap_year(2015), False) + def year_divisible_by_2_not_divisible_by_4(self): + self.assertIs(is_leap_year(1970), False) + def test_year_divisible_by_4_not_divisible_by_100(self): self.assertIs(is_leap_year(1996), True) From a0323972046a9785f2eb2cb54fff9350ebf34670 Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Mon, 25 Mar 2019 09:05:05 -0500 Subject: [PATCH 09/13] rational-numbers: update tests to v1.1.0 (#1732) Fixes #1724 --- exercises/rational-numbers/rational_numbers_test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/exercises/rational-numbers/rational_numbers_test.py b/exercises/rational-numbers/rational_numbers_test.py index 081feb2fec1..a7fe7812f5a 100644 --- a/exercises/rational-numbers/rational_numbers_test.py +++ b/exercises/rational-numbers/rational_numbers_test.py @@ -5,7 +5,7 @@ from rational_numbers import Rational -# Tests adapted from `problem-specifications//canonical-data.json` @ v1.0.0 +# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0 class RationalNumbersTest(unittest.TestCase): @@ -71,9 +71,15 @@ def test_divide_by_one(self): def test_absolute_value_of_positive(self): self.assertEqual(abs(Rational(1, 2)), Rational(1, 2)) + def test_absolute_value_of_positive_negative_numerator_denominator(self): + self.assertEqual(abs(Rational(-1, -2)), Rational(1, 2)) + def test_absolute_value_of_negative(self): self.assertEqual(abs(Rational(-1, 2)), Rational(1, 2)) + def test_absolute_value_of_negative_with_negative_denominator(self): + self.assertEqual(abs(Rational(1, -2)), Rational(1, 2)) + def test_absolute_value_of_zero(self): self.assertEqual(abs(Rational(0, 1)), Rational(0, 1)) From 58a689c21b2487cf759d3cc00809227b0d383cbd Mon Sep 17 00:00:00 2001 From: AnAccountForReportingBugs <45908752+AnAccountForReportingBugs@users.noreply.github.com> Date: Mon, 25 Mar 2019 09:08:24 -0500 Subject: [PATCH 10/13] simple-cipher: update tests to v2.0.0 (#1733) * simple-cipher: update tests to v2.0.0 Fixes #1725 * Fix flake8 violation --- exercises/simple-cipher/simple_cipher_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/exercises/simple-cipher/simple_cipher_test.py b/exercises/simple-cipher/simple_cipher_test.py index b54f4e24b26..6e8839cd752 100644 --- a/exercises/simple-cipher/simple_cipher_test.py +++ b/exercises/simple-cipher/simple_cipher_test.py @@ -4,7 +4,7 @@ from simple_cipher import Cipher -# Tests adapted from `problem-specifications//canonical-data.json` @ v1.2.0 +# Tests adapted from `problem-specifications//canonical-data.json` @ v2.0.0 class SimpleCipherTest(unittest.TestCase): # Utility functions @@ -65,10 +65,14 @@ def test_can_wrap_on_decode(self): cipher = Cipher('abcdefghij') self.assertEqual(cipher.decode('zabcdefghi'), 'zzzzzzzzzz') - def test_can_handle_messages_longer_than_key(self): + def test_can_encode_messages_longer_than_key(self): cipher = Cipher('abc') self.assertEqual(cipher.encode('iamapandabear'), 'iboaqcnecbfcr') + def test_can_decode_messages_longer_than_key(self): + cipher = Cipher('abc') + self.assertEqual(cipher.decode('iboaqcnecbfcr'), 'iamapandabear') + if __name__ == '__main__': unittest.main() From 148f6d1312752c09d8dd499a89dce520fc8e8683 Mon Sep 17 00:00:00 2001 From: Corey McCandless Date: Tue, 26 Mar 2019 09:17:31 -0400 Subject: [PATCH 11/13] Travis: enforce configlet fmt (#1710) * Travis: enforce configlet fmt * REVERTME test new check * Revert "REVERTME test new check" This reverts commit 0c3bfc6dfd5d2c677119db2675c6105bb83b42d0. --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 143abfb8e2e..a4dc35d2b2b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,12 @@ matrix: - env: JOB=HOUSEKEEPING install: ./bin/fetch-configlet before_script: ./bin/check-readmes.sh - script: ./bin/configlet lint . + script: + # May provide more useful output than configlet fmt + # if JSON is not valid or items are incomplete + - ./bin/configlet lint . + # Verify correct formatting in config.json + - ./bin/configlet fmt . && git diff --quiet allow_failures: - python: nightly From ccd399510a58ad42d03420e43de67893f55dd411 Mon Sep 17 00:00:00 2001 From: Corey McCandless Date: Tue, 26 Mar 2019 09:23:51 -0400 Subject: [PATCH 12/13] Create CODEOWNERS file (#1719) See https://help.github.com/en/articles/about-code-owners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..b4c8efe0704 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @exercism/python From 912c8f8f3626c7da92b6864e02dfc2534f4f7873 Mon Sep 17 00:00:00 2001 From: Sam Bryant Date: Wed, 3 Apr 2019 14:43:14 +0100 Subject: [PATCH 13/13] Stop leep test being ignored --- exercises/leap/leap_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exercises/leap/leap_test.py b/exercises/leap/leap_test.py index f5f259d4dff..92ea304e617 100644 --- a/exercises/leap/leap_test.py +++ b/exercises/leap/leap_test.py @@ -5,11 +5,12 @@ # Tests adapted from `problem-specifications//canonical-data.json` @ v1.5.1 + class LeapTest(unittest.TestCase): def test_year_not_divisible_by_4(self): self.assertIs(is_leap_year(2015), False) - def year_divisible_by_2_not_divisible_by_4(self): + def test_year_divisible_by_2_not_divisible_by_4(self): self.assertIs(is_leap_year(1970), False) def test_year_divisible_by_4_not_divisible_by_100(self):