Skip to content

Commit

Permalink
Allow specifying workers alternatively as "max" instead of integer
Browse files Browse the repository at this point in the history
  • Loading branch information
BlankSpruce committed Oct 8, 2024
1 parent fde9345 commit a4a9755
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .gersemirc.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ list_expansion: favour-inlining
quiet: false
unsafe: false
warn_about_unknown_commands: true
workers: 8
workers: max
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Changelog
## [0.16.0] 2024-10-08
### Changed
- number of workers can now be specified with either integer or "max", default value will now be "max" instead of numerical value of max on given machine

## [0.15.1] 2024-08-19
### Fixed
- when source or definition path doesn't exist `gersemi` will fail early
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ configuration:
entities will be formatted in such way that sublists will be
completely expanded once expansion becomes necessary at all.
[default: favour-inlining]
-w INTEGER, --workers INTEGER
Number of workers used to format multiple files in parallel.
[default: number of CPUs on this system]
-w INTEGER, --workers (INTEGER | max)
Explicit number of workers or 'max' for maximum possible number
of workers on given machine used to format multiple files
in parallel.
[default: max]
--cache, --no-cache Enables cache with data about files that are known to be
formatted to speed up execution.
[default: cache enabled]
Expand Down
8 changes: 4 additions & 4 deletions gersemi/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Configuration,
ListExpansion,
indent_type,
workers_type,
)
from gersemi.mode import get_mode
from gersemi.return_codes import SUCCESS, FAIL
Expand Down Expand Up @@ -152,12 +153,11 @@ def create_argparser():
configuration_group.add_argument(
"-w",
"--workers",
metavar="INTEGER",
metavar="(INTEGER | max)",
dest="workers",
type=int,
type=workers_type,
help=f"""
{conf_doc['workers']}
[default: number of CPUs on this system]
{conf_doc['workers']} [default: {Configuration.workers.value}]
""",
)
configuration_group.add_argument(
Expand Down
52 changes: 40 additions & 12 deletions gersemi/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import yaml


def number_of_workers():
def max_number_of_workers():
result = multiprocessing.cpu_count()
if sys.platform == "win32":
# https://bugs.python.org/issue26903
Expand Down Expand Up @@ -49,7 +49,27 @@ class Tabs(EnumWithMetadata):
def indent_type(thing) -> Indent:
if thing == Tabs.Tabs.value:
return Tabs.Tabs
return int(thing)

return max(1, int(thing))


class MaxWorkers(EnumWithMetadata):
MaxWorkers = dict(
value="max",
description="Use maximum possible amount of workers.",
title="Max workers",
)


NumberOfWorkers = int
Workers = Union[NumberOfWorkers, MaxWorkers]


def workers_type(thing) -> Workers:
if thing == MaxWorkers.MaxWorkers.value:
return MaxWorkers.MaxWorkers

return max(1, int(thing))


class ListExpansion(EnumWithMetadata):
Expand Down Expand Up @@ -150,11 +170,17 @@ class Configuration: # pylint: disable=too-many-instance-attributes
),
)

workers: int = field(
default=number_of_workers(),
workers: Workers = field(
default=MaxWorkers.MaxWorkers,
metadata=dict(
title="Workers",
description="Number of workers used to format multiple files in parallel.",
description=doc(
"""
Explicit number of workers or 'max' for maximum possible
number of workers on given machine used to format multiple
files in parallel.
"""
),
),
)

Expand Down Expand Up @@ -191,6 +217,14 @@ def summary(self):
return hasher.hexdigest()


def represent_enum_with_metadata(dumper, data):
return dumper.represent_str(data.value)


yaml.SafeDumper.add_representer(Tabs, represent_enum_with_metadata)
yaml.SafeDumper.add_representer(MaxWorkers, represent_enum_with_metadata)


def make_configuration_file(configuration):
d = asdict(configuration)
d["list_expansion"] = d["list_expansion"].value
Expand Down Expand Up @@ -249,10 +283,6 @@ def sanitize_list_expansion(list_expansion):
)


