diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 9938d31c24..a49635f99c 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1395,18 +1395,34 @@ class EnumMember implements PythonBase { } interface ModuleOpts { - assembly: spec.Assembly; - assemblyFilename: string; - loadAssembly?: boolean; - package?: Package; + readonly assembly: spec.Assembly; + readonly assemblyFilename: string; + readonly loadAssembly?: boolean; + readonly package?: Package; + + /** + * The docstring to emit at the top of this module, if any. + */ + readonly moduleDocumentation?: string; } +/** + * Python module + * + * Will be called for jsii submodules and namespaces. + */ class PythonModule implements PythonType { + /** + * Converted to put on the module + * + * The format is in markdown, with code samples converted from TS to Python. + */ + public readonly moduleDocumentation?: string; + private readonly assembly: spec.Assembly; private readonly assemblyFilename: string; private readonly loadAssembly: boolean; private readonly members = new Array(); - private readonly package?: Package; public constructor( public readonly pythonName: string, @@ -1416,7 +1432,7 @@ class PythonModule implements PythonType { this.assembly = opts.assembly; this.assemblyFilename = opts.assemblyFilename; this.loadAssembly = !!opts.loadAssembly; - this.package = opts.package; + this.moduleDocumentation = opts.moduleDocumentation; } public addMember(member: PythonBase) { @@ -1573,13 +1589,9 @@ class PythonModule implements PythonType { * Emit the README as module docstring if this is the entry point module (it loads the assembly) */ private emitModuleDocumentation(code: CodeMaker) { - if ( - this.package && - this.fqn === this.assembly.name && - this.package.convertedReadme.trim().length > 0 - ) { + if (this.moduleDocumentation) { code.line(DOCSTRING_QUOTES); - code.line(this.package.convertedReadme); + code.line(this.moduleDocumentation); code.line(DOCSTRING_QUOTES); } } @@ -1674,7 +1686,10 @@ interface PackageData { } class Package { - public convertedReadme = ''; + /** + * The PythonModule that represents the root module of the package + */ + public rootModule?: PythonModule; public readonly name: string; public readonly version: string; @@ -1683,12 +1698,7 @@ class Package { private readonly modules = new Map(); private readonly data = new Map(); - public constructor( - private readonly generator: PythonGenerator, - name: string, - version: string, - metadata: spec.Assembly, - ) { + public constructor(name: string, version: string, metadata: spec.Assembly) { this.name = name; this.version = version; this.metadata = metadata; @@ -1696,6 +1706,11 @@ class Package { public addModule(module: PythonModule) { this.modules.set(module.pythonName, module); + + // This is the module that represents the assembly + if (module.fqn === this.metadata.name) { + this.rootModule = module; + } } public addData( @@ -1711,13 +1726,6 @@ class Package { } public write(code: CodeMaker, context: EmitContext) { - if (this.metadata.readme) { - // Conversion is expensive, so cache the result in a variable (we need it twice) - this.convertedReadme = this.generator - .convertMarkdown(this.metadata.readme.markdown) - .trim(); - } - const modules = [...this.modules.values()].sort((a, b) => a.pythonName.localeCompare(b.pythonName), ); @@ -1770,8 +1778,13 @@ class Package { ); } + // Need to always write this file as the build process depends on it. + // Make up some contents if we don't have anything useful to say. code.openFile('README.md'); - code.line(this.convertedReadme); + code.line( + this.rootModule?.moduleDocumentation ?? + `${this.name}\n${'='.repeat(this.name.length)}`, + ); code.closeFile('README.md'); // Strip " (build abcdef)" from the jsii version @@ -2266,13 +2279,12 @@ class PythonGenerator extends Generator { protected onBeginAssembly(assm: spec.Assembly, _fingerprint: boolean) { this.package = new Package( - this, assm.targets!.python!.distName, toReleaseVersion(assm.version, TargetName.PYTHON), assm, ); - // This is the '._jsii' module + // This is the '._jsii' module for this assembly const assemblyModule = new PythonModule( this.getAssemblyModuleName(assm), undefined, @@ -2302,11 +2314,23 @@ class PythonGenerator extends Generator { }); } + /** + * Will be called for assembly root, namespaces and submodules (anything that contains other types, based on its FQN) + */ protected onBeginNamespace(ns: string) { + // 'ns' contains something like '@scope/jsii-calc-base-of-base' + const submoduleLike = + ns === this.assembly.name + ? this.assembly + : this.assembly.submodules?.[ns]; + const module = new PythonModule(toPackageName(ns, this.assembly), ns, { assembly: this.assembly, assemblyFilename: this.getAssemblyFileName(), package: this.package, + moduleDocumentation: submoduleLike?.readme + ? this.convertMarkdown(submoduleLike.readme?.markdown).trim() + : undefined, }); this.package.addModule(module); diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap index 5c528c59b6..6c73a2332c 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap @@ -410,7 +410,8 @@ include pyproject.toml `; exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/README.md 1`] = ` - +foo +=== `; @@ -919,7 +920,8 @@ include pyproject.toml `; exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/README.md 1`] = ` - +foo +=== `; @@ -1407,7 +1409,8 @@ include pyproject.toml `; exports[`foo@2.0.0-rc.42: /python/README.md 1`] = ` - +foo +=== `; @@ -1892,7 +1895,8 @@ include pyproject.toml `; exports[`foo@4.5.6-pre.1337: /python/README.md 1`] = ` - +foo +=== `; diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap index 2704bc83a1..49697b5a68 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap @@ -236,7 +236,8 @@ Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. `; exports[`Generated code for "@scope/jsii-calc-base": /python/README.md 1`] = ` - +scope.jsii-calc-base +==================== `; @@ -717,7 +718,8 @@ Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. `; exports[`Generated code for "@scope/jsii-calc-base-of-base": /python/README.md 1`] = ` - +scope.jsii-calc-base-of-base +============================ `; @@ -1170,7 +1172,8 @@ Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. `; exports[`Generated code for "@scope/jsii-calc-lib": /python/README.md 1`] = ` - +scope.jsii-calc-lib +=================== `; @@ -11183,6 +11186,11 @@ publication.publish() `; exports[`Generated code for "jsii-calc": /python/src/jsii_calc/submodule/__init__.py 1`] = ` +''' +# Read you, read me + +This is the readme of the \`jsii-calc.submodule\` module. +''' import abc import builtins import datetime @@ -11546,6 +11554,11 @@ publication.publish() `; exports[`Generated code for "jsii-calc": /python/src/jsii_calc/submodule/isolated/__init__.py 1`] = ` +''' +# Read you, read me + +This is the readme of the \`jsii-calc.submodule.isolated\` module. +''' import abc import builtins import datetime