Skip to content

Commit f299755

Browse files
authored
Merge branch 'canbula:master' into master
2 parents 85b4b82 + 8415c79 commit f299755

8 files changed

Lines changed: 275 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3+
4+
name: Week05 Homework
5+
6+
on:
7+
push:
8+
branches: ["master"]
9+
paths: ["Week05/**"]
10+
pull_request:
11+
branches: ["master"]
12+
paths: ["Week05/**"]
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v3
23+
- name: Set up Python 3.12
24+
uses: actions/setup-python@v3
25+
with:
26+
python-version: "3.12"
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install flake8 pytest
31+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
32+
- name: Lint with flake8
33+
run: |
34+
# stop the build if there are Python syntax errors or undefined names
35+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
36+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38+
- name: Test with pytest
39+
run: |
40+
pytest -q --tb=no 'Week05/test_emails.py'

‎Week01/info_batuhan_keskin.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
student_id = "230315022"
2+
full_name = "Batuhan Keskin"

‎Week01/info_ferhat_kilic.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
student_id = "220315050"
2+
full_name = "Ferhat Kılıç"

‎Week02/types_hilmican_karadag.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
my_int = 10
2+
my_float = 3.14
3+
my_bool = True
4+
my_complex = 3 + 9j

‎Week03/pyramid_hilmican_karadag.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def calculate_pyramid_height(number_of_blocks):
2+
height = 0
3+
blocks_needed = 1
4+
5+
while number_of_blocks >= blocks_needed:
6+
number_of_blocks -= blocks_needed
7+
height += 1
8+
blocks_needed += 1
9+
10+
return height
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
def remove_duplicates(seq: list) -> list:
2+
"""
3+
This function removes duplicates from a list.
4+
"""
5+
result = []
6+
for item in seq:
7+
if item not in result:
8+
result.append(item)
9+
return result
10+
11+
12+
def list_counts(seq: list) -> dict:
13+
"""
14+
This function counts the number of occurrences of each item in a list.
15+
"""
16+
counts = {}
17+
for item in seq:
18+
counts[item] = counts.get(item, 0) + 1
19+
return counts
20+
21+
22+
def reverse_dict(d: dict) -> dict:
23+
"""
24+
This function reverses the keys and values of a dictionary.
25+
"""
26+
return {value: key for key, value in d.items()}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import functools
2+
import time
3+
import tracemalloc
4+
5+
6+
def performance(fn):
7+
"""
8+
Decorator that measures execution time and memory of the wrapped function.
9+
10+
Statistics are stored as attributes on the decorator itself:
11+
12+
- ``performance.counter``: number of decorated-function calls
13+
- ``performance.total_time``: total time spent in seconds
14+
- ``performance.total_mem``: total memory consumed in bytes
15+
16+
:param fn: the function to decorate
17+
:type fn: callable
18+
:return: the wrapped function
19+
:rtype: callable
20+
"""
21+
22+
@functools.wraps(fn)
23+
def wrapper(*args, **kwargs):
24+
started_here = not tracemalloc.is_tracing()
25+
if started_here:
26+
tracemalloc.start()
27+
tracemalloc.reset_peak()
28+
mem_before = tracemalloc.get_traced_memory()[0]
29+
start = time.perf_counter()
30+
31+
try:
32+
return fn(*args, **kwargs)
33+
finally:
34+
elapsed = time.perf_counter() - start
35+
peak = tracemalloc.get_traced_memory()[1]
36+
if started_here:
37+
tracemalloc.stop()
38+
performance.counter += 1
39+
performance.total_time += elapsed
40+
performance.total_mem += max(peak - mem_before, 0)
41+
42+
return wrapper
43+
44+
45+
performance.counter = 0
46+
performance.total_time = 0.0
47+
performance.total_mem = 0
48+
49+
50+
if __name__ == "__main__":
51+
52+
@performance
53+
def build_list(n: int) -> list[int]:
54+
return [i * i for i in range(n)]
55+
56+
build_list(100_000)
57+
build_list(50_000)
58+
print(performance.counter, performance.total_time, performance.total_mem)

