@suss/adapter-python 0.27.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.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
@@ -717,12 +751,15 @@ interface StorageLookup {
717
751
  }
718
752
 
719
753
  /**
720
- * What a call's callee is, read through the binder and the import
721
- * facts: a function in this run the walk can step into, or a reason it
722
- * cannot. A name is followed only through a binding that says where it
723
- * came from, so a name that could be two definitions is a stop rather
724
- * than a guess. The package README lists the spellings that are
725
- * followed and the ones that stop.
754
+ * What a call's callee is: a function in this run the walk can step
755
+ * into, or a reason it cannot.
756
+ *
757
+ * The rules in @suss/resolution decide it. Every language feature that
758
+ * moves a value is a hop they already state, so nothing here reads a
759
+ * name, an alias, an attribute, or an instance for itself.
760
+ *
761
+ * What is left is about files rather than values: a module before the
762
+ * dot, and a name only a wildcard import could have brought in.
726
763
  */
727
764
 
728
765
  /** A function in this run, and the export path its summary gets. */
@@ -754,6 +791,8 @@ interface WrapperIndexOptions {
754
791
  packs: readonly PythonPack[];
755
792
  roots: string[];
756
793
  facts: Database | undefined;
794
+ /** The function each function key was read from. */
795
+ definitions: ReadonlyMap<string, Node>;
757
796
  storageFor: (file: BoundPythonFile) => StorageLookup | undefined;
758
797
  }
759
798
  /** The route asking which wrappers reach it: the decorator it was found by, and where that decorator was read. */
