Skip to content

Configuration

When is configuration needed?

setuptools-scm provides flexible activation options:

Simplified Activation (No Configuration Needed)

For basic usage, use the simple extra with no configuration:

pyproject.toml
[build-system]
requires = ["setuptools>=80", "setuptools-scm[simple]>=9.2"]

[project]
dynamic = ["version"]

The [simple] extra enables version inference with default settings. See the usage guide for details.

Explicit Configuration (Full Control)

Use the [tool.setuptools_scm] section when you need to:

  • Write version files (version_file)
  • Customize version schemes (version_scheme, local_scheme)
  • Set tag matching options (tag.prefix, tag.strict, tag.regex)
  • Configure fallback behavior (fallback_version)
  • Or any other non-default behavior

Core Configuration

These configuration options control version inference and formatting behavior.

Configuration parameters can be configured in pyproject.toml or setup.py. Callables or other Python objects must be passed in setup.py (via the use_scm_version keyword argument).

root : Path | PathLike[str]
Relative path to the SCM root, defaults to . and is relative to the file path passed in relative_to
version_scheme : str | Callable[[ScmVersion], str]
Configures how the version number is constructed; either an entrypoint name or a callable. See Version number construction for predefined implementations.
local_scheme : str | Callable[[ScmVersion], str]
Configures how the local component of the version (the optional part after the +) is constructed; either an entrypoint name or a callable. See Version number construction for predefined implementations.

Tag Matching Configuration

These options control which VCS tags are considered version tags and how they are parsed. They are configured under the tag table in pyproject.toml:

pyproject.toml
[tool.setuptools_scm.tag]
prefix = ""        # default – no prefix filtering
strict = true      # require tags to contain at least one dot
tag.prefix: str = ""

A literal prefix that version tags must start with. The prefix is used to filter tags in git describe --match and is stripped before version parsing.

Use this for monorepos or multi-package repositories where each package has its own tag namespace.

pyproject.toml – monorepo example
[tool.setuptools_scm.tag]
prefix = "hatchling-v"   # matches hatchling-v1.0.0, strips to 1.0.0
tag.prefix value Tags matched Extracted version
"" (default) v1.0.0, 1.0.0, 2026-event v1.0.0, 1.0.0
"v" v1.0.0, V1.0.0 1.0.0
"hatchling-v" hatchling-v1.0.0 1.0.0
"py-v" py-v2.3.1 2.3.1
tag.strict: bool | None = None

Controls how strictly tags must look like version numbers.

Value Behavior
unset (None) Current permissive matching (*[0-9]*).
true Strict – tags must contain at least one dot (e.g. *[0-9]*.*[0-9]*). Event-like tags such as 2026-event are rejected.
false Permissive – matches any tag containing a digit (*[0-9]*).

Migration

In a future major release the default will change from permissive to strict. Set tag.strict = false now if you rely on the permissive matching, or tag.strict = true to adopt the stricter behavior early.

While tag.strict is unset, a warning is logged only if the future default would actually pick a different tag for your repository, naming both the current and the future version. Projects the change cannot affect are never nagged. Silence it with SETUPTOOLS_SCM_DEBUG=ERROR if you cannot act on it, for example when building someone else's project from a checkout.

tag.prefix and tag.strict compose naturally:

tag.prefix tag.strict Effective --match glob
"" false / unset *[0-9]*
"" true *[0-9]*.*[0-9]*
"hatchling-v" false / unset hatchling-v*[0-9]*
"hatchling-v" true hatchling-v*[0-9]*.*[0-9]*

Mercurial

Mercurial applies the equivalent regex (\d+ / \d+\.\d+, prefixed when tag.prefix is set) both when looking for the latest tag and when the checked-out changeset carries tags of its own. Under tag.strict = true a changeset tagged only with event-style names is treated as untagged, so versioning continues from the last real version tag -- the same thing git describe --match does.

Before setuptools-scm 9 the Mercurial backend always required a dot, so for Mercurial projects the coming strict default restores the historical behavior.

tag.regex: str | Pattern[str]

