@suss/adapter-python 0.28.0 → 0.29.0
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/dist/index.cjs +35 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +35 -1
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -1905,12 +1905,19 @@ function declaredMemberKey(emitter, member, classKey) {
|
|
|
1905
1905
|
}
|
|
1906
1906
|
return null;
|
|
1907
1907
|
}
|
|
1908
|
+
function writtenBaseName(base) {
|
|
1909
|
+
return base.type === "identifier" || base.type === "attribute" ? base.text : null;
|
|
1910
|
+
}
|
|
1908
1911
|
function emitClassFacts(emitter, cls) {
|
|
1909
1912
|
const classKey = nodeId(emitter.filePath, cls);
|
|
1910
1913
|
add(emitter, "objectValue", classKey);
|
|
1911
1914
|
const bases = field(cls, "superclasses");
|
|
1912
1915
|
for (const base of bases === null ? [] : children(bases)) {
|
|
1913
1916
|
add(emitter, "extends", classKey, valueKey(emitter, base));
|
|
1917
|
+
const written = writtenBaseName(base);
|
|
1918
|
+
if (written !== null) {
|
|
1919
|
+
add(emitter, "extendsNamed", classKey, written);
|
|
1920
|
+
}
|
|
1914
1921
|
}
|
|
1915
1922
|
const body = field(cls, "body");
|
|
1916
1923
|
for (const statement of body === null ? [] : children(body)) {
|
|
@@ -7646,6 +7653,31 @@ function reportUnresolvedProjectModules(options, db) {
|
|
|
7646
7653
|
}
|
|
7647
7654
|
}
|
|
7648
7655
|
}
|
|
7656
|
+
function emitModelQueryFacts(db, packs) {
|
|
7657
|
+
for (const pack of packs) {
|
|
7658
|
+
for (const model of pack.models ?? []) {
|
|
7659
|
+
for (const base of model.baseNames) {
|
|
7660
|
+
for (const method of model.givesBack) {
|
|
7661
|
+
db.add("givesBackOne", [base, method]);
|
|
7662
|
+
}
|
|
7663
|
+
for (const entry of model.entryMethods) {
|
|
7664
|
+
db.add("givesBackOneOfArgument", [
|
|
7665
|
+
base,
|
|
7666
|
+
entry.method,
|
|
7667
|
+
String(entry.argument)
|
|
7668
|
+
]);
|
|
7669
|
+
}
|
|
7670
|
+
}
|
|
7671
|
+
for (const entry of model.entryFunctions) {
|
|
7672
|
+
db.add("givesBackOneOfImport", [
|
|
7673
|
+
entry.module,
|
|
7674
|
+
entry.name,
|
|
7675
|
+
String(entry.argument)
|
|
7676
|
+
]);
|
|
7677
|
+
}
|
|
7678
|
+
}
|
|
7679
|
+
}
|
|
7680
|
+
}
|
|
7649
7681
|
async function extractPythonProject(options) {
|
|
7650
7682
|
const timer = options.onTiming !== void 0 ? (0, import_extractor10.createTimer)() : (0, import_extractor10.noopTimer)();
|
|
7651
7683
|
const cacheDir = adapterStamp.declineWhenRunFromSource(
|
|
@@ -7693,8 +7725,9 @@ async function extractPythonProject(options) {
|
|
|
7693
7725
|
);
|
|
7694
7726
|
const storagePatterns = options.packs.flatMap((pack) => pack.storage ?? []);
|
|
7695
7727
|
const rawSqlPatterns = options.packs.flatMap((pack) => pack.rawSql ?? []);
|
|
7728
|
+
const modelQueries = options.packs.flatMap((pack) => pack.models ?? []);
|
|
7696
7729
|
const discovers = options.packs.some((pack) => pack.discovery.length > 0);
|
|
7697
|
-
const needsValues = discovers || mountsRouters || storagePatterns.length > 0;
|
|
7730
|
+
const needsValues = discovers || mountsRouters || storagePatterns.length > 0 || modelQueries.length > 0;
|
|
7698
7731
|
const definitions = /* @__PURE__ */ new Map();
|
|
7699
7732
|
timer.time("discover", () => {
|
|
7700
7733
|
for (const { file, root, module: moduleBinding } of bound) {
|
|
@@ -7707,6 +7740,7 @@ async function extractPythonProject(options) {
|
|
|
7707
7740
|
if (needsValues) {
|
|
7708
7741
|
bindEvaluator(db, { files: bound, definitions });
|
|
7709
7742
|
}
|
|
7743
|
+
emitModelQueryFacts(db, options.packs);
|
|
7710
7744
|
});
|
|
7711
7745
|
reportUnresolvedProjectModules(options, db);
|
|
7712
7746
|
const couldMatch = timer.time(
|
package/dist/index.d.cts
CHANGED
|
@@ -109,6 +109,8 @@ interface PythonPack {
|
|
|
109
109
|
clients?: PyClientCall[];
|
|
110
110
|
/** What the library's own database queries look like. The README says how one is matched. */
|
|
111
111
|
storage?: StoragePattern[];
|
|
112
|
+
/** Which of the library's calls give back one of a model class. The README says what a chain of them composes into. */
|
|
113
|
+
models?: PyModelQueries[];
|
|
112
114
|
/** How the library lets a project hand the database SQL it wrote itself. */
|
|
113
115
|
rawSql?: RawSqlPattern[];
|
|
114
116
|
}
|
|
@@ -148,6 +150,38 @@ interface StoragePattern {
|
|
|
148
150
|
/** Which database the library is talking to, for the boundary binding. */
|
|
149
151
|
storageSystem: "postgresql" | "mysql" | "sqlite";
|
|
150
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* What a library gives back when a call is passed one of a project's
|
|
155
|
+
* model classes, so a method read off the result runs the one that
|
|
156
|
+
* class declares. SQLAlchemy and SQLModel take the class as an argument,
|
|
157
|
+
* `session.get(User, id)` and `select(User)`, rather than as the
|
|
158
|
+
* receiver a Rails finder is called on.
|
|
159
|
+
*/
|
|
160
|
+
interface PyModelQueries {
|
|
161
|
+
/**
|
|
162
|
+
* The names a model's ancestry arrives at: a base class the library
|
|
163
|
+
* exports, `DeclarativeBase`, or the function that builds one,
|
|
164
|
+
* `declarative_base`.
|
|
165
|
+
*/
|
|
166
|
+
baseNames: string[];
|
|
167
|
+
/** Methods whose result is the model again: one row, or a query a later read narrows to one. */
|
|
168
|
+
givesBack: string[];
|
|
169
|
+
/** Methods that take the model class and give back one of it, with the position it is written at. */
|
|
170
|
+
entryMethods: PyModelEntryMethod[];
|
|
171
|
+
/** Functions the library exports that do the same, called on their own rather than read off a session. */
|
|
172
|
+
entryFunctions: PyModelEntryFunction[];
|
|
173
|
+
}
|
|
174
|
+
/** `session.get(User, id)`: the method, and where the class is written. */
|
|
175
|
+
interface PyModelEntryMethod {
|
|
176
|
+
method: string;
|
|
177
|
+
argument: number;
|
|
178
|
+
}
|
|
179
|
+
/** `select(User)`: the function, the module it comes from, and where the class is written. */
|
|
180
|
+
interface PyModelEntryFunction {
|
|
181
|
+
module: string;
|
|
182
|
+
name: string;
|
|
183
|
+
argument: number;
|
|
184
|
+
}
|
|
151
185
|
/**
|
|
152
186
|
* The function a library gives a project for handing the database a
|
|
153
187
|
* statement written as SQL, and where it comes from. SQLAlchemy exports
|
|
@@ -1042,4 +1076,4 @@ declare function pythonImportEvidence(options: PythonImportEvidenceOptions): Pro
|
|
|
1042
1076
|
*/
|
|
1043
1077
|
declare const ADAPTER_VERSION = "0.1.0";
|
|
1044
1078
|
|
|
1045
|
-
export { ADAPTER_VERSION, type AnnotationContext, type Binding, type BoundPythonFile, type DecoratedClassRoute, type DecoratedFunctionRoute, type DecoratorArg, type DecoratorClassification, type DiscoveryOptions, type ExtractPythonOptions, type ExtractPythonResult, type ModuleBinding, type ModuleResolution, type ModuleResolverOptions, type MountObjectCarrier, type MountObjectPrefix, type MountPrefixEffect, type NoValuePrefix, type PathRepeatedSlashes, type PrefixTrailingSlash, type PyStatusCall, type PythonDiscoveryPattern, type PythonImportEvidence, type PythonImportEvidenceOptions, type PythonImportSite, type PythonPack, type PythonValueHandle, PythonWhySession, type PythonWhySessionOptions, type RawSqlPattern, type RelativeModuleSpec, type RouteConventions, type RoutePrefixResolution, type RouterComposition, type RouterIndex, type Scope, type ScopeKind, type StoragePattern, annotationToShape, bindModule, buildRouterIndex, classifyDecorator, containedValues, discoverUnits, emitEntryFact, emitModuleImportFacts, emitValueFacts, extractPythonProject, findPythonFiles, nameKeyIn, nodeId, objectReturnedBy, parsePython, parsePythonSync, preloadPythonGrammar, pythonImportEvidence, readKey, resolveAbsoluteModule, resolveCalls, resolveModule, resolveName, resolveRelativeModule, shapeFromName, unitKey };
|
|
1079
|
+
export { ADAPTER_VERSION, type AnnotationContext, type Binding, type BoundPythonFile, type DecoratedClassRoute, type DecoratedFunctionRoute, type DecoratorArg, type DecoratorClassification, type DiscoveryOptions, type ExtractPythonOptions, type ExtractPythonResult, type ModuleBinding, type ModuleResolution, type ModuleResolverOptions, type MountObjectCarrier, type MountObjectPrefix, type MountPrefixEffect, type NoValuePrefix, type PathRepeatedSlashes, type PrefixTrailingSlash, type PyModelEntryFunction, type PyModelEntryMethod, type PyModelQueries, type PyStatusCall, type PythonDiscoveryPattern, type PythonImportEvidence, type PythonImportEvidenceOptions, type PythonImportSite, type PythonPack, type PythonValueHandle, PythonWhySession, type PythonWhySessionOptions, type RawSqlPattern, type RelativeModuleSpec, type RouteConventions, type RoutePrefixResolution, type RouterComposition, type RouterIndex, type Scope, type ScopeKind, type StoragePattern, annotationToShape, bindModule, buildRouterIndex, classifyDecorator, containedValues, discoverUnits, emitEntryFact, emitModuleImportFacts, emitValueFacts, extractPythonProject, findPythonFiles, nameKeyIn, nodeId, objectReturnedBy, parsePython, parsePythonSync, preloadPythonGrammar, pythonImportEvidence, readKey, resolveAbsoluteModule, resolveCalls, resolveModule, resolveName, resolveRelativeModule, shapeFromName, unitKey };
|
package/dist/index.d.ts
CHANGED
|
@@ -109,6 +109,8 @@ interface PythonPack {
|
|
|
109
109
|
clients?: PyClientCall[];
|
|
110
110
|
/** What the library's own database queries look like. The README says how one is matched. */
|
|
111
111
|
storage?: StoragePattern[];
|
|
112
|
+
/** Which of the library's calls give back one of a model class. The README says what a chain of them composes into. */
|
|
113
|
+
models?: PyModelQueries[];
|
|
112
114
|
/** How the library lets a project hand the database SQL it wrote itself. */
|
|
113
115
|
rawSql?: RawSqlPattern[];
|
|
114
116
|
}
|
|
@@ -148,6 +150,38 @@ interface StoragePattern {
|
|
|
148
150
|
/** Which database the library is talking to, for the boundary binding. */
|
|
149
151
|
storageSystem: "postgresql" | "mysql" | "sqlite";
|
|
150
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* What a library gives back when a call is passed one of a project's
|
|
155
|
+
* model classes, so a method read off the result runs the one that
|
|
156
|
+
* class declares. SQLAlchemy and SQLModel take the class as an argument,
|
|
157
|
+
* `session.get(User, id)` and `select(User)`, rather than as the
|
|
158
|
+
* receiver a Rails finder is called on.
|
|
159
|
+
*/
|
|
160
|
+
interface PyModelQueries {
|
|
161
|
+
/**
|
|
162
|
+
* The names a model's ancestry arrives at: a base class the library
|
|
163
|
+
* exports, `DeclarativeBase`, or the function that builds one,
|
|
164
|
+
* `declarative_base`.
|
|
165
|
+
*/
|
|
166
|
+
baseNames: string[];
|
|
167
|
+
/** Methods whose result is the model again: one row, or a query a later read narrows to one. */
|
|
168
|
+
givesBack: string[];
|
|
169
|
+
/** Methods that take the model class and give back one of it, with the position it is written at. */
|
|
170
|
+
entryMethods: PyModelEntryMethod[];
|
|
171
|
+
/** Functions the library exports that do the same, called on their own rather than read off a session. */
|
|
172
|
+
entryFunctions: PyModelEntryFunction[];
|
|
173
|
+
}
|
|
174
|
+
/** `session.get(User, id)`: the method, and where the class is written. */
|
|
175
|
+
interface PyModelEntryMethod {
|
|
176
|
+
method: string;
|
|
177
|
+
argument: number;
|
|
178
|
+
}
|
|
179
|
+
/** `select(User)`: the function, the module it comes from, and where the class is written. */
|
|
180
|
+
interface PyModelEntryFunction {
|
|
181
|
+
module: string;
|
|
182
|
+
name: string;
|
|
183
|
+
argument: number;
|
|
184
|
+
}
|
|
151
185
|
/**
|
|
152
186
|
* The function a library gives a project for handing the database a
|
|
153
187
|
* statement written as SQL, and where it comes from. SQLAlchemy exports
|
|
@@ -1042,4 +1076,4 @@ declare function pythonImportEvidence(options: PythonImportEvidenceOptions): Pro
|
|
|
1042
1076
|
*/
|
|
1043
1077
|
declare const ADAPTER_VERSION = "0.1.0";
|
|
1044
1078
|
|
|
1045
|
-
export { ADAPTER_VERSION, type AnnotationContext, type Binding, type BoundPythonFile, type DecoratedClassRoute, type DecoratedFunctionRoute, type DecoratorArg, type DecoratorClassification, type DiscoveryOptions, type ExtractPythonOptions, type ExtractPythonResult, type ModuleBinding, type ModuleResolution, type ModuleResolverOptions, type MountObjectCarrier, type MountObjectPrefix, type MountPrefixEffect, type NoValuePrefix, type PathRepeatedSlashes, type PrefixTrailingSlash, type PyStatusCall, type PythonDiscoveryPattern, type PythonImportEvidence, type PythonImportEvidenceOptions, type PythonImportSite, type PythonPack, type PythonValueHandle, PythonWhySession, type PythonWhySessionOptions, type RawSqlPattern, type RelativeModuleSpec, type RouteConventions, type RoutePrefixResolution, type RouterComposition, type RouterIndex, type Scope, type ScopeKind, type StoragePattern, annotationToShape, bindModule, buildRouterIndex, classifyDecorator, containedValues, discoverUnits, emitEntryFact, emitModuleImportFacts, emitValueFacts, extractPythonProject, findPythonFiles, nameKeyIn, nodeId, objectReturnedBy, parsePython, parsePythonSync, preloadPythonGrammar, pythonImportEvidence, readKey, resolveAbsoluteModule, resolveCalls, resolveModule, resolveName, resolveRelativeModule, shapeFromName, unitKey };
|
|
1079
|
+
export { ADAPTER_VERSION, type AnnotationContext, type Binding, type BoundPythonFile, type DecoratedClassRoute, type DecoratedFunctionRoute, type DecoratorArg, type DecoratorClassification, type DiscoveryOptions, type ExtractPythonOptions, type ExtractPythonResult, type ModuleBinding, type ModuleResolution, type ModuleResolverOptions, type MountObjectCarrier, type MountObjectPrefix, type MountPrefixEffect, type NoValuePrefix, type PathRepeatedSlashes, type PrefixTrailingSlash, type PyModelEntryFunction, type PyModelEntryMethod, type PyModelQueries, type PyStatusCall, type PythonDiscoveryPattern, type PythonImportEvidence, type PythonImportEvidenceOptions, type PythonImportSite, type PythonPack, type PythonValueHandle, PythonWhySession, type PythonWhySessionOptions, type RawSqlPattern, type RelativeModuleSpec, type RouteConventions, type RoutePrefixResolution, type RouterComposition, type RouterIndex, type Scope, type ScopeKind, type StoragePattern, annotationToShape, bindModule, buildRouterIndex, classifyDecorator, containedValues, discoverUnits, emitEntryFact, emitModuleImportFacts, emitValueFacts, extractPythonProject, findPythonFiles, nameKeyIn, nodeId, objectReturnedBy, parsePython, parsePythonSync, preloadPythonGrammar, pythonImportEvidence, readKey, resolveAbsoluteModule, resolveCalls, resolveModule, resolveName, resolveRelativeModule, shapeFromName, unitKey };
|
package/dist/index.js
CHANGED
|
@@ -1857,12 +1857,19 @@ function declaredMemberKey(emitter, member, classKey) {
|
|
|
1857
1857
|
}
|
|
1858
1858
|
return null;
|
|
1859
1859
|
}
|
|
1860
|
+
function writtenBaseName(base) {
|
|
1861
|
+
return base.type === "identifier" || base.type === "attribute" ? base.text : null;
|
|
1862
|
+
}
|
|
1860
1863
|
function emitClassFacts(emitter, cls) {
|
|
1861
1864
|
const classKey = nodeId(emitter.filePath, cls);
|
|
1862
1865
|
add(emitter, "objectValue", classKey);
|
|
1863
1866
|
const bases = field(cls, "superclasses");
|
|
1864
1867
|
for (const base of bases === null ? [] : children(bases)) {
|
|
1865
1868
|
add(emitter, "extends", classKey, valueKey(emitter, base));
|
|
1869
|
+
const written = writtenBaseName(base);
|
|
1870
|
+
if (written !== null) {
|
|
1871
|
+
add(emitter, "extendsNamed", classKey, written);
|
|
1872
|
+
}
|
|
1866
1873
|
}
|
|
1867
1874
|
const body = field(cls, "body");
|
|
1868
1875
|
for (const statement of body === null ? [] : children(body)) {
|
|
@@ -7658,6 +7665,31 @@ function reportUnresolvedProjectModules(options, db) {
|
|
|
7658
7665
|
}
|
|
7659
7666
|
}
|
|
7660
7667
|
}
|
|
7668
|
+
function emitModelQueryFacts(db, packs) {
|
|
7669
|
+
for (const pack of packs) {
|
|
7670
|
+
for (const model of pack.models ?? []) {
|
|
7671
|
+
for (const base of model.baseNames) {
|
|
7672
|
+
for (const method of model.givesBack) {
|
|
7673
|
+
db.add("givesBackOne", [base, method]);
|
|
7674
|
+
}
|
|
7675
|
+
for (const entry of model.entryMethods) {
|
|
7676
|
+
db.add("givesBackOneOfArgument", [
|
|
7677
|
+
base,
|
|
7678
|
+
entry.method,
|
|
7679
|
+
String(entry.argument)
|
|
7680
|
+
]);
|
|
7681
|
+
}
|
|
7682
|
+
}
|
|
7683
|
+
for (const entry of model.entryFunctions) {
|
|
7684
|
+
db.add("givesBackOneOfImport", [
|
|
7685
|
+
entry.module,
|
|
7686
|
+
entry.name,
|
|
7687
|
+
String(entry.argument)
|
|
7688
|
+
]);
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7691
|
+
}
|
|
7692
|
+
}
|
|
7661
7693
|
async function extractPythonProject(options) {
|
|
7662
7694
|
const timer = options.onTiming !== void 0 ? createTimer() : noopTimer();
|
|
7663
7695
|
const cacheDir = adapterStamp.declineWhenRunFromSource(
|
|
@@ -7705,8 +7737,9 @@ async function extractPythonProject(options) {
|
|
|
7705
7737
|
);
|
|
7706
7738
|
const storagePatterns = options.packs.flatMap((pack) => pack.storage ?? []);
|
|
7707
7739
|
const rawSqlPatterns = options.packs.flatMap((pack) => pack.rawSql ?? []);
|
|
7740
|
+
const modelQueries = options.packs.flatMap((pack) => pack.models ?? []);
|
|
7708
7741
|
const discovers = options.packs.some((pack) => pack.discovery.length > 0);
|
|
7709
|
-
const needsValues = discovers || mountsRouters || storagePatterns.length > 0;
|
|
7742
|
+
const needsValues = discovers || mountsRouters || storagePatterns.length > 0 || modelQueries.length > 0;
|
|
7710
7743
|
const definitions = /* @__PURE__ */ new Map();
|
|
7711
7744
|
timer.time("discover", () => {
|
|
7712
7745
|
for (const { file, root, module: moduleBinding } of bound) {
|
|
@@ -7719,6 +7752,7 @@ async function extractPythonProject(options) {
|
|
|
7719
7752
|
if (needsValues) {
|
|
7720
7753
|
bindEvaluator(db, { files: bound, definitions });
|
|
7721
7754
|
}
|
|
7755
|
+
emitModelQueryFacts(db, options.packs);
|
|
7722
7756
|
});
|
|
7723
7757
|
reportUnresolvedProjectModules(options, db);
|
|
7724
7758
|
const couldMatch = timer.time(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/adapter-python",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Read a Python codebase with suss and check what each FastAPI or Flask route returns against the clients, specs and infrastructure that depend on it.",
|
|
6
6
|
"keywords": [
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"typecheck": "tsc --noEmit"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@suss/behavioral-ir": "0.
|
|
53
|
-
"@suss/datalog": "0.
|
|
54
|
-
"@suss/extractor": "0.
|
|
55
|
-
"@suss/ir-core": "0.
|
|
56
|
-
"@suss/resolution": "0.
|
|
57
|
-
"@suss/sql": "0.
|
|
58
|
-
"@suss/values": "0.
|
|
52
|
+
"@suss/behavioral-ir": "0.29.0",
|
|
53
|
+
"@suss/datalog": "0.29.0",
|
|
54
|
+
"@suss/extractor": "0.29.0",
|
|
55
|
+
"@suss/ir-core": "0.29.0",
|
|
56
|
+
"@suss/resolution": "0.29.0",
|
|
57
|
+
"@suss/sql": "0.29.0",
|
|
58
|
+
"@suss/values": "0.29.0",
|
|
59
59
|
"web-tree-sitter": "^0.26.11"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|