pyproject.tomlsetup.py based project?pyproject.toml specification¶Warning
This is atechnical, formal specification. For a gentle,user-friendly guide topyproject.toml, seeWriting your pyproject.toml.
Thepyproject.toml file acts as a configuration file for packaging-relatedtools (as well as other tools).
Thepyproject.toml file is written inTOML. Threetables are currently specified, namely[build-system],[project] and[tool]. Other tables are reserved for futureuse (tool-specific configuration should use the[tool] table).
[build-system] table¶The[build-system] table declares any Python level dependencies thatmust be installed in order to run the project’s build systemsuccessfully.
The[build-system] table is used to store build-related data.Initially, only one key of the table is valid and is mandatoryfor the table:requires. This key must have a value of a listof strings representing dependencies required to execute thebuild system. The strings in this list follow theversion specifierspecification.
An example[build-system] table for a project built withsetuptools is:
[build-system]# Minimum requirements for the build system to execute.requires=["setuptools"]
Build tools are expected to use the example configuration file above astheir default semantics when apyproject.toml file is not present.
Tools should not require the existence of the[build-system] table.Apyproject.toml file may be used to store configuration detailsother than build-related data and thus lack a[build-system] tablelegitimately. If the file exists but is lacking the[build-system]table then the default values as specified above should be used.If the table is specified but is missing required fields then the toolshould consider it an error.
Tools may choose to present an error to the user if the file exists,[build-system] table is missing, and there is no clear indicationthat the project should be built (e.g., no setup.py/setup.cfg or otherbuild configuration files, and no[project] table).
To provide a type-specific representation of the resulting data fromthe TOML file for illustrative purposes only, the followingJSON Schema would match the data format:
{"$schema":"http://json-schema.org/schema#","type":"object","additionalProperties":false,"properties":{"build-system":{"type":"object","additionalProperties":false,"properties":{"requires":{"type":"array","items":{"type":"string"}}},"required":["requires"]},"tool":{"type":"object"}}}
[project] table¶The[project] table specifies the project’score metadata.
There are two kinds of metadata:static anddynamic. Staticmetadata is specified in thepyproject.toml file directly andcannot be specified or changed by a tool (this includes datareferred to by the metadata, e.g. the contents of files referencedby the metadata). Dynamic metadata is listed via thedynamic key(defined later in this specification) and represents metadata that atool will later provide.
The lack of a[project] table implicitly means thebuild backendwill dynamically provide all keys.
The only keys required to be statically defined are:
name
The keys which are required but may be specifiedeither staticallyor listed as dynamic are:
version
All other keys are considered optional and may be specifiedstatically, listed as dynamic, or left unspecified.
The complete list of keys allowed in the[project] table are:
authors
classifiers
dependencies
description
dynamic
entry-points
gui-scripts
import-names
import-namespaces
keywords
license
license-files
maintainers
name
optional-dependencies
readme
requires-python
scripts
urls
version
name¶TOML type: string
Correspondingcore metadata field:Name
The name of the project.
Tools SHOULDnormalize this name, as soonas it is read for internal consistency.
version¶TOML type: string
Correspondingcore metadata field:Version
The version of the project, as defined in theVersion specifier specification.
Users SHOULD prefer to specify already-normalized versions.
description¶TOML type: string
Correspondingcore metadata field:Summary
The summary description of the project in one line. Tools MAY errorif this includes multiple lines.
readme¶TOML type: string or table
Correspondingcore metadata field:Description andDescription-Content-Type
The full description of the project (i.e. the README).
The key accepts either a string or a table. If it is a string thenit is a path relative topyproject.toml to a text file containingthe full description. Tools MUST assume the file’s encoding is UTF-8.If the file path ends in a case-insensitive.md suffix, then toolsMUST assume the content-type istext/markdown. If the file pathends in a case-insensitive.rst, then tools MUST assume thecontent-type istext/x-rst. If a tool recognizes more extensionsthan this PEP, they MAY infer the content-type for the user withoutspecifying this key asdynamic. For all unrecognized suffixeswhen a content-type is not provided, tools MUST raise an error.
Thereadme key may also take a table. Thefile key has astring value representing a path relative topyproject.toml to afile containing the full description. Thetext key has a stringvalue which is the full description. These keys aremutually-exclusive, thus tools MUST raise an error if the metadataspecifies both keys.
A table specified in thereadme key also has acontent-typekey which takes a string specifying the content-type of the fulldescription. A tool MUST raise an error if the metadata does notspecify this key in the table. If the metadata does not specify thecharset parameter, then it is assumed to be UTF-8. Tools MAYsupport other encodings if they choose to. Tools MAY supportalternative content-types which they can transform to a content-typeas supported by thecore metadata. Otherwisetools MUST raise an error for unsupported content-types.
requires-python¶TOML type: string
Correspondingcore metadata field:Requires-Python
The Python version requirements of the project.
license¶TOML type: string
Correspondingcore metadata field:License-Expression
Text string that is a valid SPDXlicense expression,as specified inLicense Expression.Tools SHOULD validate and perform case normalization of the expression.
This key shouldonly be specified if the license expression for anyand all distribution files created by a build backend using thepyproject.toml is the same as the one specified. If the licenseexpression will differ then it should either be specified as dynamic ornot set at all.
TOML type: table
Correspondingcore metadata field:License
The table may have one of two keys. Thefile key has a stringvalue that is a file path relative topyproject.toml to the filewhich contains the license for the project. Tools MUST assume thefile’s encoding is UTF-8. Thetext key has a string value which isthe license of the project. These keys are mutually exclusive, so atool MUST raise an error if the metadata specifies both keys.
The table subkeys were deprecated byPEP 639 in favor of the string value.
license-files¶TOML type: array of strings
Correspondingcore metadata field:License-File
An array specifying paths in the project source tree relative to the projectroot directory (i.e. directory containingpyproject.toml or legacy projectconfiguration files, e.g.setup.py,setup.cfg, etc.)to file(s) containing licenses and other legal notices to bedistributed with the package.
The strings MUST contain valid glob patterns, as specified inglob patterns.
Patterns are relative to the directory containingpyproject.toml,
Tools MUST assume that license file content is valid UTF-8 encoded text,and SHOULD validate this and raise an error if it is not.
Build tools:
MUST include all files matched by a listed pattern in all distributionarchives.
MUST list each matched file path under a License-File field in theCore Metadata.
If thelicense-files key is present andis set to a value of an empty array, then tools MUST NOT include anylicense files and MUST NOT raise an error.If thelicense-files key is not defined, tools can decide how to handlelicense files. For example they can choose not to include any files or usetheir own logic to discover the appropriate files in the distribution.
authors/maintainers¶TOML type: Array of inline tables with string keys and values
Correspondingcore metadata field:Author,Author-email,Maintainer, andMaintainer-email
The people or organizations considered to be the “authors” of theproject. The exact meaning is open to interpretation — it may list theoriginal or primary authors, current maintainers, or owners of thepackage.
The “maintainers” key is similar to “authors” in that its exactmeaning is open to interpretation.
These keys accept an array of tables with 2 keys:name andemail. Both values must be strings. Thename value MUST be avalid email name (i.e. whatever can be put as a name, before an email,inRFC 822) and not contain commas. Theemail value MUST be avalid email address. Both keys are optional, but at least one of thekeys must be specified in the table.
Using the data to fill incore metadata is asfollows:
If onlyname is provided, the value goes inAuthor orMaintainer as appropriate.
If onlyemail is provided, the value goes inAuthor-email orMaintainer-emailas appropriate.
If bothemail andname are provided, the value goes inAuthor-email orMaintainer-emailas appropriate, with the format{name}<{email}>.
Multiple values should be separated by commas.
keywords¶TOML type: array of strings
Correspondingcore metadata field:Keywords
The keywords for the project.
classifiers¶TOML type: array of strings
Correspondingcore metadata field:Classifier
Trove classifiers which apply to the project.
The use ofLicense:: classifiers is deprecated and tools MAY issue awarning informing users about that.Build tools MAY raise an error if both thelicense string value(translating toLicense-Expression metadata field) and theLicense::classifiers are used.
urls¶TOML type: table with keys and values of strings
Correspondingcore metadata field:Project-URL
A table of URLs where the key is the URL label and the value is theURL itself. SeeWell-known Project URLs in Metadata for normalization rulesand well-known rules when processing metadata for presentation.
TOML type: table ([project.scripts],[project.gui-scripts],and[project.entry-points])
There are three tables related to entry points. The[project.scripts] table corresponds to theconsole_scriptsgroup in theentry points specification. The keyof the table is the name of the entry point and the value is theobject reference.
The[project.gui-scripts] table corresponds to thegui_scriptsgroup in theentry points specification. Itsformat is the same as[project.scripts].
The[project.entry-points] table is a collection of tables. Eachsub-table’s name is an entry point group. The key and value semanticsare the same as[project.scripts]. Users MUST NOT createnested sub-tables but instead keep the entry point groups to only onelevel deep.
Build back-ends MUST raise an error if the metadata defines a[project.entry-points.console_scripts] or[project.entry-points.gui_scripts] table, as they wouldbe ambiguous in the face of[project.scripts] and[project.gui-scripts], respectively.
dependencies/optional-dependencies¶TOML type: Array ofPEP 508 strings (dependencies), and atable with values of arrays ofPEP 508 strings(optional-dependencies)
Correspondingcore metadata field:Requires-Dist andProvides-Extra
The (optional) dependencies of the project.
Fordependencies, it is a key whose value is an array of strings.Each string represents a dependency of the project and MUST beformatted as a validPEP 508 string. Each string maps directly toaRequires-Dist entry.
Foroptional-dependencies, it is a table where each key specifiesan extra and whose value is an array of strings. The strings of thearrays must be validPEP 508 strings. The keys MUST be valid valuesforProvides-Extra. Each valuein the array thus becomes a correspondingRequires-Dist entry for thematchingProvides-Extrametadata.
import-names¶TOML type: array of strings
Correspondingcore metadata field:Import-Name
An array of strings specifying the import names that the project exclusivelyprovides when installed. Each string MUST be a valid Python identifier or canbe empty. An import name MAY be followed by a semicolon and the term “private”(e.g.";private") with any amount of whitespace surrounding the semicolon.
Projects SHOULD list all the shortest import names that are exclusively providedby the project. If any of the shortest names are dotted names, all interveningnames from that name to the top-level name should also be listed appropriatelyinimport-names and/orimport-namespaces. For instance, a project whichis a single package named spam with multiple submodules would only listproject.import-names=["spam"]. A project that listsspam.bacon.eggswould also need to account forspam andspam.bacon appropriately inimport-names andimport-namespaces. Listing all names acts as a checkthat the intent of the import names is as expected. As well, projects SHOULDlist all import names, public or private, using the;private modifier asappropriate.
If a project lists the same name in bothimport-names andimport-namespaces, then tools MUST raise an error due to ambiguity.
Projects MAY setimport-names to an empty array to represent a project withno import names (i.e. there are no Python modules of any kind in thedistribution file).
Build back-ends MAY support dynamically calculating the value if the userdeclares the key inproject.dynamic.
Examples:
[project]name="pillow"import-names=["PIL"]
[project]name="myproject"import-names=["mypackage","_private_module ; private"]
import-namespaces¶TOML type: array of strings
Correspondingcore metadata field:Import-Namespace
An array of strings specifying the import names that the project provides wheninstalled, but not exclusively. Each string MUST be a valid Python identifier.An import name MAY be followed by a semicolon and the term “private” (e.g.";private") with any amount of whitespace surrounding the semicolon. Notethat unlikeimport-names,import-namespaces CANNOT be an empty array.
Projects SHOULD list all the shortest import names that are exclusively providedby the project. If any of the shortest names are dotted names, all interveningnames from that name to the top-level name should also be listed appropriatelyinimport-names and/orimport-namespaces.
This field is used for namespace packages where multiple projects can contributeto the same import namespace. Projects all listing the same import name inimport-namespaces can be installed together without shadowing each other.
If a project lists the same name in bothimport-names andimport-namespaces, then tools MUST raise an error due to ambiguity.
Build back-ends MAY support dynamically calculating the value if the userdeclares the key inproject.dynamic.
Example:
[project]name="zope-interface"import-namespaces=["zope"]import-names=["zope.interface"]
dynamic¶TOML type: array of string
Correspondingcore metadata field:Dynamic
Specifies which keys listed by this PEP were intentionallyunspecified so another tool can/will provide such metadatadynamically. This clearly delineates which metadata is purposefullyunspecified and expected to stay unspecified compared to beingprovided via tooling later on.
A build back-end MUST honour statically-specified metadata (whichmeans the metadata did not list the key indynamic).
A build back-end MUST raise an error if the metadata specifiesname indynamic.
If thecore metadata specification lists afield as “Required”, then the metadata MUST specify the keystatically or list it indynamic (build back-ends MUST raise anerror otherwise, i.e. it should not be possible for a required keyto not be listed somehow in the[project] table).
If thecore metadata specification lists afield as “Optional”, the metadata MAY list it indynamic if theexpectation is a build back-end will provide the data for the keylater.
Build back-ends MUST raise an error if the metadata specifies akey statically as well as being listed indynamic.
If the metadata does not list a key indynamic, then a buildback-end CANNOT fill in the requisite metadata on behalf of the user(i.e.dynamic is the only way to allow a tool to fill inmetadata and the user must opt into the filling in).
Build back-ends MUST raise an error if the metadata specifies akey indynamic but the build back-end was unable to determinethe data for it (omitting the data, if determined to be the accuratevalue, is acceptable).
[tool] table¶The[tool] table is where any tool related to your Pythonproject, not just build tools, can have users specify configurationdata as long as they use a sub-table within[tool], e.g. theflit tool would store itsconfiguration in[tool.flit].
A mechanism is needed to allocate names within thetool.*namespace, to make sure that different projects do not attempt to usethe same sub-table and collide. Our rule is that a project can usethe subtabletool.$NAME if, and only if, they own the entry for$NAME in the Cheeseshop/PyPI.
May 2016: The initial specification of thepyproject.toml file, with justa[build-system] containing arequires key and a[tool] table, wasapproved throughPEP 518.
November 2020: The specification of the[project] table was approvedthroughPEP 621.
December 2024: Thelicense key was redefined, thelicense-files key wasadded andLicense:: classifiers were deprecated throughPEP 639.
September 2025: Clarity that thelicense key applies to all distributionfiles generated from thepyproject.toml file.
October 2025: Theimport-names andimport-namespaces keys were addedthroughPEP 794.