A Python regex to extract the version part from a tag after the tag.prefix has been stripped. The regex needs a single capture group or a named group version.

Defaults to vcs_versioning._config.DEFAULT_TAG_REGEX which supports tags with optional "v" prefix, project prefixes, and various version formats.

Tip

Most users should use tag.prefix and tag.strict instead of customizing the regex directly.

tag_regex (deprecated)

Deprecated: Use tag.regex instead.

Top-level tag_regex is still accepted for backward compatibility but emits a DeprecationWarning. It cannot be used together with tag.regex.

Other Configuration

parentdir_prefix_version: str | None = None

If the normal methods for detecting the version (SCM version, sdist metadata) fail, and the parent directory name starts with parentdir_prefix_version, then this prefix is stripped and the rest of the parent directory name is matched with tag_regex to get a version string. If this parameter is unset (the default), then this fallback is not used.

This was intended to cover GitHub's "release tarballs", which extract into directories named projectname-tag/ (in which case parentdir_prefix_version can be set e.g. to projectname-).

fallback_version: str | None = None
A version string that will be used if no other method for detecting the version worked (e.g., when using a tarball with no metadata). If this is unset (the default), setuptools-scm will error if it fails to detect the version.
fallback_root: Path | PathLike[str] = "."

The directory to use when SCM metadata is not available (e.g., in extracted archives like PyPI tarballs). This is particularly useful for legacy configurations that need to work both in development (with SCM metadata) and from archives (without SCM metadata). Defaults to the current directory.

When SCM metadata is present, the root parameter is used; when it's not available, fallback_root is used instead. This allows the same configuration to work in both scenarios without modification.

normalize
A boolean flag indicating if the version string should be normalized. Defaults to True. Setting this to False is equivalent to setting version_cls to vcs_versioning.NonNormalizedVersion
version_cls: type|str = packaging.version.Version

An optional class used to parse, verify and possibly normalize the version string. Its constructor should receive a single string argument, and its str should return the normalized version string to use. This option can also receive a class qualified name as a string.

The vcs_versioning.NonNormalizedVersion convenience class is provided to disable the normalization step done by packaging.version.Version. If this is used while setuptools-scm is integrated in a setuptools packaging process, the non-normalized version number will appear in all files (see version_file note).

normalization still applies to artifact filenames

Setuptools will still normalize it to create the final distribution, so as to stay compliant with the python packaging standards.

scm.git.describe_command

This command will be used instead the default git describe --long command.

Defaults to the value set by vcs_versioning._backends._git.DEFAULT_DESCRIBE

Overrides tag.strict

When scm.git.describe_command is explicitly set, it supplies its own --match pattern, so tag.strict has no effect on tag matching. A warning is emitted only if the two would actually select different tags for your repository.

tag.prefix is not overridden: it still strips the prefix from the selected tag before version parsing, so combining it with an explicit describe_command is a supported way to bring your own match pattern while keeping prefix stripping.

scm.git.pre_parse

A string specifying which git pre-parse function to use before parsing version information. Available options:

  • "warn_on_shallow" (default): Warns when the repository is shallow (skipped when HEAD is exactly on a tag, where a shallow clone is sufficient)
  • "fail_on_shallow": Fails with an error when the repository is shallow (not when HEAD is exactly on a tag)
  • "fetch_on_shallow": Automatically fetches to rectify shallow repositories (skipped when HEAD is exactly on a tag)
  • "fail_on_missing_submodules": Fails when submodules are defined but not initialized

    The "fail_on_missing_submodules" option is useful to prevent packaging incomplete projects when submodules are required for a complete build.

Note: This setting is overridden by any explicit pre_parse parameter passed to the git parse function.

scm.git.distance_scope

Restrict the distance count to the commits that touch this project, for projects living in a subdirectory of a monorepo.

  • false (default): count every commit since the tag, as git describe does.
  • true: count only commits touching the project directory.
  • a list of paths: count commits touching the project directory or any of the listed directories. Paths are relative to the VCS root, not to the project.
[tool.setuptools_scm.scm.git]
distance_scope = true

