trackler 2.2.1.52 → 2.2.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/problem-specifications/exercises/leap/canonical-data.json +2 -2
  4. data/tracks/cfml/tasks/FormatConfig.cfc +6 -4
  5. data/tracks/cfml/tasks/GenerateReadme.cfc +197 -0
  6. data/tracks/cfml/tasks/ScaffoldExercise.cfc +6 -0
  7. data/tracks/csharp/config.json +1 -1
  8. data/tracks/delphi/exercises/leap/uLeapTests.pas +1 -1
  9. data/tracks/fsharp/exercises/clock/Clock.fs +1 -1
  10. data/tracks/fsharp/exercises/clock/ClockTest.fs +239 -61
  11. data/tracks/fsharp/exercises/clock/Example.fs +3 -3
  12. data/tracks/fsharp/exercises/dominoes/DominoesTest.fs +29 -26
  13. data/tracks/fsharp/exercises/largest-series-product/LargestSeriesProductTest.fs +30 -15
  14. data/tracks/fsharp/exercises/leap/LeapTest.fs +2 -2
  15. data/tracks/fsharp/exercises/rectangles/Example.fs +1 -1
  16. data/tracks/fsharp/exercises/rectangles/Rectangles.fs +1 -1
  17. data/tracks/fsharp/exercises/rectangles/RectanglesTest.fs +66 -43
  18. data/tracks/fsharp/generators/Generators.fs +85 -1
  19. data/tracks/java/scripts/canonical_data_check.sh +8 -0
  20. data/tracks/kotlin/.gitignore +1 -0
  21. data/tracks/kotlin/exercises/acronym/.meta/version +1 -0
  22. data/tracks/kotlin/exercises/acronym/src/test/kotlin/AcronymTest.kt +9 -10
  23. data/tracks/kotlin/exercises/all-your-base/.meta/version +1 -1
  24. data/tracks/kotlin/exercises/all-your-base/src/test/kotlin/BaseConverterTest.kt +20 -20
  25. data/tracks/kotlin/exercises/allergies/.meta/version +1 -0
  26. data/tracks/kotlin/exercises/allergies/src/test/kotlin/AllergiesTest.kt +19 -72
  27. data/tracks/kotlin/exercises/anagram/.meta/src/reference/kotlin/Anagram.kt +7 -4
  28. data/tracks/kotlin/exercises/anagram/.meta/version +1 -0
  29. data/tracks/kotlin/exercises/anagram/src/test/kotlin/AnagramTest.kt +76 -29
  30. data/tracks/kotlin/exercises/atbash-cipher/.meta/version +1 -0
  31. data/tracks/kotlin/exercises/atbash-cipher/src/test/kotlin/AtbashTest.kt +6 -3
  32. data/tracks/kotlin/exercises/beer-song/.meta/version +1 -0
  33. data/tracks/kotlin/exercises/beer-song/src/test/kotlin/BeerSongTest.kt +21 -46
  34. data/tracks/kotlin/exercises/binary-search/.meta/version +1 -0
  35. data/tracks/kotlin/exercises/binary-search/src/test/kotlin/BinarySearchTest.kt +30 -19
  36. data/tracks/kotlin/exercises/bob/.meta/src/reference/kotlin/Bob.kt +8 -7
  37. data/tracks/kotlin/exercises/bob/.meta/version +1 -0
  38. data/tracks/kotlin/exercises/bob/src/test/kotlin/BobTest.kt +57 -15
  39. data/tracks/kotlin/exercises/bracket-push/.meta/version +1 -0
  40. data/tracks/kotlin/exercises/bracket-push/src/test/kotlin/BracketPushTest.kt +3 -1
  41. data/tracks/kotlin/exercises/collatz-conjecture/.meta/version +1 -1
  42. data/tracks/kotlin/exercises/difference-of-squares/.meta/version +1 -0
  43. data/tracks/kotlin/exercises/difference-of-squares/src/test/kotlin/SquaresTest.kt +10 -23
  44. data/tracks/kotlin/exercises/etl/.meta/src/reference/kotlin/ETL.kt +7 -1
  45. data/tracks/kotlin/exercises/etl/.meta/version +1 -0
  46. data/tracks/kotlin/exercises/etl/src/test/kotlin/ETLTest.kt +10 -10
  47. data/tracks/kotlin/exercises/flatten-array/.meta/version +1 -0
  48. data/tracks/kotlin/exercises/flatten-array/src/test/kotlin/FlattenerTest.kt +8 -16
  49. data/tracks/kotlin/exercises/gigasecond/.meta/version +1 -0
  50. data/tracks/kotlin/exercises/gigasecond/src/test/kotlin/GigasecondTest.kt +1 -1
  51. data/tracks/kotlin/exercises/hamming/.meta/src/reference/kotlin/Hamming.kt +1 -1
  52. data/tracks/kotlin/exercises/hamming/.meta/version +1 -1
  53. data/tracks/kotlin/exercises/hamming/src/test/kotlin/HammingTest.kt +4 -4
  54. data/tracks/kotlin/exercises/hello-world/.meta/version +1 -0
  55. data/tracks/kotlin/exercises/hello-world/src/test/kotlin/HelloWorldTest.kt +1 -1
  56. data/tracks/kotlin/exercises/isogram/.meta/version +1 -0
  57. data/tracks/kotlin/exercises/isogram/src/test/kotlin/IsogramTest.kt +5 -8
  58. data/tracks/kotlin/exercises/largest-series-product/.meta/src/reference/kotlin/Series.kt +2 -3
  59. data/tracks/kotlin/exercises/largest-series-product/.meta/version +1 -0
  60. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesTest.kt +97 -0
  61. data/tracks/kotlin/exercises/leap/.meta/version +1 -0
  62. data/tracks/kotlin/exercises/leap/src/test/kotlin/LeapTest.kt +8 -26
  63. data/tracks/kotlin/exercises/list-ops/.meta/version +1 -1
  64. data/tracks/kotlin/exercises/luhn/.meta/version +1 -0
  65. data/tracks/kotlin/exercises/luhn/src/test/kotlin/LuhnTest.kt +0 -3
  66. data/tracks/kotlin/exercises/nth-prime/.meta/version +1 -0
  67. data/tracks/kotlin/exercises/nth-prime/src/test/kotlin/PrimeTest.kt +0 -2
  68. data/tracks/kotlin/exercises/nucleotide-count/.meta/src/reference/kotlin/{DNA.kt → Dna.kt} +3 -8
  69. data/tracks/kotlin/exercises/nucleotide-count/.meta/version +1 -0
  70. data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/DnaTest.kt +48 -0
  71. data/tracks/kotlin/exercises/pangram/.meta/src/reference/kotlin/{Pangrams.kt → Pangram.kt} +1 -1
  72. data/tracks/kotlin/exercises/pangram/.meta/version +1 -1
  73. data/tracks/kotlin/exercises/pangram/src/test/kotlin/PangramTest.kt +15 -9
  74. data/tracks/kotlin/exercises/pascals-triangle/.meta/version +1 -0
  75. data/tracks/kotlin/exercises/pascals-triangle/src/test/kotlin/PascalsTriangleTest.kt +32 -14
  76. data/tracks/kotlin/exercises/perfect-numbers/.meta/src/reference/kotlin/NaturalNumber.kt +1 -1
  77. data/tracks/kotlin/exercises/perfect-numbers/.meta/version +1 -0
  78. data/tracks/kotlin/exercises/perfect-numbers/src/test/kotlin/{PerfectNumbersTest.kt → NaturalNumberTest.kt} +25 -7
  79. data/tracks/kotlin/exercises/phone-number/.meta/src/reference/kotlin/PhoneNumber.kt +15 -7
  80. data/tracks/kotlin/exercises/phone-number/.meta/version +1 -0
  81. data/tracks/kotlin/exercises/phone-number/src/test/kotlin/PhoneNumberTest.kt +46 -29
  82. data/tracks/kotlin/exercises/pig-latin/.meta/src/reference/kotlin/PigLatin.kt +2 -2
  83. data/tracks/kotlin/exercises/pig-latin/.meta/version +1 -0
  84. data/tracks/kotlin/exercises/pig-latin/src/test/kotlin/PigLatinTest.kt +21 -10
  85. data/tracks/kotlin/exercises/raindrops/.meta/version +1 -0
  86. data/tracks/kotlin/exercises/raindrops/src/test/kotlin/RaindropsTest.kt +19 -26
  87. data/tracks/kotlin/exercises/react/.meta/version +1 -0
  88. data/tracks/kotlin/exercises/react/src/test/kotlin/ReactTest.kt +11 -4
  89. data/tracks/kotlin/exercises/robot-simulator/.meta/version +1 -1
  90. data/tracks/kotlin/exercises/roman-numerals/.meta/version +1 -0
  91. data/tracks/kotlin/exercises/roman-numerals/src/test/kotlin/RomanNumeralTest.kt +1 -2
  92. data/tracks/kotlin/exercises/rotational-cipher/.meta/version +1 -1
  93. data/tracks/kotlin/exercises/rotational-cipher/src/test/kotlin/RotationalCipherTest.kt +7 -7
  94. data/tracks/kotlin/exercises/scrabble-score/.meta/src/reference/kotlin/{Scrabble.kt → ScrabbleScore.kt} +1 -1
  95. data/tracks/kotlin/exercises/scrabble-score/.meta/version +1 -0
  96. data/tracks/kotlin/exercises/scrabble-score/src/test/kotlin/ScrabbleScoreTest.kt +9 -7
  97. data/tracks/kotlin/exercises/sieve/.meta/version +1 -0
  98. data/tracks/kotlin/exercises/sieve/src/test/kotlin/SieveTest.kt +8 -0
  99. data/tracks/kotlin/exercises/space-age/.meta/version +1 -0
  100. data/tracks/kotlin/exercises/space-age/src/test/kotlin/SpaceAgeTest.kt +1 -16
  101. data/tracks/kotlin/exercises/sum-of-multiples/.meta/version +1 -0
  102. data/tracks/kotlin/exercises/sum-of-multiples/src/test/kotlin/SumOfMultiplesTest.kt +7 -7
  103. data/tracks/kotlin/exercises/triangle/.meta/version +1 -0
  104. data/tracks/kotlin/exercises/two-fer/.meta/version +1 -0
  105. data/tracks/kotlin/exercises/two-fer/src/test/kotlin/TwoferTest.kt +0 -1
  106. data/tracks/kotlin/exercises/word-count/.meta/src/reference/kotlin/WordCount.kt +6 -2
  107. data/tracks/kotlin/exercises/word-count/.meta/version +1 -0
  108. data/tracks/kotlin/exercises/word-count/src/test/kotlin/WordCountTest.kt +31 -9
  109. data/tracks/kotlin/scripts/canonical_data_check.sh +8 -0
  110. data/tracks/perl6/exercises/leap/leap.t +2 -2
  111. data/tracks/php/config.json +16 -0
  112. data/tracks/php/exercises/crypto-square/crypto-square_test.php +50 -0
  113. data/tracks/php/exercises/crypto-square/example.php +32 -0
  114. data/tracks/php/exercises/meetup/README.md +21 -0
  115. data/tracks/php/exercises/meetup/example.php +19 -0
  116. data/tracks/php/exercises/meetup/meetup_test.php +577 -0
  117. data/tracks/python/README.md +7 -5
  118. data/tracks/python/config.json +36 -27
  119. data/tracks/python/docs/TESTS.md +36 -12
  120. data/tracks/python/exercises/complex-numbers/complex_numbers_test.py +1 -1
  121. data/tracks/python/exercises/diffie-hellman/.meta/hints.md +16 -0
  122. data/tracks/python/exercises/diffie-hellman/README.md +15 -2
  123. data/tracks/python/exercises/error-handling/README.md +23 -0
  124. data/tracks/python/exercises/error-handling/error_handling.py +14 -0
  125. data/tracks/python/exercises/error-handling/error_handling_test.py +66 -0
  126. data/tracks/python/exercises/error-handling/example.py +21 -0
  127. data/tracks/python/exercises/forth/forth_test.py +1 -1
  128. data/tracks/python/exercises/isogram/isogram_test.py +5 -3
  129. data/tracks/python/exercises/leap/leap_test.py +2 -2
  130. data/tracks/python/exercises/rotational-cipher/rotational_cipher_test.py +4 -4
  131. data/tracks/python/exercises/simple-cipher/.meta/hints.md +16 -0
  132. data/tracks/python/exercises/simple-cipher/README.md +17 -0
  133. data/tracks/python/exercises/sum-of-multiples/sum_of_multiples_test.py +4 -1
  134. data/tracks/python/exercises/twelve-days/example.py +3 -3
  135. data/tracks/python/exercises/twelve-days/twelve_days.py +2 -2
  136. metadata +53 -9
  137. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesInvalidInputTest.kt +0 -30
  138. data/tracks/kotlin/exercises/largest-series-product/src/test/kotlin/SeriesValidInputTest.kt +0 -34
  139. data/tracks/kotlin/exercises/nucleotide-count/src/test/kotlin/NucleotideTest.kt +0 -87
