Skip to content

Commit

Permalink
Merge branch 'exercism:main' into acronym-approaches
Browse files Browse the repository at this point in the history
  • Loading branch information
BethanyG authored Jul 29, 2023
2 parents 7e46847 + 6c9a7ea commit 4a9fcb6
Show file tree
Hide file tree
Showing 409 changed files with 5,218 additions and 1,959 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.10.6
python-version: 3.11.2

- name: Download & Install dependencies
run: |
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
needs: housekeeping
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, 3.10.6]
python-version: [3.7, 3.8, 3.9, 3.10.6, 3.11.2]
steps:
- uses: actions/checkout@v3

Expand All @@ -66,7 +66,7 @@ jobs:
run: pip install dataclasses

- name: Install pytest
run: pip install pytest~=7.1.2
run: pip install pytest~=7.2.2

- name: Check exercises
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v7
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 21
Expand Down
21 changes: 11 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ Please read this [community blog post](https://exercism.org/blog/freeing-our-mai
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.

🌟   Track exercises support Python `3.7` - `3.10.6`.
🌟   Track exercises support Python `3.7` - `3.11.2`.
Exceptions to this support are noted where they occur.
🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.10.6`.
🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`.

Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴  .
Concept exercises are constrained to a small set of language or syntax features.
Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_.
These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴 .
Concept exercises are constrained to a small set of language or syntax features.
Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.

<br>

Expand Down Expand Up @@ -196,12 +195,12 @@ _We know it, and trust us, we are working on fixing it._ But if you see &nbsp;

<br>

This track officially supports Python `3.7 - 3.10.6` for students completing exercises.
The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.10.6-slim`.
This track officially supports Python `3.7 - 3.11.2` for students completing exercises.
The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.11.2-slim`.

Although the majority of test cases are written using `unittest.TestCase`,

- All exercises should be written for compatibility with Python `3.7` - `3.10.6`.
- All exercises should be written for compatibility with Python `3.7` - `3.11.2`.
- Version backward _incompatibility_ (_e.g_ an exercise using features introduced in `3.8`, `3.9`, or `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes.

- Here is an example of how the Python documentation handles [version-tagged &nbsp;🏷&nbsp;][version-tagged-language-features] feature introduction.
Expand All @@ -228,7 +227,7 @@ Although the majority of test cases are written using `unittest.TestCase`,
- Any updates or changes need to be proposed/approved in `problem-specifications` first.
- If Python-specific changes become necessary, they need to be appended to the canonical instructions by creating a `instructions.append.md` file in this (`exercism/Python`) repository.

- Practice Exercise **Test Suits** for many practice exercises are similarly [auto-generated](#auto-generated-files) from data in [problem specifications][problem-specifications].
- Practice Exercise **Test Suits** for most practice exercises are similarly [auto-generated](#auto-generated-files) from data in [problem specifications][problem-specifications].

- Any changes to them need to be proposed/discussed in the `problem-specifications` repository and approved by **3 track maintainers**, since changes could potentially affect many (_or all_) exercism language tracks.
- If Python-specific test changes become necessary, they can be appended to the exercise `tests.toml` file.
Expand Down Expand Up @@ -372,6 +371,7 @@ configlet generate <path/to/track> --spec-path path/to/problem/specifications
<br>
[.flake8]: https://github.com/exercism/python/blob/main/.flake8
[.style.yapf]: https://github.com/exercism/python/blob/main/.style.yapf
[american-english]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md
Expand All @@ -381,6 +381,7 @@ configlet generate <path/to/track> --spec-path path/to/problem/specifications
[concept-exercise-anatomy]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md
[concept-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md
[config-json]: https://github.com/exercism/javascript/blob/main/config.json
[config-json]: https://github.com/exercism/python/blob/main/config.json
[configlet-general]: https://github.com/exercism/configlet
[configlet-lint]: https://github.com/exercism/configlet#configlet-lint
[configlet]: https://github.com/exercism/docs/blob/main/building/configlet/generating-documents.md
Expand Down
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<p vertical-align="middle"><h1>Exercism Python Track</h1></p>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[![Discourse topics](https://img.shields.io/discourse/topics?color=8A08E6&label=Connect%20&labelColor=FFDF58&logo=Discourse&logoColor=8A08E6&server=https%3A%2F%2Fforum.exercism.org&style=social)](https://forum.exercism.org)
&nbsp;&nbsp;[![Exercism_II](https://img.shields.io/badge/Exercism--Built-9101FF?logo=python&logoColor=FFDF58&labelColor=3D7AAB&label=Python%203.10%20Powered)](https://exercism.org)
&nbsp;&nbsp;[![Exercism_II](https://img.shields.io/badge/Exercism--Built-9101FF?logo=python&logoColor=FFDF58&labelColor=3D7AAB&label=Python%203.11%20Powered)](https://exercism.org)
&nbsp;&nbsp;[![Exercism_III](https://img.shields.io/badge/PAUSED-C73D4E?labelColor=3D454D&label=Contributions)](https://exercism.org/blog/freeing-our-maintainers)
&nbsp; [![Build Status](https://github.com/exercism/python/workflows/Exercises%20check/badge.svg)](https://github.com/exercism/python/actions?query=workflow%3A%22Exercises+check%22)

Expand All @@ -17,11 +17,13 @@ Hi. &nbsp;👋🏽 &nbsp;👋 &nbsp;**We are happy you are here.**&nbsp; 🎉&nb
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.

🌟 &nbsp;&nbsp;Track exercises support Python `3.7` - `3.10.6`.
🌟 &nbsp;&nbsp;Track exercises support Python `3.7` - `3.11.2`.
Exceptions to this support are noted where they occur.
🌟 &nbsp;&nbsp;Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.10.6`.
🌟 &nbsp;&nbsp;Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`.

Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree &nbsp;🌴 &nbsp;. Concept exercises are constrained to a small set of language or syntax features. Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree &nbsp;🌴&nbsp;.
Concept exercises are constrained to a small set of language or syntax features.
Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.

<br><br>

Expand All @@ -43,24 +45,25 @@ It might also be helpful to look at [Being a Good Community Member][being-a-good

We&nbsp;💛&nbsp;💙 &nbsp; our community.
**`But our maintainers are not accepting community contributions at this time.`**
Please read this [community blog post](https://exercism.org/blog/freeing-our-maintainers) for details.
Please read this [community blog post][freeing-maintainers] for details.

<br>
<img align="left" width="95" height="85" src="https://github.com/exercism/website-icons/blob/main/exercises/boutique-suggestions.svg">
<img align="left" width="95" height="90" src="https://github.com/exercism/website-icons/blob/main/exercises/boutique-suggestions.svg">

Here to suggest a new feature or new exercise?? **Hooray!** &nbsp;🎉 &nbsp;
We'd love if you did that via our [Exercism Community Forum](https://forum.exercism.org/). Please keep in mind [Chesterton's Fence][chestertons-fence].
We'd love if you did that via our [Exercism Community Forum](https://forum.exercism.org/).
Please read [Suggesting Exercise Improvements][suggesting-improvements] & [Chesterton's Fence][chestertons-fence].
_Thoughtful suggestions will likely result faster & more enthusiastic responses from volunteers._

<br>

<img align="left" width="85" height="80" src="https://github.com/exercism/website-icons/blob/main/exercises/word-search.svg">

&nbsp;🦄&nbsp; _**Want to jump directly into Exercism specifications & detail?**_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Structure][exercism-track-structure] **|** [Tasks][exercism-tasks] **|** [Concepts][exercism-concepts] **|** [Concept Exercises][concept-exercises] **|** [Practice Exercises][practice-exercises] **|** [Presentation][exercise-presentation]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Writing Style Guide][exercism-writing-style] **|** [Markdown Specification][exercism-markdown-specification] (_✨ version in [contributing][website-contributing-section] on exercism.org_)

<br><br>
<br>
<br>

## Python Software and Documentation

Expand Down Expand Up @@ -94,10 +97,12 @@ This repository uses the [MIT License](/LICENSE).
[exercism-track-structure]: https://github.com/exercism/docs/tree/main/building/tracks
[exercism-website]: https://exercism.org/
[exercism-writing-style]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md
[freeing-maintainers]: https://exercism.org/blog/freeing-our-maintainers
[practice-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md
[prs]: https://github.com/exercism/docs/blob/main/community/good-member/pull-requests.md
[psf-license]: https://docs.python.org/3/license.html#psf-license
[python-syllabus]: https://exercism.org/tracks/python/concepts
[suggesting-improvements]: https://github.com/exercism/docs/blob/main/community/good-member/suggesting-exercise-improvements.md
[the-words-that-we-use]: https://github.com/exercism/docs/blob/main/community/good-member/words.md
[website-contributing-section]: https://exercism.org/docs/building
[zero-clause-bsd]: https://docs.python.org/3/license.html#zero-clause-bsd-license-for-code-in-the-python-release-documentation
11 changes: 9 additions & 2 deletions bin/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@
from itertools import chain
import json
from pathlib import Path
import tomli
from typing import List, Any, Dict, Type

# Tomli was subsumed into Python 3.11.x, but was renamed to to tomllib.
# This avoids ci failures for Python < 3.11.2.
try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib



def _custom_dataclass_init(self, *args, **kwargs):
# print(self.__class__.__name__, "__init__")
Expand Down Expand Up @@ -355,7 +362,7 @@ class TestsTOML:
@classmethod
def load(cls, toml_path: Path):
with toml_path.open("rb") as f:
data = tomli.load(f)
data = tomllib.load(f)
return cls({uuid: TestCaseTOML(uuid, *opts) for
uuid, opts in
data.items() if
Expand Down
50 changes: 38 additions & 12 deletions bin/generate_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
from githelp import Repo

_py = sys.version_info
if _py.major < 3 or (_py.major == 3 and _py.minor < 6):
print("Python version must be at least 3.6")
if _py.major < 3 or (_py.major == 3 and _py.minor < 7):
print("Python version must be at least 3.7")
sys.exit(1)

import argparse
from datetime import datetime
from datetime import timezone
import difflib
import filecmp
import importlib.util
Expand All @@ -34,11 +35,17 @@
from itertools import repeat
from string import punctuation, whitespace
from subprocess import check_call
import tomli
from tempfile import NamedTemporaryFile
from textwrap import wrap
from typing import Any, Dict, List, NoReturn, Union

# Tomli was subsumed into Python 3.11.x, but was renamed to to tomllib.
# This avoids ci failures for Python < 3.11.2.
try:
import tomllib
except ModuleNotFoundError:
import tomli as tomllib

from jinja2 import Environment, FileSystemLoader, TemplateNotFound, UndefinedError
from dateutil.parser import parse

Expand Down Expand Up @@ -254,6 +261,19 @@ def format_file(path: Path) -> NoReturn:


def check_template(slug: str, tests_path: Path, tmpfile: Path):
"""Generate a new test file and diff against existing file.
Note: The timestamp in each test file creates issues with
Python difflib, so it is skipped when being prepped
for diff.
You can see this "skipping" on lines 281 & 283.
However, this rather crude method creates
an empty "false positive" diff. This empty diff is
then skipped in lines 293 & 294, so that it can be
considered a pass..
"""

try:
check_ok = True
if not tmpfile.is_file():
Expand All @@ -264,20 +284,25 @@ def check_template(slug: str, tests_path: Path, tmpfile: Path):
check_ok = False
if check_ok and not filecmp.cmp(tmpfile, tests_path):
with tests_path.open() as f:
current_lines = f.readlines()
current_lines = f.readlines()[3:]
with tmpfile.open() as f:
rendered_lines = f.readlines()
diff = difflib.unified_diff(
rendered_lines = f.readlines()[3:]

diff = list(difflib.unified_diff(
current_lines,
rendered_lines,
fromfile=f"[current] {tests_path.name}",
tofile=f"[generated] {tmpfile.name}",
)
logger.debug(f"{slug}: ##### DIFF START #####")
for line in diff:
logger.debug(line.strip())
logger.debug(f"{slug}: ##### DIFF END #####")
check_ok = False
lineterm="\n",
))
if not diff:
check_ok = True
else:
logger.debug(f"{slug}: ##### DIFF START #####")
for line in diff:
logger.debug(line.strip())
logger.debug(f"{slug}: ##### DIFF END #####")
check_ok = False
if not check_ok:
logger.error(
f"{slug}: check failed; tests must be regenerated with bin/generate_tests.py"
Expand Down Expand Up @@ -387,6 +412,7 @@ def generate(
env.filters["zip"] = zip
env.filters["parse_datetime"] = parse_datetime
env.filters["escape_invalid_escapes"] = escape_invalid_escapes
env.globals["current_date"] = datetime.now(tz=timezone.utc).date()
env.tests["error_case"] = error_case
result = True
for exercise in sorted(Path("exercises/practice").glob(exercise_glob)):
Expand Down
2 changes: 1 addition & 1 deletion concepts/basics/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ On the Python track, [variables][variables] are always written in [`snake_case`]
## Name Assignment (Variables & Constants)

In Python, there are no keywords used in creating variables or constants.
Instead, programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables__) to any type of object using the assignment `=` operator: `<name> = <value>`.
Instead, programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: `<name> = <value>`.
A name can be reassigned (or re-bound) to different values (different object types) over its lifetime.

For example, `my_first_variable` can be re-assigned many times using `=`, and can refer to different object types with each re-assignment:
Expand Down
2 changes: 1 addition & 1 deletion concepts/basics/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Python was created by Guido van Rossum and first released in 1991.

## Name Assignment (Variables & Constants)

Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables__) to any type of object using the assignment `=` operator: `<name> = <value>`.
Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: `<name> = <value>`.
A name can be reassigned (or re-bound) to different values (different object types) over its lifetime.


Expand Down
4 changes: 4 additions & 0 deletions concepts/binary-octal-hexadecimal/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"blurb": "Other numerical systems in Python: binary (0b11), octal (0o71), and hex (0xFF)",
"authors": ["BethanyG", "meatball133"]
}
Loading

0 comments on commit 4a9fcb6

Please sign in to comment.