Use the list form for directories the project actually depends on -- shared libraries, generated code, build tooling. Without them, a change to a dependency does not move the project's version even though it changes what gets built:

[tool.setuptools_scm.scm.git]
distance_scope = ["shared/common", "tooling"]

Requires the project to live below the VCS root; scoping to the root itself would be a no-op and is rejected. Not available for Mercurial, Jujutsu, or hg-git checkouts.

set tag.prefix when projects are tagged separately

git describe picks the topologically nearest tag, which in a monorepo tagged pkg-a-v1.2, pkg-b-v3.0 may well belong to a different project -- and the distance would then be counted from that project's release. A warning is emitted when the reachable tags span several namespaces. Repositories on a single release train (v1.2, v1.3 for everything) need no prefix.

shallow clones are rejected

A scoped count walks history looking for commits that touch the paths, so a truncated history does not merely shorten the answer -- it can miss every relevant commit and report 0, which reads as an exact tag. This is an error regardless of scm.git.pre_parse.

git archives carry a repository-wide distance

git archive records its describe output through %(describe), which takes no pathspec, so an archive of a non-tag commit carries a count that is an upper bound on the scoped one -- the version comes out too high, and a warning says so. An archive of a tag has distance 0 and is exact either way, so release tarballs are unaffected. Build from an sdist, which carries the already-computed version.

scm.git.distance_count

How commits are counted once scm.git.distance_scope restricts them. Ignored when distance_scope is not set.

  • "full-history" (default): every commit whose content at the scoped paths differs from a parent. Counts work done on merged feature branches, so the numbers can get large in merge-heavy repositories.
  • "first-parent": the same, restricted to the first-parent chain, so a merged feature branch counts once no matter how many commits it held. Counts on topic branches are not comparable to mainline's and can decrease when the branch is merged, so use this only if you release from mainline.

Both are set predicates over the commits reachable from HEAD but not from the tag, so neither can make the distance shrink as mainline history advances. Git's own default history simplification (what plain git log -- path shows) is deliberately not offered: it follows only one parent at a merge, which can make the distance shrink.

git_describe_command (deprecated)

Deprecated since 8.4.0: Use scm.git.describe_command instead.

This field is maintained for backward compatibility but will issue a deprecation warning when used.

relative_to: Path | PathLike[str] = "pyproject.toml"
A file/directory from which the root can be resolved. Typically called by a script or module that is not in the root of the repository to point to the root of the repository by supplying __file__.
parse: Callable[[Path, Config], ScmVersion] | None = None
A function that will be used instead of the discovered SCM for parsing the version. Use with caution, this is a function for advanced use and you should be familiar with the vcs-versioning internals to use it.
version_file: Path | PathLike[str] | None = None

A path to a file that gets replaced with a file containing the current version. It is ideal for creating a _version.py file within the package, typically used to avoid using importlib.metadata (which adds some overhead).

Only files with .py and .txt extensions have builtin templates, for other file types it is necessary to provide version_file_template.

version_file_template: str | None = None
A new-style format string taking version, scm_version and version_tuple as parameters. version is the generated next_version as string, version_tuple is a tuple of split numbers/strings and scm_version is the ScmVersion instance the current version was rendered from
write_to_source: bool | None = None

Controls whether version files (specified by version_file or write_to) are written to the source tree during version inference.

Value Behavior
unset Writes to source tree and emits a DeprecationWarning advising you to set this option explicitly, since the default will change in a future major release.
true Writes to source tree, no warning — explicit opt-in.
false Does not write to source tree, no warning — explicit opt-out. Version files are still written to the build directory during build_py.

The SETUPTOOLS_SCM_WRITE_TO_SOURCE environment variable overrides this setting (see Environment Variables below).

Deprecation cycle

In a future major release, the default will change from writing to source to not writing to source. Set write_to_source = true now if you rely on version files being present in your source tree.

pyproject.toml
[tool.setuptools_scm]
version_file = "mypackage/_version.py"
write_to_source = true

setuptools-scm Specific Configuration