@@ -787,6 +826,8 @@ declare class PythonWrapperIndex {
787
826
  private readonly unitsByKey;
788
827
  private readonly unitsByFile;
789
828
  constructor(options: WrapperIndexOptions, filesByPath: ReadonlyMap<string, BoundPythonFile>);
829
+ /** The project function a module-level name in this file refers to, or null for anything else. */
830
+ functionCalled(file: string, name: string): ReachedFunction | null;
790
831
  register(covers: {
791
832
  kind: "everyRoute";
792
833
  pack: string;
@@ -843,11 +884,7 @@ interface DiscoveryOptions {
843
884
  }
844
885
  declare function discoverUnits(root: Node, module: ModuleBinding, options: DiscoveryOptions): RawCodeStructure[];
845
886
 
846
- /**
847
- * Ask what these calls come down to, then derive. Asking about every call in
848
- * a project costs seconds on a large one and answers questions nobody has,
849
- * so a caller names the handful it needs.
850
- */
887
+ /** Ask what these calls come down to, then derive. */
851
888
  declare function resolveCalls(db: Database, callKeys: readonly string[]): void;
852
889
  /**
853
890
  * The values an object contains under its own keys, in the order the source
@@ -857,6 +894,19 @@ declare function containedValues(db: Database, objectKey: string): string[];
857
894
  /** What a call comes down to, when the rules settled it on an object. */
858
895
  declare function objectReturnedBy(db: Database, callKey: string): string | null;
859
896
 
897
+ /**
898
+ * values.ts: the facts @suss/resolution already joins, emitted for Python.
899
+ * The relation names and shapes come from that package's own header, so a
900
+ * Python value follows the same rules a TypeScript one does.
901
+ *
902
+ * A name is keyed by the scope that binds it. A function's own names take
903
+ * the function's key, so two handlers that both write `query` stay apart,
904
+ * and a module's names take the file's key, which is what another file
905
+ * imports back out. Every write to a name in one scope is collected in
906
+ * source order and `valueLeftByWrites` says what the name comes down to,
907
+ * so a reassigned name states one value or none rather than two.
908
+ */
909
+
860
910
  /**
861
911
  * A node's identity across the whole run. The end is part of it because a
862
912
  * call and its callee start at the same offset.
@@ -868,6 +918,11 @@ declare function nodeId(filePath: string, node: Node): string;
868
918
  * the function the expression is written in, or null at module level.
869
919
  */
870
920
  declare function readKey(filePath: string, node: Node, enclosing: Node | null): string;
921
+ /**
922
+ * The key a name joins on, for a caller holding the name as text and the
923
+ * function it is written in.
924
+ */
925
+ declare function nameKeyIn(filePath: string, enclosing: Node | null, name: string): string;
871
926
  /**
872
927
  * Walk a module and emit the value facts. A nested function is walked in its
873
928
  * own right, so a body's returns and calls belong to the function that wrote
@@ -1021,4 +1076,4 @@ declare function pythonImportEvidence(options: PythonImportEvidenceOptions): Pro
1021
1076
  */
1022
1077
  declare const ADAPTER_VERSION = "0.1.0";
1023
1078
 
1024
- 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, 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
@@ -717,12 +751,15 @@ interface StorageLookup {
717
751
  }
718
752
 
719
753
  /**
720
- * What a call's callee is, read through the binder and the import
721
- * facts: a function in this run the walk can step into, or a reason it
722
- * cannot. A name is followed only through a binding that says where it
723
- * came from, so a name that could be two definitions is a stop rather
724
- * than a guess. The package README lists the spellings that are
725
- * followed and the ones that stop.
754
+ * What a call's callee is: a function in this run the walk can step
755
+ * into, or a reason it cannot.
756
+ *
757
+ * The rules in @suss/resolution decide it. Every language feature that
758
+ * moves a value is a hop they already state, so nothing here reads a
759
+ * name, an alias, an attribute, or an instance for itself.
760
+ *
761
+ * What is left is about files rather than values: a module before the
762
+ * dot, and a name only a wildcard import could have brought in.
726
763
  */
727
764
 
728
765
  /** A function in this run, and the export path its summary gets. */
@@ -754,6 +791,8 @@ interface WrapperIndexOptions {
754
791
  packs: readonly PythonPack[];
755
792
  roots: string[];
756
793
  facts: Database | undefined;
794
+ /** The function each function key was read from. */
795
+ definitions: ReadonlyMap<string, Node>;
757
796
  storageFor: (file: BoundPythonFile) => StorageLookup | undefined;
758
797
  }
759
798
  /** The route asking which wrappers reach it: the decorator it was found by, and where that decorator was read. */
@@ -787,6 +826,8 @@ declare class PythonWrapperIndex {
787
826
  private readonly unitsByKey;
788
827
  private readonly unitsByFile;
789
828
  constructor(options: WrapperIndexOptions, filesByPath: ReadonlyMap<string, BoundPythonFile>);
829
+ /** The project function a module-level name in this file refers to, or null for anything else. */
830
+ functionCalled(file: string, name: string): ReachedFunction | null;
790
831
  register(covers: {
791
832
  kind: "everyRoute";
792
833
  pack: string;
@@ -843,11 +884,7 @@ interface DiscoveryOptions {
843
884
  }
844
885
  declare function discoverUnits(root: Node, module: ModuleBinding, options: DiscoveryOptions): RawCodeStructure[];
845
886
 
846
- /**
847
- * Ask what these calls come down to, then derive. Asking about every call in
848
- * a project costs seconds on a large one and answers questions nobody has,
849
- * so a caller names the handful it needs.
850
- */
887
+ /** Ask what these calls come down to, then derive. */
851
888
  declare function resolveCalls(db: Database, callKeys: readonly string[]): void;
852
889
  /**
853
890
  * The values an object contains under its own keys, in the order the source
@@ -857,6 +894,19 @@ declare function containedValues(db: Database, objectKey: string): string[];
857
894
  /** What a call comes down to, when the rules settled it on an object. */
858
895
  declare function objectReturnedBy(db: Database, callKey: string): string | null;
859
896
 
897
+ /**
898
+ * values.ts: the facts @suss/resolution already joins, emitted for Python.
899
+ * The relation names and shapes come from that package's own header, so a
900
+ * Python value follows the same rules a TypeScript one does.
901
+ *
902
+ * A name is keyed by the scope that binds it. A function's own names take
903
+ * the function's key, so two handlers that both write `query` stay apart,
904
+ * and a module's names take the file's key, which is what another file
905
+ * imports back out. Every write to a name in one scope is collected in
906
+ * source order and `valueLeftByWrites` says what the name comes down to,
907
+ * so a reassigned name states one value or none rather than two.
908
+ */
909
+
860
910
  /**
861
911
  * A node's identity across the whole run. The end is part of it because a
862
912
  * call and its callee start at the same offset.
@@ -868,6 +918,11 @@ declare function nodeId(filePath: string, node: Node): string;
868
918
  * the function the expression is written in, or null at module level.
869
919
  */
870
920
  declare function readKey(filePath: string, node: Node, enclosing: Node | null): string;
921
+ /**
922
+ * The key a name joins on, for a caller holding the name as text and the
923
+ * function it is written in.
924
+ */
925
+ declare function nameKeyIn(filePath: string, enclosing: Node | null, name: string): string;
871
926
  /**
872
927
  * Walk a module and emit the value facts. A nested function is walked in its
873
928
  * own right, so a body's returns and calls belong to the function that wrote
@@ -1021,4 +1076,4 @@ declare function pythonImportEvidence(options: PythonImportEvidenceOptions): Pro
1021
1076
  */
1022
1077
  declare const ADAPTER_VERSION = "0.1.0";
1023
1078
 
1024
- 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, 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 };