Skip to content

Commit

Permalink
Show PyPi link in requirements (#23288)
Browse files Browse the repository at this point in the history
Show PyPi link in requirements, see #14495.

Apart from the test to verify the register of
`RequirementsTxtLinkActivator`, there are no other tests. This is my
first contribution in TypeScript, if you have an example of a test that
could be done, I'm interested :)

---------

Co-authored-by: Karthik Nadig <[email protected]>
  • Loading branch information
LouisGobert and karthiknadig authored May 7, 2024
1 parent 8ead7e2 commit 569ca65
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/client/activation/requirementsTxtLinkActivator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { injectable } from 'inversify';
import { Hover, languages, TextDocument, Position } from 'vscode';
import { IExtensionSingleActivationService } from './types';

const PYPI_PROJECT_URL = 'https://pypi.org/project';

export function generatePyPiLink(name: string): string | null {
// Regex to allow to find every possible pypi package (base regex from https://peps.python.org/pep-0508/#names)
const projectName = name.match(/^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*)($|=| |;|\[)/i);
return projectName ? `${PYPI_PROJECT_URL}/${projectName[1]}/` : null;
}

@injectable()
export class RequirementsTxtLinkActivator implements IExtensionSingleActivationService {
public readonly supportedWorkspaceTypes = { untrustedWorkspace: true, virtualWorkspace: true };

// eslint-disable-next-line class-methods-use-this
public async activate(): Promise<void> {
languages.registerHoverProvider([{ pattern: '**/*requirement*.txt' }, { pattern: '**/requirements/*.txt' }], {
provideHover(document: TextDocument, position: Position) {
const link = generatePyPiLink(document.lineAt(position.line).text);
return link ? new Hover(link) : null;
},
});
}
}
6 changes: 6 additions & 0 deletions src/client/activation/serviceRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { LoadLanguageServerExtension } from './common/loadLanguageServerExtensio
import { PartialModeStatusItem } from './partialModeStatus';
import { ILanguageServerWatcher } from '../languageServer/types';
import { LanguageServerWatcher } from '../languageServer/watcher';
import { RequirementsTxtLinkActivator } from './requirementsTxtLinkActivator';

export function registerTypes(serviceManager: IServiceManager): void {
serviceManager.addSingleton<IExtensionActivationService>(IExtensionActivationService, PartialModeStatusItem);
Expand All @@ -34,4 +35,9 @@ export function registerTypes(serviceManager: IServiceManager): void {

serviceManager.addSingleton<ILanguageServerWatcher>(ILanguageServerWatcher, LanguageServerWatcher);
serviceManager.addBinding(ILanguageServerWatcher, IExtensionActivationService);

serviceManager.addSingleton<IExtensionSingleActivationService>(
IExtensionSingleActivationService,
RequirementsTxtLinkActivator,
);
}
25 changes: 25 additions & 0 deletions src/test/activation/requirementsTxtLinkActivator.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

'use strict';

import { expect } from 'chai';
import { generatePyPiLink } from '../../client/activation/requirementsTxtLinkActivator';

suite('Link to PyPi in requiements test', () => {
[
['pytest', 'pytest'],
['pytest-cov', 'pytest-cov'],
['pytest_cov', 'pytest_cov'],
['pytest_cov[an_extra]', 'pytest_cov'],
['pytest == 0.6.1', 'pytest'],
['pytest== 0.6.1', 'pytest'],
['requests [security] >= 2.8.1, == 2.8.* ; python_version < "2.7"', 'requests'],
['# a comment', null],
['', null],
].forEach(([input, expected]) => {
test(`PyPI link case: "${input}"`, () => {
expect(generatePyPiLink(input!)).equal(expected ? `https://pypi.org/project/${expected}/` : null);
});
});
});
7 changes: 7 additions & 0 deletions src/test/activation/serviceRegistry.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { ServiceManager } from '../../client/ioc/serviceManager';
import { IServiceManager } from '../../client/ioc/types';
import { LoadLanguageServerExtension } from '../../client/activation/common/loadLanguageServerExtension';
import { RequirementsTxtLinkActivator } from '../../client/activation/requirementsTxtLinkActivator';

suite('Unit Tests - Language Server Activation Service Registry', () => {
let serviceManager: IServiceManager;
Expand Down Expand Up @@ -46,5 +47,11 @@ suite('Unit Tests - Language Server Activation Service Registry', () => {
LoadLanguageServerExtension,
),
).once();
verify(
serviceManager.addSingleton<IExtensionSingleActivationService>(
IExtensionSingleActivationService,
RequirementsTxtLinkActivator,
),
).once();
});
});

0 comments on commit 569ca65

Please sign in to comment.