These options control setuptools integration behavior.

write_to: PathLike[str] | Path | None = None
(deprecated) legacy option to create a version file relative to the SCM root. It's broken for usage from an sdist and fixing it would be a fatal breaking change, use version_file instead.

Environment Variables

Version Detection Overrides

These environment variables override version detection behavior.

SETUPTOOLS_SCM_PRETEND_VERSION

used as the primary source for the version number in which case it will be an unparsed string

it is strongly recommended to use distribution-specific pretend versions (see below).

SETUPTOOLS_SCM_PRETEND_VERSION_FOR_${DIST_NAME}

used as the primary source for the version number, in which case it will be an unparsed string. Specifying distribution-specific pretend versions will avoid possible collisions with third party distributions also using setuptools-scm

the dist name normalization follows adapted PEP 503 semantics, with one or more of ".-_" being replaced by a single "_", and the name being upper-cased

this will take precedence over SETUPTOOLS_SCM_PRETEND_VERSION

SETUPTOOLS_SCM_PRETEND_METADATA
A TOML inline table for overriding individual version metadata fields. See the overrides documentation for details.
SETUPTOOLS_SCM_PRETEND_METADATA_FOR_${DIST_NAME}
Same as above but specific to a package (recommended over the generic version).
SETUPTOOLS_SCM_DEBUG
Enable debug logging for version detection and processing.
SOURCE_DATE_EPOCH
Used as the timestamp from which the node-and-date and node-and-timestamp local parts are derived, otherwise the current time is used. Standard environment variable from reproducible-builds.org.

setuptools-scm Overrides

These environment variables control setuptools-scm specific behavior.

SETUPTOOLS_SCM_IGNORE_VCS_ROOTS
A os.pathsep separated list of directory names to ignore for root finding
SETUPTOOLS_SCM_HG_COMMAND

Command used for running Mercurial (defaults to hg)

For example, set this to chg to reduce start-up overhead of Mercurial

SETUPTOOLS_SCM_OVERRIDES_FOR_${DIST_NAME}
A TOML inline table to override configuration from pyproject.toml. See the overrides documentation for details.
SETUPTOOLS_SCM_WRITE_TO_SOURCE
Override the write_to_source configuration option. Set to 1/true/yes to write version files to the source tree, or 0/false/no to disable it. When set, no deprecation warning is emitted regardless of the pyproject.toml setting.
SETUPTOOLS_SCM_SUBPROCESS_TIMEOUT
Override the subprocess timeout (default: 40 seconds). See the overrides documentation for details.
SETUPTOOLS_SCM_DISABLE_JJ

Disable Jujutsu (jj) backend discovery. When set to 1/true/yes, setuptools-scm will skip the jj backend even if a .jj/ directory is present, falling back to Git or Mercurial detection instead.

This is useful in container or CI environments where a colocated Jujutsu/Git repository is used but the jj binary is not installed. Without this variable, a missing jj binary in a .jj/ repository raises an error.

Also available as VCS_VERSIONING_DISABLE_JJ.

See Jujutsu repositories for details.

Automatic File Inclusion

Setuptools File Finder Integration

setuptools-scm still registers a setuptools file finder that includes all SCM-tracked files in source distributions. For projects that configure setuptools-scm, file listing uses the validated workdir API instead of this entry point.

Using the global setuptools.file_finders entry point without configuring setuptools-scm is deprecated and will be removed in a future major release. Unconfigured projects that still hit the entry point get a DeprecationWarning.

How it works:

When setuptools-scm is configured, ScmEggInfoMixin lists tracked files from the discovered workdir. The legacy setuptools.file_finders entry point remains registered for compatibility:

  1. Automatically discovers SCM-managed files (Git, Mercurial, Jujutsu)
  2. Includes them in source distributions (python -m build --sdist)
  3. Works for include_package_data = True in package building

Entry point registration:

[project.entry-points."setuptools.file_finders"]
setuptools_scm = "setuptools_scm._integration.file_finders:find_files"

