Skip to content

Commit

Permalink
Replaced YAPF with black (#265)
Browse files Browse the repository at this point in the history
YAPF was giving us headaches as the reformattings were neither intuitive
nor predictable. We wanted to upgrade for Python 3.11, and tried to
upgrade YAPF to the latest version. As it caused a lot of reformatting,
we decided to drop YAPF and replace it with black.

Black seems a bit more stable, and subjectively gives us nicer
formatting.
  • Loading branch information
mristin authored Sep 15, 2023
1 parent 44d5596 commit a3061d2
Show file tree
Hide file tree
Showing 53 changed files with 3,104 additions and 1,240 deletions.
90 changes: 61 additions & 29 deletions benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
import cpuinfo

import icontract

"""Run benchmarks and, if specified, overwrite README."""


def benchmark_against_others(repo_root: pathlib.Path, overwrite: bool) -> None:
"""Run benchmars against other libraries and include them in the Readme."""
script_rel_paths = [
'benchmarks/against_others/compare_invariant.py', 'benchmarks/against_others/compare_precondition.py',
'benchmarks/against_others/compare_postcondition.py'
"benchmarks/against_others/compare_invariant.py",
"benchmarks/against_others/compare_precondition.py",
"benchmarks/against_others/compare_postcondition.py",
]

if not overwrite:
Expand All @@ -24,58 +26,88 @@ def benchmark_against_others(repo_root: pathlib.Path, overwrite: bool) -> None:
print()
subprocess.check_call([sys.executable, str(repo_root / script_rel_path)])
else:
out = ['The following scripts were run:\n\n']
out = ["The following scripts were run:\n\n"]
for script_rel_path in script_rel_paths:
out.append('* `{0} <https://github.com/Parquery/icontract/tree/master/{0}>`_\n'.format(script_rel_path))
out.append('\n')

out.append(('The benchmarks were executed on {}.\nWe used Python {}, '
'icontract {}, deal 4.23.3 and dpcontracts 0.6.0.\n\n').format(cpuinfo.get_cpu_info()['brand'],
platform.python_version(),
icontract.__version__))

out.append('The following tables summarize the results.\n\n')
out.append(
"* `{0} <https://github.com/Parquery/icontract/tree/master/{0}>`_\n".format(
script_rel_path
)
)
out.append("\n")

out.append(
(
"The benchmarks were executed on {}.\nWe used Python {}, "
"icontract {}, deal 4.23.3 and dpcontracts 0.6.0.\n\n"
).format(
cpuinfo.get_cpu_info()["brand"],
platform.python_version(),
icontract.__version__,
)
)

out.append("The following tables summarize the results.\n\n")
stdouts = [] # type: List[str]

for script_rel_path in script_rel_paths:
stdout = subprocess.check_output([sys.executable, str(repo_root / script_rel_path)]).decode()
stdout = subprocess.check_output(
[sys.executable, str(repo_root / script_rel_path)]
).decode()
stdouts.append(stdout)

out.append(stdout)
out.append('\n')
out.append("\n")

readme_path = repo_root / "docs" / "source" / "benchmarks.rst"
readme = readme_path.read_text(encoding='utf-8')
marker_start = '.. Becnhmark report from benchmark.py starts.'
marker_end = '.. Benchmark report from benchmark.py ends.'
readme = readme_path.read_text(encoding="utf-8")
marker_start = ".. Becnhmark report from benchmark.py starts."
marker_end = ".. Benchmark report from benchmark.py ends."
lines = readme.splitlines()

try:
index_start = lines.index(marker_start)
except ValueError as exc:
raise ValueError('Could not find the marker for the benchmarks in the {}: {}'.format(
readme_path, marker_start)) from exc
raise ValueError(
"Could not find the marker for the benchmarks in the {}: {}".format(
readme_path, marker_start
)
) from exc

try:
index_end = lines.index(marker_end)
except ValueError as exc:
raise ValueError('Could not find the start marker for the benchmarks in the {}: {}'.format(
readme_path, marker_end)) from exc

assert index_start < index_end, 'Unexpected end marker before start marker for the benchmarks.'

lines = lines[:index_start + 1] + ['\n'] + (''.join(out)).splitlines() + ['\n'] + lines[index_end:]
readme_path.write_text('\n'.join(lines) + '\n', encoding='utf-8')
raise ValueError(
"Could not find the start marker for the benchmarks in the {}: {}".format(
readme_path, marker_end
)
) from exc

assert (
index_start < index_end
), "Unexpected end marker before start marker for the benchmarks."

lines = (
lines[: index_start + 1]
+ ["\n"]
+ ("".join(out)).splitlines()
+ ["\n"]
+ lines[index_end:]
)
readme_path.write_text("\n".join(lines) + "\n", encoding="utf-8")

# This is necessary so that the benchmarks do not complain on a Windows machine if the console encoding has not
# been properly set.
sys.stdout.buffer.write(('\n\n'.join(stdouts) + '\n').encode('utf-8'))
sys.stdout.buffer.write(("\n\n".join(stdouts) + "\n").encode("utf-8"))


def main() -> int:
""""Execute main routine."""
""" "Execute main routine."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--overwrite", help="Overwrites the corresponding section in the docs.", action='store_true')
parser.add_argument(
"--overwrite",
help="Overwrites the corresponding section in the docs.",
action="store_true",
)

args = parser.parse_args()

Expand Down
33 changes: 20 additions & 13 deletions benchmarks/against_others/compare_invariant.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self, identifier: str) -> None:
self.parts = identifier.split(".")

def some_func(self) -> str:
return '.'.join(self.parts)
return ".".join(self.parts)


@dpcontracts.invariant("some dummy invariant", lambda self: len(self.parts) > 0)
Expand All @@ -31,7 +31,7 @@ def __init__(self, identifier: str) -> None:
self.parts = identifier.split(".")

def some_func(self) -> str:
return '.'.join(self.parts)
return ".".join(self.parts)


@deal.inv(validator=lambda self: len(self.parts) > 0, message="some dummy invariant")
Expand All @@ -40,7 +40,7 @@ def __init__(self, identifier: str) -> None:
self.parts = identifier.split(".")

def some_func(self) -> str:
return '.'.join(self.parts)
return ".".join(self.parts)


class ClassWithInlineContract:
Expand All @@ -50,18 +50,18 @@ def __init__(self, identifier: str) -> None:

def some_func(self) -> str:
assert len(self.parts) > 0
result = '.'.join(self.parts)
result = ".".join(self.parts)
assert len(self.parts) > 0
return result


# dpcontracts change __name__ attribute of the class, so we can not use
# ClassWithDpcontractsInvariant.__name__ for a more maintainable list.
clses = [
'ClassWithIcontract',
'ClassWithDpcontracts',
'ClassWithDeal',
'ClassWithInlineContract',
"ClassWithIcontract",
"ClassWithDpcontracts",
"ClassWithDeal",
"ClassWithInlineContract",
]


Expand All @@ -72,8 +72,8 @@ def writeln_utf8(text: str) -> None:
We can not use ``print()`` as we can not rely on the correct encoding in Windows.
See: https://stackoverflow.com/questions/31469707/changing-the-locale-preferred-encoding-in-python-3-in-windows
"""
sys.stdout.buffer.write(text.encode('utf-8'))
sys.stdout.buffer.write(os.linesep.encode('utf-8'))
sys.stdout.buffer.write(text.encode("utf-8"))
sys.stdout.buffer.write(os.linesep.encode("utf-8"))


def measure_invariant_at_init() -> None:
Expand All @@ -82,7 +82,11 @@ def measure_invariant_at_init() -> None:
number = 1 * 1000 * 1000

for i, cls in enumerate(clses):
duration = timeit.timeit("{}('X.Y')".format(cls), setup="from __main__ import {}".format(cls), number=number)
duration = timeit.timeit(
"{}('X.Y')".format(cls),
setup="from __main__ import {}".format(cls),
number=number,
)
durations[i] = duration

writeln_utf8("Benchmarking invariant at __init__:\n")
Expand Down Expand Up @@ -116,7 +120,10 @@ def measure_invariant_at_function() -> None:

for i, cls in enumerate(clses):
duration = timeit.timeit(
"a.some_func()", setup="from __main__ import {0}; a = {0}('X.Y')".format(cls), number=number)
"a.some_func()",
setup="from __main__ import {0}; a = {0}('X.Y')".format(cls),
number=number,
)
durations[i] = duration