@@ -19,10 +19,12 @@ A list of missing exercise can be found here: http://exercism.io/languages/pytho
19
19
 
20
20
  ### Conventions
21
21
 
22
- - We use minimalistic stub files for all exercises (#272).
22
+ - We use minimalistic stub files for all exercises ([#272](https://github.com/exercism/python/issues/272)).
23
23
  - We use `unittest` (Python Standard Library) and no 3rd-party-framework.
24
- - We use the parameter order `self.assertEqual(actual, expected)` (#440).
25
- - We use context managers (`with self.assertRaises(\<exception type\>):`) for testing for exceptions (#477).
24
+ - We use the parameter order `self.assertEqual(actual, expected)` ([#440](https://github.com/exercism/python/issues/440)).
25
+ - We use context managers (`with self.assertRaises(\<exception type\>):`) for testing for exceptions ([#477](https://github.com/exercism/python/issues/477)).
26
+ - We use `assertIs(actual, True)` and `assertIs(actual, False)` rather than `assertTrue(actual)` or `assertFalse(actual)` ([#419](https://github.com/exercism/python/pull/419)).
27
+ - We use a comment string in the test file to reference the version of the exercise's `canonical-data.json` that tests were adapted from (wording can be found in: [#784](https://github.com/exercism/python/issues/784)).
26
28
 
27
29
 
28
30
  ### Testing
@@ -56,12 +58,12 @@ It will automatically check the code style, the problem configuration, and run t
56
58
 
57
59
  ## Pull Requests
58
60
 
59
- We :heart: pull requests!
61
+ We :heart: pull requests!
60
62
  We even :sparkling_heart: them if they contain well written commit messages!
61
63
 
62
64
  Please write the first line of your commit message in the following style:
63
65
 
64
- ```exercise-name: Change some things```
66
+ ```exercise-name: Change some things```
65
67
 
66
68
  Please try to follow the [The seven rules of a great Git commit message](https://chris.beams.io/posts/git-commit/#seven-rules) like to capitalize the subject line and use the imperative mood. If there are more details to add, put those into the body of the commit message.
67
69
 
@@ -9,9 +9,9 @@
9
9
  "unlocked_by": null,
10
10
  "difficulty": 1,
11
11
  "topics": [
12
- "control-flow (if-else statements)",
13
- "optional values",
14
- "text formatting"
12
+ "conditionals",
13
+ "optional_values",
14
+ "text_formatting"
15
15
  ]
16
16
  },
17
17
  {
@@ -21,7 +21,7 @@
21
21
  "unlocked_by": null,
22
22
  "difficulty": 1,
23
23
  "topics": [
24
- "control-flow (if-else statements)",
24
+ "conditionals",
25
25
  "booleans",
26
26
  "logic"
27
27
  ]
@@ -46,8 +46,8 @@
46
46
  "unlocked_by": null,
47
47
  "difficulty": 1,
48
48
  "topics": [
49
- "control-flow (loops)",
50
- "control-flow (if-else statements)",
49
+ "loops",
50
+ "conditionals",
51
51
  "strings",
52
52
  "algorithms",
53
53
  "filtering",
@@ -61,8 +61,8 @@
61
61
  "unlocked_by": null,
62
62
  "difficulty": 1,
63
63
  "topics": [
64
- "control-flow (if-else statements)",
65
- "control-flow (loops)",
64
+ "conditionals",
65
+ "loops",
66
66
  "maps",
67
67
  "strings",
68
68
  "logic",
@@ -76,8 +76,8 @@
76
76
  "unlocked_by": null,
77
77
  "difficulty": 1,
78
78
  "topics": [
79
- "control-flow (if-else statements)",
80
- "control-flow (loops)",
79
+ "conditionals",
80
+ "loops",
81
81
  "sequences",
82
82
  "sets",
83
83
  "strings",
@@ -96,8 +96,8 @@
96
96
  "strings",
97
97
  "algorithms",
98
98
  "logic",
99
- "pattern recognition",
100
- "text formatting"
99
+ "pattern_recognition",
100
+ "text_formatting"
101
101
  ]
102
102
  },
103
103
  {
@@ -158,7 +158,7 @@
158
158
  "topics": [
159
159
  "strings",
160
160
  "logic",
161
- "control-flow (loops)"
161
+ "loops"
162
162
  ]
163
163
  },
164
164
  {
@@ -479,8 +479,7 @@
479
479
  "topics": [
480
480
  "lists",
481
481
  "searching",
482
- "loops",
483
- "iteration"
482
+ "loops"
484
483
  ]
485
484
  },
486
485
  {
@@ -672,7 +671,7 @@
672
671
  "topics": [
673
672
  "lists",
674
673
  "parsing",
675
- "transformation",
674
+ "transforming",
676
675
  "loops",
677
676
  "games"
678
677
  ]
@@ -908,7 +907,7 @@
908
907
  "time",
909
908
  "mathematics",
910
909
  "logic",
911
- "text formatting"
910
+ "text_formatting"
912
911
  ]
913
912
  },
914
913
  {
@@ -919,7 +918,7 @@
919
918
  "difficulty": 4,
920
919
  "topics": [
921
920
  "files",
922
- "text formatting",
921
+ "text_formatting",
923
922
  "searching"
924
923
  ]
925
924
  },
@@ -967,7 +966,7 @@
967
966
  "difficulty": 3,
968
967
  "topics": [
969
968
  "strings",
970
- "pattern matching"
969
+ "pattern_matching"
971
970
  ]
972
971
  },
973
972
  {
@@ -978,7 +977,7 @@
978
977
  "difficulty": 3,
979
978
  "topics": [
980
979
  "strings",
981
- "pattern matching"
980
+ "pattern_matching"
982
981
  ]
983
982
  },
984
983
  {
@@ -988,9 +987,9 @@
988
987
  "unlocked_by": null,
989
988
  "difficulty": 4,
990
989
  "topics": [
991
- "Control-flow (loops)",
992
- "Arrays",
993
- "Algorithms"
990
+ "loops",
991
+ "arrays",
992
+ "algorithms"
994
993
  ]
995
994
  },
996
995
  {
@@ -1000,9 +999,9 @@
1000
999
  "unlocked_by": null,
1001
1000
  "difficulty": 1,
1002
1001
  "topics": [
1003
- "control-flow (if-else statements)",
1004
- "optional values",
1005
- "text formatting"
1002
+ "conditionals",
1003
+ "optional_values",
1004
+ "text_formatting"
1006
1005
  ]
1007
1006
  },
1008
1007
  {
@@ -1012,7 +1011,7 @@
1012
1011
  "unlocked_by": null,
1013
1012
  "difficulty": 1,
1014
1013
  "topics": [
1015
- "control-flow (loops)"
1014
+ "loops"
1016
1015
  ]
1017
1016
  },
1018
1017
  {
@@ -1089,6 +1088,16 @@
1089
1088
  "trees"
1090
1089
  ]
1091
1090
  },
1091
+ {
1092
+ "uuid": "3a2a947a-01b3-1e80-e32b-de1756fd88365adf12e",
1093
+ "slug": "error-handling",
1094
+ "core": false,
1095
+ "unlocked_by": null,
1096
+ "difficulty": 3,
1097
+ "topics": [
1098
+ "exception_handling"
1099
+ ]
1100
+ },
1092
1101
  {
1093
1102
  "uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
1094
1103
  "slug": "accumulate",
@@ -4,14 +4,38 @@ We recommend you install [pytest](http://pytest.org/latest/) and
4
4
  [pytest-cache](http://pythonhosted.org/pytest-cache/). `pytest` is a testing
5
5
  tool that will give you more flexibility over running your unit tests.
6
6
 
7
+ If you want to install `pytest` for Python 2, then use `pip`.
8
+
7
9
  ```bash
8
10
  pip install pytest pytest-cache
9
11
  ```
12
+ If you instead want the version of `pytest` for Python 3, then use `pip3`.
13
+
14
+ ```bash
15
+ pip3 install pytest pytest-cache
16
+ ```
10
17
 
11
18
  If you get a `command not found` response from your system, you can find a
12
19
  tutorial on how to install `pip`
13
20
  [here](https://pip.pypa.io/en/stable/installing/).
14
21
 
22
+ **Note:** Whichever version of `pytest` you install last will be the default one used whenever `pytest` is executed, regardless of whether you have installed both versions.
23
+
24
+ If you want to check what the default version of `pytest` being used is, run the following:
25
+
26
+ ```bash
27
+ pytest --version
28
+ ```
29
+
30
+ If you have either version of `pytest` installed and you want to specifically run one of the versions, you can run that version by using `python` with the `-m` flag.
31
+
32
+ For example, you could run the Python 3 version of pytest like so:
33
+
34
+ ```bash
35
+ $ python3 -m pytest --version
36
+ This is pytest version 3.2.3, imported from /usr/local/lib/python3.5/dist-packages/pytest.py
37
+ ```
38
+
15
39
  If you choose not to install `pytest`, you can still run tests individually and
16
40
  skip the rest of this tutorial:
17
41
 
@@ -29,7 +53,7 @@ an example here), place yourself in the directory where that exercise has been
29
53
  fetched and run:
30
54
 
31
55
  ```bash
32
- py.test bob_test.py
56
+ pytest bob_test.py
33
57
  ```
34
58
 
35
59
  **Note:** To run the tests you need to pass the name of the testsuite file to
@@ -56,7 +80,7 @@ The above will run all the tests, whether they fail or not. If you'd rather stop
56
80
  the process and exit on the first failure, run:
57
81
 
58
82
  ```bash
59
- py.test -x bob_test.py
83
+ pytest -x bob_test.py
60
84
  ```
61
85
 
62
86
  ### Failed Tests First
@@ -64,14 +88,14 @@ py.test -x bob_test.py
64
88
  `pytest-cache` remembers which tests failed, and can run those tests first.
65
89
 
66
90
  ```bash
67
- py.test --ff bob_test.py
91
+ pytest --ff bob_test.py
68
92
  ```
69
93
 
70
94
  ### Running All Tests for All Exercises
71
95
 
72
96
  ```bash
73
97
  cd exercism/python/
74
- py.test
98
+ pytest
75
99
  ```
76
100
 
77
101
  ## Recommended Workflow
@@ -80,7 +104,7 @@ We recommend you run this command while working on exercises.
80
104
 
81
105
  ```bash
82
106
  cd exercism/python/bob
83
- py.test -x --ff bob_test.py
107
+ pytest -x --ff bob_test.py
84
108
  ```
85
109
 
86
110
  ## PDB
@@ -89,28 +113,28 @@ Will drop you into the python debugger when a test fails. To learn how to use
89
113
  pdb, check out the
90
114
  [documentation](https://docs.python.org/3/library/pdb.html#debugger-commands).
91
115
 
92
- You may also be interested in watching [Clayton Parker's "So you think you can
93
- pdb?" PyCon 2015 talk](https://www.youtube.com/watch?v=P0pIW5tJrRM)
94
-
95
116
  ```bash
96
- py.test --pdb bob_test.py
117
+ pytest --pdb bob_test.py
97
118
  ```
98
119
 
120
+ You may also be interested in watching [Clayton Parker's "So you think you can
121
+ pdb?" PyCon 2015 talk](https://www.youtube.com/watch?v=P0pIW5tJrRM).
122
+
99
123
  ## PEP8
100
124
 
101
125
  PEP8 is the [Style Guide for Python
102
126
  Code](https://www.python.org/dev/peps/pep-0008/). If you would like to test for
103
127
  compliance to the style guide, install
104
- [pytest-pep8](https://pypi.python.org/pypi/pytest-pep8)
128
+ [pytest-pep8](https://pypi.python.org/pypi/pytest-pep8).
105
129
 
106
130
  ```bash
107
131
  pip install pytest-pep8
108
132
  ```
109
133
 
110
- and add the pep8 flag to your command
134
+ Then, just add the `--pep8` flag to your command
111
135
 
112
136
  ```bash
113
- py.test --pep8 bob_test.py
137
+ pytest --pep8 bob_test.py
114
138
  ```
115
139
 
116
140
  Read the [pytest documentation](http://pytest.org/latest/contents.html#toc) and
@@ -55,7 +55,7 @@ class ComplexNumbersTest(unittest.TestCase):
55
55
  self.assertEqual(first_input.sub(second_input).real, 2)
56
56
  self.assertEqual(first_input.sub(second_input).imaginary, 0)
57
57
 
58
- def test_substract_numbers_with_real_and_imaginary_part(self):
58
+ def test_subtract_numbers_with_real_and_imaginary_part(self):
59
59
  first_input = ComplexNumber(1, 2)
60
60
  second_input = ComplexNumber(-2, -2)
61
61
  self.assertEqual(first_input.sub(second_input).real, 3)
@@ -0,0 +1,16 @@
1
+ ## Should I use random or secrets?
2
+
3
+ Python, as of version 3.6, includes two different random modules.
4
+
5
+ The module called `random` is pseudo-random, meaning it does not generate
6
+ true randomness, but follows an algorithm that simulates randomness.
7
+ Since random numbers are generated through a known algorithm, they are not truly random.
8
+
9
+ The `random` module is not correctly suited for cryptography and should not be used,
10
+ precisely because it is pseudo-random.
11
+
12
+ For this reason, in version 3.6, Python introduced the `secrets` module, which generates
13
+ cryptographically strong random numbers that provide the greater security required for cryptography.
14
+
15
+ Since this is only an exercise, `random` is fine to use, but note that **it would be
16
+ very insecure if actually used for cryptography.**
@@ -37,9 +37,22 @@ Bob calculates
37
37
  The calculations produce the same result! Alice and Bob now share
38
38
  secret s.
39
39
 
40
- ## Notes
40
+ ## Should I use random or secrets?
41
41
 
42
- Python, as of version 3.6, includes two different random modules. The module called `random` is pseudo-random, meaning it does not generate true randomness, but follows and algorithm that simulates randomness. Since random numbers are generated through a known algorithm, they are not truly random. The `random` module is not correctly suited for cryptography and should not be used, because it is pseudo-random. In version 3.6, Python introduced the `secrets` module, which generates cryptographically strong random numbers that provide the greater security required for cryptography. Since this is only an exercise, `random` is fine to use, but note that it would be very insecure if actually used for cryptography.
42
+ Python, as of version 3.6, includes two different random modules.
43
+
44
+ The module called `random` is pseudo-random, meaning it does not generate
45
+ true randomness, but follows an algorithm that simulates randomness.
46
+ Since random numbers are generated through a known algorithm, they are not truly random.
47
+
48
+ The `random` module is not correctly suited for cryptography and should not be used,
49
+ precisely because it is pseudo-random.
50
+
51
+ For this reason, in version 3.6, Python introduced the `secrets` module, which generates
52
+ cryptographically strong random numbers that provide the greater security required for cryptography.
53
+
54
+ Since this is only an exercise, `random` is fine to use, but note that **it would be
55
+ very insecure if actually used for cryptography.**
43
56
 
44
57
  ### Submitting Exercises
45
58
 
@@ -0,0 +1,23 @@
1
+ # Error Handling
2
+
3
+ Implement various kinds of error handling and resource management.
4
+
5
+ An important point of programming is how to handle errors and close
6
+ resources even if errors occur.
7
+
8
+ This exercise requires you to handle various errors. Because error handling
9
+ is rather programming language specific you'll have to refer to the tests
10
+ for your track to see what's exactly required.
11
+
12
+ ### Submitting Exercises
13
+
14
+ Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
15
+
16
+ For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
17
+
18
+
19
+ For more detailed information about running tests, code style and linting,
20
+ please see the [help page](http://exercism.io/languages/python).
21
+
22
+ ## Submitting Incomplete Solutions
23
+ It's possible to submit an incomplete solution so you can see how others have completed the exercise.
@@ -0,0 +1,14 @@
1
+ def handle_error_by_throwing_exception():
2
+ pass
3
+
4
+
5
+ def handle_error_by_returning_none(input_data):
6
+ pass
7
+
8
+
9
+ def handle_error_by_returning_tuple(input_data):
10
+ pass
11
+
12
+
13
+ def filelike_objects_are_closed_on_exception(filelike_object):
14
+ pass
@@ -0,0 +1,66 @@
1
+ import unittest
2
+
3
+ import error_handling as er
4
+
5
+
6
+ class FileLike(object):
7
+ def __init__(self):
8
+ self.is_open = False
9
+ self.was_open = False
10
+ self.did_something = False
11
+
12
+ def open(self):
13
+ self.was_open = False
14
+ self.is_open = True
15
+
16
+ def close(self):
17
+ self.is_open = False
18
+ self.was_open = True
19
+
20
+ def __enter__(self):
21
+ self.open()
22
+ return self
23
+
24
+ def __exit__(self, *args):
25
+ self.close()
26
+
27
+ def do_something(self):
28
+ self.did_something = True
29
+ raise Exception()
30
+
31
+
32
+ class ErrorHandlingTest(unittest.TestCase):
33
+ def test_throw_exception(self):
34
+ with self.assertRaises(Exception):
35
+ er.handle_error_by_throwing_exception()
36
+
37
+ def test_return_none(self):
38
+ self.assertEqual(er.handle_error_by_returning_none('1'), 1,
39
+ 'Result of valid input should not be None')
40
+ self.assertIsNone(er.handle_error_by_returning_none('a'),
41
+ 'Result of invalid input should be None')
42
+
43
+ def test_return_tuple(self):
44
+ successful_result, result = er.handle_error_by_returning_tuple('1')
45
+ self.assertIs(successful_result, True,
46
+ 'Valid input should be successful')
47
+ self.assertEqual(result, 1, 'Result of valid input should not be None')
48
+
49
+ failure_result, result = er.handle_error_by_returning_tuple('a')
50
+ self.assertIs(failure_result, False,
51
+ 'Invalid input should not be successful')
52
+
53
+ def test_filelike_objects_are_closed_on_exception(self):
54
+ filelike_object = FileLike()
55
+ with self.assertRaises(Exception):
56
+ er.filelike_objects_are_closed_on_exception(filelike_object)
57
+ self.assertIs(filelike_object.is_open, False,
58
+ 'filelike_object should be closed')
59
+ self.assertIs(filelike_object.was_open, True,
60
+ 'filelike_object should have been opened')
61
+ self.assertIs(filelike_object.did_something, True,
62
+ 'filelike_object should call do_something()')
63
+
64
+
65
+ if __name__ == '__main__':
66
+ unittest.main()