Files included by default:

  • All files tracked by Git (git ls-files)
  • All files tracked by Mercurial (hg files)
  • All files tracked by Jujutsu (jj file list)
  • Includes: source code, documentation, tests, config files, etc.
  • Excludes: untracked files, files in .gitignore/.hgignore

Controlling inclusion:

Use MANIFEST.in to override the automatic behavior:

MANIFEST.in
# Exclude development files
exclude .pre-commit-config.yaml
exclude tox.ini
global-exclude *.pyc __pycache__/

# Exclude entire directories
prune docs/
prune testing/

# Include non-SCM files
include data/important.json

Debugging file inclusion:

# List files that will be included
python -m setuptools_scm ls

# Build and inspect sdist contents
python -m build --sdist
tar -tzf dist/package-*.tar.gz

Cannot be disabled today

The file finder cannot be turned off through configuration while the entry point is still registered. To stop using it, either configure setuptools-scm (so builds use the workdir path) or remove setuptools-scm from the build environment. The unconfigured entry-point path will be removed in a future major release.

API Reference

constants

vcs_versioning._config.DEFAULT_TAG_REGEX module-attribute

DEFAULT_TAG_REGEX = compile('^(?:[\\w-]+-)?(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$')

default tag regex that tries to match PEP440 style versions with prefix consisting of dashed words

vcs_versioning._backends._git.DEFAULT_DESCRIBE module-attribute

DEFAULT_DESCRIBE = make_describe_command('*[0-9]*')

the configuration class

vcs_versioning.Configuration dataclass

Global configuration model

