UNPKG

4.77 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const path_1 = __importDefault(require("path"));
7const PackageGenerator_1 = __importDefault(require("./PackageGenerator"));
8const PythonSystemPackageLookup_1 = __importDefault(require("./PythonSystemPackageLookup"));
9const GENERATED_REQUIREMENTS_FILE = '.requirements.txt';
10/**
11 * A Dockerfile generator for Python packages
12 */
13class PythonGenerator extends PackageGenerator_1.default {
14 // Methods that override those in `Generator`
15 constructor(urlFetcher, pkg, folder, pythonMajorVersion = 3) {
16 super(urlFetcher, pkg, folder);
17 this.pythonMajorVersion = pythonMajorVersion;
18 this.systemPackageLookup = PythonSystemPackageLookup_1.default.fromFile(path_1.default.join(__dirname, 'PythonSystemDependencies.json'));
19 }
20 /**
21 * Return the `pythonMajorVersion` (as string) if it is not 2, otherwise return an empty string (if it is 2). This is
22 * for appending to things like pip{3} or python{3}.
23 */
24 pythonVersionSuffix() {
25 return this.pythonMajorVersion === 2 ? '' : `${this.pythonMajorVersion}`;
26 }
27 /**
28 * Check if this Generator's package applies (if it is Python).
29 */
30 applies() {
31 return this.package.runtimePlatform === 'Python';
32 }
33 /**
34 * Generate a list of system (apt) packages by looking up with `this.systemPackageLookup`.
35 */
36 aptPackages(sysVersion) {
37 let aptRequirements = [];
38 this.package.softwareRequirements.map(requirement => {
39 aptRequirements = aptRequirements.concat(this.systemPackageLookup.lookupSystemPackage(requirement.name, this.pythonMajorVersion, 'deb', sysVersion));
40 });
41 let dedupedRequirements = [];
42 aptRequirements.map(aptRequirement => {
43 if (!dedupedRequirements.includes(aptRequirement)) {
44 dedupedRequirements.push(aptRequirement);
45 }
46 });
47 return [`python${this.pythonVersionSuffix()}`, `python${this.pythonVersionSuffix()}-pip`].concat(dedupedRequirements);
48 }
49 /**
50 * Build the contents of a `requirements.txt` file by joining the Python package name to its version specifier.
51 */
52 generateRequirementsContent() {
53 if (!this.package.softwareRequirements) {
54 return '';
55 }
56 return this.filterPackages('Python').map(requirement => `${requirement.name}${requirement.version}`).join('\n');
57 }
58 /**
59 * Get the pip command to install the Stencila package
60 */
61 stencilaInstall(sysVersion) {
62 return `pip${this.pythonVersionSuffix()} install --no-cache-dir https://github.com/stencila/py/archive/91a05a139ac120a89fc001d9d267989f062ad374.zip`;
63 }
64 /**
65 * Write out the generated requirements content to `GENERATED_REQUIREMENTS_FILE` or none exists, just instruct the
66 * copy of a `requirements.txt` file as part of the Dockerfile. If that does not exist, then no COPY should be done.
67 */
68 installFiles(sysVersion) {
69 let requirementsContent = this.generateRequirementsContent();
70 if (requirementsContent !== '') {
71 this.write(GENERATED_REQUIREMENTS_FILE, requirementsContent);
72 return [[GENERATED_REQUIREMENTS_FILE, 'requirements.txt']];
73 }
74 if (this.exists('requirements.txt')) {
75 return [['requirements.txt', 'requirements.txt']];
76 }
77 return [];
78 }
79 /**
80 * Generate the right pip command to install the requirements, appends the correct Python major version to `pip`.
81 */
82 installCommand(sysVersion) {
83 return `pip${this.pythonVersionSuffix()} install --requirement requirements.txt`;
84 }
85 /**
86 * The files to copy into the Docker image
87 *
88 * Copies all `*.py` files to the container
89 */
90 projectFiles() {
91 const pyFiles = this.glob('**/*.py');
92 return pyFiles.map(file => [file, file]);
93 }
94 /**
95 * The command to execute in a container created from the Docker image
96 *
97 * If there is a top-level `main.py` or `cmd.py` then that will be used,
98 * otherwise, the first `*.R` files by alphabetical order will be used.
99 */
100 runCommand() {
101 const pyFiles = this.glob('**/*.py');
102 if (pyFiles.length === 0)
103 return;
104 let script;
105 if (pyFiles.includes('main.py'))
106 script = 'main.py';
107 else if (pyFiles.includes('cmd.py'))
108 script = 'cmd.py';
109 else
110 script = pyFiles[0];
111 return `python${this.pythonVersionSuffix()} ${script}`;
112 }
113}
114exports.default = PythonGenerator;