From 23c5fbf1a70ca5778a53ebd7699c65c5ea83f46f Mon Sep 17 00:00:00 2001 From: Martin Hloska Date: Wed, 29 Dec 2021 15:08:04 +0100 Subject: [PATCH] feat: add db benchmark (#9) * refactor: separate benchmark command * add db benchmark command --- bench_wizard/__version__.py | 2 +- bench_wizard/benchmark.py | 140 ++++++++++------------------ bench_wizard/config.py | 21 ----- bench_wizard/db_bench.py | 47 ++++++---- bench_wizard/main.py | 114 ++++++++++++----------- bench_wizard/output.py | 50 +++++++++- bench_wizard/parser.py | 5 +- bench_wizard/performance.py | 176 ++++++++++++++++++++++++++++++++++++ poetry.lock | 96 +++++++++++++++++++- pyproject.toml | 3 +- tests/test_bench_wizard.py | 2 +- 11 files changed, 464 insertions(+), 192 deletions(-) delete mode 100644 bench_wizard/config.py create mode 100644 bench_wizard/performance.py diff --git a/bench_wizard/__version__.py b/bench_wizard/__version__.py index df12433..3d18726 100644 --- a/bench_wizard/__version__.py +++ b/bench_wizard/__version__.py @@ -1 +1 @@ -__version__ = "0.4.2" +__version__ = "0.5.0" diff --git a/bench_wizard/benchmark.py b/bench_wizard/benchmark.py index 85abf77..841cf2c 100644 --- a/bench_wizard/benchmark.py +++ b/bench_wizard/benchmark.py @@ -1,53 +1,51 @@ -import json +from __future__ import annotations + import os import subprocess -from typing import List +from dataclasses import dataclass +from typing import List, Optional from bench_wizard.cargo import Cargo -from bench_wizard.config import Config from bench_wizard.exceptions import BenchmarkCargoException from bench_wizard.output import Output -from bench_wizard.parser import BenchmarkParser -# TODO: need as configurable option -DIFF_MARGIN = 10 # percent +@dataclass +class BenchmarksConfig: + pallets: [str] + dump_results: Optional[str] = None + output_dir: Optional[str] = None + template: Optional[str] = None class Benchmark: - """ Represents single benchmark""" + """Represents single benchmark""" - def __init__(self, pallet: str, command: [str], ref_value: float, extrinsics: list): + def __init__(self, pallet: str, command: [str]): self._pallet = pallet self._stdout = None self._command = command - self._ref_value = ref_value - self._extrinsics = extrinsics - - self._extrinsics_results = [] - self._total_time = 0 self._completed = False self._acceptable = False self._rerun = False + self._error = False + self._error_reason = None + @property def pallet(self): return self._pallet - @property - def acceptable(self) -> bool: - return self._acceptable - - @acceptable.setter - def acceptable(self, value: bool): - self._acceptable = value - @property def completed(self) -> bool: return self._completed + @property + def is_error(self) -> bool: + return self._error + @property def raw(self) -> bytes: return self._stdout @@ -57,19 +55,11 @@ def run(self, rerun: bool = False) -> None: result = subprocess.run(self._command, capture_output=True) if result.returncode != 0: - raise BenchmarkCargoException(result.stderr.decode("utf-8")) + self._error = True + self._error_reason = result.stderr.decode("utf-8") + return self._stdout = result.stdout - - parser = BenchmarkParser(result.stdout) - - self._total_time = parser.total_time(self._extrinsics) - - margin = int(self._ref_value * DIFF_MARGIN / 100) - - diff = int(self._ref_value - self._total_time) - - self.acceptable = diff >= -margin self._rerun = rerun self._completed = True @@ -78,60 +68,36 @@ def dump(self, dest: str) -> None: with open(os.path.join(dest, f"{self._pallet}.results"), "wb") as f: f.write(self._stdout) - @property - def ref_value(self): - return self._ref_value - - @property - def total_time(self): - return self._total_time - @property def rerun(self): return self._rerun - @property - def percentage(self) -> float: - diff = int(self._ref_value - self._total_time) - - percentage = (diff / self._ref_value) * 100 - - return percentage - -def _prepare_benchmarks(config: Config, reference_values: dict) -> List[Benchmark]: +def _prepare_benchmarks(config: BenchmarksConfig) -> List[Benchmark]: benchmarks = [] for pallet in config.pallets: cargo = Cargo(pallet=pallet, template=config.template) + if config.output_dir: output_file = os.path.join(config.output_dir, f"{pallet}.rs") cargo.output = output_file - ref_data = reference_values[pallet] - ref_value = sum(list(map(lambda x: float(x), ref_data.values()))) - benchmarks.append( - Benchmark(pallet, cargo.command(), ref_value, ref_data.keys()) - ) + benchmarks.append(Benchmark(pallet, cargo.command())) return benchmarks -def _run_benchmarks(benchmarks: List[Benchmark], output: Output, rerun=False) -> None: - # Note : this can be simplified into one statement - - if rerun: - [bench.run(rerun) for bench in benchmarks if bench.acceptable is False] - else: - output.track(benchmarks) - for bench in benchmarks: - # Output updates to easily show progress - output.update(bench) - bench.run() - output.update(bench) +def _run_benchmarks(benchmarks: List[Benchmark], output: Output) -> None: + output.track(benchmarks) + for bench in benchmarks: + # Output updates to easily show progress + output.update(bench) + bench.run() + output.update(bench) -def _build(manifest: str) -> None: +def _build_with_runtime_features(manifest: str) -> None: command = [ "cargo", "build", @@ -146,38 +112,24 @@ def _build(manifest: str) -> None: raise BenchmarkCargoException(result.stderr.decode("utf-8")) -def run_pallet_benchmarks(config: Config, to_output: Output) -> None: - if not config.do_pallet_bench: - return - - to_output.info("Substrate Node Performance check ... ") - - if config.do_pallet_bench: - with open(config.reference_values, "r") as f: - s = json.load(f) +def run_pallet_benchmarks(config: BenchmarksConfig, to_output: Output) -> None: + benchmarks = _prepare_benchmarks(config) + pallets = [] + for bench in benchmarks: + pallets.append(bench.pallet) - benchmarks = _prepare_benchmarks(config, s) + to_output.info(f"Benchmarking: {pallets}") - to_output.info("Compiling - this may take a while...") + to_output.info("Compiling - this may take a while...") - _build("node/Cargo.toml") + _build_with_runtime_features("node/Cargo.toml") - to_output.info("Running benchmarks - this may take a while...") + to_output.info("Running benchmarks - this may take a while...") - _run_benchmarks(benchmarks, to_output) + _run_benchmarks(benchmarks, to_output) - if [b.acceptable for b in benchmarks].count(False) == 1: - # if only one failed - rerun it - _run_benchmarks(benchmarks, to_output, True) - - to_output.results(benchmarks) + to_output.results(benchmarks) + if config.dump_results: for bench in benchmarks: - if not config.performance_check: - # TODO: consolidate the check mess here ( there are too many flags ) - print(bench.raw.decode("utf-8")) - - if config.dump_results: - bench.dump(config.dump_results) - - to_output.footnote() + bench.dump(config.dump_results) diff --git a/bench_wizard/config.py b/bench_wizard/config.py deleted file mode 100644 index 812cbf2..0000000 --- a/bench_wizard/config.py +++ /dev/null @@ -1,21 +0,0 @@ -from dataclasses import dataclass, field -from typing import Optional - -# TODO: remove default Hydra pallets - pallets will become required parameter -PALLETS = ["amm", "exchange", "transaction_multi_payment"] - - -@dataclass -class Config: - do_db_bench: bool = False - substrate_repo_path: str = "./substrate" - do_pallet_bench: bool = True - performance_check: bool = False - reference_values: Optional[str] = None - dump_results: Optional[str] = None - - # Directory - # TODO: support for file ( but if multiple pallets in one run - different files ?) - output_dir: Optional[str] = None - template: Optional[str] = None - pallets: [str] = field(default_factory=lambda: PALLETS) diff --git a/bench_wizard/db_bench.py b/bench_wizard/db_bench.py index 9d486b4..b343a4e 100644 --- a/bench_wizard/db_bench.py +++ b/bench_wizard/db_bench.py @@ -1,23 +1,24 @@ import json import os import subprocess +from dataclasses import dataclass from typing import Tuple, Union -from bench_wizard.config import Config +@dataclass +class DBPerformanceConfig: + substrate_dir: str -def db_benchmark(config: Config) -> Union[None, Tuple[dict, dict]]: - if not config.do_db_bench: - return None - print("Performing Database benchmark ( this may take a while ) ... ") +def db_benchmark(config: DBPerformanceConfig) -> Union[None, Tuple[dict, dict]]: + print("Performing Database read/write benchmark ( this may take a while ) ... ") # clone only if dir does not exit - if not os.path.isdir(config.substrate_repo_path): - print(f"Cloning Substrate repository into {config.substrate_repo_path}") + if not os.path.isdir(config.substrate_dir): + print(f"Cloning Substrate repository into {config.substrate_dir}") - command = f"git clone https://github.com/paritytech/substrate.git {config.substrate_repo_path}".split( + command = f"git clone https://github.com/paritytech/substrate.git {config.substrate_dir}".split( " " ) result = subprocess.run(command) @@ -34,7 +35,7 @@ def db_benchmark(config: Config) -> Union[None, Tuple[dict, dict]]: ) read_result = subprocess.run( - read_benchmark_command, capture_output=True, cwd=config.substrate_repo_path + read_benchmark_command, capture_output=True, cwd=config.substrate_dir ) if read_result.returncode != 0: @@ -42,7 +43,7 @@ def db_benchmark(config: Config) -> Union[None, Tuple[dict, dict]]: return None write_result = subprocess.run( - write_benchmark_command, capture_output=True, cwd=config.substrate_repo_path + write_benchmark_command, capture_output=True, cwd=config.substrate_dir ) if write_result.returncode != 0: @@ -56,20 +57,34 @@ def db_benchmark(config: Config) -> Union[None, Tuple[dict, dict]]: def display_db_benchmark_results(results: tuple) -> None: if not results: + print("Failed to run db benchmarks") return print("Database benchmark results:\n") - print(f"{'Name':^75}|{'Raw average(ns)':^26}|{'Average(ns)':^21}|") + print(f"{'Name':^75}|{'Raw average(ns)':^26}|{'Average(ns)':^21}| Reference value") for oper in results: for result in oper: - print( - f"{result['name']:<75}| {result['raw_average']:^25}| {result['average']:^20}|" - ) - + name = result["name"] + if "RocksDb" in name and "read" in name: + print( + f"{result['name']:<75}| {result['raw_average']:^25}| {result['average']:^20}| 25000" + ) + elif "RocksDb" in name and "write" in name: + print( + f"{result['name']:<75}| {result['raw_average']:^25}| {result['average']:^20}| 100000" + ) + elif "read" in name: + print( + f"{result['name']:<75}| {result['raw_average']:^25}| {result['average']:^20}| 8000" + ) + else: + print( + f"{result['name']:<75}| {result['raw_average']:^25}| {result['average']:^20}| 50000" + ) print("") -def run_db_benchmark(config: Config): +def run_db_benchmark(config: DBPerformanceConfig): results = db_benchmark(config) display_db_benchmark_results(results) diff --git a/bench_wizard/main.py b/bench_wizard/main.py index 1706bd9..458f670 100644 --- a/bench_wizard/main.py +++ b/bench_wizard/main.py @@ -1,15 +1,15 @@ +import os import sys -from functools import partial from typing import Optional import click from bench_wizard import __version__ -from bench_wizard.benchmark import run_pallet_benchmarks -from bench_wizard.config import Config, PALLETS -from bench_wizard.db_bench import run_db_benchmark +from bench_wizard.benchmark import run_pallet_benchmarks, BenchmarksConfig +from bench_wizard.db_bench import DBPerformanceConfig, run_db_benchmark from bench_wizard.exceptions import BenchmarkCargoException -from bench_wizard.output import Output +from bench_wizard.output import Output, PerformanceOutput +from bench_wizard.performance import run_pallet_performance, PerformanceConfig @click.group() @@ -23,39 +23,12 @@ def version(): @main.command("benchmark") -@click.option( - "--include-db-benchmark", - type=bool, - default=False, - is_flag=True, - help="Perform Substrate Database benchmark", -) -@click.option( - "--no-pallet-benchmarks", - type=bool, - default=False, - is_flag=True, - help="Skip pallets benchmarks", -) -@click.option( - "--substrate-repo-path", - type=str, - default="./substrate", - help="Substrate repository path (cloned if not provided or does not exist)", -) -@click.option( - "--reference-values", - type=str, - default=".maintain/bench-check/hydradx-bench-data.json", - help="Reference values - json format", -) @click.option( "-p", "--pallet", type=str, multiple=True, - required=False, - default=PALLETS, + required=True, help="Pallets", ) @click.option( @@ -79,41 +52,74 @@ def version(): required=False, help="Weight hbs template file ", ) -@click.option( - "-pc", - "--performance-check", - type=bool, - default=False, - is_flag=True, - help="Weight hbs template file", -) def benchmark( - include_db_benchmark: bool, - no_pallet_benchmarks: bool, - substrate_repo_path: str, - reference_values: str, - performance_check: bool, - pallet: Optional[list], + pallet: list, dump_results: Optional[str], template: Optional[str], output_dir: Optional[str], ): - config = Config( - do_db_bench=include_db_benchmark, - substrate_repo_path=substrate_repo_path, - do_pallet_bench=not no_pallet_benchmarks, - reference_values=reference_values, + config = BenchmarksConfig( pallets=pallet, dump_results=dump_results, template=template, output_dir=output_dir, - performance_check=performance_check, + ) + + run_pallet_benchmarks(config, Output()) + + +@main.command("pc") +@click.option( + "-rf", + "--reference-values", + type=str, + required=True, + help="Reference values - json format", +) +@click.option( + "-p", + "--pallet", + type=str, + multiple=True, + required=True, + help="Pallets", +) +def pc( + reference_values: str, + pallet: list, +): + + if not os.path.isfile(reference_values): + print(f"{reference_values} does not exist", file=sys.stderr) + exit(1) + + + config = PerformanceConfig( + reference_values=reference_values, + pallets=pallet, ) try: - run_pallet_benchmarks(config, Output(not performance_check)) + run_pallet_performance(config, PerformanceOutput()) except BenchmarkCargoException as e: print(str(e), file=sys.stderr) exit(1) + + +@main.command("db") +@click.option( + "-d", + "--substrate-dir", + type=str, + required=True, + help="Substrate directory", +) +def db_benchmark( + substrate_dir: str, +): + config = DBPerformanceConfig( + substrate_dir=substrate_dir, + ) + run_db_benchmark(config) diff --git a/bench_wizard/output.py b/bench_wizard/output.py index d89a9b9..9ea9bec 100644 --- a/bench_wizard/output.py +++ b/bench_wizard/output.py @@ -1,12 +1,14 @@ from typing import Any, TYPE_CHECKING - if TYPE_CHECKING: from .benchmark import Benchmark + from .performance import PalletPerformance + # TODO: need as configurable option DIFF_MARGIN = 10 # percent + class Output: """A class used to handle console output""" @@ -38,6 +40,50 @@ def update(self, benchmark: "Benchmark"): def results(self, benchmarks: ["Benchmark"]): self.info("\nResults:\n\n") + self.info(f"{'Pallet':^25}|{'Result': ^12}") + + for bench in benchmarks: + note = "Failed" if bench.is_error else "Ok" + + if bench.is_error: + reason = bench._error_reason.split("\n")[-2] + else: + reason = "" + + self.print(f"{bench.pallet:<25}| {note:^10} | {reason}") + + +class PerformanceOutput: + """A class used to handle console output""" + + def __init__(self, quiet: bool = False): + self._quiet = quiet + self._tracker = 0 + self._completed = 1 + + def print(self, *objects: Any): + if self._quiet: + return + + for item in objects: + print(item) + + def info(self, msg: str): + self.print(msg) + + def track(self, benchmarks: ["PalletPerformance"]): + self._tracker = len(benchmarks) + + def update(self, benchmark: "PalletPerformance"): + print( + f"Running {self._completed}/{self._tracker} (pallet: {benchmark.pallet})", + end="\r", + ) + self._completed += benchmark.completed + + def results(self, benchmarks: ["PalletPerformance"]): + self.info("\nResults:\n\n") + self.info( f"{'Pallet':^25}|{'Time comparison (µs)':^27}|{'diff* (µs)':^15}|{'diff* (%)':^16}|{'': ^12}| {'Rerun': ^10}" ) @@ -48,7 +94,7 @@ def results(self, benchmarks: ["Benchmark"]): note = "OK" if bench.acceptable else "FAILED" diff = f"{(bench.ref_value - bench.total_time):.2f}" - times = f"{bench.ref_value:.2f} vs {bench.total_time:.2f}" + times = f"{bench.ref_value:.2f} (ref) vs {bench.total_time:.2f}" rerun = "*" if bench.rerun else "" diff --git a/bench_wizard/parser.py b/bench_wizard/parser.py index 7b7f759..1b01c28 100644 --- a/bench_wizard/parser.py +++ b/bench_wizard/parser.py @@ -37,7 +37,7 @@ def process(self) -> None: info = line.split(",") self._pallet = info[0].split(":")[1].strip()[1:-1] extrinsic = info[1].split(":")[1].strip()[1:-1] - time = self.extract_time(lines[idx + 1 : idx + 21]) + time = self.extract_time(lines[idx + 1 :]) self._extrinsics[extrinsic] = time @staticmethod @@ -45,3 +45,6 @@ def extract_time(data: List[str]) -> float: for entry in data: if entry.startswith("Time"): return float(entry.split(" ")[-1]) + if entry.startswith("Pallet:"): + # we did not find time for some reason + raise IOError(f"Failed to find time for an extrinsic. Invalid format?!") diff --git a/bench_wizard/performance.py b/bench_wizard/performance.py new file mode 100644 index 0000000..11fc37a --- /dev/null +++ b/bench_wizard/performance.py @@ -0,0 +1,176 @@ +import json +import subprocess +from dataclasses import dataclass +from typing import List + +from bench_wizard.benchmark import Benchmark +from bench_wizard.cargo import Cargo +from bench_wizard.exceptions import BenchmarkCargoException +from bench_wizard.output import PerformanceOutput + +from bench_wizard.parser import BenchmarkParser + +# TODO: need as configurable option +DIFF_MARGIN = 10 # percent + + +@dataclass +class PerformanceConfig: + pallets: [str] + reference_values: str + + +class PalletPerformance: + def __init__(self, pallet: str, ref_value: float, extrinsics: list): + self._pallet = pallet + self._stdout = None + self._ref_value = ref_value + self._extrinsics = extrinsics + + self._extrinsics_results = [] + + self._total_time = 0 + + self._completed = False + self._acceptable = False + self._rerun = False + + self._is_error = False + self._error_reason = False + + @property + def pallet(self): + return self._pallet + + @property + def acceptable(self) -> bool: + return self._acceptable + + @acceptable.setter + def acceptable(self, value: bool): + self._acceptable = value + + @property + def completed(self) -> bool: + return self._completed + + @property + def raw(self) -> bytes: + return self._stdout + + def run(self, rerun: bool = False) -> None: + """Run benchmark and parse the result""" + + cargo = Cargo(pallet=self.pallet) + benchmark = Benchmark(self.pallet, cargo.command()) + benchmark.run() + + if benchmark.is_error: + self._is_error = True + self._error_reason = benchmark._error_reason + return + + self._stdout = benchmark.raw + + parser = BenchmarkParser(benchmark.raw) + + self._total_time = parser.total_time(self._extrinsics) + + margin = int(self._ref_value * DIFF_MARGIN / 100) + + diff = int(self._ref_value - self._total_time) + + self.acceptable = diff >= -margin + self._rerun = rerun + self._completed = True + + @property + def ref_value(self): + return self._ref_value + + @property + def total_time(self): + return self._total_time + + @property + def rerun(self): + return self._rerun + + @property + def percentage(self) -> float: + diff = int(self._ref_value - self._total_time) + + percentage = (diff / self._ref_value) * 100 + + return percentage + + +def _prepare_benchmarks( + config: PerformanceConfig, reference_values: dict +) -> List[PalletPerformance]: + benchmarks = [] + + for pallet in config.pallets: + ref_data = reference_values[pallet] + ref_value = sum(list(map(lambda x: float(x), ref_data.values()))) + benchmarks.append(PalletPerformance(pallet, ref_value, ref_data.keys())) + + return benchmarks + + +def _run_benchmarks( + benchmarks: List[PalletPerformance], output: PerformanceOutput, rerun=False +) -> None: + # Note : this can be simplified into one statement + + if rerun: + [bench.run(rerun) for bench in benchmarks if bench.acceptable is False] + else: + output.track(benchmarks) + for bench in benchmarks: + # Output updates to easily show progress + output.update(bench) + bench.run() + output.update(bench) + + +def _build(manifest: str) -> None: + command = [ + "cargo", + "build", + "--release", + "--features=runtime-benchmarks", + f"--manifest-path={manifest}", + ] + + result = subprocess.run(command, capture_output=True) + + if result.returncode != 0: + raise BenchmarkCargoException(result.stderr.decode("utf-8")) + + +def run_pallet_performance( + config: PerformanceConfig, to_output: PerformanceOutput +) -> None: + to_output.info("Substrate Node Performance check ... ") + + with open(config.reference_values, "r") as f: + s = json.load(f) + + benchmarks = _prepare_benchmarks(config, s) + + to_output.info("Compiling - this may take a while...") + + _build("node/Cargo.toml") + + to_output.info("Running benchmarks - this may take a while...") + + _run_benchmarks(benchmarks, to_output) + + if [b.acceptable for b in benchmarks].count(False) == 1: + # if only one failed - rerun it + _run_benchmarks(benchmarks, to_output, True) + + to_output.results(benchmarks) + + to_output.footnote() diff --git a/poetry.lock b/poetry.lock index 916cd67..f9b6f65 100644 --- a/poetry.lock +++ b/poetry.lock @@ -20,6 +20,32 @@ docs = ["furo", "sphinx", "zope.interface"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +[[package]] +name = "black" +version = "21.12b0" +description = "The uncompromising code formatter." +category = "dev" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +click = ">=7.1.2" +mypy-extensions = ">=0.4.3" +pathspec = ">=0.9.0,<1" +platformdirs = ">=2" +tomli = ">=0.2.6,<2.0.0" +typing-extensions = [ + {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, + {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, +] + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +python2 = ["typed-ast (>=1.4.3)"] +uvloop = ["uvloop (>=0.15.2)"] + [[package]] name = "click" version = "7.1.2" @@ -44,6 +70,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "mypy-extensions" +version = "0.4.3" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "packaging" version = "20.9" @@ -55,6 +89,26 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] pyparsing = ">=2.0.2" +[[package]] +name = "pathspec" +version = "0.9.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" + +[[package]] +name = "platformdirs" +version = "2.4.1" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] +test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] + [[package]] name = "pluggy" version = "0.13.1" @@ -111,10 +165,26 @@ category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +[[package]] +name = "tomli" +version = "1.2.3" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "typing-extensions" +version = "4.0.1" +description = "Backported and Experimental Type Hints for Python 3.6+" +category = "dev" +optional = false +python-versions = ">=3.6" + [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "22830503ed9ce84460ea7a25731e48cb902ed091eb9b63797e2f323d3334d874" +content-hash = "bb03db31fc489d0ae9675e563624981f793cc8f278b29324f9c724b8999a1273" [metadata.files] atomicwrites = [ @@ -125,6 +195,10 @@ attrs = [ {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, ] +black = [ + {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, + {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, +] click = [ {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, @@ -137,10 +211,22 @@ iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] +mypy-extensions = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] packaging = [ {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, ] +pathspec = [ + {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, + {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, +] +platformdirs = [ + {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"}, + {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"}, +] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, @@ -161,3 +247,11 @@ toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] +tomli = [ + {file = "tomli-1.2.3-py3-none-any.whl", hash = "sha256:e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c"}, + {file = "tomli-1.2.3.tar.gz", hash = "sha256:05b6166bff487dc068d322585c7ea4ef78deed501cc124060e0f238e89a9231f"}, +] +typing-extensions = [ + {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, + {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, +] diff --git a/pyproject.toml b/pyproject.toml index ecb0e61..aaa16cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "bench-wizard" -version = "0.4.2" +version = "0.5.0" description = "" authors = ["Martin Hloska "] @@ -13,6 +13,7 @@ benchwizard = 'bench_wizard.main:main' [tool.poetry.dev-dependencies] pytest = "6.2.2" +black = "^21.12b0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tests/test_bench_wizard.py b/tests/test_bench_wizard.py index da4b27b..34133df 100644 --- a/tests/test_bench_wizard.py +++ b/tests/test_bench_wizard.py @@ -2,4 +2,4 @@ def test_version(): - assert __version__ == "0.4.2" + assert __version__ == "0.5.0"