Source code in vcs-versioning/src/vcs_versioning/_config.py
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
@dataclasses.dataclass
class Configuration:
    """Global configuration model"""

    relative_to: _t.PathT | None = None
    root: _t.PathT = "."
    version_scheme: _t.VERSION_SCHEMES = DEFAULT_VERSION_SCHEME
    local_scheme: _t.VERSION_SCHEMES = DEFAULT_LOCAL_SCHEME
    tag_regex: dataclasses.InitVar[str | Pattern[str] | None] = _TagRegexDescriptor()
    parentdir_prefix_version: str | None = None
    fallback_version: str | None = None
    fallback_root: _t.PathT = "."
    write_to: _t.PathT | None = None
    write_to_template: str | None = None
    version_file: _t.PathT | None = None
    version_file_template: str | None = None
    parse: ParseFunction | None = None
    git_describe_command: dataclasses.InitVar[_t.CMD_TYPE | None] = (
        _GitDescribeCommandDescriptor()
    )

    dist_name: str | None = None
    version_cls: type[_VersionAlias] = _Version
    search_parent_directories: bool = False
    project_path: str | None = None

    parent: _t.PathT | None = None

    write_to_source: bool | None = None
    """Whether to write version files to the source tree at inference time.

    - ``None`` (default): write to source **and** emit a ``DeprecationWarning``
      telling users to set this explicitly, since the default will change
      in the next major release.
    - ``True``: write to source tree, no warning.
    - ``False``: do **not** write to source tree, no warning.

    The ``SETUPTOOLS_SCM_WRITE_TO_SOURCE`` / ``VCS_VERSIONING_WRITE_TO_SOURCE``
    environment variable overrides this setting.
    """

    # Nested configurations
    tag: TagConfiguration = dataclasses.field(
        default_factory=lambda: TagConfiguration()
    )
    scm: ScmConfiguration = dataclasses.field(
        default_factory=lambda: ScmConfiguration()
    )

    _env: VcsEnvironment | None = dataclasses.field(
        default=None, repr=False, compare=False
    )
    """The :class:`~vcs_versioning._environment.VcsEnvironment` for this config.

    Populated by ``VcsEnvironment.build_config()`` or lazily on first
    ``env`` access (with a ``DeprecationWarning``).  ``None`` until then.
    """

    # Deprecated fields (handled in __post_init__)

    def __post_init__(
        self,
        tag_regex: str | Pattern[str] | None,
        git_describe_command: _t.CMD_TYPE | None,
    ) -> None:
        # Handle deprecated top-level tag_regex
        if tag_regex is not None and not isinstance(tag_regex, _TagRegexDescriptor):
            is_from_dataclasses = _is_called_from_dataclasses()
            same_value = tag_regex == self.tag.regex or (
                isinstance(tag_regex, Pattern)
                and tag_regex.pattern == self.tag.regex.pattern
            )
            if is_from_dataclasses and same_value:
                pass
            else:
                warnings.warn(
                    "Configuration field 'tag_regex' is deprecated. "
                    "Use 'tag.regex' instead.",
                    DeprecationWarning,
                    stacklevel=2,
                )
                if self.tag.regex.pattern != DEFAULT_TAG_REGEX.pattern:
                    raise ValueError(
                        "Cannot specify both 'tag_regex' (deprecated) and "
                        "'tag.regex'. Please use only 'tag.regex'."
                    )
                self.tag = dataclasses.replace(
                    self.tag, regex=_check_tag_regex(tag_regex)
                )

        # tag.strict and describe_command diagnostics deliberately do not live
        # here: they are only actionable once the SCM has been consulted, so the
        # git backend reports them when they actually change the version (#1429)

        self._resolved_paths = resolve_paths(
            relative_to=self.relative_to,
            root=self.root,
            project_path=self.project_path,
        )
        if self.project_path is None and self._resolved_paths.project_path is not None:
            self.project_path = self._resolved_paths.project_path

        # Handle deprecated git_describe_command
        # Check if it's a descriptor object (happens when no value is passed)
        if git_describe_command is not None and not isinstance(
            git_describe_command, _GitDescribeCommandDescriptor
        ):
            # Check if this is being called from dataclasses
            is_from_dataclasses = _is_called_from_dataclasses()

            same_value = (
                self.scm.git.describe_command is not None
                and self.scm.git.describe_command == git_describe_command
            )

            if is_from_dataclasses and same_value:
                # Ignore the passed value - it's from dataclasses.replace() with same value
                pass
            else:
                warnings.warn(
                    "Configuration field 'git_describe_command' is deprecated. "
                    "Use 'scm.git.describe_command' instead.",
                    DeprecationWarning,
                    stacklevel=2,
                )
                # Check for conflicts
                if self.scm.git.describe_command is not None:
                    raise ValueError(
                        "Cannot specify both 'git_describe_command' (deprecated) and "
                        "'scm.git.describe_command'. Please use only 'scm.git.describe_command'."
                    )
                self.scm.git.describe_command = git_describe_command

    @property
    def absolute_root(self) -> str:
        return str(self._resolved_paths.scm_probe_root)

    @property
    def env(self) -> VcsEnvironment:
        """The :class:`~vcs_versioning._environment.VcsEnvironment` for this config.

        Always non-None after first access — set by ``VcsEnvironment.build_config()``
        or lazily resolved on first access (with a ``DeprecationWarning``).
        """
        if self._env is None:
            warnings.warn(
                "Configuration was created without VcsEnvironment. "
                "Use VcsEnvironment.build_config() to create configurations "
                "with runtime settings attached explicitly. "
                "This will become an error in vcs-versioning 2.0.",
                DeprecationWarning,
                stacklevel=2,
            )
            from ._environment import resolve_runtime_env

            object.__setattr__(self, "_env", resolve_runtime_env())
        assert self._env is not None
        return self._env

    def discover_workdir(self) -> ScmWorkdir | FallbackWorkdir | None:
        """Discover the workdir for this configuration."""
        from ._worktree_discovery import discover_workdir

        return discover_workdir(self)

    @classmethod
    def from_file(
        cls,
        name: str | os.PathLike[str] = "pyproject.toml",
        dist_name: str | None = None,
        pyproject_data: PyProjectData | None = None,
        *,
        tool_names: tuple[str, ...] | None = None,
        env: Mapping[str, str] | None = None,
        _env: VcsEnvironment | None = None,
        **kwargs: Any,
    ) -> Configuration:
        """
                Read Configuration from pyproject.toml (or similar).
                Raises exceptions when file is not found or toml is
                not installed or the file has invalid format.

        Parameters:
        - name: path to pyproject.toml
        - dist_name: name of the distribution
        - tool_names: env-var prefix order for TOML overrides
        - env: environment mapping for TOML overrides (default: os.environ)
        - _env: VcsEnvironment to attach to the resulting Configuration
        - **kwargs: additional keyword arguments to pass to the Configuration constructor
        """

        if pyproject_data is None:
            pyproject_data = read_pyproject(Path(name))
        args = get_args_for_pyproject(pyproject_data, dist_name, kwargs)

        # Per-project overrides: lower priority than env overrides
        from ._project_overrides import read_project_overrides

        relative_to = args.pop("relative_to", name)
        resolved = resolve_paths(
            relative_to=relative_to,
            root=args.get("root", "."),
            project_path=args.get("project_path"),
        )
        project_overrides = read_project_overrides(
            scm_root=resolved.scm_probe_root,
            project_path=resolved.project_path or "",
        )
        args.update(project_overrides)

        # Env overrides: highest priority
        if _env is not None:
            args.update(_env.read_toml_overrides(args["dist_name"]))
        else:
            args.update(
                read_toml_overrides(args["dist_name"], tool_names=tool_names, env=env)
            )
        return cls.from_data(relative_to=relative_to, data=args, _env=_env)

    @classmethod
    def from_data(
        cls,
        relative_to: str | os.PathLike[str],
        data: dict[str, Any],
        _env: VcsEnvironment | None = None,
    ) -> Configuration:
        """
        given configuration data
        create a config instance after validating tag regex/version class
        """
        version_cls = _validate_version_cls(
            data.pop("version_cls", None), data.pop("normalize", True)
        )

        # Migrate top-level tag_regex into tag.regex
        tag_data = data.pop("tag", None) or {}
        top_level_tag_regex = data.pop("tag_regex", None)
        if top_level_tag_regex is not None:
            if "regex" in tag_data:
                raise ValueError(
                    "Cannot specify both 'tag_regex' (deprecated) and "
                    "'tag.regex'. Please use only 'tag.regex'."
                )
            warnings.warn(
                "Configuration key 'tag_regex' is deprecated. Use 'tag.regex' instead.",
                DeprecationWarning,
                stacklevel=2,
            )
            tag_data["regex"] = top_level_tag_regex

        tag_config = TagConfiguration.from_data(tag_data if tag_data else None)
        scm_data = data.pop("scm", {})
        scm_config = ScmConfiguration.from_data(scm_data)
        return cls(
            relative_to=relative_to,
            version_cls=version_cls,
            tag=tag_config,
            scm=scm_config,
            _env=_env,
            **data,
        )
