Skip to content

Commit 77d0898

Browse files
Copilotluabud
andcommitted
Remove README and enhance inline code documentation
Co-authored-by: luabud <45497113+luabud@users.noreply.github.com>
1 parent 59eb674 commit 77d0898

File tree

6 files changed

+85
-98
lines changed

6 files changed

+85
-98
lines changed

DATAFRAME_DETECTION_README.md

Lines changed: 0 additions & 81 deletions
This file was deleted.

src/client/debugger/extension/adapter/activator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class DebugAdapterActivator implements IExtensionSingleActivationService
3636
this.disposables.push(
3737
this.debugService.registerDebugAdapterTrackerFactory(DebuggerTypeName, this.debuggerPromptFactory),
3838
);
39+
// Register DataFrame tracker to monitor for dataframe variables and suggest Jupyter extension
3940
this.disposables.push(
4041
this.debugService.registerDebugAdapterTrackerFactory(DebuggerTypeName, this.dataFrameTrackerFactory),
4142
);

src/client/debugger/extension/adapter/dataFrameTracker.ts

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,48 @@ import { IExtensions } from '../../../common/types';
1919
import { JUPYTER_EXTENSION_ID } from '../../../common/constants';
2020

2121
/**
22-
* Debug adapter tracker that monitors for dataframe-like variables
23-
* and suggests installing the Jupyter extension when they are detected
24-
* but the Jupyter extension is not installed.
22+
* Debug adapter tracker that monitors for dataframe-like variables during debugging sessions
23+
* and suggests installing the Jupyter extension when they are detected but the Jupyter extension
24+
* is not installed. This helps users discover the data viewer functionality when working with
25+
* dataframes without the Jupyter extension.
2526
*/
2627
class DataFrameVariableTracker implements DebugAdapterTracker {
2728
private readonly extensions: IExtensions;
29+
30+
/** Flag to ensure we only show the notification once per debug session to avoid spam */
2831
private hasNotifiedAboutJupyter = false;
2932

30-
// Types that are considered dataframe-like
33+
/**
34+
* Known dataframe type patterns from popular Python data processing libraries.
35+
* These patterns are matched against variable type strings in debug protocol responses.
36+
*/
3137
private readonly dataFrameTypes = [
32-
'pandas.core.frame.DataFrame',
33-
'pandas.DataFrame',
34-
'polars.DataFrame',
35-
'cudf.DataFrame',
36-
'dask.dataframe.core.DataFrame',
37-
'modin.pandas.DataFrame',
38-
'vaex.dataframe.DataFrame',
39-
'geopandas.geodataframe.GeoDataFrame',
38+
'pandas.core.frame.DataFrame', // Full pandas path
39+
'pandas.DataFrame', // Simplified pandas
40+
'polars.DataFrame', // Polars dataframes
41+
'cudf.DataFrame', // RAPIDS cuDF
42+
'dask.dataframe.core.DataFrame', // Dask distributed dataframes
43+
'modin.pandas.DataFrame', // Modin pandas-compatible
44+
'vaex.dataframe.DataFrame', // Vaex out-of-core dataframes
45+
'geopandas.geodataframe.GeoDataFrame', // GeoPandas geographic data
4046
];
4147

4248
constructor(_session: DebugSession, extensions: IExtensions) {
4349
this.extensions = extensions;
4450
}
4551

52+
/**
53+
* Intercepts debug protocol messages to monitor for variable responses.
54+
* When a variables response is detected, checks for dataframe-like objects.
55+
*
56+
* @param message - Debug protocol message from the debug adapter
57+
*/
4658
public onDidSendMessage(message: DebugProtocol.Message): void {
4759
if (this.hasNotifiedAboutJupyter) {
4860
return; // Only notify once per debug session
4961
}
5062

51-
// Check if this is a variables response
63+
// Check if this is a variables response from the debug protocol
5264
if ('type' in message && message.type === 'response' && 'command' in message && message.command === 'variables') {
5365
const response = message as unknown as DebugProtocol.VariablesResponse;
5466
if (response.success && response.body?.variables) {
@@ -57,13 +69,20 @@ class DataFrameVariableTracker implements DebugAdapterTracker {
5769
}
5870
}
5971

72+
/**
73+
* Examines an array of debug variables to detect dataframe-like objects.
74+
* Uses multiple detection strategies: type matching, value inspection, and name heuristics.
75+
*
76+
* @param variables - Array of variables from debug protocol variables response
77+
* @returns true if any dataframe-like variables were detected
78+
*/
6079
private checkForDataFrameVariables(variables: DebugProtocol.Variable[]): boolean {
61-
// Check if any variable is a dataframe-like object
80+
// Check if any variable is a dataframe-like object using multiple detection methods
6281
const hasDataFrame = variables.some((variable) =>
6382
this.dataFrameTypes.some((dfType) =>
6483
variable.type?.includes(dfType) ||
6584
variable.value?.includes(dfType) ||
66-
// Also check if the variable name suggests it's a dataframe
85+
// Also check if the variable name suggests it's a dataframe (common naming patterns)
6786
(variable.name?.match(/^(df|data|dataframe)/i) && variable.type?.includes('pandas'))
6887
)
6988
);
@@ -75,8 +94,12 @@ class DataFrameVariableTracker implements DebugAdapterTracker {
7594
return hasDataFrame;
7695
}
7796

97+
/**
98+
* Checks if the Jupyter extension is installed and shows notification if not.
99+
* This is the core logic that determines whether the user needs the suggestion.
100+
*/
78101
private checkAndNotifyJupyterExtension(): void {
79-
// Check if Jupyter extension is installed
102+
// Check if Jupyter extension is installed using VS Code extension API
80103
const jupyterExtension = this.extensions.getExtension(JUPYTER_EXTENSION_ID);
81104

82105
if (!jupyterExtension) {
@@ -85,6 +108,10 @@ class DataFrameVariableTracker implements DebugAdapterTracker {
85108
}
86109
}
87110

111+
/**
112+
* Displays an information message suggesting Jupyter extension installation.
113+
* Provides a direct action button to open the extension marketplace.
114+
*/
88115
private showJupyterInstallNotification(): void {
89116
const message = l10n.t('Install Jupyter extension to inspect dataframe objects in the data viewer.');
90117
const installAction = l10n.t('Install Jupyter Extension');
@@ -99,10 +126,22 @@ class DataFrameVariableTracker implements DebugAdapterTracker {
99126
}
100127
}
101128

129+
/**
130+
* Factory for creating DataFrameVariableTracker instances for debug sessions.
131+
* This factory is registered with VS Code's debug adapter tracker system to
132+
* automatically monitor all Python debug sessions for dataframe variables.
133+
*/
102134
@injectable()
103135
export class DataFrameTrackerFactory implements DebugAdapterTrackerFactory {
104136
constructor(@inject(IExtensions) private readonly extensions: IExtensions) {}
105137

138+
/**
139+
* Creates a new DataFrameVariableTracker for each debug session.
140+
* Each debug session gets its own tracker instance to maintain session-specific state.
141+
*
142+
* @param session - The debug session that this tracker will monitor
143+
* @returns A new DataFrameVariableTracker instance
144+
*/
106145
public createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker> {
107146
return new DataFrameVariableTracker(session, this.extensions);
108147
}

src/client/debugger/extension/serviceRegistry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export function registerTypes(serviceManager: IServiceManager): void {
6464
IOutdatedDebuggerPromptFactory,
6565
OutdatedDebuggerPromptFactory,
6666
);
67+
// Register DataFrameTrackerFactory to monitor debug sessions for dataframe variables
68+
// and suggest Jupyter extension installation when needed
6769
serviceManager.addSingleton<IDataFrameTrackerFactory>(
6870
IDataFrameTrackerFactory,
6971
DataFrameTrackerFactory,

src/client/debugger/extension/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ export const IOutdatedDebuggerPromptFactory = Symbol('IOutdatedDebuggerPromptFac
1919

2020
export interface IOutdatedDebuggerPromptFactory extends DebugAdapterTrackerFactory {}
2121

22+
/** Symbol identifier for the DataFrameTrackerFactory service */
2223
export const IDataFrameTrackerFactory = Symbol('IDataFrameTrackerFactory');
2324

25+
/**
26+
* Interface for debug adapter tracker factory that monitors dataframe variables
27+
* and suggests Jupyter extension installation when dataframes are detected.
28+
*/
2429
export interface IDataFrameTrackerFactory extends DebugAdapterTrackerFactory {}
2530

2631
export enum PythonPathSource {

src/test/debugger/extension/adapter/dataFrameTracker.unit.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import { IExtensions } from '../../../../client/common/types';
1212
import { JUPYTER_EXTENSION_ID } from '../../../../client/common/constants';
1313
import { DataFrameTrackerFactory } from '../../../../client/debugger/extension/adapter/dataFrameTracker';
1414

15+
/**
16+
* Test suite for DataFrame Tracker functionality.
17+
* Tests the detection of dataframe variables in debug sessions and
18+
* Jupyter extension installation suggestions.
19+
*/
1520
suite('DataFrame Tracker', () => {
1621
let extensions: IExtensions;
1722
let mockExtensions: IExtensions;
@@ -29,6 +34,10 @@ suite('DataFrame Tracker', () => {
2934
expect(tracker).to.not.be.undefined;
3035
});
3136

37+
/**
38+
* Test that pandas DataFrame variables are correctly detected
39+
* from debug protocol variable responses.
40+
*/
3241
test('Should detect pandas DataFrame variable', () => {
3342
const mockSession = {} as any;
3443
const tracker = trackerFactory.createDebugAdapterTracker(mockSession) as any;
@@ -67,6 +76,10 @@ suite('DataFrame Tracker', () => {
6776
verify(mockExtensions.getExtension(JUPYTER_EXTENSION_ID)).once();
6877
});
6978

79+
/**
80+
* Test that the tracker doesn't show notifications when Jupyter extension is already installed.
81+
* This prevents unnecessary notifications for users who already have the data viewer available.
82+
*/
7083
test('Should not show notification if Jupyter extension is installed', () => {
7184
const mockSession = {} as any;
7285
const tracker = trackerFactory.createDebugAdapterTracker(mockSession) as any;
@@ -99,6 +112,10 @@ suite('DataFrame Tracker', () => {
99112
verify(mockExtensions.getExtension(JUPYTER_EXTENSION_ID)).once();
100113
});
101114

115+
/**
116+
* Test that the tracker recognizes all supported dataframe types from various libraries.
117+
* This ensures comprehensive coverage of popular dataframe implementations.
118+
*/
102119
test('Should detect various dataframe types', () => {
103120
// This test verifies that the dataFrameTypes array contains the expected types
104121
const expectedTypes = [
@@ -119,10 +136,14 @@ suite('DataFrame Tracker', () => {
119136
});
120137
});
121138

139+
/**
140+
* Test that the tracker correctly rejects non-dataframe variables.
141+
* This prevents false positives on regular variables like strings, numbers, etc.
142+
*/
122143
test('Should not detect non-dataframe variables', () => {
123144
const nonDataFrameTypes = [
124145
'str',
125-
'int',
146+
'int',
126147
'list',
127148
'dict',
128149
'numpy.ndarray',

0 commit comments

Comments
 (0)