diff --git a/docs/configuration.md b/docs/configuration.md index 025267c230..3998e199bd 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -154,6 +154,22 @@ The `python` target requires two configuration entries: * `module` - the name of the generated **Python** module, which will be used by users in `import` directives. * `distName` - the [PyPI] distribution name for the package. +* `classifiers` - a list of [trove classifiers] to declare on the package. It is + the user's responsibility to specify *valid* values (the authoritative list of + valid [trove classifiers] is masted in the [pypa/trove-classifiers] package). + * Some classifiers are automatically included (and should not be added to the + `classifiers` property) based on relevant configuration from the + `package.json` file: + * `Development Status :: ` is determined based on the package's `stability` + * `License ::` is determined based on the package's `license` + * `Operating System :: OS Independent` is always set + * `Typing :: Typed` is always set + * Additionally, the following `Programming Language ::` classifiers are + already set (more could be added by the user if relevant): + * `Programming Language :: Python :: 3 :: Only` + * `Programming Language :: Python :: 3.6` + * `Programming Language :: Python :: 3.7` + * `Programming Language :: Python :: 3.8` Example: ```js @@ -162,7 +178,11 @@ Example: "targets": { "python": { "module": "hello_jsii", // Required - "distName": "hello-jsii" // Required + "distName": "hello-jsii", // Required + "classifiers": [ // Optional + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ] }, // ... } @@ -175,6 +195,8 @@ Example: The resulting package can be published to [PyPI]. [PyPI]: https://pypi.org/ +[trove classifiers]: https://www.python.org/dev/peps/pep-0301/#distutils-trove-classification +[pypa/trove-classifiers]: https://github.com/pypa/trove-classifiers #### Configuring `Java` diff --git a/packages/@jsii/kernel/test/kernel.test.ts b/packages/@jsii/kernel/test/kernel.test.ts index e8ab48b1ee..504bcb724a 100644 --- a/packages/@jsii/kernel/test/kernel.test.ts +++ b/packages/@jsii/kernel/test/kernel.test.ts @@ -406,7 +406,11 @@ defineTest( }, }, js: { npm: 'jsii-calc' }, - python: { distName: 'jsii-calc', module: 'jsii_calc' }, + python: { + distName: 'jsii-calc', + module: 'jsii_calc', + classifiers: ['Test :: Classifier :: Is Dummy'], + }, }); expect(sandbox.naming({ assembly: '@scope/jsii-calc-lib' }).naming).toEqual( { diff --git a/packages/jsii-calc/package.json b/packages/jsii-calc/package.json index 99de1914a7..96561044ad 100644 --- a/packages/jsii-calc/package.json +++ b/packages/jsii-calc/package.json @@ -73,7 +73,10 @@ }, "python": { "distName": "jsii-calc", - "module": "jsii_calc" + "module": "jsii_calc", + "classifiers": [ + "Test :: Classifier :: Is Dummy" + ] } }, "metadata": { diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index fc62bbbf1a..321c8da7f6 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -247,6 +247,9 @@ "npm": "jsii-calc" }, "python": { + "classifiers": [ + "Test :: Classifier :: Is Dummy" + ], "distName": "jsii-calc", "module": "jsii_calc" } @@ -13819,5 +13822,5 @@ } }, "version": "0.0.0", - "fingerprint": "NsqdwWgXi+kjrpLQtQ27eA/znULJ7TtXy03ht68N9Ms=" + "fingerprint": "TXGVwLZ10oZ08NxDzu6i+fqPtaw5aEqME8+d+KEhL08=" } diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index fc56f31e62..8450c28ca0 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1709,10 +1709,54 @@ class Package { setupKwargs.classifiers.push('License :: OSI Approved'); } + const additionalClassifiers = this.metadata.targets?.python?.classifiers; + if (additionalClassifiers != null) { + if (!Array.isArray(additionalClassifiers)) { + throw new Error( + `The "jsii.targets.python.classifiers" value must be an array of strings if provided, but found ${JSON.stringify( + additionalClassifiers, + null, + 2, + )}`, + ); + } + // We discourage using those since we automatically set a value for them + for (let classifier of additionalClassifiers.sort()) { + if (typeof classifier !== 'string') { + throw new Error( + `The "jsii.targets.python.classifiers" value can only contain strings, but found ${JSON.stringify( + classifier, + null, + 2, + )}`, + ); + } + // We'll split on `::` and re-join later so classifiers are "normalized" to a standard spacing + const parts = classifier.split('::').map((part) => part.trim()); + const reservedClassifiers = [ + 'Development Status', + 'License', + 'Operating System', + 'Typing', + ]; + if (reservedClassifiers.includes(parts[0])) { + warn( + `Classifiers starting with ${reservedClassifiers + .map((x) => `"${x} ::"`) + .join( + ', ', + )} are automatically set and should not be manually configured`, + ); + } + classifier = parts.join(' :: '); + if (setupKwargs.classifiers.includes(classifier)) { + continue; + } + setupKwargs.classifiers.push(classifier); + } + } + // We Need a setup.py to make this Package, actually a Package. - // TODO: - // - License - // - Classifiers code.openFile('setup.py'); code.line('import json'); code.line('import setuptools'); diff --git a/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap b/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap index f428ff92a9..2618d8b6bf 100644 --- a/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap +++ b/packages/jsii-pacmak/test/__snapshots__/jsii-pacmak.test.ts.snap @@ -7100,6 +7100,9 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu "npm": "jsii-calc" }, "python": { + "classifiers": [ + "Test :: Classifier :: Is Dummy" + ], "distName": "jsii-calc", "module": "jsii_calc" } @@ -20672,7 +20675,7 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu } }, "version": "0.0.0", - "fingerprint": "NsqdwWgXi+kjrpLQtQ27eA/znULJ7TtXy03ht68N9Ms=" + "fingerprint": "TXGVwLZ10oZ08NxDzu6i+fqPtaw5aEqME8+d+KEhL08=" } `; @@ -55774,7 +55777,8 @@ kwargs = json.loads( "Programming Language :: Python :: 3.8", "Typing :: Typed", "Development Status :: 4 - Beta", - "License :: OSI Approved" + "License :: OSI Approved", + "Test :: Classifier :: Is Dummy" ] } """