topmark 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. topmark/__init__.py +14 -0
  2. topmark/cli/__init__.py +23 -0
  3. topmark/cli/cli_types.py +299 -0
  4. topmark/cli/commands/__init__.py +11 -0
  5. topmark/cli/commands/default.py +295 -0
  6. topmark/cli/commands/dump_config.py +108 -0
  7. topmark/cli/commands/filetypes.py +39 -0
  8. topmark/cli/commands/init_config.py +60 -0
  9. topmark/cli/commands/show_defaults.py +54 -0
  10. topmark/cli/commands/version.py +32 -0
  11. topmark/cli/config_resolver.py +82 -0
  12. topmark/cli/main.py +464 -0
  13. topmark/cli/options.py +276 -0
  14. topmark/cli/utils.py +245 -0
  15. topmark/config/__init__.py +520 -0
  16. topmark/config/logging.py +148 -0
  17. topmark/constants.py +24 -0
  18. topmark/file_resolver.py +228 -0
  19. topmark/filetypes/__init__.py +16 -0
  20. topmark/filetypes/base.py +81 -0
  21. topmark/filetypes/instances.py +327 -0
  22. topmark/filetypes/policy.py +44 -0
  23. topmark/filetypes/registry.py +79 -0
  24. topmark/pipeline/__init__.py +25 -0
  25. topmark/pipeline/context.py +363 -0
  26. topmark/pipeline/contracts.py +22 -0
  27. topmark/pipeline/pipelines.py +93 -0
  28. topmark/pipeline/processors/__init__.py +96 -0
  29. topmark/pipeline/processors/base.py +754 -0
  30. topmark/pipeline/processors/pound.py +154 -0
  31. topmark/pipeline/processors/xml.py +278 -0
  32. topmark/pipeline/runner.py +49 -0
  33. topmark/pipeline/steps/__init__.py +11 -0
  34. topmark/pipeline/steps/builder.py +135 -0
  35. topmark/pipeline/steps/comparer.py +73 -0
  36. topmark/pipeline/steps/patcher.py +171 -0
  37. topmark/pipeline/steps/reader.py +173 -0
  38. topmark/pipeline/steps/renderer.py +64 -0
  39. topmark/pipeline/steps/resolver.py +103 -0
  40. topmark/pipeline/steps/scanner.py +146 -0
  41. topmark/pipeline/steps/updater.py +128 -0
  42. topmark/py.typed +1 -0
  43. topmark/rendering/api.py +80 -0
  44. topmark/rendering/formats.py +26 -0
  45. topmark/utils/__init__.py +11 -0
  46. topmark/utils/file.py +42 -0
  47. topmark-0.1.0.dist-info/METADATA +308 -0
  48. topmark-0.1.0.dist-info/RECORD +52 -0
  49. topmark-0.1.0.dist-info/WHEEL +5 -0
  50. topmark-0.1.0.dist-info/entry_points.txt +2 -0
  51. topmark-0.1.0.dist-info/licenses/LICENSE +21 -0
  52. topmark-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,108 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : dump_config.py