writeln_utf8("Benchmarking invariant at a function:\n")
Expand Down Expand Up @@ -145,5 +152,5 @@ def measure_invariant_at_function() -> None:

if __name__ == "__main__":
measure_invariant_at_init()
writeln_utf8('')
writeln_utf8("")
measure_invariant_at_function()
19 changes: 13 additions & 6 deletions benchmarks/against_others/compare_postcondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,29 @@ def writeln_utf8(text: str) -> None:
We can not use ``print()`` as we can not rely on the correct encoding in Windows.
See: https://stackoverflow.com/questions/31469707/changing-the-locale-preferred-encoding-in-python-3-in-windows
"""
sys.stdout.buffer.write(text.encode('utf-8'))
sys.stdout.buffer.write(os.linesep.encode('utf-8'))
sys.stdout.buffer.write(text.encode("utf-8"))
sys.stdout.buffer.write(os.linesep.encode("utf-8"))


def measure_functions() -> None:
funcs = [
'function_with_icontract', 'function_with_dpcontracts', 'function_with_deal_post', 'function_with_deal_ensure',
'function_with_inline_contract'
"function_with_icontract",
"function_with_dpcontracts",
"function_with_deal_post",
"function_with_deal_ensure",
"function_with_inline_contract",
]

durations = [0.0] * len(funcs)

number = 10 * 1000

for i, func in enumerate(funcs):
duration = timeit.timeit("{}(198.4)".format(func), setup="from __main__ import {}".format(func), number=number)
duration = timeit.timeit(
"{}(198.4)".format(func),
setup="from __main__ import {}".format(func),
number=number,
)
durations[i] = duration

table = [] # type: List[List[str]]
Expand Down Expand Up @@ -92,5 +99,5 @@ def measure_functions() -> None:

if __name__ == "__main__":
writeln_utf8("Benchmarking postcondition:")
writeln_utf8('')
writeln_utf8("")
measure_functions()
19 changes: 13 additions & 6 deletions benchmarks/against_others/compare_precondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def function_with_deal(some_arg: int) -> float:


def function_with_inline_contract(some_arg: int) -> float:
assert (some_arg > 0)
assert some_arg > 0
return math.sqrt(some_arg)


Expand All @@ -48,21 +48,28 @@ def writeln_utf8(text: str) -> None:
We can not use ``print()`` as we can not rely on the correct encoding in Windows.
See: https://stackoverflow.com/questions/31469707/changing-the-locale-preferred-encoding-in-python-3-in-windows
"""
sys.stdout.buffer.write(text.encode('utf-8'))
sys.stdout.buffer.write(os.linesep.encode('utf-8'))
sys.stdout.buffer.write(text.encode("utf-8"))
sys.stdout.buffer.write(os.linesep.encode("utf-8"))


