@cyclonedx/cdxgen 9.9.0 → 9.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -20
- package/bin/cdxgen.js +71 -13
- package/bin/evinse.js +1 -18
- package/data/frameworks-list.json +29 -11
- package/data/lic-mapping.json +44 -5
- package/data/pypi-pkg-aliases.json +6 -0
- package/evinser.js +145 -45
- package/index.js +33 -10
- package/package.json +2 -2
- package/server.js +34 -16
- package/utils.js +317 -99
- package/utils.test.js +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
cdxgen is a
|
|
5
|
+
cdxgen is a CLI tool, library, [REPL](./ADVANCED.md), and server to create a valid and compliant [CycloneDX][cyclonedx-homepage] Software Bill of Materials (SBOM) containing an aggregate of all project dependencies for C/C++, Node.js, PHP, Python, Ruby, Rust, Java, .Net, Dart, Haskell, Elixir, and Go projects in JSON format. CycloneDX 1.5 is a lightweight SBOM specification that is easily created, human and machine-readable, and simple to parse.
|
|
6
6
|
|
|
7
7
|
When used with plugins, cdxgen could generate an OBOM for Linux docker images and even VMs running Linux or Windows operating systems. cdxgen also includes an evinse tool to generate component evidence and SaaSBOM for some languages.
|
|
8
8
|
|
|
@@ -20,21 +20,21 @@ Most SBOM tools are like barcode scanners. They can scan a few package manifest
|
|
|
20
20
|
|
|
21
21
|
| Language/Platform | Package format | Transitive dependencies | Evidence |
|
|
22
22
|
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------- |
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
23
|
+
| Node.js | npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js | Yes except .min.js | Yes |
|
|
24
|
+
| Java | maven (pom.xml [1]), gradle (build.gradle, .kts), scala (sbt), bazel | Yes unless pom.xml is manually parsed due to unavailability of maven or errors | Yes |
|
|
25
|
+
| PHP | composer.lock | Yes | |
|
|
26
|
+
| Python | pyproject.toml, setup.py, requirements.txt [2], Pipfile.lock, poetry.lock, pdm.lock, bdist_wheel, .whl, .egg-info | Yes using the automatic pip install/freeze. When disabled, only with Pipfile.lock and poetry.lock | Yes |
|
|
27
|
+
| Go | binary, go.mod, go.sum, Gopkg.lock | Yes except binary | Yes |
|
|
28
|
+
| Ruby | Gemfile.lock, gemspec | Only for Gemfile.lock | |
|
|
29
|
+
| Rust | binary, Cargo.toml, Cargo.lock | Only for Cargo.lock | |
|
|
30
30
|
| .Net | .csproj, packages.config, project.assets.json [3], packages.lock.json, .nupkg, paket.lock | Only for project.assets.json, packages.lock.json, paket.lock | |
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
31
|
+
| Dart | pubspec.lock, pubspec.yaml | Only for pubspec.lock | |
|
|
32
|
+
| Haskell | cabal.project.freeze | Yes | |
|
|
33
|
+
| Elixir | mix.lock | Yes | |
|
|
34
|
+
| C/C++/Objective C/C++11 | conan.lock, conanfile.txt, \*.cmake, CMakeLists.txt, meson.build, codebase without package managers! | Yes only for conan.lock. Best effort basis for cmake without version numbers. | Yes |
|
|
35
|
+
| Clojure | Clojure CLI (deps.edn), Leiningen (project.clj) | Yes unless the files are parsed manually due to lack of clojure cli or leiningen command | |
|
|
36
|
+
| Swift | Package.resolved, Package.swift (swiftpm) | Yes | |
|
|
37
|
+
| Docker / oci image | All supported languages. Linux OS packages with plugins [4] | Best effort based on lock files | Yes |
|
|
38
38
|
| GitHub Actions | .github/workflows/\*.yml | N/A | Yes |
|
|
39
39
|
| Linux | All supported languages. Linux OS packages with plugins [5] | Best effort based on lock files | Yes |
|
|
40
40
|
| Windows | All supported languages. OS packages with best effort [5] | Best effort based on lock files | Yes |
|
|
@@ -170,10 +170,7 @@ Options:
|
|
|
170
170
|
faults to true. Pass --no-validate to disable.
|
|
171
171
|
[boolean] [default: true]
|
|
172
172
|
--evidence Generate SBOM with evidence for supported languag
|
|
173
|
-
es.
|
|
174
|
-
--usages-slices-file Path for the usages slice file created by atom.
|
|
175
|
-
--data-flow-slices-file Path for the data-flow slice file created by atom
|
|
176
|
-
.
|
|
173
|
+
es. [boolean] [default: false]
|
|
177
174
|
--spec-version CycloneDX Specification version to use. Defaults
|
|
178
175
|
to 1.5 [default: 1.5]
|
|
179
176
|
--filter Filter components containining this word in purl.
|
|
@@ -399,7 +396,7 @@ sudo npm install -g @cyclonedx/cdxgen-plugins-bin
|
|
|
399
396
|
cdxgen odoo@sha256:4e1e147f0e6714e8f8c5806d2b484075b4076ca50490577cdf9162566086d15e -o /tmp/bom.json
|
|
400
397
|
```
|
|
401
398
|
|
|
402
|
-
You can also pass `-t docker`
|
|
399
|
+
You can also pass `-t docker` with repository names. Only the `latest` tag would be pulled if none was specified.
|
|
403
400
|
|
|
404
401
|
```shell
|
|
405
402
|
cdxgen shiftleft/scan-slim -o /tmp/bom.json -t docker
|
package/bin/cdxgen.js
CHANGED
|
@@ -10,10 +10,19 @@ import crypto from "node:crypto";
|
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import globalAgent from "global-agent";
|
|
12
12
|
import process from "node:process";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
printCallStack,
|
|
15
|
+
printOccurrences,
|
|
16
|
+
printServices,
|
|
17
|
+
printReachables,
|
|
18
|
+
printTable,
|
|
19
|
+
printDependencyTree
|
|
20
|
+
} from "../display.js";
|
|
14
21
|
import { findUpSync } from "find-up";
|
|
15
22
|
import { load as _load } from "js-yaml";
|
|
16
23
|
import { postProcess } from "../postgen.js";
|
|
24
|
+
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
25
|
+
import { ATOM_DB } from "../utils.js";
|
|
17
26
|
|
|
18
27
|
// Support for config files
|
|
19
28
|
const configPath = findUpSync([
|
|
@@ -48,7 +57,14 @@ const args = yargs(hideBin(process.argv))
|
|
|
48
57
|
.env("CDXGEN")
|
|
49
58
|
.option("output", {
|
|
50
59
|
alias: "o",
|
|
51
|
-
description: "Output file for bom.xml or bom.json. Default bom.json"
|
|
60
|
+
description: "Output file for bom.xml or bom.json. Default bom.json",
|
|
61
|
+
default: "bom.json"
|
|
62
|
+
})
|
|
63
|
+
.option("evinse-output", {
|
|
64
|
+
description:
|
|
65
|
+
"Create bom with evidence as a separate file. Default bom.json",
|
|
66
|
+
default: "bom.json",
|
|
67
|
+
hidden: true
|
|
52
68
|
})
|
|
53
69
|
.option("type", {
|
|
54
70
|
alias: "t",
|
|
@@ -90,14 +106,17 @@ const args = yargs(hideBin(process.argv))
|
|
|
90
106
|
})
|
|
91
107
|
.option("project-version", {
|
|
92
108
|
description: "Dependency track project version",
|
|
93
|
-
default: ""
|
|
109
|
+
default: "",
|
|
110
|
+
type: "string"
|
|
94
111
|
})
|
|
95
112
|
.option("project-id", {
|
|
96
113
|
description:
|
|
97
|
-
"Dependency track project id. Either provide the id or the project name and version together"
|
|
114
|
+
"Dependency track project id. Either provide the id or the project name and version together",
|
|
115
|
+
type: "string"
|
|
98
116
|
})
|
|
99
117
|
.option("parent-project-id", {
|
|
100
|
-
description: "Dependency track parent project id"
|
|
118
|
+
description: "Dependency track parent project id",
|
|
119
|
+
type: "string"
|
|
101
120
|
})
|
|
102
121
|
.option("required-only", {
|
|
103
122
|
type: "boolean",
|
|
@@ -143,20 +162,34 @@ const args = yargs(hideBin(process.argv))
|
|
|
143
162
|
"Validate the generated SBOM using json schema. Defaults to true. Pass --no-validate to disable."
|
|
144
163
|
})
|
|
145
164
|
.option("evidence", {
|
|
146
|
-
hidden: true,
|
|
147
165
|
type: "boolean",
|
|
148
166
|
default: false,
|
|
149
|
-
description: "Generate SBOM with evidence for supported languages.
|
|
167
|
+
description: "Generate SBOM with evidence for supported languages."
|
|
168
|
+
})
|
|
169
|
+
.option("deps-slices-file", {
|
|
170
|
+
description: "Path for the parsedeps slice file created by atom.",
|
|
171
|
+
default: "deps.slices.json",
|
|
172
|
+
hidden: true
|
|
150
173
|
})
|
|
151
174
|
.option("usages-slices-file", {
|
|
152
|
-
description: "Path for the usages
|
|
175
|
+
description: "Path for the usages slices file created by atom.",
|
|
176
|
+
default: "usages.slices.json",
|
|
177
|
+
hidden: true
|
|
153
178
|
})
|
|
154
179
|
.option("data-flow-slices-file", {
|
|
155
|
-
description: "Path for the data-flow
|
|
180
|
+
description: "Path for the data-flow slices file created by atom.",
|
|
181
|
+
default: "data-flow.slices.json",
|
|
182
|
+
hidden: true
|
|
183
|
+
})
|
|
184
|
+
.option("reachables-slices-file", {
|
|
185
|
+
description: "Path for the reachables slices file created by atom.",
|
|
186
|
+
default: "reachables.slices.json",
|
|
187
|
+
hidden: true
|
|
156
188
|
})
|
|
157
189
|
.option("spec-version", {
|
|
158
190
|
description: "CycloneDX Specification version to use. Defaults to 1.5",
|
|
159
|
-
default: 1.5
|
|
191
|
+
default: 1.5,
|
|
192
|
+
type: "number"
|
|
160
193
|
})
|
|
161
194
|
.option("filter", {
|
|
162
195
|
description:
|
|
@@ -289,9 +322,6 @@ const checkPermissions = (filePath) => {
|
|
|
289
322
|
if (options.requiredOnly || options["filter"] || options["only"]) {
|
|
290
323
|
bomNSData = postProcess(bomNSData, options);
|
|
291
324
|
}
|
|
292
|
-
if (!args.output) {
|
|
293
|
-
args.output = "bom.json";
|
|
294
|
-
}
|
|
295
325
|
if (
|
|
296
326
|
args.output &&
|
|
297
327
|
(typeof args.output === "string" || args.output instanceof String)
|
|
@@ -458,6 +488,34 @@ const checkPermissions = (filePath) => {
|
|
|
458
488
|
console.log("Try running the command with -t <type> or -r argument");
|
|
459
489
|
}
|
|
460
490
|
}
|
|
491
|
+
// Evidence generation
|
|
492
|
+
if (args.evidence) {
|
|
493
|
+
const evinseOptions = {
|
|
494
|
+
_: args._,
|
|
495
|
+
input: options.output,
|
|
496
|
+
output: options.evinseOutput,
|
|
497
|
+
language: options.projectType || "java",
|
|
498
|
+
dbPath: process.env.ATOM_DB || ATOM_DB,
|
|
499
|
+
skipMavenCollector: false,
|
|
500
|
+
force: false,
|
|
501
|
+
withReachables: options.deep,
|
|
502
|
+
usagesSlicesFile: options.usagesSlicesFile,
|
|
503
|
+
dataFlowSlicesFile: options.dataFlowSlicesFile,
|
|
504
|
+
reachablesSlicesFile: options.reachablesSlicesFile
|
|
505
|
+
};
|
|
506
|
+
const dbObjMap = await prepareDB(evinseOptions);
|
|
507
|
+
if (dbObjMap) {
|
|
508
|
+
const sliceArtefacts = await analyzeProject(dbObjMap, evinseOptions);
|
|
509
|
+
const evinseJson = createEvinseFile(sliceArtefacts, evinseOptions);
|
|
510
|
+
bomNSData.bomJson = evinseJson;
|
|
511
|
+
if (args.print && evinseJson) {
|
|
512
|
+
printOccurrences(evinseJson);
|
|
513
|
+
printCallStack(evinseJson);
|
|
514
|
+
printReachables(sliceArtefacts);
|
|
515
|
+
printServices(evinseJson);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
461
519
|
// Perform automatic validation
|
|
462
520
|
if (args.validate) {
|
|
463
521
|
if (!validateBom(bomNSData.bomJson)) {
|
package/bin/evinse.js
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
// Evinse (Evinse Verification Is Nearly SBOM Evidence)
|
|
4
4
|
import yargs from "yargs";
|
|
5
5
|
import { hideBin } from "yargs/helpers";
|
|
6
|
-
import { join } from "node:path";
|
|
7
6
|
import fs from "node:fs";
|
|
8
|
-
import { homedir, platform as _platform } from "node:os";
|
|
9
7
|
import process from "node:process";
|
|
10
8
|
import { analyzeProject, createEvinseFile, prepareDB } from "../evinser.js";
|
|
11
9
|
import { validateBom } from "../validator.js";
|
|
@@ -15,6 +13,7 @@ import {
|
|
|
15
13
|
printServices,
|
|
16
14
|
printReachables
|
|
17
15
|
} from "../display.js";
|
|
16
|
+
import { ATOM_DB } from "../utils.js";
|
|
18
17
|
import { findUpSync } from "find-up";
|
|
19
18
|
import { load as _load } from "js-yaml";
|
|
20
19
|
|
|
@@ -38,22 +37,6 @@ if (configPath) {
|
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
const isWin = _platform() === "win32";
|
|
42
|
-
const isMac = _platform() === "darwin";
|
|
43
|
-
let ATOM_DB = join(homedir(), ".local", "share", ".atomdb");
|
|
44
|
-
if (isWin) {
|
|
45
|
-
ATOM_DB = join(homedir(), "AppData", "Local", ".atomdb");
|
|
46
|
-
} else if (isMac) {
|
|
47
|
-
ATOM_DB = join(homedir(), "Library", "Application Support", ".atomdb");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!process.env.ATOM_DB && !fs.existsSync(ATOM_DB)) {
|
|
51
|
-
try {
|
|
52
|
-
fs.mkdirSync(ATOM_DB, { recursive: true });
|
|
53
|
-
} catch (e) {
|
|
54
|
-
// ignore
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
40
|
const args = yargs(hideBin(process.argv))
|
|
58
41
|
.env("EVINSE")
|
|
59
42
|
.option("input", {
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"System.ServiceModel",
|
|
5
5
|
"System.Data",
|
|
6
6
|
"spring",
|
|
7
|
-
"flask",
|
|
8
|
-
"django",
|
|
7
|
+
"pkg:pypi/flask",
|
|
8
|
+
"pkg:pypi/django",
|
|
9
9
|
"beego",
|
|
10
10
|
"chi",
|
|
11
11
|
"echo",
|
|
@@ -30,15 +30,33 @@
|
|
|
30
30
|
"express",
|
|
31
31
|
"knex",
|
|
32
32
|
"vue",
|
|
33
|
-
"aiohttp",
|
|
34
|
-
"bottle",
|
|
35
|
-
"cherrypy",
|
|
36
|
-
"drt",
|
|
37
|
-
"falcon",
|
|
38
|
-
"hug",
|
|
39
|
-
"pyramid",
|
|
40
|
-
"sanic",
|
|
41
|
-
"tornado",
|
|
33
|
+
"pkg:pypi/aiohttp",
|
|
34
|
+
"pkg:pypi/bottle",
|
|
35
|
+
"pkg:pypi/cherrypy",
|
|
36
|
+
"pkg:pypi/drt",
|
|
37
|
+
"pkg:pypi/falcon",
|
|
38
|
+
"pkg:pypi/hug",
|
|
39
|
+
"pkg:pypi/pyramid",
|
|
40
|
+
"pkg:pypi/sanic",
|
|
41
|
+
"pkg:pypi/tornado",
|
|
42
|
+
"pkg:pypi/fastapi",
|
|
43
|
+
"pkg:pypi/pyqt",
|
|
44
|
+
"pkg:pypi/tkinter",
|
|
45
|
+
"pkg:pypi/kivy",
|
|
46
|
+
"pkg:pypi/pyside",
|
|
47
|
+
"pkg:pypi/scikit",
|
|
48
|
+
"pkg:pypi/tensorflow",
|
|
49
|
+
"pkg:pypi/pytorch",
|
|
50
|
+
"pkg:pypi/keras",
|
|
51
|
+
"pkg:pypi/numpy",
|
|
52
|
+
"pkg:pypi/scipy",
|
|
53
|
+
"pkg:pypi/pandas",
|
|
54
|
+
"pkg:pypi/matplotlib",
|
|
55
|
+
"pkg:pypi/google-api-core",
|
|
56
|
+
"pkg:pypi/google-cloud",
|
|
57
|
+
"pkg:pypi/botocore",
|
|
58
|
+
"pkg:pypi/boto3",
|
|
59
|
+
"pkg:pypi/azure",
|
|
42
60
|
"vibora",
|
|
43
61
|
"koa",
|
|
44
62
|
"-sdk",
|
package/data/lic-mapping.json
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
{
|
|
3
3
|
"exp": "Apache-2.0",
|
|
4
4
|
"names": [
|
|
5
|
+
"Apache2",
|
|
5
6
|
"Apache 2",
|
|
6
7
|
"Apache 2.0",
|
|
7
8
|
"Apache Version 2.0",
|
|
8
9
|
"Apache 2.0 License",
|
|
9
10
|
"Apache Software License, Version 2.0",
|
|
10
11
|
"The Apache Software License, Version 2.0",
|
|
12
|
+
"Apache License v2.0",
|
|
11
13
|
"Apache License (v2.0)",
|
|
12
14
|
"Apache License 2.0",
|
|
13
15
|
"Apache License Version 2.0",
|
|
@@ -20,6 +22,9 @@
|
|
|
20
22
|
"Apache-2.0 OR MIT",
|
|
21
23
|
"Apache2.0",
|
|
22
24
|
"apache-2-0",
|
|
25
|
+
"APL2",
|
|
26
|
+
"the Apache License, ASL Version 2.0",
|
|
27
|
+
"Apache Publich License 2.0",
|
|
23
28
|
"https://opensource.org/licenses/Apache2.0",
|
|
24
29
|
"https://opensource.org/license/apache-2-0",
|
|
25
30
|
"http://www.apache.org/licenses/LICENSE-2.0.html"
|
|
@@ -27,7 +32,14 @@
|
|
|
27
32
|
},
|
|
28
33
|
{
|
|
29
34
|
"exp": "0BSD",
|
|
30
|
-
"names": [
|
|
35
|
+
"names": [
|
|
36
|
+
"Zero-Clause BSD",
|
|
37
|
+
"BSD",
|
|
38
|
+
"BSD License",
|
|
39
|
+
"BSD-like",
|
|
40
|
+
"new BSD License",
|
|
41
|
+
"new BSD"
|
|
42
|
+
]
|
|
31
43
|
},
|
|
32
44
|
{
|
|
33
45
|
"exp": "BSD-2-Clause",
|
|
@@ -37,7 +49,8 @@
|
|
|
37
49
|
"BSD-2-Clause",
|
|
38
50
|
"BSD 2-Clause License",
|
|
39
51
|
"The BSD 2-Clause License",
|
|
40
|
-
"The 2-Clause BSD License"
|
|
52
|
+
"The 2-Clause BSD License",
|
|
53
|
+
"The BSD License"
|
|
41
54
|
]
|
|
42
55
|
},
|
|
43
56
|
{
|
|
@@ -46,6 +59,7 @@
|
|
|
46
59
|
"BSD 3 Clause",
|
|
47
60
|
"BSD 3-Clause",
|
|
48
61
|
"BSD-3-Clause",
|
|
62
|
+
"BSD 3-clause",
|
|
49
63
|
"BSD 3-Clause License",
|
|
50
64
|
"The BSD 3-Clause License",
|
|
51
65
|
"BSD 3-Clause \"New\" or \"Revised\" License (BSD-3-Clause)",
|
|
@@ -55,7 +69,8 @@
|
|
|
55
69
|
"Revised BSD",
|
|
56
70
|
"Revised BSD License",
|
|
57
71
|
"The New BSD License",
|
|
58
|
-
"BSD (3-clause)"
|
|
72
|
+
"BSD (3-clause)",
|
|
73
|
+
"3-Clause BSD License"
|
|
59
74
|
]
|
|
60
75
|
},
|
|
61
76
|
{
|
|
@@ -70,6 +85,10 @@
|
|
|
70
85
|
"BSD (4-clause)"
|
|
71
86
|
]
|
|
72
87
|
},
|
|
88
|
+
{
|
|
89
|
+
"exp": "CC0-1.0",
|
|
90
|
+
"names": ["CC0"]
|
|
91
|
+
},
|
|
73
92
|
{
|
|
74
93
|
"exp": "CDDL-1.0",
|
|
75
94
|
"names": [
|
|
@@ -151,6 +170,7 @@
|
|
|
151
170
|
"LGPL v2.1",
|
|
152
171
|
"LGPL-2.1",
|
|
153
172
|
"LGPL2.1",
|
|
173
|
+
"LGPL, version 2.1",
|
|
154
174
|
"GNU Lesser General Public License",
|
|
155
175
|
"GNU Lesser General Public License Version 2.1",
|
|
156
176
|
"GNU Lesser General Public License Version 2.1, February 1999",
|
|
@@ -270,7 +290,13 @@
|
|
|
270
290
|
},
|
|
271
291
|
{
|
|
272
292
|
"exp": "MPL-2.0",
|
|
273
|
-
"names": [
|
|
293
|
+
"names": [
|
|
294
|
+
"MPL 2.0",
|
|
295
|
+
"Mozilla Public License 2.0",
|
|
296
|
+
"Mozilla Public License version 2.0",
|
|
297
|
+
"Mozilla Public License, version 2.0",
|
|
298
|
+
"Mozilla Public License 2.0 (MPL 2.0)"
|
|
299
|
+
]
|
|
274
300
|
},
|
|
275
301
|
{
|
|
276
302
|
"exp": "NetCDF",
|
|
@@ -282,6 +308,19 @@
|
|
|
282
308
|
},
|
|
283
309
|
{
|
|
284
310
|
"exp": "ISC",
|
|
285
|
-
"names": ["ISC license"]
|
|
311
|
+
"names": ["ISC license", "ISC License (ISCL)"]
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"exp": "ICU",
|
|
315
|
+
"names": ["Unicode/ICU License"]
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"exp": "PSF-2.0",
|
|
319
|
+
"names": [
|
|
320
|
+
"Python Software Foundation License",
|
|
321
|
+
"Python Software Foundation License (PSFL)",
|
|
322
|
+
"Python Software Foundation License 2.0",
|
|
323
|
+
"PSFL"
|
|
324
|
+
]
|
|
286
325
|
}
|
|
287
326
|
]
|
|
@@ -553,6 +553,7 @@
|
|
|
553
553
|
"creole": "python-creole",
|
|
554
554
|
"creoleparser": "creoleparser",
|
|
555
555
|
"crispy-forms": "django-crispy-forms",
|
|
556
|
+
"crum": "django-crum",
|
|
556
557
|
"cronlog": "python-crontab",
|
|
557
558
|
"crontab": "python-crontab",
|
|
558
559
|
"crypto": "pycryptodome",
|
|
@@ -589,6 +590,7 @@
|
|
|
589
590
|
"djcelery": "django-celery",
|
|
590
591
|
"djkombu": "django-kombu",
|
|
591
592
|
"djorm-pgarray": "djorm-ext-pgarray",
|
|
593
|
+
"django-filters": "filters-django",
|
|
592
594
|
"dns": "dnspython",
|
|
593
595
|
"docgen": "ansible-docgenerator",
|
|
594
596
|
"docker": "docker-py",
|
|
@@ -631,6 +633,7 @@
|
|
|
631
633
|
"fdpexpect": "pexpect",
|
|
632
634
|
"fedora": "python-fedora",
|
|
633
635
|
"fias": "ailove-django-fias",
|
|
636
|
+
"fieldsignals": "django-fieldsignals",
|
|
634
637
|
"fiftyone-degrees": "51degrees-mobile-detector",
|
|
635
638
|
"fiftyonedegrees": "51degrees-mobile-detector-v3-wrapper",
|
|
636
639
|
"five": "five.customerize",
|
|
@@ -709,6 +712,7 @@
|
|
|
709
712
|
"igraph": "python-igraph",
|
|
710
713
|
"imdb": "imdbpy",
|
|
711
714
|
"impala": "impyla",
|
|
715
|
+
"imagekit": "django-imagekit",
|
|
712
716
|
"impersonate": "django-impersonate",
|
|
713
717
|
"inmemorystorage": "ambition-inmemorystorage",
|
|
714
718
|
"ipaddress": "backport-ipaddress",
|
|
@@ -845,6 +849,7 @@
|
|
|
845
849
|
"path": "path.py",
|
|
846
850
|
"patricia": "patricia-trie",
|
|
847
851
|
"paver": "paver",
|
|
852
|
+
"packageurl": "packageurl-python",
|
|
848
853
|
"peak": "proxytypes",
|
|
849
854
|
"picasso": "anderson.picasso",
|
|
850
855
|
"picklefield": "django-picklefield",
|
|
@@ -1057,6 +1062,7 @@
|
|
|
1057
1062
|
"slugify": "unicode-slugify",
|
|
1058
1063
|
"smarkets": "smk-python-sdk",
|
|
1059
1064
|
"snappy": "ctypes-snappy",
|
|
1065
|
+
"social-core": "social-auth-core",
|
|
1060
1066
|
"social-django": "social-auth-app-django",
|
|
1061
1067
|
"socketio": "python-socketio",
|
|
1062
1068
|
"socketserver": "pies2overrides",
|