env property
env: VcsEnvironment

The :class:~vcs_versioning._environment.VcsEnvironment for this config.

Always non-None after first access — set by VcsEnvironment.build_config() or lazily resolved on first access (with a DeprecationWarning).

write_to_source class-attribute instance-attribute
write_to_source: bool | None = None

Whether to write version files to the source tree at inference time.

  • None (default): write to source and emit a DeprecationWarning telling users to set this explicitly, since the default will change in the next major release.
  • True: write to source tree, no warning.
  • False: do not write to source tree, no warning.

The SETUPTOOLS_SCM_WRITE_TO_SOURCE / VCS_VERSIONING_WRITE_TO_SOURCE environment variable overrides this setting.

discover_workdir
discover_workdir() -> ScmWorkdir | FallbackWorkdir | None

Discover the workdir for this configuration.

Source code in vcs-versioning/src/vcs_versioning/_config.py
485
486
487
488
489
def discover_workdir(self) -> ScmWorkdir | FallbackWorkdir | None:
    """Discover the workdir for this configuration."""
    from ._worktree_discovery import discover_workdir

    return discover_workdir(self)
from_data classmethod
from_data(relative_to: str | PathLike[str], data: dict[str, Any], _env: VcsEnvironment | None = None) -> Configuration

given configuration data create a config instance after validating tag regex/version class

