Repository: exercism/python
Pull request #2829 (2021-12-27 14:27:49)

Clock: adding support for `repr` and `str` functionality
This pull request aims to add helpful instructions about the difference between the `__repr__` and `__str__` methods to the Clock exercise, to address #2813.

github-actions[bot]: Hi & Welcome! 👋🏽&nbsp;👋

**Thank you** for contributing to `exercism/python` 💛&nbsp;💙 -- we really appreciate it! 🌟 🌈


<br>

This is an automated [🤖&nbsp;🤖 &nbsp;] comment for the  **`maintainers`** of this repository, notifying them of your contribution.  🎉
Someone will review/reply to your changes shortly. (_usually within **72 hours**._)
You can safely ignore the **`maintainers`**  section below.

<br>
<details open>
  <summary>⚠️ &nbsp;<b>Please be aware</b>&nbsp;⚠️ </summary>

  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_This repo does not generally accept [Pull Requests](https://github.com/exercism/docs/blob/main/community/good-member/pull-requests.md) unless they follow our [contributing guidelines](https://github.com/exercism/python/blob/main/CONTRIBUTING.md) and are:_

  &nbsp;&nbsp;&nbsp;&nbsp; 1️⃣ &nbsp;&nbsp;&nbsp; Small, contained fixes for typos/grammar/punctuation/code syntax on [one] exercise,
  &nbsp;&nbsp;&nbsp;&nbsp; 2️⃣ &nbsp;&nbsp;&nbsp;&nbsp;Medium changes that have been agreed/discussed via a filed issue,
  &nbsp;&nbsp;&nbsp;&nbsp; 3️⃣ &nbsp;&nbsp;&nbsp;&nbsp;Contributions from our [help wanted][help-wanted] issue list,
  &nbsp;&nbsp;&nbsp;&nbsp; 4️⃣ &nbsp;&nbsp;&nbsp;&nbsp;Larger (_previously agreed-upon_) contributions from recent & regular (_within the last 6 months_) contributors.

  &nbsp;&nbsp;&nbsp;&nbsp;Pull Requests not in these categories **will be closed**.  😞

</details>
<br>


---

 #### **`💙  It looks like you are changing/adding files in a Practice Exercise! 💙 `**

**`Please note:`** generally, changes to existing [practice exercises](https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md) or the addition
of new ones are proposed & discussed in [problem-specifications](https://github.com/exercism/problem-specifications) first, so that all tracks can potentially benefit.
Once a change is approved there by three maintainers, it becomes available for various language tracks to then implement.

<br>
<details>
  <summary>‼️&nbsp;&nbsp;<b><em>Did You...</em></b></summary>
<br>
<table>
<td><br>

 - [ ]  &nbsp;Update & rebase your branch with any (recent) upstream changes.
 - [ ]  &nbsp;Spell and grammar check all prose changes.
 - [ ]  &nbsp;Run [Prettier](https://prettier.io/) on all markdown and JSON files.
     - (_Optionally_) run [yapf](https://github.com/google/yapf) ([_yapf config_](https://github.com/exercism/python/blob/main/.style.yapf)) to help format your code.
 - [ ]  &nbsp;Run [flake8](http://flake8.pycqa.org/) with [_flake8 config_](https://github.com/exercism/python/blob/main/.flake8) to check general code style standards.
 - [ ] &nbsp; Run [pylint](https://pylint.pycqa.org/en/v2.11.1/user_guide/index.html) with [_pylint config_](https://github.com/exercism/python/blob/main/pylintrc) to check extended code style standards.
 - [ ]  &nbsp;Use pytest or the [python-track-test-runner](https://github.com/exercism/python-test-runner) to test any changed `example.py`/`exemplar.py`files
 &nbsp;against their associated test files.
 - [ ]  &nbsp;Similarly, use [pytest](https://docs.pytest.org/en/6.2.x/contents.html) or the [python-track-test-runner](https://github.com/exercism/python-test-runner) to test any changed _**test**_ files.
     - Check that tests **fail** properly, as well as succeed.
     &nbsp;(_**e.g.**, make some tests fail on purpose to "test the tests" & failure messages_).
 - [ ]  &nbsp;Double-check all files for proper EOL.
 - [ ]  &nbsp;[Regenerate](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#generating-practice-exercise-documents) exercise documents when you modified or created a `hints.md` file for a practice exercise.
 - [ ]  &nbsp;[Regenerate the test file](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#auto-generated-test-files-and-test-templates) if you modified or created a `JinJa2` template file for a practice exercise.
     -  Run the generated test file result against its `example.py`.
 - [ ]  &nbsp;Run [`configlet-lint`](https://github.com/exercism/configlet#configlet-lint) if the track [config.json](https://github.com/exercism/docs/blob/main/building/tracks/config-json.md), or any other exercise `config.json` has been modified.

<br>
</td>
</table>
<br>
</details>

<details>
<summary>✅️&nbsp;&nbsp;<b><em>Have You Checked...</em></b></summary>
<br>
<table>
<td>

.
_**Are there any additional changes you need to make?**_
Please make sure all associated files are present and consistent with your changes!

[Practice Exercise Anatomy](https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md)

   - [ ] `.docs/instructions.md`(**required**)
   - [ ] `.docs/introduction.md`(_optional_)
   - [ ] `.docs/introduction.append.md`(_optional_)
   - [ ] `.docs/instructions.append.md` (_optional_)
   - [ ] `.docs/hints.md`(_optional_)
   - [ ] `.meta/config.json` (**required**)
   - [ ] `.meta/example.py` (**required**)
   - [ ] `.meta/design.md` (_optional_)
   - [ ] `.meta/template.j2` (_template for generating tests from canonical data_)
   - [ ] `.meta/tests.toml` (_do you need to include or exclude any cases?_)
   - [ ] `<exercise-slug>_test.py` (_**do you need to regenerate this?**_)
   - [ ] `<exercise-slug>.py` (**required**)

</td>
</table>
</details>
<br>



<h2>🛠️ &nbsp;&nbsp; Maintainers &nbsp;&nbsp;</h2>
<h3> Please take note 📒  of the following sections/review items 👀   ✨ </h3>
<br>
<br>
<details>
<summary> 🌈  &nbsp;Acknowledgements and Reputation</summary>
<br>
<table>
<td>

- ❓ Does this PR need to receive a label with a [`reputation modifier`](https://github.com/exercism/docs/blob/main/using/product/reputation.md#creating-a-pull-request)?
     -  `medium` is awarded by default.
- ❓ Does this contributor need to be added to the **exercise** [`authors` or `contributors`](https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md#file-metaconfigjson)?
- ❓ Does this contributor need to be added to the **concept** [`authors` or `contributors`](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-metaconfigjson)?
- ❓ Is there an associated issue or issues that should be linked to this PR?

</td>
</table>
</details>
<details>
<summary>💫 &nbsp;General Code Quality</summary>
<ul>
<table>
<td>
  <h4>Verify:</h4>

  -  [ ]  &nbsp;The branch was updated & rebased with any (recent) upstream changes.
  -  [ ]  &nbsp;All prose was checked for spelling and grammar.
  -  [ ]  &nbsp;Files are formatted via [yapf](https://github.com/google/yapf) ([_yapf config_](https://github.com/exercism/python/blob/main/.style.yapf)) & conform to our [coding standards](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#coding-standards)
  -  [ ]  &nbsp;Files pass [flake8](http://flake8.pycqa.org/) with [_flake8 config_](https://github.com/exercism/python/blob/main/.flake8) & [pylint](https://pylint.pycqa.org/en/v2.11.1/user_guide/index.html) with [_pylint config_](https://github.com/exercism/python/blob/main/pylintrc).
  -  [ ]  &nbsp;Changed `example.py`/`exemplar.py` files still pass their associated **test files**.
  -  [ ]  &nbsp;Changed _**test files**_ still work with associated `example.py`/`exemplar.py` files.
      - Check that tests **fail** properly, as well as succeed.
             (_**e.g.**, make some tests fail on purpose to "test the tests" & failure messages_).
  -  [ ]  &nbsp;All files have proper EOL.
  -  [ ]  &nbsp;If a `JinJa2` template was modified/created, was the test file [regenerated](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#auto-generated-test-files-and-test-templates)?
      - Does the regenerated test file successfully test the exercises `example.py` file?
  -  [ ]  &nbsp;The branch passes all CI checks & [`configlet-lint`](https://github.com/exercism/configlet#configlet-lint).

<br>
</td>
</table>
</ul>
<br>
</details>
<details>
<summary>🌿 &nbsp;Changes to Concept Exercises</summary>
<br>

  -   ❓ Are all required files still up-to-date & configured correctly for this change?_
  -   ❓ Does `<exercise>/.meta/design.md` need to be updated with new implementation/design decisions
  -   ❓ Do these changes require follow-on/supporting changes to related **concept** documents?

<ul>
<details>
<summary><em><b> ✨ &nbsp;Where applicable, check the following&nbsp;✨  </b></em></summary>
<br>
<ul>
<table>
<td>

(_as a reminder: [Concept Exercise Anatomy](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md)_)
  - [ ] Exercise `introduction.md`
    - [ ]  Do all code examples compile, run, and return the shown output?
    - [ ]  Are all the code examples formatted per the Python docs?
  - [ ]  Exercise `instructions.md`
  - [ ]  Exercise  `hints.md`
  - [ ]   Check that exercise `design.md` was fulfilled or edited appropriately
  - [ ]   Exercise `exemplar.py`
    - [ ]  Only uses syntax previously introduced or explained.
    - [ ]  Is correct and appropriate for the exercise and story.
  - [ ]   Exercise `<exercise_name>.py` (stub)
    - [ ]  Includes appropriate docstrings and function names.
    - [ ]  Includes `pass` for each function
    - [ ]  Includes an EOL at the end
  - [ ]   Exercise  `<exercise_name>_test.py`
    - [ ]   Tests cover all (reasonable) inputs and scenarios
    - [ ]   At least one test for each task in the exercise
    - [ ]   If using subtests or fixtures they're [formatted correctly](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#Test-File_style) for the runner
    - [ ]   Classnames are `<ExerciseName>Test`
    - [ ]   Test functions are `test_<test_name>`
  - [ ]   Exercise `config.json` --> **valid UUID4**
  - [ ]   Corresponding concept `introduction.md`
  - [ ]   Corresponding concept `about.md`
  - [ ]   Concept  `config.json`
  - [ ]   All Markdown Files :  Prettier linting (_for all markdown docs_)
  - [ ]   All Code files: PyLint linting (**_except for test files_**)
  - [ ]   All files with text:  Spell check & grammar review.

</td>
</table>
</ul>
</details>
</ul>
</details>

<details>
<summary>🚀&nbsp;  Changes to Practice Exercises</summary>
<br>
<ul>
<table>
<td>

_Is the exercise is in line with [Practice Exercise Anatomy](https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md)?_
- [ ] `.docs/instructions.md`(**required**)
   - Was this file updated and regenerated properly?
- [ ] `.docs/introduction.md`(_optional_)
- [ ] `.docs/introduction.append.md`(_optional_)
- [ ] `.docs/instructions.append.md` (_optional_)
   - Are any additional instructions needed/provided?
   &nbsp;(_e.g. error handling or information on classes_)
- [ ] `.docs/hints.md`(_optional_)
   - Was this file regenerated properly?
- [ ] `.meta/config.json` (**required**)
- [ ] `.meta/example.py` (**required**)
   - Does this pass all the current tests as written/generated?
- [ ] `.meta/design.md` (_optional_)
- [ ] `.meta/template.j2` (_template for generating tests from canonical data_)
  - Was a test file properly regenerated from this template?
- [ ] `.meta/tests.toml`
   -  Are there additional test cases to include or exclude?
   -  Are there any Python-specific test cases needed for this exercise?
- [ ] `<exercise-slug>_test.py`
   - Does this file need to be regenerated?
   - Does this file correctly test the `example.py` file?
   - Does this file correctly report test failures and messages?
- [ ] `<exercise-slug>.py` (**required**)
   - Does this stub have enough information to get
   &nbsp;the student started coding a valid solution?

</td>
</table>
</ul>
</details>
  <details>
    <summary>🐣 &nbsp;Brand-New Concept Exercises</summary>
<br>
<ul>
<table>
<td>

_Is the exercise is in line with [Concept Exercise Anatomy](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md)?_
  - [ ] Exercise `introduction.md`
    - [ ]  Do all code examples compile, run, and return the shown output?
    - [ ]  Are all the code examples formatted per the Python docs?
  - [ ]  Exercise `instructions.md`
  - [ ]  Exercise  `hints.md`
  - [ ]   Check that exercise `design.md` was fulfilled or edited appropriately
  - [ ]   Exercise `exemplar.py`
    - [ ]  Only uses syntax previously introduced or explained.
    - [ ]  Is correct and appropriate for the exercise and story.
  - [ ]   Exercise `<exercise_name>.py` (stub)
    - [ ]  Includes appropriate docstrings and function names.
    - [ ]  Includes `pass` for each function
    - [ ]  Includes an EOL at the end
  - [ ]   Exercise  `<exercise_name>_test.py`
    - [ ]   Tests cover all (reasonable) inputs and scenarios
    - [ ]   At least one test for each task in the exercise
    - [ ]   If using subtests or fixtures they're formatted correctly for the runner
    - [ ]   Classnames are `<ExerciseName>Test`
    - [ ]   Test functions are `test_<test_name>`
  - [ ]   Exercise `config.json` --> valid UUID4
  - [ ]   Corresponding concept `introduction.md`
  - [ ]   Corresponding concept `about.md`
  - [ ]   Concept  `config.json`
  - [ ]   All Markdown Files :  Prettier linting (_for all markdown docs_)
  - [ ]   All Code files: Flake8 & PyLint linting
  - [ ]   All Code Examples:  proper formatting and fencing.  Verify they run in the REPL
  - [ ]   All files with text:  Spell check & grammar review.

<br>
</td>
</table>
</ul>
</details>
<br>
<h3>Our &nbsp; 💖  &nbsp; for all your review efforts! 🌟 🦄</h3>


<!-- pr-commenter-metadata: any-file-changed,change-practice-exercise -->
IsaacG: The `.meta/example.py` file needs updating, too!
BethanyG: @IsaacG  -- two things here.

1.  This PR should have had the CI run before any review was undertaken.  Please do not review PRs in the future without running CI checks **first**.
2.  Your review was not requested, nor did you read the note in the issue that said this was a draft intended for my review.  Please do not review PRs  where your review or a general review (from the reviewers group) is not requested - it adds confusion and chaos.  

BethanyG: @Chris-May  -- I have not yet reviewed this PR, but will hold off until you've accepted/rejected the current edits to avoid confusion/noise.
Chris-May: Sorry, @BethanyG! I didn't see your message. :)
BethanyG: @Chris-May  -- no need to revert!  Accept the suggestions/edits you like, but don't feel they are required.  I am going to hold off running the CI or reviewing until you are done with the first pass...just so that it's less noisy.  There may be issues the CI finds -- I just don't want them mixed in with the current suggestions...if that makes sense?
Chris-May: Totally. Thanks!

I think the suggestions were great, and I made them. The first pass is finished.

I have not yet been able to check in on all the suggestions from the github-actions bot, especially running the tests. But I won't be able to do that until tomorrow afternoon.

Feel free to run the CI if you feel like it. Otherwise, I'll comb through the bot's suggestions.
BethanyG: @Chris-May  --

I might have said (or forgotten to say! 😱 ) that this exercise has auto-generated tests pulled from the `problem-specifications` repo, which puts some interesting wrinkles into the process of altering/updating it.  Rather than changing the `clock_test.py` file by adding new test cases, you'll need to create  `.meta/additional_tests.json`  (see an [example here](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.meta/additional_tests.json) from the `queen-attack` exercise) for "addendum" tests.

We then have to re-generate the test file via the `bin/generate_tests.py` script, and check in the result for this PR.  Otherwise, the CI won't pass.  We may or may not also need to adjust the [JinJa2 template for `Clock`](https://github.com/exercism/python/tree/main/exercises/practice/clock/.meta) -- I'll need to check and see if you've altered existing test cases.

You can read a bit more about the process [here](https://github.com/exercism/python/blob/main/CONTRIBUTING.md#auto-generated-test-files-and-test-templates).  I'll also be around tomorrow (and tonight) to answer questions.
Chris-May: @BethanyG, I think I'm ready for another review.

I was able to edit the template for the tests, and I welcome suggestions for it... or any other changes.
Chris-May: Another thought that might be complicating this idea further is:

Python has a `dataclass` decorator in the `dataclasses` module. For people getting started with classes, this is a better way to start creating classes, as:

1. It's a simpler syntax
2. It creates the `__init__` and `__repr__` methods for you.

I don't know if Exercism explores this idea at all. It might be an excellent addition to an exercise.
BethanyG: > Another thought that might be complicating this idea further is:
> 
> Python has a `dataclass` decorator in the `dataclasses` module. For people getting started with classes, this is a better way to start creating classes, as:
> 
> 1. It's a simpler syntax
> 2. It creates the `__init__` and `__repr__` methods for you.
> 
> I don't know if Exercism explores this idea at all. It might be an excellent addition to an exercise.

So the TL;DR is that ... that is indeed an _excellent_ point!  But, er, maybe not for this specific exercise??

We don't .. _currently_ have anything detailed or explicit on `dataclasses`. It's all TBD.  You know how I mentioned that we have a whole `classes` branch to explore in our concept exercise syllabus tree?  Yes, that.  😁    As well as higher-order functions and decorators.  So - if you'd like to dive off the cliff and help discuss/plan/write ....  we would be _delighted_ to have you participate.  😄 

Here is our [current "roadmap"](https://github.com/exercism/python/blob/main/reference/track_exercises_overview.md), if you will.  Subject to change as we (maybe) break down topics and add additional concept exercises.  Additionally, we've been thinking of also adding new **_practice_** exercises in support of concepts that don't yet have good practice exercise support -- so the sky's the limit really (_well, and also there are only so many hours in the day...._).

If you haven't read the docs around [concept exercises](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md) vs [practice exercises](https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md) and [concepts docs](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md), those are also good background.

[This](https://github.com/exercism/python/issues?q=is%3Aopen+is%3Aissue+label%3A%22new+exercise+%E2%9C%A8%22) is a list of the current issues we've managed to outline for concept exercises.  Its not exhaustive, and we need to add to it.  So if any that have [help wanted] on them look appealing as-is, you are more than welcome to take one on.  They are also open to discussion, if the included topics don't feel quite right.

For less formal and more synchronous discussions, we have a Slack group.  I think there is a join link on the website under becoming a mentor.  Or I can add you via your github email (if it is public?).  Just let me or @J08K know!

Patch:
diff --git a/exercises/concept/little-sisters-vocab/.docs/instructions.md b/exercises/concept/little-sisters-vocab/.docs/instructions.md
index cd37fa92..6100cdb1 100644
--- a/exercises/concept/little-sisters-vocab/.docs/instructions.md
+++ b/exercises/concept/little-sisters-vocab/.docs/instructions.md
@@ -82,16 +82,15 @@ Suffixes are often used to change the part of speech a word has.
 In this task, your sister is going to practice "verbing" words by extracting an adjective from a sentence and turning it into a verb.
  Fortunately, all the words that need to be transformed here are "regular" - they don't need spelling changes to add the suffix.
 
-Implement the `noun_to_verb(<sentence>, <index>)` function that takes two parameters.
+Implement the `adjective_to_verb(<sentence>, <index>)` function that takes two parameters.
  A `sentence` using the vocabulary word, and the `index` of the word, once that sentence is split apart.
  The function should return the extracted adjective as a verb.
 
 
 ```python
->>> noun_to_verb('I need to make that bright.', -1 )
+>>> adjective_to_verb('I need to make that bright.', -1 )
 'brighten'
 
->>> noun_to_verb('It got dark as the sun set.', 2)
+>>> adjective_to_verb('It got dark as the sun set.', 2)
 'darken'
 ```
-
diff --git a/exercises/concept/little-sisters-vocab/.meta/exemplar.py b/exercises/concept/little-sisters-vocab/.meta/exemplar.py
index b0145fb3..ccd00092 100644
--- a/exercises/concept/little-sisters-vocab/.meta/exemplar.py
+++ b/exercises/concept/little-sisters-vocab/.meta/exemplar.py
@@ -45,7 +45,7 @@ def remove_suffix_ness(word):
     return word
 
 
-def noun_to_verb(sentence, index):
+def adjective_to_verb(sentence, index):
     """
 
     :param sentence: str that uses the word in sentence
diff --git a/exercises/concept/little-sisters-vocab/strings.py b/exercises/concept/little-sisters-vocab/strings.py
index 10ceba8f..56aaa04a 100644
--- a/exercises/concept/little-sisters-vocab/strings.py
+++ b/exercises/concept/little-sisters-vocab/strings.py
@@ -38,7 +38,7 @@ def remove_suffix_ness(word):
     pass
 
 
-def noun_to_verb(sentence, index):
+def adjective_to_verb(sentence, index):
     """
 
     :param sentence: str that uses the word in sentence
diff --git a/exercises/practice/clock/.docs/instructions.append.md b/exercises/practice/clock/.docs/instructions.append.md
new file mode 100644
index 00000000..76fb934b
--- /dev/null
+++ b/exercises/practice/clock/.docs/instructions.append.md
@@ -0,0 +1,69 @@
+# Instructions append
+
+The tests for this exercise expect your clock will be implemented via a Clock `class` in Python.
+If you are unfamiliar with classes in Python, [classes][classes in python] from the Python docs is a good place to start.
+## Representing your class
+
+When working with and debugging objects, it's important to have a string representation of that object.
+For example, if you were to create a new `datetime.datetime` object in the Python [REPL][REPL] environment, you could see its string representation:
+
+```python
+>>> from datetime import datetime
+>>> new_date = datetime(2022, 5, 4)
+>>> new_date
+datetime.datetime(2022, 5, 4, 0, 0)
+
+Your Clock `class` will create a custom `object` that handles times without dates.
+One important aspect of this `class` will be how it is represented as a _string_.
+Other programmers who use or call Clock `objects` created from the Clock `class` will refer to this string representation for debugging and other activities.  
+However, the default string representation on a `class` is usually not very helpful.
+
+```python
+>>> Clock(12, 34)
+<Clock object st 0x102807b20 >
+```
+
+To create a more helpful representation, you can define a `__repr__` method on the `class` that returns a string.
+
+Ideally, the `__repr__` method returns valid Python code that can be used to recreate the object -- as laid out in the [specification for a `__repr__` method][repr-docs].
+Returning valid Python code allows you to copy-paste the `str` directly into code or the REPL.
+
+For example, a `Clock` that represents 11:30 AM could look like this: `Clock(11, 30)`.
+
+Defining a `__repr__` method is good practice for all classes.
+Some things to consider:
+
+- The information returned from this method should be beneficial when debugging issues.
+- _Ideally_, the method returns a string that is valid Python code -- although that might not always be possible.
+- If valid Python code is not practical, returning a description between angle brackets: `< ...a practical description... >` is the convention.
+
+
+### String conversion
+
+In addition to the `__repr__` method, there might also be a need for an alternative "human-readable" string representation of the `class`.
+This might be used to format the object for program output or documentation.
+Looking at `datetime.datetime` again:
+
+```python
+>>> str(datetime.datetime(2022, 5, 4))
+'2022-05-04 00:00:00'
+```
+
+When a `datetime` object is asked to convert itself to a string representation, it returns a `str` formatted according to the [ISO 8601 standard][ISO 8601], which can be parsed by most datetime libraries into a human-readable date and time.
+
+In this exercise, you will get a chance to write a `__str__` method, as well as a `__repr__`.
+
+```python
+>>> str(Clock(11, 30))
+'11:30'
+```
+
+To support this string conversion, you will need to create a `__str__` method on your class that returns a more "human readable" string showing the Clock time.
+
+If you don't create a `__str__` method and you call `str()` on your class, python will try calling `__repr__` on your class as a fallback. So if you only implement one of the two, it would be better to create a `__repr__` method.
+
+[repr-docs]: https://docs.python.org/3/reference/datamodel.html#object.__repr__
+[classes in python]: https://docs.python.org/3/tutorial/classes.html
+[REPL]: https://pythonprogramminglanguage.com/repl/
+[ISO 8601]: https://www.iso.org/iso-8601-date-and-time-format.html
+
diff --git a/exercises/practice/clock/.meta/config.json b/exercises/practice/clock/.meta/config.json
index 6a917e5d..441a88c4 100644
--- a/exercises/practice/clock/.meta/config.json
+++ b/exercises/practice/clock/.meta/config.json
@@ -16,7 +16,8 @@
     "rootulp",
     "smalley",
     "thomasjpfan",
-    "tqa236"
+    "tqa236",
+    "chrismay"
   ],
   "files": {
     "solution": [
diff --git a/exercises/practice/clock/.meta/example.py b/exercises/practice/clock/.meta/example.py
index 0c76dca2..47d52681 100644
--- a/exercises/practice/clock/.meta/example.py
+++ b/exercises/practice/clock/.meta/example.py
@@ -7,6 +7,9 @@ class Clock:
         self.cleanup()
 
     def __repr__(self):
+        return f'Clock({self.hour}, {self.minute})'
+
+    def __str__(self):
         return '{:02d}:{:02d}'.format(self.hour, self.minute)
 
     def __eq__(self, other):
diff --git a/exercises/practice/clock/.meta/template.j2 b/exercises/practice/clock/.meta/template.j2
index 106b1c76..f786b2f1 100644
--- a/exercises/practice/clock/.meta/template.j2
+++ b/exercises/practice/clock/.meta/template.j2
@@ -4,6 +4,8 @@ Clock({{ obj["hour"] }}, {{ obj["minute"] }})
 {%- endmacro -%}
 {{ macros.header(["Clock"])}}
 
+{% set cases = additional_cases + cases %}
+
 class {{ exercise | camel_case }}Test(unittest.TestCase):
     {% for casegroup in cases -%}
     # {{ casegroup["description"].title() }}
@@ -17,7 +19,7 @@ class {{ exercise | camel_case }}Test(unittest.TestCase):
                 {{- clock(input["clock1"]) }},
                 {{- clock(input["clock2"]) }}
             {% else -%}
-                Equal(str({{ clock(input) }}
+                Equal({{ 'repr' if prop == 'repr' else 'str' }}({{ clock(input) }}
                 {%- if prop == "add" %} + {{ input["value"] }}
                 {%- elif prop == "subtract" %} - {{ input["value"] }}
                 {%- endif %}), "
@@ -27,5 +29,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase):
 
     {% endfor %}
     {%- endfor %}
-
 {{ macros.footer() }}
diff --git a/exercises/practice/clock/clock.py b/exercises/practice/clock/clock.py
index 26739a78..1102992a 100644
--- a/exercises/practice/clock/clock.py
+++ b/exercises/practice/clock/clock.py
@@ -5,6 +5,9 @@ class Clock:
     def __repr__(self):
         pass
 
+    def __str__(self):
+        pass
+
     def __eq__(self, other):
         pass
 


Test patch:
diff --git a/exercises/concept/little-sisters-vocab/strings_test.py b/exercises/concept/little-sisters-vocab/strings_test.py
index aca9e45e..79ca4abc 100644
--- a/exercises/concept/little-sisters-vocab/strings_test.py
+++ b/exercises/concept/little-sisters-vocab/strings_test.py
@@ -3,7 +3,7 @@ import pytest
 from strings import (add_prefix_un,
                      make_word_groups,
                      remove_suffix_ness,
-                     noun_to_verb)
+                     adjective_to_verb)
 
 
 class LittleSistersVocabTest(unittest.TestCase):
@@ -73,22 +73,22 @@ class LittleSistersVocabTest(unittest.TestCase):
                                  msg=f'Expected: {result} but got a different word instead.')
 
     @pytest.mark.task(taskno=4)
-    def test_noun_to_verb(self):
+    def test_adjective_to_verb(self):
         input_data = ['Look at the bright sky.',
                       'His expression went dark.',
                       'The bread got hard after sitting out.',
                       'The butter got soft in the sun.',
-                      'Her face was filled with light.',
+                      'Her eyes were light blue.',
                       'The morning fog made everything damp with mist.',
                       'He cut the fence pickets short by mistake.',
                       'Charles made weak crying noises.',
                       'The black oil got on the white dog.']
-        index_data = [-2, -1, 3, 3, -1, -3, 5, 2, 1]
+        index_data = [-2, -1, 3, 3, -2, -3, 5, 2, 1]
         result_data = ['brighten', 'darken', 'harden', 'soften',
                        'lighten', 'dampen', 'shorten', 'weaken', 'blacken']
         number_of_variants = range(1, len(input_data) + 1)
 
         for variant, sentence, index, result in zip(number_of_variants, input_data, index_data, result_data):
             with self.subTest(f'variation #{variant}', sentence=sentence, index=index, result=result):
-                self.assertEqual(noun_to_verb(sentence, index), result,
+                self.assertEqual(adjective_to_verb(sentence, index), result,
                                  msg=f'Expected: {result} but got a different word instead.')
diff --git a/exercises/practice/clock/.meta/additional_tests.json b/exercises/practice/clock/.meta/additional_tests.json
new file mode 100644
index 00000000..ba0c72bb
--- /dev/null
+++ b/exercises/practice/clock/.meta/additional_tests.json
@@ -0,0 +1,39 @@
+{
+  "cases": [
+    {
+      "description": "Create a string representation",
+      "cases": [
+        {
+          "uuid": "d2c8f173-018d-488c-8c4c-009f8c772313",
+          "description": "lunch time",
+          "property": "repr",
+          "input": {
+            "hour": 12,
+            "minute": 0
+          },
+          "expected": "Clock(12, 0)"
+        },
+        {
+          "uuid": "61a68f88-b980-46cd-a9f5-844832618092",
+          "description": "breakfast time",
+          "property": "repr",
+          "input": {
+            "hour": 6,
+            "minute": 45
+          },
+          "expected": "Clock(6, 45)"
+        },
+        {
+          "uuid": "ea93b367-fb03-44e4-a845-51756b8c9f3a",
+          "description": "dinner time",
+          "property": "repr",
+          "input": {
+            "hour": 18,
+            "minute": 30
+          },
+          "expected": "Clock(18, 30)"
+        }
+      ]
+    }
+  ]
+}
diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py
index f73af094..fe063366 100644
--- a/exercises/practice/clock/clock_test.py
+++ b/exercises/practice/clock/clock_test.py
@@ -8,6 +8,16 @@ from clock import (
 
 
 class ClockTest(unittest.TestCase):
+    # Create A String Representation
+    def test_lunch_time(self):
+        self.assertEqual(repr(Clock(12, 0)), "Clock(12, 0)")
+
+    def test_breakfast_time(self):
+        self.assertEqual(repr(Clock(6, 45)), "Clock(6, 45)")
+
+    def test_dinner_time(self):
+        self.assertEqual(repr(Clock(18, 30)), "Clock(18, 30)")
+
     # Create A New Clock With An Initial Time
     def test_on_the_hour(self):
         self.assertEqual(str(Clock(8, 0)), "08:00")