Skip to content

Commit

Permalink
refactor(manager/poetry): Use schema for lockfile parsing (#23973)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Aug 21, 2023
1 parent 756387f commit 847721e
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 56 deletions.
28 changes: 11 additions & 17 deletions lib/modules/manager/poetry/artifacts.ts
Expand Up @@ -15,9 +15,11 @@ import {
} from '../../../util/fs';
import { find } from '../../../util/host-rules';
import { regEx } from '../../../util/regex';
import { Result } from '../../../util/result';
import { PypiDatasource } from '../../datasource/pypi';
import { dependencyPattern } from '../pip_requirements/extract';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
import { Lockfile } from './schema';
import type { PoetryFile, PoetryLock, PoetrySource } from './types';

export function getPythonConstraint(
Expand All @@ -36,12 +38,6 @@ export function getPythonConstraint(

const pkgValRegex = regEx(`^${dependencyPattern}$`);

const poetryConstraint: Record<string, string> = {
'1.0': '<1.1.0',
'1.1': '<1.3.0',
'2.0': '>=1.3.0',
};

export function getPoetryRequirement(
pyProjectContent: string,
existingLockFileContent: string
Expand All @@ -53,18 +49,16 @@ export function getPoetryRequirement(
logger.debug('Using poetry version from poetry.lock header');
return poetryVersionMatch[1];
}
try {
const data = parse(existingLockFileContent) as PoetryLock;
const lockVersion = data?.metadata?.['lock-version'];
if (is.string(lockVersion)) {
if (poetryConstraint[lockVersion]) {
logger.debug('Using poetry version from poetry.lock metadata');
return poetryConstraint[lockVersion];
}
}
} catch (err) {
// Do nothing

const { val: lockfilePoetryConstraint } = Result.parse(
Lockfile.transform(({ poetryConstraint }) => poetryConstraint),
existingLockFileContent
).unwrap();
if (lockfilePoetryConstraint) {
logger.debug('Using poetry version from poetry.lock metadata');
return lockfilePoetryConstraint;
}

try {
const pyproject: PoetryFile = parse(pyProjectContent);
// https://python-poetry.org/docs/pyproject/#poetry-and-pep-517
Expand Down
18 changes: 11 additions & 7 deletions lib/modules/manager/poetry/extract.ts
Expand Up @@ -8,17 +8,18 @@ import {
} from '../../../util/fs';
import { parseGitUrl } from '../../../util/git/url';
import { regEx } from '../../../util/regex';
import { Result } from '../../../util/result';
import { GithubTagsDatasource } from '../../datasource/github-tags';
import { PypiDatasource } from '../../datasource/pypi';
import * as pep440Versioning from '../../versioning/pep440';
import * as poetryVersioning from '../../versioning/poetry';
import type { PackageDependency, PackageFileContent } from '../types';
import { extractLockFileEntries } from './locked-version';
import type {
PoetryDependencyRecord,
PoetryGroupRecord,
PoetrySchema,
PoetrySectionSchema,
import {
Lockfile,
type PoetryDependencyRecord,
type PoetryGroupRecord,
type PoetrySchema,
type PoetrySectionSchema,
} from './schema';
import { parsePoetry } from './utils';

Expand Down Expand Up @@ -179,7 +180,10 @@ export async function extractPackageFile(
// TODO #22198
const lockContents = (await readLocalFile(lockfileName, 'utf8'))!;

const lockfileMapping = extractLockFileEntries(lockContents);
const lockfileMapping = Result.parse(
Lockfile.transform(({ lock }) => lock),
lockContents
).unwrap({});

const deps = [
...extractFromDependenciesSection(
Expand Down
25 changes: 0 additions & 25 deletions lib/modules/manager/poetry/locked-version.ts

This file was deleted.

51 changes: 50 additions & 1 deletion lib/modules/manager/poetry/schema.ts
@@ -1,5 +1,5 @@
import { z } from 'zod';
import { LooseRecord, Toml } from '../../../util/schema-utils';
import { LooseArray, LooseRecord, Toml } from '../../../util/schema-utils';

const PoetryDependencySchema = z.object({
path: z.string().optional(),
Expand Down Expand Up @@ -53,3 +53,52 @@ export const PoetrySchema = z.object({
export type PoetrySchema = z.infer<typeof PoetrySchema>;

export const PoetrySchemaToml = Toml.pipe(PoetrySchema);

const poetryConstraint: Record<string, string> = {
'1.0': '<1.1.0',
'1.1': '<1.3.0',
'2.0': '>=1.3.0',
};

export const Lockfile = Toml.pipe(
z.object({
package: LooseArray(
z
.object({
name: z.string(),
version: z.string(),
})
.transform(({ name, version }): [string, string] => [name, version])
)
.transform((entries) => Object.fromEntries(entries))
.catch({}),
metadata: z
.object({
'lock-version': z
.string()
.transform((lockVersion) => poetryConstraint[lockVersion])
.optional()
.catch(undefined),
'python-versions': z.string().optional().catch(undefined),
})
.transform(
({
'lock-version': poetryConstraint,
'python-versions': pythonVersions,
}) => ({
poetryConstraint,
pythonVersions,
})
)
.catch({
poetryConstraint: undefined,
pythonVersions: undefined,
}),
})
).transform(
({ package: lock, metadata: { poetryConstraint, pythonVersions } }) => ({
lock,
poetryConstraint,
pythonVersions,
})
);
18 changes: 12 additions & 6 deletions lib/modules/manager/poetry/update-locked.ts
@@ -1,6 +1,7 @@
import { logger } from '../../../logger';
import { Result } from '../../../util/result';
import type { UpdateLockedConfig, UpdateLockedResult } from '../types';
import { extractLockFileEntries } from './locked-version';
import { Lockfile } from './schema';

export function updateLockedDependency(
config: UpdateLockedConfig
Expand All @@ -10,9 +11,14 @@ export function updateLockedDependency(
logger.debug(
`poetry.updateLockedDependency: ${depName}@${currentVersion} -> ${newVersion} [${lockFile}]`
);
const locked = extractLockFileEntries(lockFileContent ?? '');
if (depName && locked[depName] === newVersion) {
return { status: 'already-updated' };
}
return { status: 'unsupported' };

const LockedVersionSchema = Lockfile.transform(({ lock }) => lock[depName]);
return Result.parse(LockedVersionSchema, lockFileContent)
.transform(
(lockedVersion): UpdateLockedResult =>
lockedVersion === newVersion
? { status: 'already-updated' }
: { status: 'unsupported' }
)
.unwrap({ status: 'unsupported' });
}

0 comments on commit 847721e

Please sign in to comment.