def measure_functions() -> None:
funcs = [
'function_with_icontract', 'function_with_dpcontracts', 'function_with_deal', 'function_with_inline_contract'
"function_with_icontract",
"function_with_dpcontracts",
"function_with_deal",
"function_with_inline_contract",
]

durations = [0.0] * len(funcs)

number = 10 * 1000

for i, func in enumerate(funcs):
duration = timeit.timeit("{}(198.4)".format(func), setup="from __main__ import {}".format(func), number=number)
duration = timeit.timeit(
"{}(198.4)".format(func),
setup="from __main__ import {}".format(func),
number=number,
)
durations[i] = duration

table = [] # type: List[List[str]]
Expand Down Expand Up @@ -90,5 +97,5 @@ def measure_functions() -> None:

if __name__ == "__main__":
writeln_utf8("Benchmarking precondition:")
writeln_utf8('')
writeln_utf8("")
measure_functions()
33 changes: 25 additions & 8 deletions benchmarks/import_cost/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ def generate_functions(functions: int, contracts: int, disabled: bool) -> str:
if not disabled:
out.write("@icontract.require(lambda x: x > {})\n".format(j))
else:
out.write("@icontract.require(lambda x: x > {}, enabled=False)\n".format(j))
out.write(
"@icontract.require(lambda x: x > {}, enabled=False)\n".format(j)
)

out.write("def some_func{}(x: int) -> None:\n pass\n".format(i))

Expand All @@ -42,25 +44,36 @@ def generate_classes(classes: int, invariants: int, disabled: bool) -> str:
if not disabled:
out.write("@icontract.invariant(lambda self: self.x > {})\n".format(j))
else:
out.write("@icontract.invariant(lambda self: self.x > {}, enabled=False)\n".format(j))
out.write(
"@icontract.invariant(lambda self: self.x > {}, enabled=False)\n".format(
j
)
)

out.write(
textwrap.dedent("""\
textwrap.dedent(
"""\
class SomeClass{}:
def __init__(self) -> None:
self.x = 100
def some_func(self) -> None:
pass
""".format(i)))
""".format(
i
)
)
)

return out.getvalue()


def main() -> None:
""""Execute the main routine."""
""" "Execute the main routine."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--outdir", help="output directory", default=os.path.dirname(__file__))
parser.add_argument(
"--outdir", help="output directory", default=os.path.dirname(__file__)
)
args = parser.parse_args()

outdir = pathlib.Path(args.outdir)
Expand All @@ -82,7 +95,9 @@ def main() -> None:
if contracts == 1:
pth = outdir / "functions_100_with_1_disabled_contract.py"
else:
pth = outdir / "functions_100_with_{}_disabled_contracts.py".format(contracts)
pth = outdir / "functions_100_with_{}_disabled_contracts.py".format(
contracts
)

text = generate_functions(functions=100, contracts=contracts, disabled=True)
pth.write_text(text)
Expand All @@ -102,7 +117,9 @@ def main() -> None:
if invariants == 1:
pth = outdir / "classes_100_with_1_disabled_invariant.py"
else:
pth = outdir / "classes_100_with_{}_disabled_invariants.py".format(invariants)
pth = outdir / "classes_100_with_{}_disabled_invariants.py".format(
invariants
)

text = generate_classes(classes=100, invariants=invariants, disabled=True)
pth.write_text(text)
Expand Down
Loading

0 comments on commit a3061d2

Please sign in to comment.