Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pacmak): Python submodules don't have docstrings #2681

Merged
merged 3 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 53 additions & 29 deletions packages/jsii-pacmak/lib/targets/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<PythonBase>();
private readonly package?: Package;

public constructor(
public readonly pythonName: string,
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -1683,19 +1698,19 @@ class Package {
private readonly modules = new Map<string, PythonModule>();
private readonly data = new Map<string, PackageData[]>();

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;
}

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(
Expand All @@ -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),
);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 '<package>._jsii' module
// This is the '<packagename>._jsii' module for this assembly
const assemblyModule = new PythonModule(
this.getAssemblyModuleName(assm),
undefined,
Expand Down Expand Up @@ -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);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.