Source code in vcs-versioning/src/vcs_versioning/_config.py
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
@classmethod
def from_data(
    cls,
    relative_to: str | os.PathLike[str],
    data: dict[str, Any],
    _env: VcsEnvironment | None = None,
) -> Configuration:
    """
    given configuration data
    create a config instance after validating tag regex/version class
    """
    version_cls = _validate_version_cls(
        data.pop("version_cls", None), data.pop("normalize", True)
    )

    # Migrate top-level tag_regex into tag.regex
    tag_data = data.pop("tag", None) or {}
    top_level_tag_regex = data.pop("tag_regex", None)
    if top_level_tag_regex is not None:
        if "regex" in tag_data:
            raise ValueError(
                "Cannot specify both 'tag_regex' (deprecated) and "
                "'tag.regex'. Please use only 'tag.regex'."
            )
        warnings.warn(
            "Configuration key 'tag_regex' is deprecated. Use 'tag.regex' instead.",
            DeprecationWarning,
            stacklevel=2,
        )
        tag_data["regex"] = top_level_tag_regex

    tag_config = TagConfiguration.from_data(tag_data if tag_data else None)
    scm_data = data.pop("scm", {})
    scm_config = ScmConfiguration.from_data(scm_data)
    return cls(
        relative_to=relative_to,
        version_cls=version_cls,
        tag=tag_config,
        scm=scm_config,
        _env=_env,
        **data,
    )
from_file classmethod
from_file(name: str | PathLike[str] = 'pyproject.toml', dist_name: str | None = None, pyproject_data: PyProjectData | None = None, *, tool_names: tuple[str, ...] | None = None, env: Mapping[str, str] | None = None, _env: VcsEnvironment | None = None, **kwargs: Any) -> Configuration
    Read Configuration from pyproject.toml (or similar).
    Raises exceptions when file is not found or toml is
    not installed or the file has invalid format.

Parameters: - name: path to pyproject.toml - dist_name: name of the distribution - tool_names: env-var prefix order for TOML overrides - env: environment mapping for TOML overrides (default: os.environ) - _env: VcsEnvironment to attach to the resulting Configuration - **kwargs: additional keyword arguments to pass to the Configuration constructor

Source code in vcs-versioning/src/vcs_versioning/_config.py
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
@classmethod
def from_file(
    cls,
    name: str | os.PathLike[str] = "pyproject.toml",
    dist_name: str | None = None,
    pyproject_data: PyProjectData | None = None,
    *,
    tool_names: tuple[str, ...] | None = None,
    env: Mapping[str, str] | None = None,
    _env: VcsEnvironment | None = None,
    **kwargs: Any,
) -> Configuration:
    """
            Read Configuration from pyproject.toml (or similar).
            Raises exceptions when file is not found or toml is
            not installed or the file has invalid format.

    Parameters:
    - name: path to pyproject.toml
    - dist_name: name of the distribution
    - tool_names: env-var prefix order for TOML overrides
    - env: environment mapping for TOML overrides (default: os.environ)
    - _env: VcsEnvironment to attach to the resulting Configuration
    - **kwargs: additional keyword arguments to pass to the Configuration constructor
    """

    if pyproject_data is None:
        pyproject_data = read_pyproject(Path(name))
    args = get_args_for_pyproject(pyproject_data, dist_name, kwargs)

    # Per-project overrides: lower priority than env overrides
    from ._project_overrides import read_project_overrides

    relative_to = args.pop("relative_to", name)
    resolved = resolve_paths(
        relative_to=relative_to,
        root=args.get("root", "."),
        project_path=args.get("project_path"),
    )
    project_overrides = read_project_overrides(
        scm_root=resolved.scm_probe_root,
        project_path=resolved.project_path or "",
    )
    args.update(project_overrides)

    # Env overrides: highest priority
    if _env is not None:
        args.update(_env.read_toml_overrides(args["dist_name"]))
    else:
        args.update(
            read_toml_overrides(args["dist_name"], tool_names=tool_names, env=env)
        )
    return cls.from_data(relative_to=relative_to, data=args, _env=_env)