‎Week05/test_emails.py‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import os
2+
import pytest
3+
4+
5+
files = [f for f in os.listdir(os.path.dirname(__file__)) if f.startswith("emails")]
6+
for f in files:
7+
exec("import " + f[:-3] + " as " + f[:-3])
8+
9+
10+
# test the file if it has the Emails class
11+
def test_names():
12+
for f in files:
13+
assert "Emails" in dir(eval(f[:-3])), "Emails is not defined in " + f[:-3]
14+
15+
16+
# test the Emails class if it is a subclass of list
17+
def test_subclass():
18+
for f in files:
19+
assert issubclass(eval(f[:-3]).Emails, list), (
20+
"Emails is not a subclass of list in " + f[:-3]
21+
)
22+
23+
24+
# check if the Emails class is an instance of the list class
25+
def test_instance():
26+
for f in files:
27+
assert isinstance(eval(f[:-3]).Emails([]), list), (
28+
"Emails is not an instance of list in " + f[:-3]
29+
)
30+
31+
32+
# test the Emails class if it has the validate method
33+
def test_validate():
34+
for f in files:
35+
assert "validate" in dir(eval(f[:-3]).Emails), (
36+
"validate is not defined in " + f[:-3]
37+
)
38+
assert callable(eval(f[:-3]).Emails.validate), (
39+
"validate is not callable in " + f[:-3]
40+
)
41+
42+
43+
# test the Emails class if it has the __init__ method
44+
def test_init():
45+
for f in files:
46+
assert "__init__" in dir(eval(f[:-3]).Emails), (
47+
"__init__ is not defined in " + f[:-3]
48+
)
49+
assert callable(eval(f[:-3]).Emails.__init__), (
50+
"__init__ is not callable in " + f[:-3]
51+
)
52+
53+
54+
# test the Emails class if it has the __repr__ method
55+
def test_repr():
56+
for f in files:
57+
assert "__repr__" in dir(eval(f[:-3]).Emails), (
58+
"__repr__ is not defined in " + f[:-3]
59+
)
60+
assert callable(eval(f[:-3]).Emails.__repr__), (
61+
"__repr__ is not callable in " + f[:-3]
62+
)
63+
64+
65+
# check Emails class can reproduce itself with the __repr__ method
66+
def test_repr_output():
67+
for f in files:
68+
assert (
69+
repr(eval(f[:-3]).Emails(["bora.canbula@cbu.edu.tr", "bora@canbula.com"]))
70+
== (
71+
eval(f[:-3]).Emails(["bora.canbula@cbu.edu.tr", "bora@canbula.com"])
72+
).__repr__()
73+
), (
74+
"The Emails class does not reproduce itself with the __repr__ method in "
75+
+ f[:-3]
76+
)
77+
78+
79+
# test the Emails class if it has the __str__ method
80+
def test_str():
81+
for f in files:
82+
assert "__str__" in dir(eval(f[:-3]).Emails), (
83+
"__str__ is not defined in " + f[:-3]
84+
)
85+
assert callable(eval(f[:-3]).Emails.__str__), (
86+
"__str__ is not callable in " + f[:-3]
87+
)
88+
89+
90+
# check if the validate method allows only strings
91+
def test_validate_strings():
92+
for f in files:
93+
with pytest.raises(ValueError) as e:
94+
eval(f[:-3]).Emails([1, 2, 3])
95+
assert str(e.type) == "<class 'ValueError'>", (
96+
"The validate method does not allow only strings in " + f[:-3]
97+
)
98+
99+
100+
# check if the validate method allows only valid email addresses, and raises ValueError otherwise
101+
def test_validate_emails():
102+
for f in files:
103+
with pytest.raises(ValueError) as e:
104+
eval(f[:-3]).Emails(["bora.canbula@cbu.edu.tr", "canbula.com"])
105+
assert str(e.type) == "<class 'ValueError'>", (
106+
"The validate method does not allow only valid email addresses in "
107+
+ f[:-3]
108+
)
109+
with pytest.raises(ValueError) as e:
110+
eval(f[:-3]).Emails(["bora@canbulacom"])
111+
assert str(e.type) == "<class 'ValueError'>", (
112+
"The validate method does not allow only valid email addresses in "
113+
+ f[:-3]
114+
)
115+
116+
117+
# check Emails class does not allow duplicate email addresses, the order is not important
118+
def test_validate_duplicates():
119+
for f in files:
120+
assert (
121+
eval(f[:-3])
122+
.Emails(
123+
[
124+
"bora.canbula@cbu.edu.tr",
125+
"bora@canbula.com",
126+
"bora.canbula@cbu.edu.tr",
127+
]
128+
)
129+
.data.count("bora.canbula@cbu.edu.tr")
130+
== 1
131+
), (
132+
"The Emails class does not allow duplicate email addresses in " + f[:-3]
133+
)

0 commit comments

Comments
 (0)