4
+ # file_relpath : src/topmark/cli/commands/dump_config.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """TopMark `dump-config` command.
12
+
13
+ Emits the effective TopMark configuration as TOML after applying defaults,
14
+ project/user config files, and any CLI overrides. The output is wrapped
15
+ between `# === BEGIN ===` and `# === END ===` markers for easy parsing in
16
+ tests or tooling.
17
+ """
18
+
19
+ import click
20
+ from yachalk import chalk
21
+
22
+ from topmark.cli.config_resolver import resolve_config_from_click
23
+ from topmark.cli.options import (
24
+ common_config_options,
25
+ common_file_and_filtering_options,
26
+ common_header_formatting_options,
27
+ typed_argument,
28
+ )
29
+ from topmark.rendering.formats import HeaderOutputFormat
30
+
31
+
32
+ @typed_argument("files", nargs=-1)
33
+ @common_config_options
34
+ @common_file_and_filtering_options
35
+ @common_header_formatting_options
36
+ def dump_config_command(
37
+ # Command arguments
38
+ files: list[str],
39
+ # Command options: common_file_filtering_options
40
+ stdin: bool,
41
+ include_patterns: list[str],
42
+ include_from: list[str],
43
+ exclude_patterns: list[str],
44
+ exclude_from: list[str],
45
+ file_types: list[str],
46
+ relative_to: str | None,
47
+ # Command options: config
48
+ no_config: bool,
49
+ config_paths: list[str],
50
+ # Command options: formatting
51
+ align_fields: bool,
52
+ header_format: HeaderOutputFormat | None,
53
+ ) -> None:
54
+ """Dump the final merged configuration as TOML.
55
+
56
+ Builds the effective configuration from defaults, discovered/explicit
57
+ config files, and CLI overrides, then prints it as TOML surrounded by
58
+ BEGIN/END markers. This is useful for debugging or for external tools
59
+ that need to consume the resolved configuration.
60
+
61
+ Args:
62
+ files: Positional file or directory paths used to influence config
63
+ discovery or resolution (may be empty).
64
+ stdin: If True, read newline‑separated paths from standard input
65
+ when resolving files (may affect config discovery).
66
+ include_patterns: Additional include glob patterns to consider.
67
+ include_from: Paths to files containing include patterns (one per line).
68
+ exclude_patterns: Glob patterns to exclude from consideration.
69
+ exclude_from: Paths to files containing exclude patterns (one per line).
70
+ file_types: Explicit file‑type filters to restrict processing.
71
+ relative_to: Optional base directory for resolving relative paths.
72
+ no_config: If True, skip loading project/user configuration files.
73
+ config_paths: Additional TOML config files to merge into the effective config.
74
+ align_fields: Whether to align header fields when rendering (captured in config).
75
+ header_format: Optional output format override for header rendering (captured in config).
76
+
77
+ Returns:
78
+ None. Prints the merged configuration as TOML to stdout.
79
+ """
80
+ ctx = click.get_current_context()
81
+ ctx.ensure_object(dict)
82
+
83
+ config = resolve_config_from_click(
84
+ ctx=ctx,
85
+ files=list(files),
86
+ stdin=stdin,
87
+ include_patterns=list(include_patterns),
88
+ include_from=list(include_from),
89
+ exclude_patterns=list(exclude_patterns),
90
+ exclude_from=list(exclude_from),
91
+ file_types=list(file_types),
92
+ relative_to=relative_to,
93
+ no_config=no_config,
94
+ config_paths=list(config_paths),
95
+ align_fields=align_fields,
96
+ header_format=header_format,
97
+ )
98
+
99
+ import toml
100
+
101
+ merged_config = toml.dumps(config.to_toml_dict())
102
+ click.echo(chalk.bold.underline("TopMark Config Dump:"))
103
+ click.echo(
104
+ chalk.dim(
105
+ f"# Merged TopMark config (TOML):\n\n# === BEGIN ===\n{merged_config}# === END ==="
106
+ )
107
+ )
108
+ return
@@ -0,0 +1,39 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : filetypes.py
4
+ # file_relpath : src/topmark/cli/commands/filetypes.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """TopMark `filetypes` command.
12
+
13
+ Lists all file types supported by TopMark along with their identifiers and
14
+ descriptions. Useful for discovering available file type filters when
15
+ configuring headers.
16
+ """
17
+
18
+ import click
19
+ from yachalk import chalk
20
+
21
+ from topmark.filetypes.instances import get_file_type_registry
22
+
23
+
24
+ def filetypes_command() -> None:
25
+ """List supported file types.
26
+
27
+ Prints all file types supported by TopMark, including their identifiers and descriptions.
28
+ Useful for reference when configuring file type filters.
29
+
30
+ Returns:
31
+ None. Prints output to stdout.
32
+ """
33
+ click.echo(chalk.bold.underline("Supported file types:"))
34
+
35
+ file_types = get_file_type_registry()
36
+ for key, value in sorted(file_types.items()):
37
+ # key is file type identifier (name)
38
+ # value contains the file type fields (e.g., description)
39
+ click.echo(f" - {key:<12} {chalk.dim(value.description)}")
@@ -0,0 +1,60 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : init_config.py
4
+ # file_relpath : src/topmark/cli/commands/init_config.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """TopMark `init-config` command.
12
+
13
+ Prints an initial TopMark configuration file to stdout. The output includes a
14
+ generated header block and the default TOML configuration. Intended as a
15
+ starting point for customizing a project's configuration.
16
+ """
17
+
18
+ import click
19
+ from yachalk import chalk
20
+
21
+ from topmark.cli.utils import default_header_overrides
22
+ from topmark.config import Config
23
+ from topmark.constants import PYPROJECT_TOML_PATH
24
+ from topmark.rendering.api import render_header_for_path
25
+
26
+
27
+ def init_config_command() -> None:
28
+ """Print a starter config file to stdout.
29
+
30
+ Outputs an initial TopMark configuration file with default values and a header.
31
+ Intended as a starting point for customization in your own project.
32
+
33
+ Returns:
34
+ None. Prints output to stdout.
35
+ """
36
+ # TODO: use topmark to generate this header
37
+ click.echo(chalk.bold.underline("Initial TopMark Configuration:"))
38
+
39
+ header_overrides = default_header_overrides(
40
+ info="Initial TopMark configuration -- adjust according to your needs",
41
+ file_label="topmark.toml",
42
+ )
43
+
44
+ topmark_header = render_header_for_path(
45
+ config=Config.from_defaults(),
46
+ path=PYPROJECT_TOML_PATH,
47
+ header_fields_overrides=["file", "version", "info", "license", "copyright"],
48
+ header_overrides=header_overrides,
49
+ )
50
+
51
+ click.echo(
52
+ chalk.gray(
53
+ f"""\
54
+ {topmark_header}
55
+
56
+ {Config.get_default_config_toml()}
57
+ ## === END of TopMark Configuration ===
58
+ """
59
+ )
60
+ )
@@ -0,0 +1,54 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : show_defaults.py
4
+ # file_relpath : src/topmark/cli/commands/show_defaults.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """TopMark `show-defaults` command.
12
+
13
+ Displays the built-in default TopMark configuration. This includes the default
14
+ header template and the default TOML configuration bundled with the package.
15
+ Intended as a reference for users customizing their own configuration files.
16
+ """
17
+
18
+ import click
19
+ from yachalk import chalk
20
+
21
+ from topmark.cli.utils import default_header_overrides
22
+ from topmark.config import Config
23
+ from topmark.constants import PYPROJECT_TOML_PATH
24
+ from topmark.rendering.api import render_header_for_path
25
+
26
+
27
+ def show_defaults_command() -> None:
28
+ """Display the built-in default configuration.
29
+
30
+ Prints the TopMark default configuration as bundled with the package, including a header.
31
+ Useful as a reference for configuration structure and default values.
32
+
33
+ Returns:
34
+ None. Prints output to stdout.
35
+ """
36
+ header_overrides = default_header_overrides(
37
+ info="Default TopMark Configuration", file_label="topmark.toml"
38
+ )
39
+ topmark_header = render_header_for_path(
40
+ config=Config.from_defaults(),
41
+ path=PYPROJECT_TOML_PATH,
42
+ header_fields_overrides=["file", "version", "info", "license", "copyright"],
43
+ header_overrides=header_overrides,
44
+ )
45
+
46
+ click.echo(chalk.bold.underline("Default TopMark Configuration:"))
47
+ click.echo(
48
+ chalk.gray(
49
+ f"""\
50
+ {topmark_header}
51
+ {Config.to_cleaned_toml(Config.get_default_config_toml())}
52
+ ## === END of TopMark Configuration ==="""
53
+ )
54
+ )
@@ -0,0 +1,32 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : version.py
4
+ # file_relpath : src/topmark/cli/commands/version.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """TopMark `version` command.
12
+
13
+ Prints the current TopMark version as installed in the active Python environment.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import click
19
+
20
+ from topmark.constants import TOPMARK_VERSION
21
+
22
+
23
+ def version_command() -> None:
24
+ """Show the current version of TopMark.
25
+
26
+ Prints the TopMark version as installed in the current Python environment.
27
+
28
+ Returns:
29
+ None. Prints output to stdout.
30
+ """
31
+ topmark_version = TOPMARK_VERSION
32
+ click.echo(f"TopMark version: {topmark_version}")
@@ -0,0 +1,82 @@
1
+ # topmark:header:start
2
+ #
3
+ # file : config_resolver.py
4
+ # file_relpath : src/topmark/cli/config_resolver.py
5
+ # project : TopMark
6
+ # license : MIT
7
+ # copyright : (c) 2025 Olivier Biot
8
+ #
9
+ # topmark:header:end
10
+
11
+ """Utilities for resolving TopMark configuration from Click parameters.
12
+
13
+ This module provides helpers to convert Click command-line parameters into an
14
+ :class:`~topmark.config.Config` object. It bridges CLI parsing and the core
15
+ configuration system by building an ArgsNamespace and merging user, project,
16
+ and default config sources.
17
+ """
18
+
19
+ import click
20
+
21
+ from topmark.cli.cli_types import ArgsNamespace, build_args_namespace
22
+ from topmark.config import Config
23
+ from topmark.config.logging import get_logger
24
+ from topmark.rendering.formats import HeaderOutputFormat
25
+
26
+ logger = get_logger(__name__)
27
+
28
+
29
+ # Helper: Build Config from Click params using ArgsNamespace and merged config logic
30
+ def resolve_config_from_click(
31
+ *,
32
+ ctx: click.Context,
33
+ files: list[str],
34
+ stdin: bool,
35
+ include_patterns: list[str],
36
+ include_from: list[str],
37
+ exclude_patterns: list[str],
38
+ exclude_from: list[str],
39
+ file_types: list[str],
40
+ relative_to: str | None,
41
+ no_config: bool,
42
+ config_paths: list[str],
43
+ align_fields: bool,
44
+ header_format: HeaderOutputFormat | None,
45
+ ) -> Config:
46
+ """Build a :class:`Config` from Click parameters.
47
+
48
+ Args:
49
+ ctx: Click context that provides the resolved log level.
50
+ files: File paths passed on the command line.
51
+ stdin: Whether to read file paths from standard input.
52
+ include_patterns: Glob patterns of files to include.
53
+ include_from: Paths to files that contain include patterns.
54
+ exclude_patterns: Glob patterns of files to exclude.
55
+ exclude_from: Paths to files that contain exclude patterns.
56
+ file_types: File type identifiers to restrict processing to.
57
+ relative_to: Root directory used to compute relative paths.
58
+ no_config: If True, ignore local project config files.
59
+ config_paths: Extra config TOML file paths to merge.
60
+ align_fields: Whether to align header fields with colons.
61
+ header_format: Selected header output format.
62
+
63
+ Returns:
64
+ Config: The merged configuration.
65
+ """
66
+ args: ArgsNamespace = build_args_namespace(
67
+ log_level=ctx.obj.get("log_level"),
68
+ files=list(files),
69
+ stdin=stdin,
70
+ include_patterns=list(include_patterns),
71
+ include_from=list(include_from),
72
+ exclude_patterns=list(exclude_patterns),
73
+ exclude_from=list(exclude_from),
74
+ no_config=no_config,
75
+ config_files=list(config_paths),
76
+ file_types=list(file_types),
77
+ relative_to=relative_to,
78
+ align_fields=align_fields,
79
+ header_format=header_format,
80
+ )
81
+ logger.trace("ArgsNamespace: %s", args)
82
+ return Config.load_merged(args)