def sanitize_workers(workers):
return max(1, workers)


def load_configuration_from_file(configuration_file_path: Path) -> Configuration:
with enter_directory(configuration_file_path.parent):
with open(configuration_file_path, "r", encoding="utf-8") as f:
Expand All @@ -264,7 +294,7 @@ def load_configuration_from_file(configuration_file_path: Path) -> Configuration
config["list_expansion"]
)
if "workers" in config:
config["workers"] = sanitize_workers(config["workers"])
config["workers"] = workers_type(config["workers"])
if "indent" in config:
config["indent"] = indent_type(config["indent"])
return Configuration(**config)
Expand All @@ -282,8 +312,6 @@ def override_configuration_with_args(
value = normalize_definitions(value)
if param == "list_expansion":
value = sanitize_list_expansion(value)
if param == "workers":
value = sanitize_workers(value)
setattr(configuration, param, value)
return configuration

Expand Down
24 changes: 20 additions & 4 deletions gersemi/configuration.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
],
"type": "string"
},
"MaxWorkers": {
"oneOf": [
{
"description": "Use maximum possible amount of workers.",
"enum": ["max"],
"title": "Max workers"
}
],
"type": "string"
},
"Tabs": {
"oneOf": [
{
Expand Down Expand Up @@ -78,10 +88,16 @@
"type": "boolean"
},
"workers": {
"minimum": 1,
"description": "Number of workers used to format multiple files in parallel.",
"title": "Workers",
"type": "integer"
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{"$ref": "#/$defs/MaxWorkers"}
],
"default": "max",
"description": "Explicit number of workers or 'max' for maximum possible number of workers on given machine used to format multiple files in parallel.",
"title": "Workers"
},
"cache": {
"default": true,
Expand Down
20 changes: 17 additions & 3 deletions gersemi/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
import sys
from typing import Callable, Dict, Iterable, Tuple, Union
from gersemi.cache import create_cache
from gersemi.configuration import Configuration
from gersemi.configuration import (
Configuration,
MaxWorkers,
max_number_of_workers,
Workers,
)
from gersemi.custom_command_definition_finder import (
find_custom_command_definitions,
get_just_definitions,
Expand Down Expand Up @@ -159,10 +164,19 @@ def consume_task_result(
return task_result.path, task_result.return_code, (len(warnings) > 0)


def create_pool(is_stdin_in_sources, num_workers):
def create_pool(is_stdin_in_sources, workers: Workers):
if is_stdin_in_sources:
return mp_dummy.Pool
return partial(mp.Pool, processes=num_workers)

if isinstance(workers, MaxWorkers):
value = max_number_of_workers()
else:
if workers <= 1:
return mp_dummy.Pool

value = workers

return partial(mp.Pool, processes=value)


def split_files(cache, configuration_summary: str, files: Iterable[Path]):
Expand Down
7 changes: 3 additions & 4 deletions tests/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Configuration,
ListExpansion,
make_configuration_file,
MaxWorkers,
Tabs,
)

Expand Down Expand Up @@ -41,12 +42,11 @@ def generate(self, schema, mode=None):
result = super().generate(schema, mode=mode)
result["$schema"] = "https://json-schema.org/draft-07/schema"
result["$defs"]["ListExpansion"] = get_representation(ListExpansion)
result["$defs"]["MaxWorkers"] = get_representation(MaxWorkers)
result["$defs"]["Tabs"] = get_representation(Tabs)

result["properties"]["indent"]["anyOf"][0]["minimum"] = 1

del result["properties"]["workers"]["default"]
result["properties"]["workers"]["minimum"] = 1
result["properties"]["workers"]["anyOf"][0]["minimum"] = 1

return result

Expand All @@ -70,5 +70,4 @@ def test_example_file_in_repository_is_consistent_with_configuration_definition(
example = f.read().strip()

configuration = Configuration()
configuration.workers = 8
assert example == make_configuration_file(configuration)

0 comments on commit a4a9755

Please sign in to comment.