diff --git a/python/leap/.exercism/config.json b/python/leap/.exercism/config.json
new file mode 100644
index 0000000..1c35f22
--- /dev/null
+++ b/python/leap/.exercism/config.json
@@ -0,0 +1,38 @@
+{
+ "authors": [],
+ "contributors": [
+ "AnAccountForReportingBugs",
+ "behrtam",
+ "BethanyG",
+ "betojulio",
+ "cmccandless",
+ "cruxicheiros",
+ "Dog",
+ "fluxusfrequency",
+ "iandexter",
+ "ikhadykin",
+ "kytrinyx",
+ "lowks",
+ "N-Parsons",
+ "olufotebig",
+ "pheanex",
+ "sambryant4",
+ "sjakobi",
+ "tqa236",
+ "yawpitch"
+ ],
+ "files": {
+ "solution": [
+ "leap.py"
+ ],
+ "test": [
+ "leap_test.py"
+ ],
+ "example": [
+ ".meta/example.py"
+ ]
+ },
+ "blurb": "Determine whether a given year is a leap year.",
+ "source": "CodeRanch Cattle Drive, Assignment 3",
+ "source_url": "https://coderanch.com/t/718816/Leap"
+}
diff --git a/python/leap/.exercism/metadata.json b/python/leap/.exercism/metadata.json
new file mode 100644
index 0000000..48fc611
--- /dev/null
+++ b/python/leap/.exercism/metadata.json
@@ -0,0 +1 @@
+{"track":"python","exercise":"leap","id":"fd4b50a0ebbe49dc8e0b0c15b5551cfc","url":"https://exercism.org/tracks/python/exercises/leap","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
\ No newline at end of file
diff --git a/python/leap/HELP.md b/python/leap/HELP.md
new file mode 100644
index 0000000..13ed4ec
--- /dev/null
+++ b/python/leap/HELP.md
@@ -0,0 +1,130 @@
+# Help
+
+## Running the tests
+
+We use [pytest][pytest: Getting Started Guide] as our website test runner.
+You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
+You should also install the following `pytest` plugins:
+
+- [pytest-cache][pytest-cache]
+- [pytest-subtests][pytest-subtests]
+
+Extended information can be found in our website [Python testing guide][Python track tests page].
+
+
+### Running Tests
+
+To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
+Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
+
+Linux/MacOS
+```bash
+$ cd {path/to/exercise-folder-location}
+```
+
+Windows
+```powershell
+PS C:\Users\foobar> cd {path\to\exercise-folder-location}
+```
+
+
+
+Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
+
+Linux/MacOS
+```bash
+$ python3 -m pytest -o markers=task {exercise_test.py}
+==================== 7 passed in 0.08s ====================
+```
+
+Windows
+```powershell
+PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
+==================== 7 passed in 0.08s ====================
+```
+
+
+### Common options
+- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
+- `-v` : enable verbose output.
+- `-x` : stop running tests on first failure.
+- `--ff` : run failures from previous test before running other test cases.
+
+For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
+
+
+### Fixing warnings
+
+If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
+
+```bash
+PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
+```
+
+To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
+We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
+
+You can also create your own `pytest.ini` file with the following content:
+
+```ini
+[pytest]
+markers =
+ task: A concept exercise task.
+```
+
+Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
+More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
+
+Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
+
+
+### Extending your IDE or Code Editor
+
+Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
+Some community-sourced options can be found on our [Python track tools page][Python track tools page].
+
+[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
+[Python track tools page]: https://exercism.org/docs/tracks/python/tools
+[Python track tests page]: https://exercism.org/docs/tracks/python/tests
+[pytest-cache]:http://pythonhosted.org/pytest-cache/
+[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
+[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
+[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
+[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
+[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
+
+## Submitting your solution
+
+You can submit your solution using the `exercism submit leap.py` command.
+This command will upload your solution to the Exercism website and print the solution page's URL.
+
+It's possible to submit an incomplete solution which allows you to:
+
+- See how others have completed the exercise
+- Request help from a mentor
+
+## Need to get help?
+
+If you'd like help solving the exercise, check the following pages:
+
+- The [Python track's documentation](https://exercism.org/docs/tracks/python)
+- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
+- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
+- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
+
+Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
+
+Below are some resources for getting help if you run into trouble:
+
+- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
+- [The Exercism Community on Discord](https://exercism.org/r/discord)
+- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
+- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
+- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
+- [Python Community Forums](https://discuss.python.org/)
+- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
+- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
+- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
+
+Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
+ If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
\ No newline at end of file
diff --git a/python/leap/README.md b/python/leap/README.md
new file mode 100644
index 0000000..e41fdaf
--- /dev/null
+++ b/python/leap/README.md
@@ -0,0 +1,53 @@
+# Leap
+
+Welcome to Leap on Exercism's Python Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Introduction
+
+A leap year (in the Gregorian calendar) occurs:
+
+- In every year that is evenly divisible by 4.
+- Unless the year is evenly divisible by 100, in which case it's only a leap year if the year is also evenly divisible by 400.
+
+Some examples:
+
+- 1997 was not a leap year as it's not divisible by 4.
+- 1900 was not a leap year as it's not divisible by 400.
+- 2000 was a leap year!
+
+~~~~exercism/note
+For a delightful, four-minute explanation of the whole phenomenon of leap years, check out [this YouTube video](https://www.youtube.com/watch?v=xX96xng7sAE).
+~~~~
+
+## Instructions
+
+Your task is to determine whether a given year is a leap year.
+
+## Source
+
+### Contributed to by
+
+- @AnAccountForReportingBugs
+- @behrtam
+- @BethanyG
+- @betojulio
+- @cmccandless
+- @cruxicheiros
+- @Dog
+- @fluxusfrequency
+- @iandexter
+- @ikhadykin
+- @kytrinyx
+- @lowks
+- @N-Parsons
+- @olufotebig
+- @pheanex
+- @sambryant4
+- @sjakobi
+- @tqa236
+- @yawpitch
+
+### Based on
+
+CodeRanch Cattle Drive, Assignment 3 - https://coderanch.com/t/718816/Leap
\ No newline at end of file
diff --git a/python/leap/leap.py b/python/leap/leap.py
new file mode 100644
index 0000000..50fd034
--- /dev/null
+++ b/python/leap/leap.py
@@ -0,0 +1,2 @@
+def leap_year(year):
+ pass
diff --git a/python/leap/leap_test.py b/python/leap/leap_test.py
new file mode 100644
index 0000000..6a1d732
--- /dev/null
+++ b/python/leap/leap_test.py
@@ -0,0 +1,38 @@
+# These tests are auto-generated with test data from:
+# https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json
+# File last updated on 2023-07-19
+
+import unittest
+
+from leap import (
+ leap_year,
+)
+
+
+class LeapTest(unittest.TestCase):
+ def test_year_not_divisible_by_4_in_common_year(self):
+ self.assertIs(leap_year(2015), False)
+
+ def test_year_divisible_by_2_not_divisible_by_4_in_common_year(self):
+ self.assertIs(leap_year(1970), False)
+
+ def test_year_divisible_by_4_not_divisible_by_100_in_leap_year(self):
+ self.assertIs(leap_year(1996), True)
+
+ def test_year_divisible_by_4_and_5_is_still_a_leap_year(self):
+ self.assertIs(leap_year(1960), True)
+
+ def test_year_divisible_by_100_not_divisible_by_400_in_common_year(self):
+ self.assertIs(leap_year(2100), False)
+
+ def test_year_divisible_by_100_but_not_by_3_is_still_not_a_leap_year(self):
+ self.assertIs(leap_year(1900), False)
+
+ def test_year_divisible_by_400_is_leap_year(self):
+ self.assertIs(leap_year(2000), True)
+
+ def test_year_divisible_by_400_but_not_by_125_is_still_a_leap_year(self):
+ self.assertIs(leap_year(2400), True)
+
+ def test_year_divisible_by_200_not_divisible_by_400_in_common_year(self):
+ self.assertIs(leap_year(1800), False)
diff --git a/python/triangle/.exercism/config.json b/python/triangle/.exercism/config.json
new file mode 100644
index 0000000..041bf28
--- /dev/null
+++ b/python/triangle/.exercism/config.json
@@ -0,0 +1,36 @@
+{
+ "authors": [],
+ "contributors": [
+ "behrtam",
+ "BethanyG",
+ "cmccandless",
+ "Dog",
+ "ikhadykin",
+ "kytrinyx",
+ "lowks",
+ "mpatibandla",
+ "N-Parsons",
+ "Nishant23",
+ "pheanex",
+ "rozuur",
+ "sjakobi",
+ "Stigjb",
+ "tqa236",
+ "xitanggg",
+ "YuriyCherniy"
+ ],
+ "files": {
+ "solution": [
+ "triangle.py"
+ ],
+ "test": [
+ "triangle_test.py"
+ ],
+ "example": [
+ ".meta/example.py"
+ ]
+ },
+ "blurb": "Determine if a triangle is equilateral, isosceles, or scalene.",
+ "source": "The Ruby Koans triangle project, parts 1 & 2",
+ "source_url": "https://web.archive.org/web/20220831105330/http://rubykoans.com"
+}
diff --git a/python/triangle/.exercism/metadata.json b/python/triangle/.exercism/metadata.json
new file mode 100644
index 0000000..c4076e3
--- /dev/null
+++ b/python/triangle/.exercism/metadata.json
@@ -0,0 +1 @@
+{"track":"python","exercise":"triangle","id":"0cf58530790e46efaaeaed5ed8256e34","url":"https://exercism.org/tracks/python/exercises/triangle","handle":"DanielSiepmann","is_requester":true,"auto_approve":false}
\ No newline at end of file
diff --git a/python/triangle/HELP.md b/python/triangle/HELP.md
new file mode 100644
index 0000000..2d9233f
--- /dev/null
+++ b/python/triangle/HELP.md
@@ -0,0 +1,130 @@
+# Help
+
+## Running the tests
+
+We use [pytest][pytest: Getting Started Guide] as our website test runner.
+You will need to install `pytest` on your development machine if you want to run tests for the Python track locally.
+You should also install the following `pytest` plugins:
+
+- [pytest-cache][pytest-cache]
+- [pytest-subtests][pytest-subtests]
+
+Extended information can be found in our website [Python testing guide][Python track tests page].
+
+
+### Running Tests
+
+To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_).
+Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded.
+
+Linux/MacOS
+```bash
+$ cd {path/to/exercise-folder-location}
+```
+
+Windows
+```powershell
+PS C:\Users\foobar> cd {path\to\exercise-folder-location}
+```
+
+
+
+Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file:
+
+Linux/MacOS
+```bash
+$ python3 -m pytest -o markers=task {exercise_test.py}
+==================== 7 passed in 0.08s ====================
+```
+
+Windows
+```powershell
+PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py}
+==================== 7 passed in 0.08s ====================
+```
+
+
+### Common options
+- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_)
+- `-v` : enable verbose output.
+- `-x` : stop running tests on first failure.
+- `--ff` : run failures from previous test before running other test cases.
+
+For additional options, use `python3 -m pytest -h` or `py -m pytest -h`.
+
+
+### Fixing warnings
+
+If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax:
+
+```bash
+PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
+```
+
+To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file.
+We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini].
+
+You can also create your own `pytest.ini` file with the following content:
+
+```ini
+[pytest]
+markers =
+ task: A concept exercise task.
+```
+
+Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings.
+More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers].
+
+Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats].
+
+
+### Extending your IDE or Code Editor
+
+Many IDEs and code editors have built-in support for using `pytest` and other code quality tools.
+Some community-sourced options can be found on our [Python track tools page][Python track tools page].
+
+[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html
+[Python track tools page]: https://exercism.org/docs/tracks/python/tools
+[Python track tests page]: https://exercism.org/docs/tracks/python/tests
+[pytest-cache]:http://pythonhosted.org/pytest-cache/
+[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests
+[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini
+[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats
+[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks
+[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers
+
+## Submitting your solution
+
+You can submit your solution using the `exercism submit triangle.py` command.
+This command will upload your solution to the Exercism website and print the solution page's URL.
+
+It's possible to submit an incomplete solution which allows you to:
+
+- See how others have completed the exercise
+- Request help from a mentor
+
+## Need to get help?
+
+If you'd like help solving the exercise, check the following pages:
+
+- The [Python track's documentation](https://exercism.org/docs/tracks/python)
+- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python)
+- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
+- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
+
+Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
+
+Below are some resources for getting help if you run into trouble:
+
+- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
+- [The Exercism Community on Discord](https://exercism.org/r/discord)
+- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
+- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
+- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done.
+- [Python Community Forums](https://discuss.python.org/)
+- [Free Code Camp Community Forums](https://forum.freecodecamp.org/)
+- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help)
+- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
+
+Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
+ If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.
\ No newline at end of file
diff --git a/python/triangle/README.md b/python/triangle/README.md
new file mode 100644
index 0000000..961c673
--- /dev/null
+++ b/python/triangle/README.md
@@ -0,0 +1,60 @@
+# Triangle
+
+Welcome to Triangle on Exercism's Python Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Instructions
+
+Determine if a triangle is equilateral, isosceles, or scalene.
+
+An _equilateral_ triangle has all three sides the same length.
+
+An _isosceles_ triangle has at least two sides the same length.
+(It is sometimes specified as having exactly two sides the same length, but for the purposes of this exercise we'll say at least two.)
+
+A _scalene_ triangle has all sides of different lengths.
+
+## Note
+
+For a shape to be a triangle at all, all sides have to be of length > 0, and the sum of the lengths of any two sides must be greater than or equal to the length of the third side.
+
+In equations:
+
+Let `a`, `b`, and `c` be sides of the triangle.
+Then all three of the following expressions must be true:
+
+```text
+a + b ≥ c
+b + c ≥ a
+a + c ≥ b
+```
+
+See [Triangle Inequality][triangle-inequality]
+
+[triangle-inequality]: https://en.wikipedia.org/wiki/Triangle_inequality
+
+## Source
+
+### Contributed to by
+
+- @behrtam
+- @BethanyG
+- @cmccandless
+- @Dog
+- @ikhadykin
+- @kytrinyx
+- @lowks
+- @mpatibandla
+- @N-Parsons
+- @Nishant23
+- @pheanex
+- @rozuur
+- @sjakobi
+- @Stigjb
+- @tqa236
+- @xitanggg
+- @YuriyCherniy
+
+### Based on
+
+The Ruby Koans triangle project, parts 1 & 2 - https://web.archive.org/web/20220831105330/http://rubykoans.com
\ No newline at end of file
diff --git a/python/triangle/triangle.py b/python/triangle/triangle.py
new file mode 100644
index 0000000..3d088c7
--- /dev/null
+++ b/python/triangle/triangle.py
@@ -0,0 +1,10 @@
+def equilateral(sides):
+ pass
+
+
+def isosceles(sides):
+ pass
+
+
+def scalene(sides):
+ pass
diff --git a/python/triangle/triangle_test.py b/python/triangle/triangle_test.py
new file mode 100644
index 0000000..b279c83
--- /dev/null
+++ b/python/triangle/triangle_test.py
@@ -0,0 +1,80 @@
+# These tests are auto-generated with test data from:
+# https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json
+# File last updated on 2023-07-19
+
+import unittest
+
+from triangle import (
+ equilateral,
+ isosceles,
+ scalene,
+)
+
+
+class EquilateralTriangleTest(unittest.TestCase):
+ def test_all_sides_are_equal(self):
+ self.assertIs(equilateral([2, 2, 2]), True)
+
+ def test_any_side_is_unequal(self):
+ self.assertIs(equilateral([2, 3, 2]), False)
+
+ def test_no_sides_are_equal(self):
+ self.assertIs(equilateral([5, 4, 6]), False)
+
+ def test_all_zero_sides_is_not_a_triangle(self):
+ self.assertIs(equilateral([0, 0, 0]), False)
+
+ def test_sides_may_be_floats(self):
+ self.assertIs(equilateral([0.5, 0.5, 0.5]), True)
+
+
+class IsoscelesTriangleTest(unittest.TestCase):
+ def test_last_two_sides_are_equal(self):
+ self.assertIs(isosceles([3, 4, 4]), True)
+
+ def test_first_two_sides_are_equal(self):
+ self.assertIs(isosceles([4, 4, 3]), True)
+
+ def test_first_and_last_sides_are_equal(self):
+ self.assertIs(isosceles([4, 3, 4]), True)
+
+ def test_equilateral_triangles_are_also_isosceles(self):
+ self.assertIs(isosceles([4, 4, 4]), True)
+
+ def test_no_sides_are_equal(self):
+ self.assertIs(isosceles([2, 3, 4]), False)
+
+ def test_first_triangle_inequality_violation(self):
+ self.assertIs(isosceles([1, 1, 3]), False)
+
+ def test_second_triangle_inequality_violation(self):
+ self.assertIs(isosceles([1, 3, 1]), False)
+
+ def test_third_triangle_inequality_violation(self):
+ self.assertIs(isosceles([3, 1, 1]), False)
+
+ def test_sides_may_be_floats(self):
+ self.assertIs(isosceles([0.5, 0.4, 0.5]), True)
+
+
+class ScaleneTriangleTest(unittest.TestCase):
+ def test_no_sides_are_equal(self):
+ self.assertIs(scalene([5, 4, 6]), True)
+
+ def test_all_sides_are_equal(self):
+ self.assertIs(scalene([4, 4, 4]), False)
+
+ def test_first_and_second_sides_are_equal(self):
+ self.assertIs(scalene([4, 4, 3]), False)
+
+ def test_first_and_third_sides_are_equal(self):
+ self.assertIs(scalene([3, 4, 3]), False)
+
+ def test_second_and_third_sides_are_equal(self):
+ self.assertIs(scalene([4, 3, 3]), False)
+
+ def test_may_not_violate_triangle_inequality(self):
+ self.assertIs(scalene([7, 3, 2]), False)
+
+ def test_sides_may_be_floats(self):
+ self.assertIs(scalene([0.5, 0.4, 0.6]), True)