diff --git a/.chronus/changes/python-testInfraImprovements-2026-2-31-14-30-46.md b/.chronus/changes/python-testInfraImprovements-2026-2-31-14-30-46.md new file mode 100644 index 00000000000..2a8f2cf7540 --- /dev/null +++ b/.chronus/changes/python-testInfraImprovements-2026-2-31-14-30-46.md @@ -0,0 +1,7 @@ +--- +changeKind: internal +packages: + - "@typespec/http-client-python" +--- + +Clean up test infrastructure, run in parallel, and use uv pip when acceptable. CI runs 2-3 x faster \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7d848f69699..bd47e87ea2e 100644 --- a/.gitignore +++ b/.gitignore @@ -228,8 +228,8 @@ BenchmarkDotnet.Artifacts/ !packages/http-client-java/package-lock.json # python emitter -packages/http-client-python/generator/test/**/generated/ -packages/http-client-python/generator/test/**/cadl-ranch-coverage.json +packages/http-client-python/tests/**/generated/ +packages/http-client-python/tests/**/cadl-ranch-coverage.json !packages/http-client-python/package-lock.json packages/http-client-python/micropip.lock packages/http-client-python/venv_build_wheel/ diff --git a/cspell.yaml b/cspell.yaml index b6c373adb21..d0911a104c1 100644 --- a/cspell.yaml +++ b/cspell.yaml @@ -276,6 +276,7 @@ words: - unassignable - Uncapitalize - uncollapsed + - unconfigure - undifferentiable - undoc - Ungroup @@ -307,6 +308,7 @@ words: - WHATWG - WINDOWSARMVMIMAGE - WINDOWSVMIMAGE + - workerid - xiangyan - xiaofei - xlarge diff --git a/packages/http-client-python/emitter/src/code-model.ts b/packages/http-client-python/emitter/src/code-model.ts index 3f1eab6608a..974008d8b3b 100644 --- a/packages/http-client-python/emitter/src/code-model.ts +++ b/packages/http-client-python/emitter/src/code-model.ts @@ -25,14 +25,7 @@ import { emitPagingHttpMethod, } from "./http.js"; import { PythonSdkContext } from "./lib.js"; -import { - KnownTypes, - disableGenerationMap, - emitEndpointType, - getType, - simpleTypesMap, - typesMap, -} from "./types.js"; +import { KnownTypes, emitEndpointType, getType } from "./types.js"; import { emitParamBase, getClientNamespace, getImplementation, getRootNamespace } from "./utils.js"; function emitBasicMethod( @@ -366,7 +359,7 @@ export function emitCodeModel(sdkContext: PythonSdkContext) { continue; } // filter out specific models not used in python, e.g., pageable models - if (disableGenerationMap.has(model)) { + if (sdkContext.__disableGenerationMap.has(model)) { continue; } // filter out core models @@ -391,7 +384,7 @@ export function emitCodeModel(sdkContext: PythonSdkContext) { } // clear usage when a model is only used by paging - for (const type of typesMap.values()) { + for (const type of sdkContext.__typesMap.values()) { if ( type["type"] === "model" && type["referredByOperationType"] === ReferredByOperationTypes.PagingOnly && @@ -402,9 +395,9 @@ export function emitCodeModel(sdkContext: PythonSdkContext) { } codeModel["types"] = [ - ...typesMap.values(), + ...sdkContext.__typesMap.values(), ...Object.values(KnownTypes), - ...simpleTypesMap.values(), + ...sdkContext.__simpleTypesMap.values(), ]; codeModel["crossLanguagePackageId"] = ignoreDiagnostics(getCrossLanguagePackageId(sdkContext)); if ((sdkContext.emitContext.options as any).flavor === "azure") { diff --git a/packages/http-client-python/emitter/src/emitter.ts b/packages/http-client-python/emitter/src/emitter.ts index 9a3b66b883a..724a2c4387b 100644 --- a/packages/http-client-python/emitter/src/emitter.ts +++ b/packages/http-client-python/emitter/src/emitter.ts @@ -10,7 +10,6 @@ import { emitCodeModel } from "./code-model.js"; import { saveCodeModelAsYaml } from "./external-process.js"; import { PythonEmitterOptions, PythonSdkContext, reportDiagnostic } from "./lib.js"; import { runPython3 } from "./run-python3.js"; -import { disableGenerationMap, simpleTypesMap, typesMap } from "./types.js"; import { getRootNamespace, md2Rst } from "./utils.js"; function addDefaultOptions(sdkContext: PythonSdkContext) { @@ -59,6 +58,9 @@ async function createPythonSdkContext( return { ...sdkContext, __endpointPathParameters: [], + __typesMap: new Map(), + __simpleTypesMap: new Map(), + __disableGenerationMap: new Set(), }; } @@ -100,12 +102,6 @@ function walkThroughNodes(yamlMap: Record): Record { return yamlMap; } -function cleanAllCache() { - typesMap.clear(); - simpleTypesMap.clear(); - disableGenerationMap.clear(); -} - export async function $onEmit(context: EmitContext) { try { await onEmitMain(context); @@ -124,9 +120,6 @@ export async function $onEmit(context: EmitContext) { } async function onEmitMain(context: EmitContext) { - // clean all cache to make sure emitter could work in watch mode - cleanAllCache(); - const program = context.program; const sdkContext = await createPythonSdkContext(context); const root = path.join(dirname(fileURLToPath(import.meta.url)), "..", ".."); @@ -168,7 +161,7 @@ async function onEmitMain(context: EmitContext) { try { await runPython3(path.join(root, "/eng/scripts/setup/install.py")); await runPython3(path.join(root, "/eng/scripts/setup/prepare.py")); - } catch (error) { + } catch { // if the python env is not ready, we use pyodide instead resolvedOptions["use-pyodide"] = true; } @@ -250,7 +243,7 @@ async function onEmitMain(context: EmitContext) { execSync( `${venvPath} -m black --line-length=120 --quiet --fast ${outputDir} --exclude "${excludePattern}"`, ); - checkForPylintIssues(outputDir, excludePattern); + await checkForPylintIssues(outputDir, excludePattern); } } } @@ -269,7 +262,7 @@ async function setupPyodideCall(root: string) { if (lockAge > 300) { fs.unlinkSync(micropipLockPath); } - } catch (err) { + } catch { // ignore } } @@ -288,14 +281,14 @@ async function setupPyodideCall(root: string) { fs.closeSync(fd); fs.unlinkSync(micropipLockPath); break; - } catch (err) { + } catch { await new Promise((resolve) => setTimeout(resolve, 1000)); } } return pyodide; } -function checkForPylintIssues(outputDir: string, excludePattern: string) { +async function checkForPylintIssues(outputDir: string, excludePattern: string) { const excludeRegex = new RegExp(excludePattern); const shouldExcludePath = (filePath: string): boolean => { @@ -304,9 +297,8 @@ function checkForPylintIssues(outputDir: string, excludePattern: string) { return excludeRegex.test(normalizedPath); }; - const processFile = (filePath: string) => { - let fileContent; - fileContent = fs.readFileSync(filePath, "utf-8"); + const processFile = async (filePath: string) => { + let fileContent = await fs.promises.readFile(filePath, "utf-8"); const pylintDisables: string[] = []; const lineEnding = fileContent.includes("\r\n") && os.platform() === "win32" ? "\r\n" : "\n"; const lines: string[] = fileContent.split(lineEnding); @@ -321,32 +313,38 @@ function checkForPylintIssues(outputDir: string, excludePattern: string) { fileContent = lines[0].includes("pylint: disable=") ? [lines[0] + "," + pylintDisables.join(",")].concat(lines.slice(1)).join(lineEnding) : `# pylint: disable=${pylintDisables.join(",")}${lineEnding}` + fileContent; + await fs.promises.writeFile(filePath, fileContent); } } - - fs.writeFileSync(filePath, fileContent); }; - const walkDir = (dir: string) => { + const collectPythonFiles = async (dir: string): Promise => { if (shouldExcludePath(dir)) { - return; + return []; } - const files = fs.readdirSync(dir); - files.forEach((file) => { - const filePath = path.join(dir, file); + const entries = await fs.promises.readdir(dir, { withFileTypes: true }); + + const promises = entries.map(async (entry) => { + const filePath = path.join(dir, entry.name); if (shouldExcludePath(filePath)) { - return; + return []; } - if (fs.statSync(filePath).isDirectory()) { - walkDir(filePath); - } else if (file.endsWith(".py")) { - processFile(filePath); + if (entry.isDirectory()) { + return collectPythonFiles(filePath); + } else if (entry.name.endsWith(".py")) { + return [filePath]; } + return []; }); + + const results = await Promise.all(promises); + return results.flat(); }; - walkDir(outputDir); + // Collect all Python files first, then process in parallel + const pythonFiles = await collectPythonFiles(outputDir); + await Promise.all(pythonFiles.map(processFile)); } diff --git a/packages/http-client-python/emitter/src/lib.ts b/packages/http-client-python/emitter/src/lib.ts index 120d008cb62..ca66478bffe 100644 --- a/packages/http-client-python/emitter/src/lib.ts +++ b/packages/http-client-python/emitter/src/lib.ts @@ -1,5 +1,6 @@ import { SdkContext, + SdkType, UnbrandedSdkEmitterOptions, } from "@azure-tools/typespec-client-generator-core"; import { createTypeSpecLibrary, JSONSchemaType, paramMessage } from "@typespec/compiler"; @@ -28,6 +29,9 @@ export interface PythonEmitterOptions { export interface PythonSdkContext extends SdkContext { __endpointPathParameters: Record[]; + __typesMap: Map>; + __simpleTypesMap: Map>; + __disableGenerationMap: Set; } export const PythonEmitterOptionsSchema: JSONSchemaType = { diff --git a/packages/http-client-python/emitter/src/system-requirements.ts b/packages/http-client-python/emitter/src/system-requirements.ts index 7f12ff5b5a7..32521654c1b 100644 --- a/packages/http-client-python/emitter/src/system-requirements.ts +++ b/packages/http-client-python/emitter/src/system-requirements.ts @@ -16,8 +16,8 @@ const execute = ( options.onCreate(cp); } - options.onStdOutData && cp.stdout.on("data", options.onStdOutData); - options.onStdErrData && cp.stderr.on("data", options.onStdErrData); + if (options.onStdOutData) cp.stdout.on("data", options.onStdOutData); + if (options.onStdErrData) cp.stderr.on("data", options.onStdErrData); let err = ""; let out = ""; @@ -34,7 +34,7 @@ const execute = ( cp.on("error", (err) => { reject(err); }); - cp.on("close", (code, signal) => + cp.on("close", (code, _signal) => resolve({ stdout: out, stderr: err, @@ -110,7 +110,7 @@ const tryPython = async ( `"${PRINT_PYTHON_VERSION_SCRIPT}"`, ]); return validateVersionRequirement(resolution, result.stdout.trim(), requirement); - } catch (e) { + } catch { return { error: true, ...resolution, diff --git a/packages/http-client-python/emitter/src/types.ts b/packages/http-client-python/emitter/src/types.ts index b7f6f579106..3e0ee6f6b32 100644 --- a/packages/http-client-python/emitter/src/types.ts +++ b/packages/http-client-python/emitter/src/types.ts @@ -28,10 +28,6 @@ import { getImplementation, } from "./utils.js"; -export const typesMap = new Map>(); -export const simpleTypesMap = new Map>(); -export const disableGenerationMap = new Set(); - export interface CredentialType { kind: "Credential"; scheme: HttpAuth; @@ -59,13 +55,16 @@ function isEmptyModel(type: SdkType): boolean { ); } -export function getSimpleTypeResult(result: Record): Record { +export function getSimpleTypeResult( + context: PythonSdkContext, + result: Record, +): Record { const key = dump(result, { sortKeys: true }); - const value = simpleTypesMap.get(key); + const value = context.__simpleTypesMap.get(key); if (value) { result = value; } else { - simpleTypesMap.set(key, result); + context.__simpleTypesMap.set(key, result); } return result; } @@ -82,16 +81,16 @@ export function getType( case "enum": return emitEnum(context, type); case "constant": - return emitConstant(type)!; + return emitConstant(context, type)!; case "array": case "dict": return emitArrayOrDict(context, type)!; case "utcDateTime": case "offsetDateTime": case "duration": - return emitDurationOrDateType(type); + return emitDurationOrDateType(context, type); case "enumvalue": - return emitEnumMember(type, emitEnum(context, type.enumType)); + return emitEnumMember(context, type, emitEnum(context, type.enumType)); case "credential": return emitCredential(context, type); case "bytes": @@ -116,7 +115,7 @@ export function getType( case "decimal128": case "string": case "url": - return emitBuiltInType(type); + return emitBuiltInType(context, type); case "unknown": return KnownTypes.any; case "nullable": @@ -133,12 +132,12 @@ function emitMultiPartFile( type: MultiPartFileType, ): Record { if (type.type.kind === "array") { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: "list", elementType: getType(context, createMultiPartFileType(type.type.valueType)), }); } - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: type.kind, description: type.type.summary ? type.type.summary : type.type.doc, }); @@ -183,7 +182,7 @@ function emitCredential( }, }; } - return getSimpleTypeResult(credential_type); + return getSimpleTypeResult(context, credential_type); } function visibilityMapping(visibility?: Visibility[]): string[] | undefined { @@ -211,14 +210,14 @@ function createMultiPartFileType(type: SdkType): MultiPartFileType { return { kind: "multipartfile", type }; } -function addDisableGenerationMap(type: SdkType): void { - if (disableGenerationMap.has(type)) return; +function addDisableGenerationMap(context: PythonSdkContext, type: SdkType): void { + if (context.__disableGenerationMap.has(type)) return; - disableGenerationMap.add(type); + context.__disableGenerationMap.add(type); if (type.kind === "model" && type.baseModel) { - addDisableGenerationMap(type.baseModel); + addDisableGenerationMap(context, type.baseModel); } else if (type.kind === "array") { - addDisableGenerationMap(type.valueType); + addDisableGenerationMap(context, type.valueType); } } @@ -231,7 +230,7 @@ function emitProperty( if (isMultipartFileInput) { sourceType = createMultiPartFileType(property.type); // Python convert all the type of file part to FileType so clear these models' usage so that they won't be generated - addDisableGenerationMap(property.type); + addDisableGenerationMap(context, property.type); } return { clientName: camelToSnakeCase(property.name), @@ -257,8 +256,8 @@ function emitModel(context: PythonSdkContext, type: SdkModelType): Record { - return getSimpleTypeResult({ +function getConstantFromEnumValueType( + context: PythonSdkContext, + type: SdkEnumValueType, +): Record { + return getSimpleTypeResult(context, { type: "constant", value: type.value, - valueType: emitBuiltInType(type.valueType), + valueType: emitBuiltInType(context, type.valueType), }); } function emitEnum(context: PythonSdkContext, type: SdkEnumType): Record { - if (typesMap.has(type)) { - return typesMap.get(type)!; + if (context.__typesMap.has(type)) { + return context.__typesMap.get(type)!; } if (type.isGeneratedName) { const types = []; for (const value of type.values) { - types.push(getConstantFromEnumValueType(value)); + types.push(getConstantFromEnumValueType(context, value)); } if (!type.isFixed) { - types.push(emitBuiltInType(type.valueType)); + types.push(emitBuiltInType(context, type.valueType)); } const newValue = { @@ -350,7 +352,7 @@ function emitEnum(context: PythonSdkContext, type: SdkEnumType): Record[] = []; @@ -361,16 +363,16 @@ function emitEnum(context: PythonSdkContext, type: SdkEnumType): Record, ): Record { - if (typesMap.has(type)) { - return typesMap.get(type)!; + if (context.__typesMap.has(type)) { + return context.__typesMap.get(type)!; } // python don't generate enum created by TCGC, so we shall not generate type for enum member of the enum, either. if (type.enumType.isGeneratedName) { - return getConstantFromEnumValueType(type); + return getConstantFromEnumValueType(context, type); } const result = { @@ -401,14 +404,17 @@ function emitEnumMember( type: type.kind, valueType: enumType["valueType"], }; - typesMap.set(type, result); + context.__typesMap.set(type, result); return result; } -function emitDurationOrDateType(type: SdkDurationType | SdkDateTimeType): Record { - return getSimpleTypeResult({ - ...emitBuiltInType(type), - wireType: emitBuiltInType(type.wireType), +function emitDurationOrDateType( + context: PythonSdkContext, + type: SdkDurationType | SdkDateTimeType, +): Record { + return getSimpleTypeResult(context, { + ...emitBuiltInType(context, type), + wireType: emitBuiltInType(context, type.wireType), }); } @@ -417,17 +423,17 @@ function emitArrayOrDict( type: SdkArrayType | SdkDictionaryType, ): Record { const kind = type.kind === "array" ? "list" : type.kind; - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: kind, elementType: getType(context, type.valueType), }); } -function emitConstant(type: SdkConstantType) { - return getSimpleTypeResult({ +function emitConstant(context: PythonSdkContext, type: SdkConstantType) { + return getSimpleTypeResult(context, { type: type.kind, value: type.value, - valueType: emitBuiltInType(type.valueType), + valueType: emitBuiltInType(context, type.valueType), }); } @@ -461,12 +467,13 @@ const sdkScalarKindToPythonKind: Record = { }; function emitBuiltInType( + context: PythonSdkContext, type: SdkBuiltInType | SdkDurationType | SdkDateTimeType, ): Record { if (type.encode) { if (type.kind === "duration") { if (type.encode === "ISO8601") { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: type.kind, encode: type.encode, }); @@ -474,13 +481,13 @@ function emitBuiltInType( } if (type.kind === "utcDateTime" || type.kind === "offsetDateTime") { if (type.encode === "unixTimestamp") { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: "unixtime", encode: type.encode, }); } if (type.encode === "rfc3339" || type.encode === "rfc7231") { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: type.kind, encode: type.encode, }); @@ -489,21 +496,21 @@ function emitBuiltInType( // fallback to wire type for unknown or unsupported encode if ("wireType" in type && type.wireType !== undefined) { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: sdkScalarKindToPythonKind[type.wireType.kind] || type.wireType.kind, encode: type.encode, }); } } - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { type: sdkScalarKindToPythonKind[type.kind] || type.kind, // TODO: switch to kind encode: type.encode, }); } function emitUnion(context: PythonSdkContext, type: SdkUnionType): Record { - return getSimpleTypeResult({ + return getSimpleTypeResult(context, { name: type.isGeneratedName ? undefined : type.name, snakeCaseName: type.isGeneratedName ? undefined : camelToSnakeCase(type.name), description: type.isGeneratedName ? "" : `Type of ${type.name}`, @@ -515,8 +522,11 @@ function emitUnion(context: PythonSdkContext, type: SdkUnionType): Record { - const cache = simpleTypesMap.get(key); +export function getConstantType( + context: PythonSdkContext, + key: string | null, +): Record { + const cache = context.__simpleTypesMap.get(key); if (cache) { return cache; } @@ -527,7 +537,7 @@ export function getConstantType(key: string | null): Record { valueType: KnownTypes.string, xmlMetadata: {}, }; - simpleTypesMap.set(key, type); + context.__simpleTypesMap.set(key, type); return type; } diff --git a/packages/http-client-python/emitter/src/utils.ts b/packages/http-client-python/emitter/src/utils.ts index 16042f71dd5..9b30231a71d 100644 --- a/packages/http-client-python/emitter/src/utils.ts +++ b/packages/http-client-python/emitter/src/utils.ts @@ -213,7 +213,7 @@ export function emitParamBase( let type = getType(context, parameter.type); if (parameter.isApiVersionParam) { if (parameter.clientDefaultValue) { - type = getSimpleTypeResult({ + type = getSimpleTypeResult(context, { type: "constant", value: parameter.clientDefaultValue, valueType: type, @@ -317,7 +317,7 @@ function parseToken(token: Token): string { case "codespan": parsed += `\`\`${token.text}\`\``; break; - case "code": + case "code": { let codeBlockStyle = token.codeBlockStyle; if (codeBlockStyle === undefined) { codeBlockStyle = token.raw.split("\n")[0].replace("```", "").trim(); @@ -328,6 +328,7 @@ function parseToken(token: Token): string { } parsed += `\n\n.. code-block:: ${codeBlockStyle ?? ""}\n\n ${token.text.split("\n").join("\n ")}`; break; + } case "link": if (token.href !== undefined) { parsed += `\`${token.text} <${token.href}>\`_`; diff --git a/packages/http-client-python/eng/pipeline/templates/ci-stages.yml b/packages/http-client-python/eng/pipeline/templates/ci-stages.yml index 24ccab887a7..63ffca6588c 100644 --- a/packages/http-client-python/eng/pipeline/templates/ci-stages.yml +++ b/packages/http-client-python/eng/pipeline/templates/ci-stages.yml @@ -26,4 +26,4 @@ stages: Condition: ${{ parameters.Condition }} DependsOn: ${{ parameters.DependsOn }} LanguageShortName: "python" - PythonVersion: "3.11" + PythonVersion: "3.12" diff --git a/packages/http-client-python/eng/scripts/Build-Packages.ps1 b/packages/http-client-python/eng/scripts/Build-Packages.ps1 index 9200e8dac8f..16fd147f5db 100644 --- a/packages/http-client-python/eng/scripts/Build-Packages.ps1 +++ b/packages/http-client-python/eng/scripts/Build-Packages.ps1 @@ -1,4 +1,30 @@ #Requires -Version 7.0 +<# +.SYNOPSIS + Builds and packages the TypeSpec Python emitter for publishing. + +.DESCRIPTION + This script is called by the CI pipeline to create publishable packages. + It runs: + 1. npm run build - Compile TypeScript emitter and build Python wheel + 2. npm run lint - Run linting (Linux only) + 3. npm pack - Create npm tarball for publishing + +.PARAMETER BuildNumber + The build number for versioning. + +.PARAMETER Output + Output directory for built packages. Defaults to ./ci-build. + +.PARAMETER Prerelease + Flag indicating if this is a prerelease build. + +.PARAMETER PublishType + Type of publish: "internal" for dev feed, otherwise public. + +.EXAMPLE + ./Build-Packages.ps1 -Output ./dist +#> param( [string] $BuildNumber, @@ -7,6 +33,15 @@ param( [string] $PublishType ) +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 3.0 + +# Setup paths and helpers +$packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') +. "$packageRoot/../../eng/emitters/scripts/CommandInvocation-Helpers.ps1" +Set-ConsoleEncoding + +# Helper function to write package info for downstream publishing function Write-PackageInfo { param( [string] $packageName, @@ -15,81 +50,71 @@ function Write-PackageInfo { ) $packageInfoPath = "$outputPath/PackageInfo" - if (!(Test-Path $packageInfoPath)) { New-Item -ItemType Directory -Force -Path $packageInfoPath | Out-Null } @{ - Name = $packageName - Version = $version + Name = $packageName + Version = $version DirectoryPath = $directoryPath - SdkType = "client" - IsNewSdk = $true + SdkType = "client" + IsNewSdk = $true ReleaseStatus = "Unreleased" } | ConvertTo-Json | Set-Content -Path "$packageInfoPath/$packageName.json" } -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version 3.0 -$packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') -. "$packageRoot/../../eng/emitters/scripts/CommandInvocation-Helpers.ps1" -Set-ConsoleEncoding - Write-Host "Building packages for BuildNumber: '$BuildNumber', Output: '$Output', Prerelease: '$Prerelease', PublishType: '$PublishType'" +# Setup output directory $outputPath = $Output ? $Output : "$packageRoot/ci-build" - -# create the output folders $outputPath = New-Item -ItemType Directory -Force -Path $outputPath | Select-Object -ExpandProperty FullName New-Item -ItemType Directory -Force -Path "$outputPath/packages" | Out-Null -Write-Host "Getting existing version" +# Get package version $emitterVersion = node -p -e "require('$packageRoot/package.json').version" +Write-Host "Package version: $emitterVersion" -# build the generator -Push-Location "$packageRoot/generator" - -# build and pack the emitter with the generator Push-Location "$packageRoot" try { - Write-Host "Working in $PWD" - + # Step 1: Build the emitter and generator + Write-Host "`n=== Building emitter and generator ===" -ForegroundColor Cyan Invoke-LoggedCommand "npm run build" -GroupOutput - # Only run lint:py on Linux OS + # Step 2: Run linting (Linux only, as CI runs on Linux) if ($IsLinux) { - Write-Host "run lint check for pygen" - Invoke-LoggedCommand "npm run lint:py" -GroupOutput + Write-Host "`n=== Running lint checks ===" -ForegroundColor Cyan + Invoke-LoggedCommand "npm run lint" -GroupOutput } - # pack the emitter + # Step 3: Create npm package + Write-Host "`n=== Creating npm package ===" -ForegroundColor Cyan Invoke-LoggedCommand "npm pack" Copy-Item "typespec-http-client-python-$emitterVersion.tgz" -Destination "$outputPath/packages" - # install packed emitter to check dependencies + # Step 4: Verify package can be installed + Write-Host "`n=== Verifying package installation ===" -ForegroundColor Cyan Invoke-LoggedCommand "npm install typespec-http-client-python-$emitterVersion.tgz" -GroupOutput - Write-PackageInfo -packageName "typespec-http-client-python" -directoryPath "packages/http-client-python/emitter/src" -version $emitterVersion + # Write package info for publishing pipeline + Write-PackageInfo -packageName "typespec-http-client-python" ` + -directoryPath "packages/http-client-python/emitter/src" ` + -version $emitterVersion } finally { Pop-Location } +# Generate override URLs for internal publishing +$overrides = @{} if ($PublishType -eq "internal") { $feedUrl = "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-js/npm/registry" - - $overrides = @{ - "@typespec/http-client-python" = "$feedUrl/@typespec/http-client-python/-/http-client-python-$emitterVersion.tgz" - } -} else { - $overrides = @{} + $overrides["@typespec/http-client-python"] = "$feedUrl/@typespec/http-client-python/-/http-client-python-$emitterVersion.tgz" } - $overrides | ConvertTo-Json | Set-Content "$outputPath/overrides.json" -$packageMatrix = [ordered]@{ - "emitter" = $emitterVersion -} +# Write package version matrix +@{ "emitter" = $emitterVersion } | ConvertTo-Json | Set-Content "$outputPath/package-versions.json" -$packageMatrix | ConvertTo-Json | Set-Content "$outputPath/package-versions.json" +Write-Host "`n=== Build complete ===" -ForegroundColor Green +Write-Host "Output: $outputPath" diff --git a/packages/http-client-python/eng/scripts/Check-GitChanges.ps1 b/packages/http-client-python/eng/scripts/Check-GitChanges.ps1 index c4bde91a49e..ba7b32178a8 100644 --- a/packages/http-client-python/eng/scripts/Check-GitChanges.ps1 +++ b/packages/http-client-python/eng/scripts/Check-GitChanges.ps1 @@ -1,4 +1,21 @@ #Requires -Version 7.0 +<# +.SYNOPSIS + Checks for uncommitted git changes. + +.DESCRIPTION + This script verifies that there are no uncommitted changes in the repository. + It excludes package.json and package-lock.json from the check since those + may be modified during npm operations. + + Used by CI to ensure regeneration produces consistent output. + +.PARAMETER Exceptions + Additional paths to exclude from the check (not currently used). + +.EXAMPLE + ./Check-GitChanges.ps1 +#> param( [string] $Exceptions @@ -6,17 +23,27 @@ param( $ErrorActionPreference = 'Stop' Set-StrictMode -Version 3.0 + +# Setup paths and helpers $packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') . "$packageRoot/../../eng/emitters/scripts/CommandInvocation-Helpers.ps1" Set-ConsoleEncoding -$diffExcludes = @( +# Files to exclude from diff check (these may change during npm operations) +$excludedFiles = @( "$packageRoot/package.json" "$packageRoot/package-lock.json" -) | ForEach-Object { "`":(exclude)$_`"" } | Join-String -Separator ' ' +) +$diffExcludes = $excludedFiles | ForEach-Object { "`":(exclude)$_`"" } | Join-String -Separator ' ' + +# Check for changes, ignoring whitespace differences at end of lines Invoke-LoggedCommand "git -c core.safecrlf=false diff --ignore-space-at-eol --exit-code -- $diffExcludes" -IgnoreExitCode -if($LastExitCode -ne 0) { +if ($LastExitCode -ne 0) { + Write-Host "`nUncommitted changes detected!" -ForegroundColor Red + Write-Host "Run 'npm run regenerate' locally and commit the changes." throw "Changes detected" } + +Write-Host "No changes detected." -ForegroundColor Green diff --git a/packages/http-client-python/eng/scripts/Functions.ps1 b/packages/http-client-python/eng/scripts/Functions.ps1 index cc90c290378..e62336c8a89 100644 --- a/packages/http-client-python/eng/scripts/Functions.ps1 +++ b/packages/http-client-python/eng/scripts/Functions.ps1 @@ -1,26 +1,65 @@ -# Return list of nupkg artifacts -function Get-Package-Artifacts ($location, $filter) -{ - $filterToUse = $filter.StartsWith("typespec-") ? $filter.SubString(0, $filter.Length - 1) + ".api.json" : $filter +<# +.SYNOPSIS + Helper functions for finding package artifacts. + +.DESCRIPTION + These functions are used by the publishing pipeline to locate + built package artifacts for API review and publishing. +#> + +<# +.SYNOPSIS + Gets package artifacts from a directory. + +.PARAMETER location + The directory containing the packages folder. + +.PARAMETER filter + Filter pattern for matching package files. +#> +function Get-Package-Artifacts { + param( + [string] $location, + [string] $filter + ) + + # Convert typespec package filter to API json filter + $filterToUse = if ($filter.StartsWith("typespec-")) { + $filter.SubString(0, $filter.Length - 1) + ".api.json" + } else { + $filter + } $packages = Get-ChildItem -Path "$location/packages" -Filter $filterToUse -Recurse - if (!$packages) - { - Write-Host "$($location)/packages does not have any packages matching filter $($filterToUse)" + if (!$packages) { + Write-Host "$location/packages does not have any packages matching filter $filterToUse" return $null } + return $packages[0] } -function Find-Artifacts-For-Apireview($artifactDir, $packageName) -{ - # Find all nupkg files in given artifact directory +<# +.SYNOPSIS + Finds artifacts for API review. + +.PARAMETER artifactDir + Directory containing build artifacts. + +.PARAMETER packageName + Name of the package to find. +#> +function Find-Artifacts-For-Apireview { + param( + [string] $artifactDir, + [string] $packageName + ) + $package = Get-Package-Artifacts $artifactDir "$packageName*" - if (!$package) - { - Write-Host "Package is not available in artifact path $($artifactDir)/packages" + if (!$package) { + Write-Host "Package is not available in artifact path $artifactDir/packages" return $null } - $packages = @{ $package.Name = $package.FullName } - return $packages + + return @{ $package.Name = $package.FullName } } diff --git a/packages/http-client-python/eng/scripts/Generate.ps1 b/packages/http-client-python/eng/scripts/Generate.ps1 index 5bd459127b6..c80196272a9 100644 --- a/packages/http-client-python/eng/scripts/Generate.ps1 +++ b/packages/http-client-python/eng/scripts/Generate.ps1 @@ -1,14 +1,48 @@ #Requires -Version 7.0 +<# +.SYNOPSIS + Regenerates all test fixtures and documentation. -Import-Module "$PSScriptRoot\Generation.psm1" -DisableNameChecking -Force; +.DESCRIPTION + This script is called by the CI pipeline to regenerate test outputs. + It runs: + 1. npm run build - Compile TypeScript emitter and build Python wheel + 2. npm run regenerate - Regenerate all test fixtures from TypeSpec files + 3. npm run regen-docs - Regenerate API documentation -$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..' '..') +.EXAMPLE + ./Generate.ps1 +#> -Write-Host "Building project ..." -& npm run build +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version 3.0 -Write-Host "Regenerating project ..." -& npm run regenerate +# Setup paths +$packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') -Write-Host "Regenerating docs ..." -& npm run regen-docs +Push-Location "$packageRoot" +try { + Write-Host "=== Building project ===" -ForegroundColor Cyan + & npm run build + if ($LASTEXITCODE -ne 0) { throw "Build failed" } + + Write-Host "`n=== Regenerating test fixtures ===" -ForegroundColor Cyan + & npm run regenerate + if ($LASTEXITCODE -ne 0) { throw "Regeneration failed" } + + Write-Host "`n=== Regenerating documentation ===" -ForegroundColor Cyan + # Check if tspd is available (requires full monorepo build) + $tspdCli = Join-Path $packageRoot "../../packages/tspd/dist/src/cli.js" + if (Test-Path $tspdCli) { + & npm run regen-docs + if ($LASTEXITCODE -ne 0) { throw "Documentation regeneration failed" } + } else { + Write-Host "Skipping documentation regeneration (tspd not built)" -ForegroundColor Yellow + Write-Host "Run from monorepo root with full build to regenerate docs" -ForegroundColor Yellow + } + + Write-Host "`n=== Generation complete ===" -ForegroundColor Green +} +finally { + Pop-Location +} diff --git a/packages/http-client-python/eng/scripts/Generation.psm1 b/packages/http-client-python/eng/scripts/Generation.psm1 index 5f69ef05343..713075efc64 100644 --- a/packages/http-client-python/eng/scripts/Generation.psm1 +++ b/packages/http-client-python/eng/scripts/Generation.psm1 @@ -1,22 +1,51 @@ +<# +.SYNOPSIS + PowerShell module with helper functions for generation scripts. + +.DESCRIPTION + This module provides the Invoke function for running shell commands + cross-platform (Windows, Linux, macOS). +#> + $repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') -function Invoke($command, $executePath=$repoRoot) -{ - Write-Host "> $command" +<# +.SYNOPSIS + Invokes a shell command cross-platform. + +.PARAMETER command + The command to execute. + +.PARAMETER executePath + The directory to execute the command in. Defaults to repo root. + +.EXAMPLE + Invoke "npm run build" +#> +function Invoke { + param( + [string] $command, + [string] $executePath = $repoRoot + ) + + Write-Host "> $command" -ForegroundColor Cyan + Push-Location $executePath - if ($IsLinux -or $IsMacOs) - { - sh -c "$command 2>&1" - } - else - { - cmd /c "$command 2>&1" - } - Pop-Location + try { + if ($IsLinux -or $IsMacOs) { + sh -c "$command 2>&1" + } + else { + cmd /c "$command 2>&1" + } - if($LastExitCode -ne 0) - { - Write-Error "Command failed to execute: $command" + if ($LastExitCode -ne 0) { + throw "Command failed: $command" + } + } + finally { + Pop-Location } } + Export-ModuleMember -Function "Invoke" diff --git a/packages/http-client-python/eng/scripts/Initialize-Repository.ps1 b/packages/http-client-python/eng/scripts/Initialize-Repository.ps1 index 4320a530734..4fc04484175 100644 --- a/packages/http-client-python/eng/scripts/Initialize-Repository.ps1 +++ b/packages/http-client-python/eng/scripts/Initialize-Repository.ps1 @@ -1,4 +1,21 @@ #Requires -Version 7.0 +<# +.SYNOPSIS + Initializes the repository by installing npm dependencies. + +.DESCRIPTION + This script is called by the CI pipeline to set up the repository. + It runs `npm ci` to install dependencies from package-lock.json. + +.PARAMETER BuildArtifactsPath + Optional path to build artifacts (used in CI for caching lock files). + +.PARAMETER UseTypeSpecNext + Optional switch for using TypeSpec next version (not currently used). + +.EXAMPLE + ./Initialize-Repository.ps1 +#> param( [string] $BuildArtifactsPath, @@ -7,32 +24,33 @@ param( $ErrorActionPreference = 'Stop' Set-StrictMode -Version 3.0 + +# Setup paths and helpers $packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') . "$packageRoot/../../eng/emitters/scripts/CommandInvocation-Helpers.ps1" Set-ConsoleEncoding Push-Location "$packageRoot" try { + # Clean install of npm dependencies if (Test-Path "./node_modules") { + Write-Host "Removing existing node_modules..." Remove-Item -Recurse -Force "./node_modules" } - # install and list npm packages - + Write-Host "Installing npm dependencies..." Invoke-LoggedCommand "npm ci" - Invoke-LoggedCommand "npm ls -a" -GroupOutput - Write-Host "artifactStagingDirectory: $env:BUILD_ARTIFACTSTAGINGDIRECTORY" - Write-Host "BuildArtifactsPath: $BuildArtifactsPath" + # Copy lock files to artifacts for CI caching (if running in Azure DevOps) $artifactStagingDirectory = $env:BUILD_ARTIFACTSTAGINGDIRECTORY if ($artifactStagingDirectory -and !$BuildArtifactsPath) { - $lockFilesPath = "$artifactStagingDirectory/lock-files" - New-Item -ItemType Directory -Path "$lockFilesPath/emitter" | Out-Null - - Write-Host "Copying emitter/package.json and emitter/package-lock.json to $lockFilesPath" - Copy-Item './package.json' "$lockFilesPath/emitter/package.json" -Force - Copy-Item './package-lock.json' "$lockFilesPath/emitter/package-lock.json" -Force + $lockFilesPath = "$artifactStagingDirectory/lock-files/emitter" + New-Item -ItemType Directory -Path $lockFilesPath -Force | Out-Null + + Write-Host "Copying lock files to $lockFilesPath" + Copy-Item './package.json' "$lockFilesPath/package.json" -Force + Copy-Item './package-lock.json' "$lockFilesPath/package-lock.json" -Force } } finally { diff --git a/packages/http-client-python/eng/scripts/Test-Packages.ps1 b/packages/http-client-python/eng/scripts/Test-Packages.ps1 index a5fba247cd8..05ea968b8cb 100644 --- a/packages/http-client-python/eng/scripts/Test-Packages.ps1 +++ b/packages/http-client-python/eng/scripts/Test-Packages.ps1 @@ -1,4 +1,32 @@ #Requires -Version 7.0 +<# +.SYNOPSIS + Runs tests for the TypeSpec Python emitter. + +.DESCRIPTION + This script is called by the CI pipeline to run tests. + + With -UnitTests: + - Runs npm run build (compile emitter) + + With -GenerationChecks: + - Runs npm run build (compile emitter) + - Runs Generate.ps1 (regenerate test fixtures) + - Runs Check-GitChanges.ps1 (verify no uncommitted changes) + - Runs npm run ci (full test suite: pytest, lint, mypy, pyright) + +.PARAMETER UnitTests + Run unit tests only (just builds the project). + +.PARAMETER GenerationChecks + Run full generation checks and test suite. + +.PARAMETER Filter + Optional filter pattern for tests (not currently used). + +.EXAMPLE + ./Test-Packages.ps1 -GenerationChecks +#> param( [switch] $UnitTests, @@ -7,57 +35,45 @@ param( ) $ErrorActionPreference = 'Stop' - Set-StrictMode -Version 3.0 + +# Setup paths and helpers $packageRoot = (Resolve-Path "$PSScriptRoot/../..").Path.Replace('\', '/') . "$packageRoot/../../eng/emitters/scripts/CommandInvocation-Helpers.ps1" Set-ConsoleEncoding +Write-Host "Python version:" Invoke-LoggedCommand "python --version" Push-Location $packageRoot try { if ($UnitTests) { - Push-Location "$packageRoot" - try { - - Write-Host "Updated PATH: $env:PATH" - # test the emitter - Invoke-LoggedCommand "npm run build" -GroupOutput - - } - finally { - Pop-Location - } + Write-Host "`n=== Running unit tests ===" -ForegroundColor Cyan + Invoke-LoggedCommand "npm run build" -GroupOutput } + if ($GenerationChecks) { - Set-StrictMode -Version 1 - - # run E2E Test for TypeSpec emitter - Write-Host "Generating test projects ..." + # Step 1: Regenerate all test fixtures + Write-Host "`n=== Regenerating test fixtures ===" -ForegroundColor Cyan & "$packageRoot/eng/scripts/Generate.ps1" - Write-Host 'Code generation is completed.' + # Step 2: Check for uncommitted changes (regeneration should be clean) + Write-Host "`n=== Checking for uncommitted changes ===" -ForegroundColor Cyan try { - Write-Host 'Checking for differences in generated code...' & "$packageRoot/eng/scripts/Check-GitChanges.ps1" - Write-Host 'Done. No code generation differences detected.' + Write-Host "No uncommitted changes detected." -ForegroundColor Green } catch { - Write-Error 'Generated code is not up to date. Please run: eng/Generate.ps1' + Write-Error "Generated code is not up to date. Please run: npm run regenerate" } - try { - Write-Host "Pip List" - & pip list - # Run tox - Write-Host 'Running tests' - & npm run ci - Write-Host 'tox tests passed' - } - catch { - Write-Error "Spector tests failed: $_" - } + # Step 3: Run full test suite + Write-Host "`n=== Running full test suite ===" -ForegroundColor Cyan + Write-Host "Installed packages:" + & pip list + + Invoke-LoggedCommand "npm run ci" + Write-Host "All tests passed." -ForegroundColor Green } } finally { diff --git a/packages/http-client-python/eng/scripts/ci/config/eslint-ci.config.mjs b/packages/http-client-python/eng/scripts/ci/config/eslint-ci.config.mjs new file mode 100644 index 00000000000..b8a1418a63e --- /dev/null +++ b/packages/http-client-python/eng/scripts/ci/config/eslint-ci.config.mjs @@ -0,0 +1,54 @@ +// @ts-check +// Standalone eslint config for http-client-python package +// This config is used in CI where monorepo dependencies may not be available +import eslint from "@eslint/js"; +import tsEslint from "typescript-eslint"; + +export default [ + { + ignores: ["**/dist/**/*", "**/node_modules/**/*"], + }, + eslint.configs.recommended, + ...tsEslint.configs.recommended, + { + rules: { + // TypeScript plugin overrides + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + varsIgnorePattern: "^_", + argsIgnorePattern: ".*", + ignoreRestSiblings: true, + caughtErrorsIgnorePattern: ".*", + }, + ], + "@typescript-eslint/no-unused-expressions": [ + "warn", + { allowShortCircuit: true, allowTernary: true }, + ], + + // Core rules + "no-inner-declarations": "off", + "no-empty": "off", + "no-constant-condition": "off", + "no-case-declarations": "off", + "no-ex-assign": "off", + "no-undef": "off", + "prefer-const": [ + "warn", + { + destructuring: "all", + }, + ], + eqeqeq: ["warn", "always", { null: "ignore" }], + "no-console": "warn", + "symbol-description": "warn", + }, + }, +]; diff --git a/packages/http-client-python/eng/scripts/ci/mypy.ini b/packages/http-client-python/eng/scripts/ci/config/mypy.ini similarity index 100% rename from packages/http-client-python/eng/scripts/ci/mypy.ini rename to packages/http-client-python/eng/scripts/ci/config/mypy.ini diff --git a/packages/http-client-python/eng/scripts/ci/pylintrc b/packages/http-client-python/eng/scripts/ci/config/pylintrc similarity index 100% rename from packages/http-client-python/eng/scripts/ci/pylintrc rename to packages/http-client-python/eng/scripts/ci/config/pylintrc diff --git a/packages/http-client-python/eng/scripts/ci/pyproject.toml b/packages/http-client-python/eng/scripts/ci/config/pyproject.toml similarity index 100% rename from packages/http-client-python/eng/scripts/ci/pyproject.toml rename to packages/http-client-python/eng/scripts/ci/config/pyproject.toml diff --git a/packages/http-client-python/eng/scripts/ci/pyrightconfig.json b/packages/http-client-python/eng/scripts/ci/config/pyrightconfig.json similarity index 100% rename from packages/http-client-python/eng/scripts/ci/pyrightconfig.json rename to packages/http-client-python/eng/scripts/ci/config/pyrightconfig.json diff --git a/packages/http-client-python/eng/scripts/ci/dev_requirements.txt b/packages/http-client-python/eng/scripts/ci/dev_requirements.txt index 7e3b05234a1..2d713225106 100644 --- a/packages/http-client-python/eng/scripts/ci/dev_requirements.txt +++ b/packages/http-client-python/eng/scripts/ci/dev_requirements.txt @@ -1,6 +1,7 @@ pyright==1.1.407 pylint==4.0.4 tox==4.16.0 +tox-uv mypy==1.19.1 colorama==0.4.6 debugpy==1.8.2 diff --git a/packages/http-client-python/eng/scripts/ci/format.ts b/packages/http-client-python/eng/scripts/ci/format.ts index 39663edcae3..96d08dedc39 100644 --- a/packages/http-client-python/eng/scripts/ci/format.ts +++ b/packages/http-client-python/eng/scripts/ci/format.ts @@ -1,3 +1,233 @@ -import { runCommand } from "./utils.js"; +/* eslint-disable no-console */ +import { spawn } from "child_process"; +import fs from "fs"; +import { dirname, join } from "path"; +import pc from "picocolors"; +import { fileURLToPath } from "url"; +import { parseArgs } from "util"; -runCommand("black", ["generator/", "eng/", "--config", "./eng/scripts/ci/pyproject.toml"]); +const root = join(dirname(fileURLToPath(import.meta.url)), "../../../"); +const monorepoRoot = join(root, "../../"); + +// Get Python venv path +function getVenvPython(): string { + const venvPath = join(root, "venv"); + if (fs.existsSync(join(venvPath, "bin"))) { + return join(venvPath, "bin", "python"); + } else if (fs.existsSync(join(venvPath, "Scripts"))) { + return join(venvPath, "Scripts", "python.exe"); + } + throw new Error("Virtual environment not found. Run 'npm run install' first."); +} + +const argv = parseArgs({ + args: process.argv.slice(2), + options: { + emitter: { type: "boolean", short: "e" }, + generator: { type: "boolean", short: "g" }, + generated: { type: "boolean" }, + check: { type: "boolean", short: "c" }, + help: { type: "boolean", short: "h" }, + }, +}); + +if (argv.values.help) { + console.log(` +${pc.bold("Usage:")} tsx format.ts [options] + +${pc.bold("Description:")} + Format code using Prettier (TypeScript) and Black (Python). + +${pc.bold("Options:")} + ${pc.cyan("-e, --emitter")} + Format TypeScript emitter code with Prettier. + + ${pc.cyan("-g, --generator")} + Format Python generator source code (pygen) with Black. + + ${pc.cyan("--generated")} + Format generated SDK packages with Black. + + ${pc.cyan("-c, --check")} + Check formatting without making changes (exit with error if unformatted). + + ${pc.cyan("-h, --help")} + Show this help message. + +${pc.bold("Examples:")} + ${pc.dim("# Format emitter + pygen source (default)")} + tsx format.ts + + ${pc.dim("# Format only TypeScript emitter")} + tsx format.ts --emitter + + ${pc.dim("# Format only pygen source code")} + tsx format.ts --generator + + ${pc.dim("# Check formatting without making changes")} + tsx format.ts --check + + ${pc.dim("# Format generated SDK packages")} + tsx format.ts --generated +`); + process.exit(0); +} + +function runCommand(command: string, args: string[]): Promise { + // Add node_modules/.bin directories to PATH so commands like prettier can be found + const pathSep = process.platform === "win32" ? ";" : ":"; + const binPaths = [ + join(root, "node_modules", ".bin"), + join(monorepoRoot, "node_modules", ".bin"), + ].join(pathSep); + const env = { + ...process.env, + PATH: `${binPaths}${pathSep}${process.env.PATH}`, + }; + + return new Promise((resolve) => { + console.log(`${pc.cyan("[RUN]")} ${command} ${args.join(" ")}`); + const proc = spawn(command, args, { + cwd: root, + stdio: "inherit", + shell: true, + env, + }); + + proc.on("close", (code) => { + if (code === 0) { + console.log(`${pc.green("[PASS]")} ${command} completed successfully`); + resolve(true); + } else { + console.log(`${pc.red("[FAIL]")} ${command} failed with code ${code}`); + resolve(false); + } + }); + + proc.on("error", (err) => { + console.log(`${pc.red("[ERROR]")} ${command}: ${err.message}`); + resolve(false); + }); + }); +} + +async function formatEmitter(check: boolean): Promise { + console.log(`\n${pc.bold("=== Formatting TypeScript Emitter ===")}\n`); + // Use prettier directly - it's available via node_modules/.bin in PATH + // Exclude CHANGELOG.md as it's managed by chronus changelog tool + const args = check + ? [ + "--check", + "emitter/", + "eng/scripts/", + "*.json", + "README.md", + "CONTRIBUTING.md", + "ARCHITECTURE.md", + ] + : [ + "--write", + "emitter/", + "eng/scripts/", + "*.json", + "README.md", + "CONTRIBUTING.md", + "ARCHITECTURE.md", + ]; + return runCommand("prettier", args); +} + +async function formatPygenSource(check: boolean): Promise { + console.log(`\n${pc.bold("=== Formatting Python Generator (pygen) ===")}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + const args = [ + "-m", + "black", + "generator/pygen", + "eng/scripts/", + "--config", + "./eng/scripts/ci/config/pyproject.toml", + ]; + if (check) { + args.push("--check"); + } + return runCommand(pythonPath, args); +} + +async function formatGeneratedPackages(check: boolean): Promise { + console.log(`\n${pc.bold("=== Formatting Generated SDK Packages ===")}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + const args = [ + "-m", + "black", + "generator/test/azure/generated", + "generator/test/unbranded/generated", + "--config", + "./eng/scripts/ci/config/pyproject.toml", + ]; + if (check) { + args.push("--check"); + } + return runCommand(pythonPath, args); +} + +async function main(): Promise { + const runEmitter = argv.values.emitter; + const runGenerator = argv.values.generator; + const runGenerated = argv.values.generated; + const check = argv.values.check || false; + + // If --generated is specified, only format generated packages + if (runGenerated) { + const result = await formatGeneratedPackages(check); + if (!result) process.exit(1); + console.log( + `\n${pc.green(pc.bold(`Generated SDK formatting ${check ? "check " : ""}complete!`))}\n`, + ); + return; + } + + // Default: format emitter + pygen source + const runBoth = !runEmitter && !runGenerator; + + let success = true; + + if (runEmitter || runBoth) { + const result = await formatEmitter(check); + if (!result) success = false; + } + + if (runGenerator || runBoth) { + const result = await formatPygenSource(check); + if (!result) success = false; + } + + if (!success) { + process.exit(1); + } + + console.log( + `\n${pc.green(pc.bold(`All formatting ${check ? "checks passed" : "complete"}!`))}\n`, + ); +} + +main().catch((error) => { + console.error(`${pc.red("Unexpected error:")}`, error); + process.exit(1); +}); diff --git a/packages/http-client-python/eng/scripts/ci/lint.ts b/packages/http-client-python/eng/scripts/ci/lint.ts index eb9c581bfcc..9d6150b9acc 100644 --- a/packages/http-client-python/eng/scripts/ci/lint.ts +++ b/packages/http-client-python/eng/scripts/ci/lint.ts @@ -1,36 +1,232 @@ +/* eslint-disable no-console */ +import { spawn } from "child_process"; +import fs from "fs"; +import { dirname, join } from "path"; +import pc from "picocolors"; +import { fileURLToPath } from "url"; import { parseArgs } from "util"; -import { runCommand } from "./utils.js"; -// PARSE INPUT ARGUMENTS +const root = join(dirname(fileURLToPath(import.meta.url)), "../../../"); +const monorepoRoot = join(root, "../../"); +const testsDir = join(root, "tests"); + +// Get Python venv path +function getVenvPython(): string { + const venvPath = join(root, "venv"); + if (fs.existsSync(join(venvPath, "bin"))) { + return join(venvPath, "bin", "python"); + } else if (fs.existsSync(join(venvPath, "Scripts"))) { + return join(venvPath, "Scripts", "python.exe"); + } + throw new Error("Virtual environment not found. Run 'npm run install' first."); +} const argv = parseArgs({ args: process.argv.slice(2), options: { - folderName: { type: "string" }, - command: { type: "string" }, + emitter: { type: "boolean", short: "e" }, + generator: { type: "boolean", short: "g" }, + generated: { type: "boolean" }, + flavor: { type: "string", short: "f" }, + help: { type: "boolean", short: "h" }, }, }); -export function pylint() { - runCommand("pylint", [argv.values.folderName!, "--rcfile", "./eng/scripts/ci/pylintrc"]); +if (argv.values.help) { + console.log(` +${pc.bold("Usage:")} tsx lint.ts [options] + +${pc.bold("Description:")} + Run linting checks on the codebase. + +${pc.bold("Options:")} + ${pc.cyan("-e, --emitter")} + Run ESLint on TypeScript emitter code. + + ${pc.cyan("-g, --generator")} + Run pylint on Python generator source code (pygen). + + ${pc.cyan("--generated")} + Run pylint on generated SDK packages (via tox). + Use with --flavor to specify azure or unbranded. + + ${pc.cyan("-f, --flavor ")} + SDK flavor to lint (only applies to --generated). + If not specified, lints both flavors. + + ${pc.cyan("-h, --help")} + Show this help message. + +${pc.bold("Examples:")} + ${pc.dim("# Lint emitter + pygen source (default)")} + tsx lint.ts + + ${pc.dim("# Lint only TypeScript emitter")} + tsx lint.ts --emitter + + ${pc.dim("# Lint only pygen source code")} + tsx lint.ts --generator + + ${pc.dim("# Lint generated SDK packages")} + tsx lint.ts --generated + + ${pc.dim("# Lint generated SDK packages for azure only")} + tsx lint.ts --generated --flavor=azure +`); + process.exit(0); +} + +function runCommand( + command: string, + args: string[], + cwd?: string, + displayName?: string, +): Promise { + const workingDir = cwd || root; + const name = displayName || command; + + // Add node_modules/.bin directories to PATH so commands like eslint can be found + // Also set NODE_PATH so that config files can resolve packages from monorepo's node_modules + const pathSep = process.platform === "win32" ? ";" : ":"; + const binPaths = [ + join(workingDir, "node_modules", ".bin"), + join(root, "node_modules", ".bin"), + join(monorepoRoot, "node_modules", ".bin"), + ].join(pathSep); + const nodePaths = [ + join(workingDir, "node_modules"), + join(root, "node_modules"), + join(monorepoRoot, "node_modules"), + ].join(pathSep); + const env = { + ...process.env, + PATH: `${binPaths}${pathSep}${process.env.PATH}`, + NODE_PATH: nodePaths, + }; + + return new Promise((resolve) => { + // If displayName is provided, show it as-is; otherwise show command + args + const logMessage = displayName ? displayName : `${command} ${args.join(" ")}`; + console.log(`${pc.cyan("[RUN]")} ${logMessage}`); + const proc = spawn(command, args, { + cwd: workingDir, + stdio: "inherit", + shell: true, + env, + }); + + proc.on("close", (code) => { + if (code === 0) { + console.log(`${pc.green("[PASS]")} ${name} completed successfully`); + resolve(true); + } else { + console.log(`${pc.red("[FAIL]")} ${name} failed with code ${code}`); + resolve(false); + } + }); + + proc.on("error", (err) => { + console.log(`${pc.red("[ERROR]")} ${name}: ${err.message}`); + resolve(false); + }); + }); } -export function mypy() { - runCommand("mypy", [argv.values.folderName!, "--config-file", "./eng/scripts/ci/mypy.ini"]); +async function lintEmitter(): Promise { + console.log(`\n${pc.bold("=== Linting TypeScript Emitter ===")}\n`); + // Run eslint with local config to avoid dependency on monorepo's eslint.config.js + // This ensures the package can be linted in CI without full monorepo dependencies + return runCommand( + "eslint", + ["emitter/", "--config", "eng/scripts/ci/config/eslint-ci.config.mjs", "--max-warnings=0"], + root, + "eslint emitter/ --max-warnings=0", + ); } -export function pyright() { - runCommand("pyright", [argv.values.folderName!, "-p", "./eng/scripts/ci/pyrightconfig.json"]); +async function lintPygenSource(): Promise { + console.log(`\n${pc.bold("=== Linting Python Generator (pygen) ===")}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + // Lint pygen source code directly with pylint + return runCommand(pythonPath, [ + "-m", + "pylint", + "generator/pygen", + "--rcfile=eng/scripts/ci/config/pylintrc", + "--recursive=y", + "--py-version=3.9", + ]); } -if (argv.values.command === "pylint") { - pylint(); -} else if (argv.values.command === "mypy") { - mypy(); -} else if (argv.values.command === "pyright") { - pyright(); -} else { - pylint(); - mypy(); - pyright(); +async function lintGeneratedPackages(flavor?: string): Promise { + const flavors = flavor ? [flavor] : ["azure", "unbranded"]; + console.log(`\n${pc.bold(`=== Linting Generated SDK Packages (${flavors.join(", ")}) ===`)}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + let success = true; + for (const f of flavors) { + const toxEnv = `lint-${f}`; + const result = await runCommand( + pythonPath, + ["-m", "tox", "-c", "tox.ini", "-e", toxEnv], + testsDir, + ); + if (!result) success = false; + } + return success; } + +async function main(): Promise { + const runEmitter = argv.values.emitter; + const runGenerator = argv.values.generator; + const runGenerated = argv.values.generated; + + // If --generated is specified, only lint generated packages + if (runGenerated) { + const result = await lintGeneratedPackages(argv.values.flavor); + if (!result) process.exit(1); + console.log(`\n${pc.green(pc.bold("Generated SDK linting complete!"))}\n`); + return; + } + + // Default: lint emitter + pygen source + const runBoth = !runEmitter && !runGenerator; + + let success = true; + + if (runEmitter || runBoth) { + const result = await lintEmitter(); + if (!result) success = false; + } + + if (runGenerator || runBoth) { + const result = await lintPygenSource(); + if (!result) success = false; + } + + if (!success) { + process.exit(1); + } + + console.log(`\n${pc.green(pc.bold("All linting checks passed!"))}\n`); +} + +main().catch((error) => { + console.error(`${pc.red("Unexpected error:")}`, error); + process.exit(1); +}); diff --git a/packages/http-client-python/eng/scripts/ci/regenerate-common.ts b/packages/http-client-python/eng/scripts/ci/regenerate-common.ts index 9f9a91266d6..101cfc7b293 100644 --- a/packages/http-client-python/eng/scripts/ci/regenerate-common.ts +++ b/packages/http-client-python/eng/scripts/ci/regenerate-common.ts @@ -282,6 +282,7 @@ export interface RegenerateFlagsInput { debug?: boolean; name?: string; pyodide?: boolean; + jobs?: number; } export interface RegenerateFlags { @@ -403,8 +404,9 @@ export function buildOptions( } if (options["emitter-output-dir"] === undefined) { const packageName = options["package-name"] || defaultPackageName(spec, config); + // Output to new tests/generated// structure options["emitter-output-dir"] = toPosix( - `${generatedFolder}/test/${flags.flavor}/generated/${packageName}`, + `${generatedFolder}/../tests/generated/${flags.flavor}/${packageName}`, ); } if (flags.debug) { @@ -423,21 +425,21 @@ export async function runTaskPool( tasks: Array<() => Promise>, poolLimit: number, ): Promise { - async function worker(start: number, end: number) { - while (start < end) { - await tasks[start](); - start++; + const executing: Set> = new Set(); + + for (const task of tasks) { + // Start the task and remove from set when done + const p: Promise = task().finally(() => executing.delete(p)); + executing.add(p); + + // If at capacity, wait for one to complete + if (executing.size >= poolLimit) { + await Promise.race(executing); } } - const workers = []; - let start = 0; - while (start < tasks.length) { - const end = Math.min(start + poolLimit, tasks.length); - workers.push((async () => await worker(start, end))()); - start = end; - } - await Promise.all(workers); + // Wait for remaining tasks + await Promise.all(executing); } export async function regenerate( @@ -467,6 +469,8 @@ export async function regenerate( }); // Run tasks with a concurrency limit - await runTaskPool(tasks, 30); + // Default: 30 jobs, or use provided value + const poolLimit = flags.jobs ?? 30; + await runTaskPool(tasks, poolLimit); } } diff --git a/packages/http-client-python/eng/scripts/ci/regenerate.ts b/packages/http-client-python/eng/scripts/ci/regenerate.ts index 84bc53727bd..3bb5d37ef15 100644 --- a/packages/http-client-python/eng/scripts/ci/regenerate.ts +++ b/packages/http-client-python/eng/scripts/ci/regenerate.ts @@ -1,41 +1,91 @@ /* eslint-disable no-console */ -import chalk from "chalk"; -import { execFile } from "child_process"; +/** + * Regenerates Python SDK code from TypeSpec definitions. + * + * Uses in-process TypeSpec compilation to avoid subprocess spawning overhead. + * This is significantly faster than spawning `tsp compile` for each spec. + */ + +import { compile, NodeHost } from "@typespec/compiler"; import { promises, rmSync } from "fs"; -import { join, resolve } from "path"; +import { platform } from "os"; +import { dirname, join, relative, resolve } from "path"; +import pc from "picocolors"; import { fileURLToPath } from "url"; -import { parseArgs, promisify } from "util"; +import { parseArgs } from "util"; import { BASE_AZURE_EMITTER_OPTIONS, BASE_EMITTER_OPTIONS, - buildOptions, - regenerate, + getSubdirectories, + SpecialFlags, toPosix, - type RegenerateConfig, type RegenerateFlags, - type RegenerateFlagsInput, - type TspCommand, } from "./regenerate-common.js"; -// PARSE INPUT ARGUMENTS - +// Parse arguments const argv = parseArgs({ args: process.argv.slice(2), options: { - flavor: { type: "string" }, - name: { type: "string" }, - debug: { type: "boolean" }, + flavor: { type: "string", short: "f" }, + name: { type: "string", short: "n" }, + debug: { type: "boolean", short: "d" }, pluginDir: { type: "string" }, emitterName: { type: "string" }, generatedFolder: { type: "string" }, - pyodide: { type: "boolean" }, + jobs: { type: "string", short: "j" }, + help: { type: "boolean", short: "h" }, }, }); -// Get the directory of the current file +if (argv.values.help) { + console.log(` +${pc.bold("Usage:")} tsx regenerate.ts [options] + +${pc.bold("Description:")} + Regenerates Python SDK code from TypeSpec definitions using in-process compilation. + This avoids spawning a new Node.js process for each spec, making it significantly faster. + +${pc.bold("Options:")} + ${pc.cyan("-f, --flavor ")} + SDK flavor to regenerate. If not specified, regenerates both flavors. + + ${pc.cyan("-n, --name ")} + Filter packages by name pattern (case-insensitive substring match). + Examples: + --name xml Regenerate packages containing "xml" + --name authentication Regenerate authentication packages + --name type/array Regenerate the type/array package + + ${pc.cyan("-d, --debug")} + Enable debug output during regeneration. + + ${pc.cyan("-j, --jobs ")} + Number of parallel compilation tasks (default: 30 on Linux/Mac, 10 on Windows). + + ${pc.cyan("-h, --help")} + Show this help message. + +${pc.bold("Examples:")} + ${pc.dim("# Regenerate all packages for both flavors")} + tsx regenerate.ts + + ${pc.dim("# Regenerate only Azure packages")} + tsx regenerate.ts --flavor azure + + ${pc.dim("# Regenerate a specific package by name")} + tsx regenerate.ts --flavor azure --name authentication-api-key + + ${pc.dim("# Regenerate with more parallelism")} + tsx regenerate.ts --jobs 50 +`); + process.exit(0); +} + +// Get paths +const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url)); const PLUGIN_DIR = argv.values.pluginDir ? resolve(argv.values.pluginDir) - : resolve(fileURLToPath(import.meta.url), "../../../../"); + : resolve(SCRIPT_DIR, "../../../"); const AZURE_HTTP_SPECS = resolve(PLUGIN_DIR, "node_modules/@azure-tools/azure-http-specs/specs"); const HTTP_SPECS = resolve(PLUGIN_DIR, "node_modules/@typespec/http-specs/specs"); const GENERATED_FOLDER = argv.values.generatedFolder @@ -43,6 +93,7 @@ const GENERATED_FOLDER = argv.values.generatedFolder : resolve(PLUGIN_DIR, "generator"); const EMITTER_NAME = argv.values.emitterName || "@typespec/http-client-python"; +// Emitter options const AZURE_EMITTER_OPTIONS: Record | Record[]> = { ...BASE_AZURE_EMITTER_OPTIONS, "client/structure/client-operation-group": { @@ -56,82 +107,268 @@ const EMITTER_OPTIONS: Record | Record { - const cmd = tspCommand.command as string[]; - const execFileAsync = promisify(execFile); +interface CompileTask { + spec: string; + outputDir: string; + options: Record; +} + +// Group of tasks for the same spec that must run sequentially +interface TaskGroup { + spec: string; + tasks: CompileTask[]; +} + +function defaultPackageName(spec: string): string { + const specDir = spec.includes("azure") ? AZURE_HTTP_SPECS : HTTP_SPECS; + return toPosix(relative(specDir, dirname(spec))) + .replace(/\//g, "-") + .toLowerCase(); +} + +function getEmitterOptions(spec: string, flavor: string): Record[] { + const specDir = spec.includes("azure") ? AZURE_HTTP_SPECS : HTTP_SPECS; + const relativeSpec = toPosix(relative(specDir, spec)); + const key = relativeSpec.includes("resiliency/srv-driven/old.tsp") + ? relativeSpec + : dirname(relativeSpec); + const emitterOpts = EMITTER_OPTIONS[key] || + (flavor === "azure" ? AZURE_EMITTER_OPTIONS[key] : [{}]) || [{}]; + return Array.isArray(emitterOpts) ? emitterOpts : [emitterOpts]; +} + +function buildTaskGroups(specs: string[], flags: RegenerateFlags): TaskGroup[] { + const groups: TaskGroup[] = []; + + for (const spec of specs) { + const tasks: CompileTask[] = []; + + for (const emitterConfig of getEmitterOptions(spec, flags.flavor)) { + const options: Record = { ...emitterConfig }; + + // Add flavor-specific options + options["flavor"] = flags.flavor; + for (const [k, v] of Object.entries(SpecialFlags[flags.flavor] ?? {})) { + options[k] = v; + } + + // Set output directory - use tests/generated// structure + const packageName = (options["package-name"] as string) || defaultPackageName(spec); + const outputDir = + (options["emitter-output-dir"] as string) || + toPosix(`${GENERATED_FOLDER}/../tests/generated/${flags.flavor}/${packageName}`); + options["emitter-output-dir"] = outputDir; + + // Debug mode + if (flags.debug) { + options["debug"] = true; + } + + // Examples directory + options["examples-dir"] = toPosix(join(dirname(spec), "examples")); + + tasks.push({ spec, outputDir, options }); + } + + groups.push({ spec, tasks }); + } + + return groups; +} + +async function compileSpec(task: CompileTask): Promise<{ success: boolean; error?: string }> { + const { spec, outputDir, options } = task; + try { - console.log(chalk.green(`start tsp ${cmd.join(" ")}`)); - await execFileAsync("tsp", cmd, { shell: true }); - console.log(chalk.green(`tsp ${cmd.join(" ")} succeeded`)); + // Build compiler options + const compilerOptions = { + emit: [PLUGIN_DIR], + options: { + [EMITTER_NAME]: options, + }, + }; + + // Compile using TypeSpec compiler directly (no subprocess) + const program = await compile(NodeHost, spec, compilerOptions); + + if (program.hasError()) { + const errors = program.diagnostics + .filter((d) => d.severity === "error") + .map((d) => d.message) + .join("\n"); + return { success: false, error: errors }; + } + + return { success: true }; } catch (err) { - rmSync(tspCommand.outputDir, { recursive: true, force: true }); - console.error(chalk.red(`exec error: ${err}`)); - throw err; + // Clean up on error + rmSync(outputDir, { recursive: true, force: true }); + return { success: false, error: String(err) }; + } +} + +async function runParallel(groups: TaskGroup[], maxJobs: number): Promise> { + const results = new Map(); + const executing: Set> = new Set(); + + // Count total tasks for progress + const totalTasks = groups.reduce((sum, g) => sum + g.tasks.length, 0); + let completed = 0; + + for (const group of groups) { + // Each group runs as a unit - tasks within a group run sequentially + // But different groups can run in parallel + const runGroup = async () => { + const specDir = group.spec.includes("azure") ? AZURE_HTTP_SPECS : HTTP_SPECS; + const shortName = toPosix(relative(specDir, dirname(group.spec))); + + // Run all tasks in this group sequentially to avoid state pollution + let groupSuccess = true; + for (const task of group.tasks) { + const packageName = (task.options["package-name"] as string) || shortName; + console.log(pc.blue(`[${completed + 1}/${totalTasks}] Compiling ${packageName}...`)); + + const result = await compileSpec(task); + completed++; + + if (result.success) { + console.log(pc.green(`[${completed}/${totalTasks}] ${packageName} succeeded`)); + } else { + console.log( + pc.red(`[${completed}/${totalTasks}] ${packageName} failed: ${result.error}`), + ); + groupSuccess = false; + } + } + + results.set(group.spec, groupSuccess); + }; + + const p = runGroup().finally(() => executing.delete(p)); + executing.add(p); + + if (executing.size >= maxJobs) { + await Promise.race(executing); + } } + + await Promise.all(executing); + return results; } -// create some files before regeneration. After regeneration, these files should be deleted and we will test it -// in test case -async function preprocess(flags: RegenerateFlagsInput): Promise { - if (flags.flavor === "azure") { - // create folder if not exists +// Preprocess: create files that should be deleted after regeneration (for testing) +async function preprocess(flavor: string): Promise { + if (flavor === "azure") { + // Use tests/generated// structure (same as output) + const testsGeneratedDir = resolve(GENERATED_FOLDER, "../tests/generated"); const folderParts = [ - "test", "azure", - "generated", "authentication-api-key", "authentication", "apikey", "_operations", ]; - await promises.mkdir(join(GENERATED_FOLDER, ...folderParts), { recursive: true }); + await promises.mkdir(join(testsGeneratedDir, ...folderParts), { recursive: true }); await promises.writeFile( - join(GENERATED_FOLDER, ...folderParts, "to_be_deleted.py"), + join(testsGeneratedDir, ...folderParts, "to_be_deleted.py"), "# This file is to be deleted after regeneration", ); } } -function _getCmdList(spec: string, flags: RegenerateFlags): TspCommand[] { - return buildOptions(spec, GENERATED_FOLDER, flags, config).map((po) => { - const optionArgs = Object.entries(po.options).flatMap(([k, v]) => [ - "--option", - `${EMITTER_NAME}.${k}="${v}"`, - ]); - return { - outputDir: po.outputDir, - command: ["compile", spec, "--emit", toPosix(PLUGIN_DIR), ...optionArgs], - }; - }); +async function regenerateFlavor( + flavor: string, + name: string | undefined, + debug: boolean, + jobs: number, +): Promise { + console.log(pc.cyan(`\n${"=".repeat(60)}`)); + console.log(pc.cyan(`Regenerating ${flavor} flavor`)); + console.log(pc.cyan(`${"=".repeat(60)}\n`)); + + const flags: RegenerateFlags = { flavor, debug, name }; + + // Preprocess + await preprocess(flavor); + + // Collect specs + const azureSpecs = flavor === "azure" ? await getSubdirectories(AZURE_HTTP_SPECS, flags) : []; + const standardSpecs = await getSubdirectories(HTTP_SPECS, flags); + const allSpecs = [...azureSpecs, ...standardSpecs]; + + // Build task groups (tasks for same spec run sequentially to avoid state pollution) + const groups = buildTaskGroups(allSpecs, flags); + const totalTasks = groups.reduce((sum, g) => sum + g.tasks.length, 0); + + console.log(pc.cyan(`Found ${allSpecs.length} specs (${totalTasks} total tasks) to compile`)); + console.log(pc.cyan(`Using ${jobs} parallel jobs\n`)); + + // Run compilation + const startTime = performance.now(); + const results = await runParallel(groups, jobs); + const duration = (performance.now() - startTime) / 1000; + + // Summary + const succeeded = Array.from(results.values()).filter((v) => v).length; + const failed = results.size - succeeded; + + console.log(pc.cyan(`\n${"=".repeat(60)}`)); + console.log(pc.cyan(`Results: ${succeeded} succeeded, ${failed} failed`)); + console.log(pc.cyan(`Time: ${duration.toFixed(1)}s`)); + console.log(pc.cyan(`${"=".repeat(60)}\n`)); + + return failed === 0; } -const config: RegenerateConfig = { - azureHttpSpecs: AZURE_HTTP_SPECS, - httpSpecs: HTTP_SPECS, - emitterOptions: EMITTER_OPTIONS, - azureEmitterOptions: AZURE_EMITTER_OPTIONS, - preprocess, - getCmdList: _getCmdList, - executeCommand, -}; +async function main() { + const isWindows = platform() === "win32"; + const flavor = argv.values.flavor; + const name = argv.values.name; + const debug = argv.values.debug ?? false; + // Windows has slower file system operations and process spawning, + // so use fewer parallel jobs to avoid I/O contention and memory pressure + const defaultJobs = isWindows ? 10 : 30; + const jobs = argv.values.jobs ? parseInt(argv.values.jobs, 10) : defaultJobs; -const start = performance.now(); -regenerate(argv.values, config) - .then(() => - console.log( - chalk.green( - `Regeneration successful, time taken: ${Math.round((performance.now() - start) / 1000)} s`, - ), - ), - ) - .catch((error) => console.error(chalk.red(`Regeneration failed: ${error.message}`))); + console.log(pc.cyan(`\nRegeneration config:`)); + console.log(pc.cyan(` Platform: ${isWindows ? "Windows" : "Unix"}`)); + console.log(pc.cyan(` Mode: in-process compilation`)); + console.log(pc.cyan(` Jobs: ${jobs}`)); + if (name) { + console.log(pc.cyan(` Filter: ${name}`)); + } + console.log(); + + const startTime = performance.now(); + let success: boolean; + + if (flavor) { + success = await regenerateFlavor(flavor, name, debug, jobs); + } else { + // Both flavors + const azureSuccess = await regenerateFlavor("azure", name, debug, jobs); + const unbrandedSuccess = await regenerateFlavor("unbranded", name, debug, jobs); + success = azureSuccess && unbrandedSuccess; + } + + const totalDuration = (performance.now() - startTime) / 1000; + console.log( + success + ? pc.green(`\nRegeneration completed successfully in ${totalDuration.toFixed(1)}s`) + : pc.red(`\nRegeneration failed after ${totalDuration.toFixed(1)}s`), + ); + + process.exit(success ? 0 : 1); +} + +main().catch((err) => { + console.error(pc.red(`Fatal error: ${err}`)); + process.exit(1); +}); diff --git a/packages/http-client-python/eng/scripts/ci/run-ci.ts b/packages/http-client-python/eng/scripts/ci/run-ci.ts deleted file mode 100644 index 11ae7456315..00000000000 --- a/packages/http-client-python/eng/scripts/ci/run-ci.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* eslint-disable no-console */ -import { execSync } from "child_process"; -import fs, { readFileSync } from "fs"; -import { platform } from "os"; -import { dirname, join } from "path"; -import { fileURLToPath } from "url"; -import { parseArgs } from "util"; - -const root = join(dirname(fileURLToPath(import.meta.url)), "../../../"); - -const argv = parseArgs({ - args: process.argv.slice(2), - options: { - validFolders: { type: "string", required: true, multiple: true }, - flavor: { type: "string" }, - command: { type: "string" }, - name: { type: "string" }, - testFolder: { type: "string" }, - }, -}); - -const foldersToProcess = argv.values.flavor - ? [argv.values.flavor] - : argv.values.validFolders || ["azure", "unbranded"]; - -const commandToRun = argv.values.command || "ci"; -const TEST_FOLDER = argv.values.testFolder || "generator/test"; - -function getCommand(command: string, flavor: string, name?: string): string { - let retval: string; - if (platform() === "win32") { - retval = `set FOLDER=${flavor} && ${venvPath} -m tox -c ./${TEST_FOLDER}/${flavor}/tox.ini -e ${command}`; - } else { - // Linux and macOS - retval = `FOLDER=${flavor} ${venvPath} -m tox -c ./${TEST_FOLDER}/${flavor}/tox.ini -e ${command}`; - } - if (name) { - return `${retval} -- -f ${name}`; - } - return retval; -} - -function sectionExistsInToxIni(command: string, flavor: string): boolean { - const toxIniPath = join(root, `${TEST_FOLDER}/${flavor}/tox.ini`); - const toxIniContent = readFileSync(toxIniPath, "utf-8"); - return command - .split(",") - .map((c) => `[testenv:${c}]`) - .every((section) => toxIniContent.includes(section)); -} - -function myExecSync(command: string, flavor: string, name?: string): void { - if (!sectionExistsInToxIni(command, flavor)) { - console.log(`No section for ${command} in tox.ini for flavor ${flavor}. Skipping...`); - return; - } - execSync(getCommand(command, flavor, name), { stdio: "inherit" }); - execSync(getCommand(command, "unittests", name), { stdio: "inherit" }); -} - -let venvPath = join(root, "venv"); -if (fs.existsSync(join(venvPath, "bin"))) { - venvPath = join(venvPath, "bin", "python"); -} else if (fs.existsSync(join(venvPath, "Scripts"))) { - venvPath = join(venvPath, "Scripts", "python.exe"); -} else { - throw new Error("Virtual environment doesn't exist."); -} - -foldersToProcess.forEach((flavor) => { - try { - if (getCommand(commandToRun, flavor, argv.values.name)) { - console.log(`Running ${commandToRun} for flavor ${flavor}...`); - myExecSync(commandToRun, flavor, argv.values.name); - } else { - console.error(`Error: Unknown command '${commandToRun}'.`); - process.exit(1); - } - } catch (error) { - const message = (error as Error).message; - if (message.includes("pyright") || message.includes("mypy") || message.includes("lint")) { - // fixing linting issues that come from upgrading python version in separate pr - process.exit(0); - } - console.error(message); - console.error(`Error executing command for flavor ${flavor}: ${message}`); - process.exit(1); - } -}); diff --git a/packages/http-client-python/eng/scripts/ci/run-tests.ts b/packages/http-client-python/eng/scripts/ci/run-tests.ts new file mode 100644 index 00000000000..2a1c9eeff24 --- /dev/null +++ b/packages/http-client-python/eng/scripts/ci/run-tests.ts @@ -0,0 +1,381 @@ +/* eslint-disable no-console */ +import { ChildProcess, spawn } from "child_process"; +import fs from "fs"; +import { cpus } from "os"; +import { dirname, join } from "path"; +import pc from "picocolors"; +import { fileURLToPath } from "url"; +import { parseArgs } from "util"; + +const root = join(dirname(fileURLToPath(import.meta.url)), "../../../"); +const monorepoRoot = join(root, "../../"); +const testsDir = join(root, "tests"); + +const argv = parseArgs({ + args: process.argv.slice(2), + options: { + emitter: { type: "boolean", short: "e" }, + generator: { type: "boolean", short: "g" }, + flavor: { type: "string", short: "f", default: "all" }, + env: { type: "string" }, + jobs: { type: "string", short: "j" }, + name: { type: "string", short: "n" }, + quiet: { type: "boolean", short: "q", default: false }, + help: { type: "boolean", short: "h", default: false }, + }, +}); + +if (argv.values.help) { + console.log(` +Usage: run-tests.ts [options] + +Options: + -e, --emitter Run TypeScript emitter tests (vitest) + -g, --generator Run Python generator tests (tox) + -f, --flavor SDK flavor to test (only applies to --generator) + If not specified, tests both flavors + --env Specific tox environments to run + Available: test, lint, mypy, pyright, docs, ci, unittest + -j, --jobs Number of parallel jobs (default: CPU cores - 2) + -n, --name Filter tests by name pattern + -q, --quiet Suppress test output (only show pass/fail summary) + -h, --help Show this help message + +Environments (for --generator): + test Run pytest tests for generated packages + lint Run pylint on generated packages + mypy Run mypy type checking on generated packages + pyright Run pyright type checking on generated packages + docs Run documentation validation (apiview, sphinx) + ci Run all checks (test + lint + mypy + pyright) + unittest Run unit tests for pygen internals + +Examples: + run-tests.ts # Run all tests (emitter + generator) + run-tests.ts --emitter # Run only emitter tests + run-tests.ts --generator # Run generator tests for all flavors + run-tests.ts --generator --flavor=azure # Run generator tests for azure only + run-tests.ts -g -f azure --env=test # Run pytest for azure only + run-tests.ts -g --env=mypy # Run mypy for all flavors + run-tests.ts -g -f unbranded --env=lint # Run pylint for unbranded only +`); + process.exit(0); +} + +// Get Python venv path +function getVenvPython(): string { + const venvPath = join(root, "venv"); + if (fs.existsSync(join(venvPath, "bin"))) { + return join(venvPath, "bin", "python"); + } else if (fs.existsSync(join(venvPath, "Scripts"))) { + return join(venvPath, "Scripts", "python.exe"); + } + throw new Error("Virtual environment not found. Run 'npm run install' first."); +} + +interface ToxResult { + env: string; + success: boolean; + duration: number; + error?: string; +} + +async function runToxEnv(env: string, pythonPath: string, name?: string): Promise { + const startTime = Date.now(); + const toxIniPath = join(testsDir, "tox.ini"); + + // Build command + const args = ["-m", "tox", "-c", toxIniPath, "-e", env]; + if (name) { + args.push("--", "-k", name); + } + + console.log(`${pc.blue("[START]")} ${env}`); + + return new Promise((resolve) => { + const proc: ChildProcess = spawn(pythonPath, args, { + cwd: testsDir, + stdio: !argv.values.quiet ? "inherit" : "pipe", + env: { ...process.env, FOLDER: env.split("-")[1] || "azure" }, + }); + + let stderr = ""; + if (argv.values.quiet && proc.stderr) { + proc.stderr.on("data", (data) => { + stderr += data.toString(); + }); + } + + proc.on("close", (code) => { + const duration = (Date.now() - startTime) / 1000; + const success = code === 0; + + if (success) { + console.log(`${pc.green("[PASS]")} ${env} (${duration.toFixed(1)}s)`); + } else { + console.log(`${pc.red("[FAIL]")} ${env} (${duration.toFixed(1)}s)`); + } + + resolve({ + env, + success, + duration, + error: success ? undefined : stderr || `Exit code: ${code}`, + }); + }); + + proc.on("error", (err) => { + const duration = (Date.now() - startTime) / 1000; + console.log(`${pc.red("[ERROR]")} ${env}: ${err.message}`); + resolve({ + env, + success: false, + duration, + error: err.message, + }); + }); + }); +} + +async function runParallel( + envs: string[], + pythonPath: string, + maxJobs: number, + name?: string, +): Promise { + const results: ToxResult[] = []; + const running: Map> = new Map(); + + for (const env of envs) { + // Wait if we're at max capacity + if (running.size >= maxJobs) { + const completed = await Promise.race(running.values()); + results.push(completed); + running.delete(completed.env); + } + + // Start new task + const task = runToxEnv(env, pythonPath, name); + running.set(env, task); + } + + // Wait for remaining tasks + const remaining = await Promise.all(running.values()); + results.push(...remaining); + + return results; +} + +async function _runSequential( + envs: string[], + pythonPath: string, + name?: string, +): Promise { + const results: ToxResult[] = []; + for (const env of envs) { + const result = await runToxEnv(env, pythonPath, name); + results.push(result); + } + return results; +} + +function printSummary(results: ToxResult[]): void { + console.log("\n" + pc.bold("═".repeat(60))); + console.log(pc.bold(" Test Results Summary")); + console.log(pc.bold("═".repeat(60)) + "\n"); + + const passed = results.filter((r) => r.success); + const failed = results.filter((r) => !r.success); + const totalDuration = results.reduce((sum, r) => sum + r.duration, 0); + + for (const result of results) { + const status = result.success ? pc.green("PASS") : pc.red("FAIL"); + console.log(` ${status} ${result.env} (${result.duration.toFixed(1)}s)`); + } + + console.log("\n" + "─".repeat(60)); + console.log( + ` ${pc.green(`Passed: ${passed.length}`)} ` + + `${pc.red(`Failed: ${failed.length}`)} ` + + `Total: ${results.length} ` + + `Duration: ${totalDuration.toFixed(1)}s`, + ); + console.log("─".repeat(60) + "\n"); + + if (failed.length > 0) { + console.log(pc.red("Failed environments:")); + for (const result of failed) { + console.log(` - ${result.env}`); + if (result.error && !argv.values.quiet) { + console.log(` ${result.error.split("\n").slice(0, 5).join("\n ")}`); + } + } + console.log(); + } +} + +async function runEmitterTests(): Promise { + const startTime = Date.now(); + console.log(`${pc.blue("[START]")} emitter (vitest)`); + + // Add node_modules/.bin directories to PATH so vitest can be found + const pathSep = process.platform === "win32" ? ";" : ":"; + const binPaths = [ + join(root, "node_modules", ".bin"), + join(monorepoRoot, "node_modules", ".bin"), + ].join(pathSep); + const env = { + ...process.env, + PATH: `${binPaths}${pathSep}${process.env.PATH}`, + }; + + return new Promise((resolve) => { + const proc: ChildProcess = spawn("vitest", ["run", "-c", "./emitter/vitest.config.ts"], { + cwd: root, + stdio: !argv.values.quiet ? "inherit" : "pipe", + shell: true, + env, + }); + + let stderr = ""; + if (argv.values.quiet && proc.stderr) { + proc.stderr.on("data", (data) => { + stderr += data.toString(); + }); + } + + proc.on("close", (code) => { + const duration = (Date.now() - startTime) / 1000; + const success = code === 0; + + if (success) { + console.log(`${pc.green("[PASS]")} emitter (vitest) (${duration.toFixed(1)}s)`); + } else { + console.log(`${pc.red("[FAIL]")} emitter (vitest) (${duration.toFixed(1)}s)`); + } + + resolve({ + env: "emitter (vitest)", + success, + duration, + error: success ? undefined : stderr || `Exit code: ${code}`, + }); + }); + + proc.on("error", (err) => { + const duration = (Date.now() - startTime) / 1000; + console.log(`${pc.red("[ERROR]")} emitter (vitest): ${err.message}`); + resolve({ + env: "emitter (vitest)", + success: false, + duration, + error: err.message, + }); + }); + }); +} + +async function main(): Promise { + const startTime = Date.now(); + + const runEmitter = argv.values.emitter; + const runGenerator = argv.values.generator; + const runBoth = !runEmitter && !runGenerator; + + const allResults: ToxResult[] = []; + + // Header + console.log(pc.cyan("\n╔══════════════════════════════════════════════════════════╗")); + console.log( + pc.cyan("║") + + pc.bold(" TypeSpec Python SDK Generator Tests ") + + pc.cyan("║"), + ); + console.log(pc.cyan("╚══════════════════════════════════════════════════════════╝") + "\n"); + + // Run emitter tests if requested + if (runEmitter || runBoth) { + console.log(`${pc.bold("=== Emitter Tests (TypeScript) ===")}\n`); + const emitterResult = await runEmitterTests(); + allResults.push(emitterResult); + } + + // Run generator tests if requested + if (runGenerator || runBoth) { + console.log(`\n${pc.bold("=== Generator Tests (Python) ===")}\n`); + + // Determine flavors + const flavors = argv.values.flavor === "all" ? ["azure", "unbranded"] : [argv.values.flavor!]; + + // Determine environments + let baseEnvs: string[]; + if (argv.values.env) { + baseEnvs = argv.values.env.split(",").map((e) => e.trim()); + } else { + // Default: run test environments + baseEnvs = ["test"]; + } + + // Build full environment list + const envs: string[] = []; + for (const env of baseEnvs) { + if (env === "unittest") { + envs.push("unittest"); + } else { + for (const flavor of flavors) { + envs.push(`${env}-${flavor}`); + } + } + } + + // Get Python path + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + process.exit(1); + } + + // Determine parallelism + // Test environments must run sequentially because they each start a mock server on port 3000 + const hasTestEnvs = envs.some((e) => e.startsWith("test-")); + const maxJobs = argv.values.jobs + ? parseInt(argv.values.jobs, 10) + : hasTestEnvs + ? 1 + : Math.max(2, cpus().length - 2); + + console.log(` Flavors: ${flavors.join(", ")}`); + console.log(` Environments: ${envs.join(", ")}`); + console.log( + ` Jobs: ${maxJobs}${hasTestEnvs && !argv.values.jobs ? " (sequential for test envs)" : ""}`, + ); + if (argv.values.name) { + console.log(` Filter: ${argv.values.name}`); + } + console.log(); + + // Run tests in parallel + const results = await runParallel(envs, pythonPath, maxJobs, argv.values.name); + + allResults.push(...results); + } + + // Print summary + printSummary(allResults); + + const totalDuration = (Date.now() - startTime) / 1000; + console.log(`Total execution time: ${totalDuration.toFixed(1)}s\n`); + + // Exit with appropriate code + const failed = allResults.filter((r) => !r.success); + if (failed.length > 0) { + process.exit(1); + } +} + +main().catch((error) => { + console.error(`${pc.red("Unexpected error:")}`, error); + process.exit(1); +}); diff --git a/packages/http-client-python/eng/scripts/ci/run_mypy.py b/packages/http-client-python/eng/scripts/ci/run_mypy.py index 72a4d477666..ce78ffb7db6 100644 --- a/packages/http-client-python/eng/scripts/ci/run_mypy.py +++ b/packages/http-client-python/eng/scripts/ci/run_mypy.py @@ -18,11 +18,12 @@ def get_config_file_location(): - mypy_ini_path = os.path.join(os.getcwd(), "../../eng/scripts/ci/mypy.ini") + # When running from tests/ directory via tox + mypy_ini_path = os.path.join(os.getcwd(), "../eng/scripts/ci/config/mypy.ini") if os.path.exists(mypy_ini_path): return mypy_ini_path - else: - return os.path.join(os.getcwd(), "../../../eng/scripts/ci/mypy.ini") + # Fallback for running from different directories + return os.path.join(os.path.dirname(__file__), "config/mypy.ini") def _single_dir_mypy(mod): diff --git a/packages/http-client-python/eng/scripts/ci/run_pylint.py b/packages/http-client-python/eng/scripts/ci/run_pylint.py index 370cf605129..bfe7296293f 100644 --- a/packages/http-client-python/eng/scripts/ci/run_pylint.py +++ b/packages/http-client-python/eng/scripts/ci/run_pylint.py @@ -18,11 +18,12 @@ def get_rfc_file_location(): - rfc_file_location = os.path.join(os.getcwd(), "../../../eng/scripts/ci/pylintrc") + # When running from tests/ directory via tox + rfc_file_location = os.path.join(os.getcwd(), "../eng/scripts/ci/config/pylintrc") if os.path.exists(rfc_file_location): return rfc_file_location - else: - return os.path.join(os.getcwd(), "../../../../eng/scripts/ci/pylintrc") + # Fallback for running from different directories + return os.path.join(os.path.dirname(__file__), "config/pylintrc") def _single_dir_pylint(mod): diff --git a/packages/http-client-python/eng/scripts/ci/run_pyright.py b/packages/http-client-python/eng/scripts/ci/run_pyright.py index c81e225b9cd..a86ccc2b3cd 100644 --- a/packages/http-client-python/eng/scripts/ci/run_pyright.py +++ b/packages/http-client-python/eng/scripts/ci/run_pyright.py @@ -19,11 +19,12 @@ def get_pyright_config_file_location(): - pyright_config = os.path.join(os.getcwd(), "../../eng/scripts/ci/pyrightconfig.json") + # When running from tests/ directory via tox + pyright_config = os.path.join(os.getcwd(), "../eng/scripts/ci/config/pyrightconfig.json") if os.path.exists(pyright_config): return pyright_config - else: - return os.path.join(os.getcwd(), "../../../eng/scripts/ci/pyrightconfig.json") + # Fallback for running from different directories + return os.path.join(os.path.dirname(__file__), "config/pyrightconfig.json") def _single_dir_pyright(mod): diff --git a/packages/http-client-python/eng/scripts/ci/typecheck.ts b/packages/http-client-python/eng/scripts/ci/typecheck.ts new file mode 100644 index 00000000000..ff794d418ec --- /dev/null +++ b/packages/http-client-python/eng/scripts/ci/typecheck.ts @@ -0,0 +1,225 @@ +/* eslint-disable no-console */ +import { spawn } from "child_process"; +import fs from "fs"; +import { dirname, join } from "path"; +import pc from "picocolors"; +import { fileURLToPath } from "url"; +import { parseArgs } from "util"; + +const root = join(dirname(fileURLToPath(import.meta.url)), "../../../"); +const testsDir = join(root, "tests"); + +// Get Python venv path +function getVenvPython(): string { + const venvPath = join(root, "venv"); + if (fs.existsSync(join(venvPath, "bin"))) { + return join(venvPath, "bin", "python"); + } else if (fs.existsSync(join(venvPath, "Scripts"))) { + return join(venvPath, "Scripts", "python.exe"); + } + throw new Error("Virtual environment not found. Run 'npm run install' first."); +} + +const argv = parseArgs({ + args: process.argv.slice(2), + options: { + generated: { type: "boolean" }, + flavor: { type: "string", short: "f" }, + mypy: { type: "boolean" }, + pyright: { type: "boolean" }, + help: { type: "boolean", short: "h" }, + }, +}); + +if (argv.values.help) { + console.log(` +${pc.bold("Usage:")} tsx typecheck.ts [options] + +${pc.bold("Description:")} + Run type checking (mypy + pyright) on Python code. + +${pc.bold("Options:")} + ${pc.cyan("--generated")} + Run type checking on generated SDK packages (via tox). + Use with --flavor to specify azure or unbranded. + + ${pc.cyan("-f, --flavor ")} + SDK flavor to check (only applies to --generated). + If not specified, checks both flavors. + + ${pc.cyan("--mypy")} + Run only mypy (skip pyright). + + ${pc.cyan("--pyright")} + Run only pyright (skip mypy). + + ${pc.cyan("-h, --help")} + Show this help message. + +${pc.bold("Examples:")} + ${pc.dim("# Type check pygen source (default - runs both mypy and pyright)")} + tsx typecheck.ts + + ${pc.dim("# Run only mypy on pygen source")} + tsx typecheck.ts --mypy + + ${pc.dim("# Run only pyright on pygen source")} + tsx typecheck.ts --pyright + + ${pc.dim("# Type check generated SDK packages")} + tsx typecheck.ts --generated + + ${pc.dim("# Type check generated SDK packages for azure only")} + tsx typecheck.ts --generated --flavor=azure +`); + process.exit(0); +} + +function runCommand(command: string, args: string[], cwd?: string): Promise { + return new Promise((resolve) => { + console.log(`${pc.cyan("[RUN]")} ${command} ${args.join(" ")}`); + const proc = spawn(command, args, { + cwd: cwd || root, + stdio: "inherit", + shell: true, + }); + + proc.on("close", (code) => { + if (code === 0) { + console.log(`${pc.green("[PASS]")} ${command} completed successfully`); + resolve(true); + } else { + console.log(`${pc.red("[FAIL]")} ${command} failed with code ${code}`); + resolve(false); + } + }); + + proc.on("error", (err) => { + console.log(`${pc.red("[ERROR]")} ${command}: ${err.message}`); + resolve(false); + }); + }); +} + +async function runMypyOnPygen(): Promise { + console.log(`\n${pc.bold("=== Running mypy on pygen ===")}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + return runCommand(pythonPath, [ + "-m", + "mypy", + "generator/pygen", + "--config-file=eng/scripts/ci/config/mypy.ini", + "--ignore-missing", + ]); +} + +async function runPyrightOnPygen(): Promise { + console.log(`\n${pc.bold("=== Running pyright on pygen ===")}\n`); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + return runCommand(pythonPath, [ + "-m", + "pyright", + "-p", + "eng/scripts/ci/config/pyrightconfig.json", + "generator/pygen", + ]); +} + +async function runTypecheckOnGenerated( + flavor?: string, + mypyOnly?: boolean, + pyrightOnly?: boolean, +): Promise { + const flavors = flavor ? [flavor] : ["azure", "unbranded"]; + console.log( + `\n${pc.bold(`=== Type Checking Generated SDK Packages (${flavors.join(", ")}) ===`)}\n`, + ); + + let pythonPath: string; + try { + pythonPath = getVenvPython(); + } catch (error) { + console.error(pc.red((error as Error).message)); + return false; + } + + let success = true; + + for (const f of flavors) { + if (!pyrightOnly) { + const mypyEnv = `mypy-${f}`; + const result = await runCommand( + pythonPath, + ["-m", "tox", "-c", "tox.ini", "-e", mypyEnv], + testsDir, + ); + if (!result) success = false; + } + + if (!mypyOnly) { + const pyrightEnv = `pyright-${f}`; + const result = await runCommand( + pythonPath, + ["-m", "tox", "-c", "tox.ini", "-e", pyrightEnv], + testsDir, + ); + if (!result) success = false; + } + } + + return success; +} + +async function main(): Promise { + const runGenerated = argv.values.generated; + const mypyOnly = argv.values.mypy && !argv.values.pyright; + const pyrightOnly = argv.values.pyright && !argv.values.mypy; + + // If --generated is specified, type check generated packages + if (runGenerated) { + const result = await runTypecheckOnGenerated(argv.values.flavor, mypyOnly, pyrightOnly); + if (!result) process.exit(1); + console.log(`\n${pc.green(pc.bold("Generated SDK type checking complete!"))}\n`); + return; + } + + // Default: type check pygen source + let success = true; + + if (!pyrightOnly) { + const mypyResult = await runMypyOnPygen(); + if (!mypyResult) success = false; + } + + if (!mypyOnly) { + const pyrightResult = await runPyrightOnPygen(); + if (!pyrightResult) success = false; + } + + if (!success) { + process.exit(1); + } + + console.log(`\n${pc.green(pc.bold("All type checks passed!"))}\n`); +} + +main().catch((error) => { + console.error(`${pc.red("Unexpected error:")}`, error); + process.exit(1); +}); diff --git a/packages/http-client-python/eng/scripts/ci/util.py b/packages/http-client-python/eng/scripts/ci/util.py index 6ebbe842d54..f15165f6937 100644 --- a/packages/http-client-python/eng/scripts/ci/util.py +++ b/packages/http-client-python/eng/scripts/ci/util.py @@ -12,7 +12,7 @@ logging.getLogger().setLevel(logging.INFO) -ROOT_FOLDER = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "..", "..", "generator")) +ROOT_FOLDER = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "..", "generator")) IGNORE_FOLDER = [] diff --git a/packages/http-client-python/eng/scripts/ci/utils.ts b/packages/http-client-python/eng/scripts/ci/utils.ts index 118b09c60da..32bbc4b0ca7 100644 --- a/packages/http-client-python/eng/scripts/ci/utils.ts +++ b/packages/http-client-python/eng/scripts/ci/utils.ts @@ -1,8 +1,8 @@ /* eslint-disable no-console */ -import chalk from "chalk"; import { execFile } from "child_process"; import { existsSync } from "fs"; import { dirname, join, resolve } from "path"; +import pc from "picocolors"; import process from "process"; import { fileURLToPath } from "url"; import { parseArgs, promisify } from "util"; @@ -21,11 +21,11 @@ export async function executeCommand(command: string, args: string[]) { const execFileAsync = promisify(execFile); try { await execFileAsync(command, args, { shell: true }); - console.log(chalk.green(`${command} passed`)); + console.log(pc.green(`${command} passed`)); } catch (err: any) { - console.error(chalk.red(`Error executing ${command}`)); - if (err.stdout) console.error(chalk.yellow("STDOUT:"), err.stdout); - if (err.stderr) console.error(chalk.yellow("STDERR:"), err.stderr); + console.error(pc.red(`Error executing ${command}`)); + if (err.stdout) console.error(pc.yellow("STDOUT:"), err.stdout); + if (err.stderr) console.error(pc.yellow("STDERR:"), err.stderr); process.exit(1); } } diff --git a/packages/http-client-python/eng/scripts/setup/build.ts b/packages/http-client-python/eng/scripts/setup/build.ts index c13770edeb8..71c258e68c6 100644 --- a/packages/http-client-python/eng/scripts/setup/build.ts +++ b/packages/http-client-python/eng/scripts/setup/build.ts @@ -4,7 +4,7 @@ import { runPython3 } from "./run-python3.js"; async function main() { await runPython3("./eng/scripts/setup/build_pygen_wheel.py"); // remove the venv_build_wheel directory - exec("rimraf ./venv_build_wheel", (error, stdout, stderr) => { + exec("rimraf ./venv_build_wheel", (error, stdout, _stderr) => { if (error) { console.error(`Error executing command: ${error.message}`); // eslint-disable-line no-console return; diff --git a/packages/http-client-python/eng/scripts/setup/build_pygen_wheel.py b/packages/http-client-python/eng/scripts/setup/build_pygen_wheel.py index ceb7ce4846d..74687b91167 100644 --- a/packages/http-client-python/eng/scripts/setup/build_pygen_wheel.py +++ b/packages/http-client-python/eng/scripts/setup/build_pygen_wheel.py @@ -25,6 +25,7 @@ from venvtools import python_run from package_manager import install_packages, create_venv_with_package_manager +# eng/scripts/setup/build_pygen_wheel.py -> need to go up 4 levels to get to package root _ROOT_DIR = Path(__file__).parent.parent.parent.parent diff --git a/packages/http-client-python/eng/scripts/setup/install.py b/packages/http-client-python/eng/scripts/setup/install.py index 4aa0a32f6c1..8a3532f1ab9 100644 --- a/packages/http-client-python/eng/scripts/setup/install.py +++ b/packages/http-client-python/eng/scripts/setup/install.py @@ -38,6 +38,7 @@ from pathlib import Path +# eng/scripts/setup/install.py -> need to go up 4 levels to get to package root _ROOT_DIR = Path(__file__).parent.parent.parent.parent diff --git a/packages/http-client-python/eng/scripts/setup/prepare.py b/packages/http-client-python/eng/scripts/setup/prepare.py index 358baa0d338..ff405d552df 100644 --- a/packages/http-client-python/eng/scripts/setup/prepare.py +++ b/packages/http-client-python/eng/scripts/setup/prepare.py @@ -15,6 +15,7 @@ from pathlib import Path from package_manager import create_venv_with_package_manager, install_packages +# eng/scripts/setup/prepare.py -> need to go up 4 levels to get to package root _ROOT_DIR = Path(__file__).parent.parent.parent.parent diff --git a/packages/http-client-python/eng/scripts/setup/prepare.ts b/packages/http-client-python/eng/scripts/setup/prepare.ts index 32d9157a243..d3cea514a62 100644 --- a/packages/http-client-python/eng/scripts/setup/prepare.ts +++ b/packages/http-client-python/eng/scripts/setup/prepare.ts @@ -3,7 +3,7 @@ import { runPython3 } from "./run-python3.js"; async function main() { try { await runPython3("./eng/scripts/setup/prepare.py"); - } catch (error) { + } catch { console.log("No Python found on your local environment. We will use Pyodide instead."); // eslint-disable-line no-console } } diff --git a/packages/http-client-python/eng/scripts/setup/run_tsp.py b/packages/http-client-python/eng/scripts/setup/run_tsp.py index 61f5a4e79b3..6d5d3247042 100644 --- a/packages/http-client-python/eng/scripts/setup/run_tsp.py +++ b/packages/http-client-python/eng/scripts/setup/run_tsp.py @@ -4,12 +4,12 @@ # license information. # -------------------------------------------------------------------------- import sys -import venv import logging from pathlib import Path from pygen import preprocess, codegen from pygen.utils import parse_args +# eng/scripts/setup/run_tsp.py -> need to go up 4 levels to get to package root _ROOT_DIR = Path(__file__).parent.parent.parent.parent _LOGGER = logging.getLogger(__name__) @@ -20,8 +20,8 @@ assert venv_preexists # Otherwise install was not done - env_builder = venv.EnvBuilder(with_pip=True) - venv_context = env_builder.ensure_directories(venv_path) + # Don't use EnvBuilder.ensure_directories() - it causes race conditions + # when multiple processes run in parallel. The venv already exists. if "--debug" in sys.argv or "--debug=true" in sys.argv: try: diff --git a/packages/http-client-python/eng/scripts/setup/system-requirements.ts b/packages/http-client-python/eng/scripts/setup/system-requirements.ts index 58e5c6b5f93..f47685db629 100644 --- a/packages/http-client-python/eng/scripts/setup/system-requirements.ts +++ b/packages/http-client-python/eng/scripts/setup/system-requirements.ts @@ -15,8 +15,12 @@ const execute = ( options.onCreate(cp); } - options.onStdOutData && cp.stdout.on("data", options.onStdOutData); - options.onStdErrData && cp.stderr.on("data", options.onStdErrData); + if (options.onStdOutData) { + cp.stdout.on("data", options.onStdOutData); + } + if (options.onStdErrData) { + cp.stderr.on("data", options.onStdErrData); + } let err = ""; let out = ""; @@ -33,7 +37,7 @@ const execute = ( cp.on("error", (err) => { reject(err); }); - cp.on("close", (code, signal) => + cp.on("close", (code, _signal) => resolve({ stdout: out, stderr: err, @@ -118,7 +122,7 @@ const tryPython = async ( `"${PRINT_PYTHON_VERSION_SCRIPT}"`, ]); return validateVersionRequirement(resolution, result.stdout.trim(), requirement); - } catch (e) { + } catch { return { error: true, ...resolution, diff --git a/packages/http-client-python/eng/scripts/setup/venvtools.py b/packages/http-client-python/eng/scripts/setup/venvtools.py index 74206ddc40b..c4afe0bcf84 100644 --- a/packages/http-client-python/eng/scripts/setup/venvtools.py +++ b/packages/http-client-python/eng/scripts/setup/venvtools.py @@ -9,6 +9,7 @@ from pathlib import Path +# eng/scripts/setup/venvtools.py -> need to go up 4 levels to get to package root _ROOT_DIR = Path(__file__).parent.parent.parent.parent diff --git a/packages/http-client-python/generator/test/azure/requirements.txt b/packages/http-client-python/generator/test/azure/requirements.txt deleted file mode 100644 index 68f042b32e7..00000000000 --- a/packages/http-client-python/generator/test/azure/requirements.txt +++ /dev/null @@ -1,125 +0,0 @@ --r ../dev_requirements.txt --e ../../ -azure-mgmt-core==1.6.0 - -# === common azure dependencies across repos === -# only for azure --e ./generated/azure-client-generator-core-access --e ./generated/azure-client-generator-core-api-version-header --e ./generated/azure-client-generator-core-api-version-path --e ./generated/azure-client-generator-core-api-version-query --e ./generated/azure-client-generator-core-client-initialization-default --e ./generated/azure-client-generator-core-client-initialization-individually --e ./generated/azure-client-generator-core-client-initialization-individuallyparent --e ./generated/azure-client-generator-core-deserialize-empty-string-as-null --e ./generated/azure-client-generator-core-flatten-property --e ./generated/azure-client-generator-core-hierarchy-building --e ./generated/azure-client-generator-core-usage --e ./generated/azure-client-generator-core-override --e ./generated/azure-client-generator-core-client-location-move-method-parameter-to-client --e ./generated/azure-client-generator-core-client-location-move-to-existing-sub-client --e ./generated/azure-client-generator-core-client-location-move-to-new-sub-client --e ./generated/azure-client-generator-core-client-location-move-to-root-client --e ./generated/azure-client-generator-core-client-default-value --e ./generated/azure-client-generator-core-alternate-type --e ./generated/azure-client-generator-core-next-link-verb --e ./generated/azure-core-basic --e ./generated/azure-core-scalar --e ./generated/azure-core-lro-rpc --e ./generated/azure-core-lro-standard --e ./generated/azure-core-model --e ./generated/azure-core-traits --e ./generated/azure-core-page --e ./generated/azure-encode-duration --e ./generated/azure-special-headers-client-request-id/ --e ./generated/azure-example-basic --e ./generated/azure-resource-manager-common-properties --e ./generated/azure-resource-manager-large-header --e ./generated/azure-resource-manager-non-resource --e ./generated/azure-resource-manager-operation-templates --e ./generated/azure-resource-manager-resources --e ./generated/azure-resource-manager-method-subscription-id --e ./generated/azure-resource-manager-multi-service --e ./generated/azure-resource-manager-multi-service-shared-models --e ./generated/azure-versioning-previewversion --e ./generated/client-namespace --e ./generated/azure-payload-pageable --e ./generated/client-naming --e ./generated/client-naming-enum-conflict --e ./generated/client-overload --e ./generated/client-structure-default --e ./generated/client-structure-clientoperationgroup --e ./generated/client-structure-multiclient --e ./generated/client-structure-renamedoperation --e ./generated/client-structure-twooperationgroup --e ./generated/resiliency-srv-driven1 --e ./generated/resiliency-srv-driven2 --e ./generated/service-multi-service -# === end common azure dependencies across repos === - -# === common test dependencies across repos === --e ./generated/authentication-api-key --e ./generated/authentication-http-custom --e ./generated/authentication-noauth-union --e ./generated/authentication-oauth2 --e ./generated/authentication-union --e ./generated/setuppy-authentication-union --e ./generated/specs-documentation --e ./generated/encode-duration --e ./generated/encode-numeric --e ./generated/encode-array --e ./generated/parameters-basic --e ./generated/parameters-collection-format --e ./generated/parameters-path --e ./generated/parameters-query --e ./generated/parameters-spread --e ./generated/serialization-encoded-name-json --e ./generated/server-endpoint-not-defined --e ./generated/server-path-multiple --e ./generated/server-path-single --e ./generated/server-versions-versioned --e ./generated/server-versions-not-versioned --e ./generated/special-words --e ./generated/streaming-jsonl --e ./generated/typetest-array --e ./generated/typetest-dictionary --e ./generated/typetest-enum-extensible --e ./generated/typetest-enum-fixed -# -e ./generated/typetest-file --e ./generated/typetest-model-enumdiscriminator --e ./generated/typetest-model-nesteddiscriminator --e ./generated/typetest-model-notdiscriminated --e ./generated/typetest-model-singlediscriminator --e ./generated/typetest-model-recursive --e ./generated/typetest-model-usage --e ./generated/typetest-model-visibility --e ./generated/typetest-property-nullable --e ./generated/typetest-property-optional --e ./generated/typetest-property-valuetypes --e ./generated/typetest-property-additionalproperties --e ./generated/typetest-scalar --e ./generated/typetest-union --e ./generated/typetest-discriminatedunion --e ./generated/typetest-model-empty --e ./generated/headasbooleantrue --e ./generated/headasbooleanfalse --e ./generated/parameters-body-optionality --e ./generated/special-headers-repeatability --e ./generated/special-headers-conditional-request --e ./generated/encode-datetime --e ./generated/encode-bytes --e ./generated/payload-content-negotiation --e ./generated/payload-json-merge-patch --e ./generated/payload-pageable --e ./generated/payload-multipart --e ./generated/payload-media-type --e ./generated/payload-xml --e ./generated/routes --e ./generated/response-status-code-range --e ./generated/versioning-added --e ./generated/versioning-madeoptional --e ./generated/versioning-removed --e ./generated/versioning-renamedfrom --e ./generated/versioning-returntypechangedfrom --e ./generated/versioning-typechangedfrom -# === end common test dependencies across repos === diff --git a/packages/http-client-python/generator/test/azure/tox.ini b/packages/http-client-python/generator/test/azure/tox.ini deleted file mode 100644 index b0fa92a1098..00000000000 --- a/packages/http-client-python/generator/test/azure/tox.ini +++ /dev/null @@ -1,64 +0,0 @@ -[tox] -envlist=base, lint, mypy, pyright, apiview, sphinx -skipsdist=True - -[testenv:ci] -deps= - -r requirements.txt -commands = - # pytest - {[testenv:test]commands} - - # pylint - {[testenv:lint]commands} - - # mypy - {[testenv:mypy]commands} - - # pyright - {[testenv:pyright]commands} - - # apiview - {[testenv:apiview]commands} - - # sphinx docstring validation - {[testenv:sphinx]commands} - -[testenv:test] -deps= - -r requirements.txt -commands = - pytest mock_api_tests ../generic_mock_api_tests - -[testenv:lint] -deps= - -r requirements.txt -commands = - pip install azure-pylint-guidelines-checker==0.5.2 --index-url="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/" - python ../../../eng/scripts/ci/run_pylint.py -t azure -s "generated" {posargs} - -[testenv:mypy] -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_mypy.py -t azure -s "generated" {posargs} - -[testenv:pyright] -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_pyright.py -t azure -s "generated" {posargs} - -[testenv:apiview] -deps= - -r requirements.txt -commands = - pip install apiview-stub-generator==0.3.19 --index-url="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/" - python ../../../eng/scripts/ci/run_apiview.py -t azure -s "generated" {posargs} - -[testenv:sphinx] -basepython = python3.10 -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_sphinx_build.py -t azure -s "generated" {posargs} diff --git a/packages/http-client-python/generator/test/dev_requirements.txt b/packages/http-client-python/generator/test/dev_requirements.txt deleted file mode 100644 index 975f7d6a79b..00000000000 --- a/packages/http-client-python/generator/test/dev_requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ --r ../../eng/scripts/ci/dev_requirements.txt -aiohttp -pytest-asyncio==0.14.0 -sphinx==8.2.0 -sphinx_rtd_theme==3.0.2 -myst_parser==4.0.1 -sphinxcontrib-jquery==4.1 diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/data/image.png b/packages/http-client-python/generator/test/unbranded/mock_api_tests/data/image.png deleted file mode 100644 index 42fe8dc1456..00000000000 Binary files a/packages/http-client-python/generator/test/unbranded/mock_api_tests/data/image.png and /dev/null differ diff --git a/packages/http-client-python/generator/test/unbranded/requirements.txt b/packages/http-client-python/generator/test/unbranded/requirements.txt deleted file mode 100644 index 9fd6dd58cbc..00000000000 --- a/packages/http-client-python/generator/test/unbranded/requirements.txt +++ /dev/null @@ -1,69 +0,0 @@ --r ../dev_requirements.txt --e ../../ - -# === common test dependencies across repos === --e ./generated/authentication-api-key --e ./generated/authentication-http-custom --e ./generated/authentication-noauth-union --e ./generated/authentication-oauth2 --e ./generated/authentication-union --e ./generated/setuppy-authentication-union --e ./generated/specs-documentation --e ./generated/encode-duration --e ./generated/encode-numeric --e ./generated/encode-array --e ./generated/parameters-basic --e ./generated/parameters-collection-format --e ./generated/parameters-path --e ./generated/parameters-query --e ./generated/parameters-spread --e ./generated/serialization-encoded-name-json --e ./generated/server-endpoint-not-defined --e ./generated/server-path-multiple --e ./generated/server-path-single --e ./generated/server-versions-versioned --e ./generated/server-versions-not-versioned --e ./generated/special-words --e ./generated/streaming-jsonl --e ./generated/typetest-array --e ./generated/typetest-dictionary --e ./generated/typetest-enum-extensible --e ./generated/typetest-enum-fixed -# -e ./generated/typetest-file --e ./generated/typetest-model-enumdiscriminator --e ./generated/typetest-model-nesteddiscriminator --e ./generated/typetest-model-notdiscriminated --e ./generated/typetest-model-singlediscriminator --e ./generated/typetest-model-recursive --e ./generated/typetest-model-usage --e ./generated/typetest-model-visibility --e ./generated/typetest-property-nullable --e ./generated/typetest-property-optional --e ./generated/typetest-property-valuetypes --e ./generated/typetest-property-additionalproperties --e ./generated/typetest-scalar --e ./generated/typetest-union --e ./generated/typetest-discriminatedunion --e ./generated/typetest-model-empty --e ./generated/headasbooleantrue --e ./generated/headasbooleanfalse --e ./generated/parameters-body-optionality --e ./generated/special-headers-repeatability --e ./generated/special-headers-conditional-request --e ./generated/encode-datetime --e ./generated/encode-bytes --e ./generated/payload-content-negotiation --e ./generated/payload-json-merge-patch --e ./generated/payload-pageable --e ./generated/payload-multipart --e ./generated/payload-media-type --e ./generated/payload-xml --e ./generated/routes --e ./generated/response-status-code-range --e ./generated/versioning-added --e ./generated/versioning-madeoptional --e ./generated/versioning-removed --e ./generated/versioning-renamedfrom --e ./generated/versioning-returntypechangedfrom --e ./generated/versioning-typechangedfrom -# === end common test dependencies across repos === diff --git a/packages/http-client-python/generator/test/unbranded/tox.ini b/packages/http-client-python/generator/test/unbranded/tox.ini deleted file mode 100644 index ae2c163746c..00000000000 --- a/packages/http-client-python/generator/test/unbranded/tox.ini +++ /dev/null @@ -1,64 +0,0 @@ -[tox] -envlist=base, lint, mypy, pyright, apiview, sphinx -skipsdist=True - -[testenv:ci] -deps= - -r requirements.txt -commands = - # pytest - {[testenv:test]commands} - - # pylint - {[testenv:lint]commands} - - # mypy - {[testenv:mypy]commands} - - # pyright - {[testenv:pyright]commands} - - # apiview - {[testenv:apiview]commands} - - # sphinx docstring validation - {[testenv:sphinx]commands} - -[testenv:test] -deps= - -r requirements.txt -commands = - pytest mock_api_tests ../generic_mock_api_tests - -[testenv:lint] -deps= - -r requirements.txt -commands = - pip install azure-pylint-guidelines-checker==0.5.2 --index-url="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/" - python ../../../eng/scripts/ci/run_pylint.py -t unbranded -s "generated" {posargs} - -[testenv:mypy] -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_mypy.py -t unbranded -s "generated" {posargs} - -[testenv:pyright] -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_pyright.py -t unbranded -s "generated" {posargs} - -[testenv:apiview] -deps= - -r requirements.txt -commands = - pip install apiview-stub-generator==0.3.19 --index-url="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/" - python ../../../eng/scripts/ci/run_apiview.py -t unbranded -s "generated" {posargs} - -[testenv:sphinx] -basepython = python3.10 -deps= - -r requirements.txt -commands = - python ../../../eng/scripts/ci/run_sphinx_build.py -t unbranded -s "generated" {posargs} diff --git a/packages/http-client-python/package-lock.json b/packages/http-client-python/package-lock.json index a07b25f8655..7fe11b9bcc7 100644 --- a/packages/http-client-python/package-lock.json +++ b/packages/http-client-python/package-lock.json @@ -39,7 +39,7 @@ "@typespec/versioning": "~0.80.0", "@typespec/xml": "~0.80.0", "c8": "^10.1.3", - "chalk": "5.3.0", + "picocolors": "~1.1.1", "rimraf": "~6.1.2", "typescript": "~5.9.2", "typescript-eslint": "^8.49.0", @@ -3280,18 +3280,6 @@ "node": ">=18" } }, - "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/change-case": { "version": "5.4.4", "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", diff --git a/packages/http-client-python/package.json b/packages/http-client-python/package.json index 75f709d16dc..811e976e1ac 100644 --- a/packages/http-client-python/package.json +++ b/packages/http-client-python/package.json @@ -29,19 +29,25 @@ "node": ">=20.0.0" }, "scripts": { - "clean": "rimraf ./dist ./temp ./emitter/temp ./generator/test/azure/generated ./generator/test/unbranded/generated ./venv", + "clean": "rimraf ./dist ./temp ./venv ./tests/generated", "build": "tsc -p ./emitter/tsconfig.build.json && tsx ./eng/scripts/setup/build.ts", "watch": "tsc -p ./emitter/tsconfig.build.json --watch", - "lint": "eslint emitter/ --max-warnings=0", - "lint:py": "tsx ./eng/scripts/ci/lint.ts --folderName generator/pygen", - "format": "pnpm -w format:dir packages/http-client-python && tsx ./eng/scripts/ci/format.ts", "install": "tsx ./eng/scripts/setup/install.ts", "prepare": "tsx ./eng/scripts/setup/prepare.ts", + "setup": "npm run build && npm run install", + "test": "tsx ./eng/scripts/ci/run-tests.ts", + "test:emitter": "tsx ./eng/scripts/ci/run-tests.ts --emitter", + "test:generator": "tsx ./eng/scripts/ci/run-tests.ts --generator", + "lint": "tsx ./eng/scripts/ci/lint.ts", + "lint:generated": "tsx ./eng/scripts/ci/lint.ts --generated", + "format": "tsx ./eng/scripts/ci/format.ts", + "format:check": "tsx ./eng/scripts/ci/format.ts --check", + "format:generated": "tsx ./eng/scripts/ci/format.ts --generated", + "typecheck": "tsx ./eng/scripts/ci/typecheck.ts", + "typecheck:generated": "tsx ./eng/scripts/ci/typecheck.ts --generated", "regenerate": "tsx ./eng/scripts/ci/regenerate.ts", - "ci": "npm run test:emitter && npm run ci:generator --", - "ci:generator": "tsx ./eng/scripts/ci/run-ci.ts", - "test:generator": "tsx ./eng/scripts/ci/run-ci.ts --command=test", - "test:emitter": "vitest run -c ./emitter/vitest.config.ts", + "ci": "npm run test && npm run lint && npm run typecheck", + "ci:generated": "tsx ./eng/scripts/ci/run-tests.ts --generator --env=ci", "change:version": "pnpm chronus version --ignore-policies --only @typespec/http-client-python", "change:add": "pnpm chronus add", "regen-docs": "node ../../packages/tspd/cmd/tspd.js doc . --enable-experimental --output-dir ../../website/src/content/docs/docs/emitters/clients/http-client-python/reference --skip-js" @@ -99,7 +105,7 @@ "@types/node": "~25.0.2", "@types/semver": "7.5.8", "c8": "^10.1.3", - "chalk": "5.3.0", + "picocolors": "~1.1.1", "rimraf": "~6.1.2", "typescript": "~5.9.2", "typescript-eslint": "^8.49.0", diff --git a/packages/http-client-python/tests/conftest.py b/packages/http-client-python/tests/conftest.py new file mode 100644 index 00000000000..1ff58143412 --- /dev/null +++ b/packages/http-client-python/tests/conftest.py @@ -0,0 +1,172 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- +import os +import subprocess +import signal +import time +import urllib.request +import urllib.error +import pytest +import importlib +from pathlib import Path + +# Root of the http-client-python package +ROOT = Path(__file__).parent.parent +DATA_FOLDER = Path(__file__).parent / "mock_api" / "shared" + +# Server configuration +SERVER_HOST = "localhost" +SERVER_PORT = 3000 +SERVER_URL = f"http://{SERVER_HOST}:{SERVER_PORT}" + +# Global server process reference (used by hooks) +_server_process = None + + +def wait_for_server(url: str, timeout: int = 60, interval: float = 0.5) -> bool: + """Wait for the server to be ready by polling the URL.""" + start_time = time.time() + while time.time() - start_time < timeout: + try: + urllib.request.urlopen(url, timeout=1) + return True + except urllib.error.HTTPError: + # Server is up but returned an error (e.g., 404) - that's fine + return True + except (urllib.error.URLError, OSError): + # Server not reachable yet + time.sleep(interval) + return False + + +def start_server_process(): + """Start the tsp-spector mock API server.""" + azure_http_path = ROOT / "node_modules/@azure-tools/azure-http-specs" + http_path = ROOT / "node_modules/@typespec/http-specs" + + # Determine flavor from environment or current directory + flavor = os.environ.get("FLAVOR", "azure") + + # Use absolute paths with forward slashes (works on all platforms including Windows) + if flavor == "unbranded": + cwd = http_path.resolve() + specs_path = str(cwd / "specs").replace("\\", "/") + cmd = f"npx tsp-spector serve {specs_path}" + else: + cwd = azure_http_path.resolve() + azure_specs = str(cwd / "specs").replace("\\", "/") + http_specs = str((http_path / "specs").resolve()).replace("\\", "/") + cmd = f"npx tsp-spector serve {azure_specs} {http_specs}" + + if os.name == "nt": + return subprocess.Popen(cmd, shell=True, cwd=str(cwd)) + return subprocess.Popen(cmd, shell=True, preexec_fn=os.setsid, cwd=str(cwd)) + + +def terminate_server_process(process): + """Terminate the mock API server process.""" + if process is None: + return + if os.name == "nt": + process.kill() + else: + try: + os.killpg(os.getpgid(process.pid), signal.SIGTERM) + except ProcessLookupError: + pass # Process already terminated + + +def pytest_configure(config): + """Start the mock server before any tests run. + + This hook runs in the controller process before workers are spawned, + ensuring the server is ready for all workers. + """ + global _server_process + + # Only start server in the controller process (not in workers) + if hasattr(config, "workerinput"): + return + + # Check if server is already running (e.g., from a previous run) + if wait_for_server(SERVER_URL, timeout=1, interval=0.1): + print(f"Mock API server already running at {SERVER_URL}") + return + + # Start the server + print(f"Starting mock API server...") + _server_process = start_server_process() + + # Check if process started successfully + if _server_process.poll() is not None: + pytest.exit(f"Mock API server process exited immediately with code {_server_process.returncode}") + + # Wait for server to be ready + if not wait_for_server(SERVER_URL, timeout=60): + # Check if process is still running + if _server_process.poll() is not None: + pytest.exit(f"Mock API server process died with code {_server_process.returncode}") + terminate_server_process(_server_process) + _server_process = None + pytest.exit(f"Mock API server failed to start within 60 seconds at {SERVER_URL}") + + print(f"Mock API server ready at {SERVER_URL}") + + +def pytest_unconfigure(config): + """Stop the mock server after all tests complete.""" + global _server_process + + # Only stop server in the controller process + if hasattr(config, "workerinput"): + return + + terminate_server_process(_server_process) + _server_process = None + + +@pytest.fixture(scope="session", autouse=True) +def testserver(request): + """Ensure the mock server is ready before tests run. + + The server is started in pytest_configure (controller process). + This fixture just verifies the server is accessible from workers. + """ + if not wait_for_server(SERVER_URL, timeout=30): + pytest.fail(f"Mock API server not available at {SERVER_URL}") + yield + + +@pytest.fixture +def core_library(): + """Import the appropriate core library (azure.core or corehttp).""" + try: + return importlib.import_module("azure.core") + except ModuleNotFoundError: + return importlib.import_module("corehttp") + + +@pytest.fixture +def key_credential(core_library): + """Get the appropriate credential class.""" + try: + return core_library.credentials.AzureKeyCredential + except AttributeError: + return core_library.credentials.ServiceKeyCredential + + +@pytest.fixture +def png_data() -> bytes: + """Load PNG test data.""" + with open(str(DATA_FOLDER / "data/image.png"), "rb") as file_in: + return file_in.read() + + +@pytest.fixture +def jpg_data() -> bytes: + """Load JPG test data.""" + with open(str(DATA_FOLDER / "data/image.jpg"), "rb") as file_in: + return file_in.read() diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/data/image.jpg b/packages/http-client-python/tests/data/image.jpg similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/data/image.jpg rename to packages/http-client-python/tests/data/image.jpg diff --git a/packages/http-client-python/tests/install_packages.py b/packages/http-client-python/tests/install_packages.py new file mode 100644 index 00000000000..f706ae93732 --- /dev/null +++ b/packages/http-client-python/tests/install_packages.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +"""Install generated packages for testing. + +This script handles cross-platform path issues that can occur with inline +tox commands on Windows. +""" + +import glob +import os +import subprocess +import sys + + +def install_packages(flavor: str, tests_dir: str) -> None: + """Install generated packages for the given flavor.""" + generated_dir = os.path.join(tests_dir, "generated", flavor) + + if not os.path.exists(generated_dir): + print(f"Warning: Generated directory does not exist: {generated_dir}") + return + + # Find all package directories + packages = glob.glob(os.path.join(generated_dir, "*")) + packages = [p for p in packages if os.path.isdir(p)] + + if not packages: + print(f"Warning: No packages found in {generated_dir}") + return + + print(f"Installing {len(packages)} packages from {generated_dir}") + + # Install packages using uv pip + # Use --no-deps to avoid dependency resolution overhead + cmd = ["uv", "pip", "install", "--no-deps"] + packages + + try: + subprocess.run(cmd, check=True) + print(f"Successfully installed {len(packages)} packages") + except subprocess.CalledProcessError as e: + print(f"Error installing packages: {e}") + sys.exit(1) + except FileNotFoundError: + # uv not found, try pip + print("uv not found, falling back to pip") + cmd = [sys.executable, "-m", "pip", "install", "--no-deps"] + packages + subprocess.run(cmd, check=True) + + +def main(): + if len(sys.argv) < 2: + print("Usage: install_packages.py [tests_dir]") + print(" flavor: azure or unbranded") + print(" tests_dir: optional, defaults to script directory") + sys.exit(1) + + flavor = sys.argv[1] + tests_dir = sys.argv[2] if len(sys.argv) > 2 else os.path.dirname(os.path.abspath(__file__)) + + if flavor not in ("azure", "unbranded"): + print(f"Error: Invalid flavor '{flavor}'. Must be 'azure' or 'unbranded'") + sys.exit(1) + + install_packages(flavor, tests_dir) + + +if __name__ == "__main__": + main() diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_commonproperties_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_commonproperties_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_commonproperties_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_commonproperties_async.py index f5a62b6a868..15b8038fefd 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_commonproperties_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_commonproperties_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.commonproperties.aio import CommonPropertiesClient from azure.resourcemanager.commonproperties import models from azure.core import exceptions @@ -12,7 +13,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with CommonPropertiesClient( credential, SUBSCRIPTION_ID, "http://localhost:3000", authentication_policy=authentication_policy diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_largeheader_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_largeheader_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_largeheader_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_largeheader_async.py index deac2360dbc..e696553a2f9 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_largeheader_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_largeheader_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.largeheader.aio import LargeHeaderClient from azure.resourcemanager.largeheader import models @@ -11,7 +12,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with LargeHeaderClient( credential, SUBSCRIPTION_ID, "http://localhost:3000", authentication_policy=authentication_policy diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_nonresource_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_nonresource_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_nonresource_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_nonresource_async.py index 7cbbc763f33..926dcb129a3 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_nonresource_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_nonresource_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.nonresource.aio import NonResourceClient from azure.resourcemanager.nonresource import models @@ -11,7 +12,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with NonResourceClient( credential, SUBSCRIPTION_ID, "http://localhost:3000", authentication_policy=authentication_policy diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_operationtemplates_async.py similarity index 99% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_operationtemplates_async.py index 2c1bc0fc4b6..d28064a1bcc 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_operationtemplates_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_operationtemplates_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.operationtemplates.aio import OperationTemplatesClient from azure.resourcemanager.operationtemplates import models @@ -11,7 +12,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with OperationTemplatesClient( credential, diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_resource_async.py similarity index 99% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_resource_async.py index 8da75bfe249..eb20ed43ee8 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_arm_resource_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_arm_resource_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.resources.aio import ResourcesClient from azure.resourcemanager.resources import models @@ -11,7 +12,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with ResourcesClient( credential, diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_access_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_access_async.py index d1b6728a30e..2091b743371 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_access_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_access_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.access.aio import AccessClient from specs.azure.clientgenerator.core.access import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with AccessClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_header_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_header_async.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_header_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_header_async.py index 7fd89f76d61..7baa44a7471 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_header_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_header_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.alternateapiversion.service.header.aio import HeaderClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with HeaderClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_path_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_path_async.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_path_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_path_async.py index 3b6c99c116f..885f6f6007e 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_path_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_path_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.alternateapiversion.service.path.aio import PathClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with PathClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_query_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_query_async.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_query_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_query_async.py index 3163f9a7c31..62f2f9847c4 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_api_version_query_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_api_version_query_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.alternateapiversion.service.query.aio import QueryClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with QueryClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_default_value_async.py similarity index 97% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_default_value_async.py index 1d7795bbfc5..f4bbaaae048 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_default_value_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_default_value_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.clientdefaultvalue.aio import ClientDefaultValueClient from specs.azure.clientgenerator.core.clientdefaultvalue.models import ModelWithDefaultValues -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ClientDefaultValueClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_initialization_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_initialization_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_initialization_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_location_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_location_async.py index a039f18932e..d320f31ffbe 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_client_location_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_client_location_async.py @@ -4,31 +4,32 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.clientlocation.parameter.aio import MoveMethodParameterToClient from specs.azure.clientgenerator.core.clientlocation.subclient.aio import MoveToExistingSubClient from specs.azure.clientgenerator.core.clientlocation.newsubclient.aio import MoveToNewSubClient from specs.azure.clientgenerator.core.clientlocation.rootclient.aio import MoveToRootClient -@pytest.fixture +@pytest_asyncio.fixture async def move_method_parameter_to_client(): async with MoveMethodParameterToClient(storage_account="testaccount") as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def move_to_existing_sub_client(): async with MoveToExistingSubClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def move_to_new_sub_client(): async with MoveToNewSubClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def move_to_root_client(): async with MoveToRootClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py similarity index 94% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py index fbb4349f5a2..e926baf8da1 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_deserialize_empty_string_as_null_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.emptystring.aio import DeserializeEmptyStringAsNullClient from specs.azure.clientgenerator.core.emptystring import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DeserializeEmptyStringAsNullClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_flatten_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_flatten_async.py index cb044b430fe..6ebe71ad861 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_flatten_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.flattenproperty.aio import FlattenPropertyClient from specs.azure.clientgenerator.core.flattenproperty.models import ( ChildFlattenModel, @@ -16,7 +17,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with FlattenPropertyClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py similarity index 97% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py index b940b639fe1..9cf9749e50d 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_hierrarchy_building_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.hierarchybuilding.aio import HierarchyBuildingClient from specs.azure.clientgenerator.core.hierarchybuilding.models import ( Pet, @@ -11,7 +12,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with HierarchyBuildingClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_next_link_verb_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_next_link_verb_async.py similarity index 95% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_next_link_verb_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_next_link_verb_async.py index 7ce1de3c50d..c9061a3f8a3 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_next_link_verb_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_next_link_verb_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.nextlinkverb.aio import NextLinkVerbClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NextLinkVerbClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_override_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_override_async.py index 8fa5849b469..aeae909856a 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_override_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_override_async.py @@ -5,10 +5,11 @@ # -------------------------------------------------------------------------- import inspect import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.override.aio import OverrideClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with OverrideClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_usage_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_usage_async.py index 66c7946d888..816279eeb94 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_usage_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_client_generator_core_usage_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.clientgenerator.core.usage.aio import UsageClient from specs.azure.clientgenerator.core.usage import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with UsageClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_basic_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_basic_async.py index 87946f37ca2..3ce2c52262a 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_basic_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_basic_async.py @@ -4,12 +4,13 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.core.basic import models, aio VALID_USER = models.User(id=1, name="Madge", etag="11bdc430-65e8-45ad-81d9-8ffa60d55b59") -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with aio.BasicClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_rpc_async.py similarity index 94% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_rpc_async.py index bc572bf298b..57c19c423b3 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_rpc_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.core.lro.rpc.aio import RpcClient from specs.azure.core.lro.rpc import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RpcClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_standard_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_standard_async.py index b9b00668cae..05c4c09a2a9 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_standard_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_lro_standard_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.core.lro.standard.aio import StandardClient from specs.azure.core.lro.standard.models import User, ExportedUser -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with StandardClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_model_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_model_async.py index b2f8eed8952..333cfb5dcb5 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_model_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_model_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.core.model.aio import ModelClient from specs.azure.core.model.models import AzureEmbeddingModel -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ModelClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_page_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_page_async.py index 557c044e9e7..01a862620f2 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_page_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_page_async.py @@ -4,13 +4,14 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typing import AsyncIterable from specs.azure.core.page import models, aio VALID_USER = models.User(id=1, name="Madge", etag="11bdc430-65e8-45ad-81d9-8ffa60d55b59") -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with aio.PageClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_scalar_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_scalar_async.py index 4616cc2b5e4..321ebf9fc11 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_scalar_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_scalar_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.core.scalar.aio import ScalarClient from specs.azure.core.scalar import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ScalarClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_traits_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_traits_async.py index dca81854423..02060f56c2b 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_core_traits_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_core_traits_async.py @@ -7,13 +7,14 @@ from datetime import datetime import pytest +import pytest_asyncio from azure.core.exceptions import HttpResponseError from azure.core import MatchConditions from specs.azure.core.traits.aio import TraitsClient from specs.azure.core.traits.models import UserActionParam -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with TraitsClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_encode_duration_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_encode_duration_async.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_encode_duration_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_encode_duration_async.py index 8a23b94955e..d1c4867b89e 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_encode_duration_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_encode_duration_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.encode.duration.aio import DurationClient from specs.azure.encode.duration import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DurationClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_example_basic_async.py similarity index 95% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_example_basic_async.py index 46a66e519d0..00ce65cfb48 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_example_basic_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_example_basic_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.example.basic.aio import AzureExampleClient from specs.azure.example.basic.models import ActionRequest, Model -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with AzureExampleClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_payload_pageable_async.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_payload_pageable_async.py index 440a4a51170..1da9e665895 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_payload_pageable_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.payload.pageable.aio import PageableClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with PageableClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_method_subscription_id_async.py similarity index 99% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_method_subscription_id_async.py index 7b96c3c297b..4cd896a3477 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_method_subscription_id_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_method_subscription_id_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.methodsubscriptionid.aio import MethodSubscriptionIdClient from azure.resourcemanager.methodsubscriptionid import models @@ -11,7 +12,7 @@ RESOURCE_GROUP_NAME = "test-rg" -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): async with MethodSubscriptionIdClient( credential, diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_async.py index 86af8d31a93..b80c58a2274 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_async.py @@ -4,12 +4,13 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.core.exceptions import HttpResponseError from azure.resourcemanager.multiservice.combined.aio import CombinedClient from azure.resourcemanager.multiservice.combined.models import VirtualMachine, Disk -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): """Create a Combined async client for testing.""" return CombinedClient( diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py similarity index 99% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py index ee1c21bfbe1..57bc4929d90 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_resource_manager_multi_service_shared_models_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from azure.resourcemanager.multiservicesharedmodels.combined.aio import CombinedClient from azure.resourcemanager.multiservicesharedmodels.combined.models import ( VirtualMachine, @@ -14,7 +15,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(credential, authentication_policy): """Create a Combined async client for testing.""" return CombinedClient( diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_special_headers_client_request_id_async.py similarity index 95% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_special_headers_client_request_id_async.py index b89ee4b732c..eb066f84278 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_special_headers_client_request_id_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_special_headers_client_request_id_async.py @@ -6,11 +6,12 @@ import functools import pytest +import pytest_asyncio from azure.specialheaders.xmsclientrequestid.aio import XmsClientRequestIdClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with XmsClientRequestIdClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_versioning_previewversion_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_versioning_previewversion_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_versioning_previewversion_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_versioning_previewversion_async.py index 512e69c817e..a7d6d3d54c3 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_azure_versioning_previewversion_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_azure_versioning_previewversion_async.py @@ -4,17 +4,18 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.azure.versioning.previewversion.aio import PreviewVersionClient from specs.azure.versioning.previewversion.models import UpdateWidgetColorRequest -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with PreviewVersionClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def stable_client(): async with PreviewVersionClient(api_version="2024-06-01") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_namespace_async.py similarity index 94% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_namespace_async.py index adc98e3d569..06812847e24 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_namespace_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.clientnamespace.aio import ClientNamespaceFirstClient from client.clientnamespace.first.models import FirstClientResult @@ -12,13 +13,13 @@ from client.clientnamespace.second.sub.models import SecondClientEnumType -@pytest.fixture +@pytest_asyncio.fixture async def first_client(): async with ClientNamespaceFirstClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def second_client(): async with ClientNamespaceSecondClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_async.py similarity index 97% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_async.py index 4ccd786e801..9a3f249740e 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.naming.main.aio import NamingClient from client.naming.main import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NamingClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_enum_conflict_async.py similarity index 97% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_enum_conflict_async.py index 27b7731d985..edcf008684b 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_naming_enum_conflict_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_naming_enum_conflict_async.py @@ -4,12 +4,13 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from client.naming.enumconflict.aio import EnumConflictClient from client.naming.enumconflict.firstnamespace import models as first_models from client.naming.enumconflict.secondnamespace import models as second_models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with EnumConflictClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_overload_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_overload_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_overload_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_overload_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_structure_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_structure_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_structure_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_structure_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_structure_clientoperationgroup_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_client_structure_clientoperationgroup_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_client_structure_clientoperationgroup_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_client_structure_clientoperationgroup_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_duration_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_duration_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_duration_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_duration_async.py index 0fca0371948..b79a501903b 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_duration_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_duration_async.py @@ -6,6 +6,7 @@ import datetime import pytest +import pytest_asyncio from encode.duration.aio import DurationClient from encode.duration.models import ( Int32SecondsDurationProperty, @@ -16,7 +17,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DurationClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_numeric_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_numeric_async.py similarity index 96% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_numeric_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_numeric_async.py index 7bd8b5e1f50..a3a8a4d1fea 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_encode_numeric_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_encode_numeric_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from encode.numeric.aio import NumericClient from encode.numeric import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NumericClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_basic_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_basic_async.py similarity index 94% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_basic_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_basic_async.py index 969e73a6c8c..2b53806b4ce 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_basic_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_basic_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.basic.aio import BasicClient from parameters.basic.models import User -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with BasicClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_spread_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_spread_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_spread_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_spread_async.py index 74032d8e511..9fa08028630 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_parameters_spread_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_parameters_spread_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.spread.aio import SpreadClient from parameters.spread.models import BodyParameter -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SpreadClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_content_negotiation_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_content_negotiation_async.py similarity index 97% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_content_negotiation_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_content_negotiation_async.py index 4c2a11f61ac..84ec7ba708c 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_content_negotiation_async.py @@ -5,11 +5,12 @@ # -------------------------------------------------------------------------- import base64 import pytest +import pytest_asyncio from payload.contentnegotiation.aio import ContentNegotiationClient from payload.contentnegotiation.models import PngImageAsJson -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ContentNegotiationClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_multipart_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_multipart_async.py similarity index 99% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_multipart_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_multipart_async.py index 5cd750c8c0b..03668f5ddbc 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_payload_multipart_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_payload_multipart_async.py @@ -5,6 +5,7 @@ # -------------------------------------------------------------------------- from pathlib import Path import pytest +import pytest_asyncio from payload.multipart import models from payload.multipart.aio import MultiPartClient @@ -12,7 +13,7 @@ PNG = Path(__file__).parent.parent / "data/image.png" -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with MultiPartClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_resiliency_srv_driven_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_resiliency_srv_driven_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_resiliency_srv_driven_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_resiliency_srv_driven_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_serialization_encoded_name_json_async.py similarity index 94% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_serialization_encoded_name_json_async.py index 70bfcc77ad0..76594bbce59 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_serialization_encoded_name_json_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from serialization.encodedname.json.aio import JsonClient from serialization.encodedname.json import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with JsonClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_service_multi_service_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_service_multi_service_async.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_service_multi_service_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_service_multi_service_async.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py b/packages/http-client-python/tests/mock_api/azure/asynctests/test_special_words_async.py similarity index 98% rename from packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py rename to packages/http-client-python/tests/mock_api/azure/asynctests/test_special_words_async.py index 6c01e8f0737..8c59ea05070 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/asynctests/test_special_words_async.py +++ b/packages/http-client-python/tests/mock_api/azure/asynctests/test_special_words_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specialwords.aio import SpecialWordsClient from specialwords import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SpecialWordsClient() as client: yield client diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/conftest.py b/packages/http-client-python/tests/mock_api/azure/conftest.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/conftest.py rename to packages/http-client-python/tests/mock_api/azure/conftest.py index 85fe619a6c3..29824951ef4 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/conftest.py +++ b/packages/http-client-python/tests/mock_api/azure/conftest.py @@ -15,8 +15,8 @@ def start_server_process(): - azure_http_path = Path(os.path.dirname(__file__)) / Path("../../../../node_modules/@azure-tools/azure-http-specs") - http_path = Path(os.path.dirname(__file__)) / Path("../../../../node_modules/@typespec/http-specs") + azure_http_path = Path(os.path.dirname(__file__)) / Path("../../../node_modules/@azure-tools/azure-http-specs") + http_path = Path(os.path.dirname(__file__)) / Path("../../../node_modules/@typespec/http-specs") os.chdir(azure_http_path.resolve()) cmd = f"npx tsp-spector serve ./specs {(http_path / 'specs').resolve()}" if os.name == "nt": @@ -25,10 +25,14 @@ def start_server_process(): def terminate_server_process(process): - if os.name == "nt": - process.kill() - else: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + try: + if os.name == "nt": + process.kill() + else: + os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + except ProcessLookupError: + # Process already terminated, which is fine + pass @pytest.fixture(scope="session", autouse=True) diff --git a/packages/http-client-python/generator/test/data/image.jpg b/packages/http-client-python/tests/mock_api/azure/data/image.jpg similarity index 100% rename from packages/http-client-python/generator/test/data/image.jpg rename to packages/http-client-python/tests/mock_api/azure/data/image.jpg diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/data/image.png b/packages/http-client-python/tests/mock_api/azure/data/image.png similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/data/image.png rename to packages/http-client-python/tests/mock_api/azure/data/image.png diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_commonproperties.py b/packages/http-client-python/tests/mock_api/azure/test_azure_arm_commonproperties.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_commonproperties.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_arm_commonproperties.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_largeheader.py b/packages/http-client-python/tests/mock_api/azure/test_azure_arm_largeheader.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_largeheader.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_arm_largeheader.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_nonresource.py b/packages/http-client-python/tests/mock_api/azure/test_azure_arm_nonresource.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_nonresource.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_arm_nonresource.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py b/packages/http-client-python/tests/mock_api/azure/test_azure_arm_operationtemplates.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_operationtemplates.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_arm_operationtemplates.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_resource.py b/packages/http-client-python/tests/mock_api/azure/test_azure_arm_resource.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_arm_resource.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_arm_resource.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_access.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_access.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_access.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_header.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_header.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_header.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_header.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_path.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_path.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_path.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_path.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_query.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_query.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_api_version_query.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_api_version_query.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_default_value.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_default_value.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_default_value.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_default_value.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_initialization.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_initialization.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_initialization.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_location.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_client_location.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_client_location.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_deserialize_empty_string_as_null.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_deserialize_empty_string_as_null.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_deserialize_empty_string_as_null.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_deserialize_empty_string_as_null.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_flatten.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_flatten.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_hierrarchy_building.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_hierrarchy_building.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_hierrarchy_building.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_hierrarchy_building.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_next_link_verb.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_next_link_verb.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_next_link_verb.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_next_link_verb.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_override.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_override.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_override.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_override.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py b/packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_usage.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_client_generator_core_usage.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_client_generator_core_usage.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_basic.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_basic.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_basic.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_basic.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_lro_rpc.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_lro_rpc.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_lro_standard.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_lro_standard.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_lro_standard.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_lro_standard.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_model.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_model.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_model.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_model.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_page.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_page.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_page.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_page.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_scalar.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_scalar.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_scalar.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_scalar.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_traits.py b/packages/http-client-python/tests/mock_api/azure/test_azure_core_traits.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_core_traits.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_core_traits.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_encode_duration.py b/packages/http-client-python/tests/mock_api/azure/test_azure_encode_duration.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_encode_duration.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_encode_duration.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_example_basic.py b/packages/http-client-python/tests/mock_api/azure/test_azure_example_basic.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_example_basic.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_example_basic.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_payload_pageable.py b/packages/http-client-python/tests/mock_api/azure/test_azure_payload_pageable.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_payload_pageable.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_payload_pageable.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_method_subscription_id.py b/packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_method_subscription_id.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_method_subscription_id.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_method_subscription_id.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service.py b/packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_multi_service.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_multi_service.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service_shared_models.py b/packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_multi_service_shared_models.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_resource_manager_multi_service_shared_models.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_resource_manager_multi_service_shared_models.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_special_headers_client_request_id.py b/packages/http-client-python/tests/mock_api/azure/test_azure_special_headers_client_request_id.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_special_headers_client_request_id.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_special_headers_client_request_id.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_versioning_previewversion.py b/packages/http-client-python/tests/mock_api/azure/test_azure_versioning_previewversion.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_azure_versioning_previewversion.py rename to packages/http-client-python/tests/mock_api/azure/test_azure_versioning_previewversion.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_clear_output_folder.py b/packages/http-client-python/tests/mock_api/azure/test_clear_output_folder.py similarity index 93% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_clear_output_folder.py rename to packages/http-client-python/tests/mock_api/azure/test_clear_output_folder.py index c49c8bf1d94..00125fde0d3 100644 --- a/packages/http-client-python/generator/test/azure/mock_api_tests/test_clear_output_folder.py +++ b/packages/http-client-python/tests/mock_api/azure/test_clear_output_folder.py @@ -5,7 +5,7 @@ # -------------------------------------------------------------------------- from pathlib import Path -GENERATED_PATH = Path(__file__).parent.parent.resolve() / "generated" +GENERATED_PATH = Path(__file__).parent.parent.parent.resolve() / "generated" / "azure" def test_clear_output_folder(): diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_namespace.py b/packages/http-client-python/tests/mock_api/azure/test_client_namespace.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_namespace.py rename to packages/http-client-python/tests/mock_api/azure/test_client_namespace.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_naming.py b/packages/http-client-python/tests/mock_api/azure/test_client_naming.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_naming.py rename to packages/http-client-python/tests/mock_api/azure/test_client_naming.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py b/packages/http-client-python/tests/mock_api/azure/test_client_naming_enum_conflict.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_naming_enum_conflict.py rename to packages/http-client-python/tests/mock_api/azure/test_client_naming_enum_conflict.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_overload.py b/packages/http-client-python/tests/mock_api/azure/test_client_overload.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_overload.py rename to packages/http-client-python/tests/mock_api/azure/test_client_overload.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_structure.py b/packages/http-client-python/tests/mock_api/azure/test_client_structure.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_structure.py rename to packages/http-client-python/tests/mock_api/azure/test_client_structure.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_client_structure_clientoperationgroup.py b/packages/http-client-python/tests/mock_api/azure/test_client_structure_clientoperationgroup.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_client_structure_clientoperationgroup.py rename to packages/http-client-python/tests/mock_api/azure/test_client_structure_clientoperationgroup.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_encode_duration.py b/packages/http-client-python/tests/mock_api/azure/test_encode_duration.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_encode_duration.py rename to packages/http-client-python/tests/mock_api/azure/test_encode_duration.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_encode_numeric.py b/packages/http-client-python/tests/mock_api/azure/test_encode_numeric.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_encode_numeric.py rename to packages/http-client-python/tests/mock_api/azure/test_encode_numeric.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_model_base_flatten_compatibility.py b/packages/http-client-python/tests/mock_api/azure/test_model_base_flatten_compatibility.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_model_base_flatten_compatibility.py rename to packages/http-client-python/tests/mock_api/azure/test_model_base_flatten_compatibility.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_parameters_basic.py b/packages/http-client-python/tests/mock_api/azure/test_parameters_basic.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_parameters_basic.py rename to packages/http-client-python/tests/mock_api/azure/test_parameters_basic.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_parameters_spread.py b/packages/http-client-python/tests/mock_api/azure/test_parameters_spread.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_parameters_spread.py rename to packages/http-client-python/tests/mock_api/azure/test_parameters_spread.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_payload_content_negotiation.py b/packages/http-client-python/tests/mock_api/azure/test_payload_content_negotiation.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_payload_content_negotiation.py rename to packages/http-client-python/tests/mock_api/azure/test_payload_content_negotiation.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_payload_multipart.py b/packages/http-client-python/tests/mock_api/azure/test_payload_multipart.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_payload_multipart.py rename to packages/http-client-python/tests/mock_api/azure/test_payload_multipart.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_resiliency_srv_driven.py b/packages/http-client-python/tests/mock_api/azure/test_resiliency_srv_driven.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_resiliency_srv_driven.py rename to packages/http-client-python/tests/mock_api/azure/test_resiliency_srv_driven.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_serialization_encoded_name_json.py b/packages/http-client-python/tests/mock_api/azure/test_serialization_encoded_name_json.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_serialization_encoded_name_json.py rename to packages/http-client-python/tests/mock_api/azure/test_serialization_encoded_name_json.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_service_multi_service.py b/packages/http-client-python/tests/mock_api/azure/test_service_multi_service.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_service_multi_service.py rename to packages/http-client-python/tests/mock_api/azure/test_service_multi_service.py diff --git a/packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py b/packages/http-client-python/tests/mock_api/azure/test_special_words.py similarity index 100% rename from packages/http-client-python/generator/test/azure/mock_api_tests/test_special_words.py rename to packages/http-client-python/tests/mock_api/azure/test_special_words.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_authentication_async.py similarity index 97% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_authentication_async.py index 2276efaf9ca..4be9d3a7310 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_authentication_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_authentication_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from authentication.apikey.aio import ApiKeyClient from authentication.http.custom.aio import CustomClient from authentication.oauth2.aio import OAuth2Client @@ -14,7 +15,7 @@ # Utilities functions -@pytest.fixture +@pytest_asyncio.fixture async def api_key_client(key_credential): client = None @@ -41,7 +42,7 @@ async def get_token_info(*scopes, **kwargs): return FakeCredential() -@pytest.fixture +@pytest_asyncio.fixture async def oauth2_client(token_credential): client = None @@ -54,7 +55,7 @@ def _build_client(client_type): await client.close() -@pytest.fixture +@pytest_asyncio.fixture async def http_custom_client(key_credential): client = None diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_array_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_array_async.py index 925780cd4aa..3ec7a56529c 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_array_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_array_async.py @@ -5,11 +5,12 @@ # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from encode.array.aio import ArrayClient from encode.array import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ArrayClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_bytes_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_bytes_async.py index 584b277edd9..5c57cb4281c 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_bytes_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_bytes_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from pathlib import Path from encode.bytes.aio import BytesClient from encode.bytes.models import ( @@ -16,7 +17,7 @@ FILE_FOLDER = Path(__file__).parent.parent -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with BytesClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_datetime_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_datetime_async.py index 1249b8e8f30..bd5b590a098 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_encode_datetime_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_encode_datetime_async.py @@ -6,6 +6,7 @@ import datetime import pytest +import pytest_asyncio from encode.datetime.aio import DatetimeClient from encode.datetime.models import ( DefaultDatetimeProperty, @@ -16,7 +17,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DatetimeClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_headasboolean_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_headasboolean_async.py index c0f69198712..d2c2f10da02 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_headasboolean_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_headasboolean_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from headasbooleantrue.aio import VisibilityClient as HeadAsBooleanTrueClient from headasbooleantrue import models as models_true @@ -11,13 +12,13 @@ from headasbooleanfalse import models as models_false -@pytest.fixture +@pytest_asyncio.fixture async def client_true(): async with HeadAsBooleanTrueClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def client_false(): async with HeadAsBooleanFalseClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_body_optionality_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_body_optionality_async.py index 7c6bbe82c8d..47bc79fd47c 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_body_optionality_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_body_optionality_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.bodyoptionality.aio import BodyOptionalityClient from parameters.bodyoptionality.models import BodyModel -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with BodyOptionalityClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_collection_format_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_collection_format_async.py index c3ae9698079..6ed93c4651e 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_collection_format_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_collection_format_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.collectionformat.aio import CollectionFormatClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with CollectionFormatClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_path_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_path_async.py index eeef36a301a..aee4b150059 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_path_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_path_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.path.aio import PathClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with PathClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_query_async.py similarity index 92% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_query_async.py index d5879ebdc2a..70fb18603d2 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_parameters_query_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_parameters_query_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.query.aio import QueryClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with QueryClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_json_merge_patch_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_json_merge_patch_async.py index e276944be33..54709bed058 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_json_merge_patch_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_json_merge_patch_async.py @@ -4,6 +4,7 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from payload.jsonmergepatch.aio import JsonMergePatchClient from payload.jsonmergepatch.models import InnerModel, Resource, ResourcePatch @@ -13,7 +14,7 @@ from corehttp.serialization import NULL -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with JsonMergePatchClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_media_type_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_media_type_async.py index d783e6ac61c..551d71bc425 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_media_type_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_media_type_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from payload.mediatype.aio import MediaTypeClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with MediaTypeClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_pageable_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_pageable_async.py index f0994df97b0..900caa49edf 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_pageable_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from payload.pageable.aio import PageableClient from payload.pageable.serverdrivenpagination.alternateinitialverb.models import Filter -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with PageableClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_xml_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_xml_async.py index 6cf981a0e4f..8ae1cc69adf 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_payload_xml_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_payload_xml_async.py @@ -5,6 +5,7 @@ # -------------------------------------------------------------------------- import datetime import pytest +import pytest_asyncio from payload.xml.aio import XmlClient from payload.xml.models import ( Author, @@ -37,7 +38,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with XmlClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_response_status_code_range_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_response_status_code_range_async.py index 3d6faa0c1f1..0dd34b667cf 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_response_status_code_range_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_response_status_code_range_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from response.statuscoderange.aio import StatusCodeRangeClient from response.statuscoderange.models import ErrorInRange, NotFoundError -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with StatusCodeRangeClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_routes_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_routes_async.py index 277e57be3a6..d3e34bc1f93 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_routes_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_routes_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from routes.aio import RoutesClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RoutesClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_endpoint_not_defined_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_server_endpoint_not_defined_async.py index 148e61dd5ca..a14997b71c5 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_endpoint_not_defined_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_endpoint_not_defined_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from server.endpoint.notdefined.aio import NotDefinedClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NotDefinedClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_multiple_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_multiple_async.py index bcdc53dd4f4..50bc53b5e3b 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_multiple_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_multiple_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from server.path.multiple.aio import MultipleClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with MultipleClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_single_async.py similarity index 92% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_single_async.py index d6ebe479f8b..efcb703028a 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_path_single_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_path_single_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from server.path.single.aio import SingleClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SingleClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_not_versioned_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_not_versioned_async.py index 738364b6e4f..14f7e4239db 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_not_versioned_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_not_versioned_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from server.versions.notversioned.aio import NotVersionedClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NotVersionedClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_versioned_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_versioned_async.py index 53e7d194f42..8f96a2f5508 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_server_versions_versioned_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_server_versions_versioned_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from server.versions.versioned.aio import VersionedClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with VersionedClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_conditional_request_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_conditional_request_async.py index e65b9d4e330..dc86ac0635e 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_conditional_request_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_conditional_request_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio import datetime from specialheaders.conditionalrequest.aio import ConditionalRequestClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ConditionalRequestClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_repeatability_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_repeatability_async.py index dbf74414e12..941890ea230 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_special_headers_repeatability_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_special_headers_repeatability_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specialheaders.repeatability.aio import RepeatabilityClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RepeatabilityClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_specs_documentation_async.py similarity index 97% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_specs_documentation_async.py index 12e4cb2e5a2..dff527765ce 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_specs_documentation_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_specs_documentation_async.py @@ -5,11 +5,12 @@ # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specs.documentation.aio import DocumentationClient from specs.documentation import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DocumentationClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_streaming_jsonl_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_streaming_jsonl_async.py index 803215abd99..74e05cebd14 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_streaming_jsonl_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from streaming.jsonl.aio import JsonlClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with JsonlClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_array_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_array_async.py index 180887ea765..66c3b24c1f4 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_array_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_array_async.py @@ -5,12 +5,13 @@ # -------------------------------------------------------------------------- import pytest +import pytest_asyncio import isodate from typetest.array.aio import ArrayClient from typetest.array import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ArrayClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_dictionary_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_dictionary_async.py index 364868b2357..76a57a1ba95 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_dictionary_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_dictionary_async.py @@ -4,12 +4,13 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.dictionary import models from typetest.dictionary.aio import DictionaryClient import isodate -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DictionaryClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_extensible_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_extensible_async.py index 75fca822ddb..aedc6e6a92c 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_extensible_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_extensible_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.enum.extensible import models, aio -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with aio.ExtensibleClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_fixed_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_fixed_async.py index de17f194b6d..5b6822fcfd2 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_enum_fixed_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_enum_fixed_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.enum.fixed import aio, models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with aio.FixedClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_file_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_file_async.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_file_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_file_async.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_empty_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_empty_async.py index b5518c5e901..030d3bd84fc 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_empty_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_empty_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.empty.aio import EmptyClient from typetest.model.empty.models import EmptyInput, EmptyOutput, EmptyInputOutput -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with EmptyClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py index 0a72d5465e3..dc176b3fd9b 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_enum_discriminator_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.enumdiscriminator.aio import EnumDiscriminatorClient from typetest.model.enumdiscriminator import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with EnumDiscriminatorClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py index c641f25eb88..f6e57f5affa 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_nested_discriminator_async.py @@ -4,17 +4,18 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.nesteddiscriminator.aio import NestedDiscriminatorClient from typetest.model.nesteddiscriminator.models import GoblinShark, Salmon, Fish -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NestedDiscriminatorClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def valid_body(): return GoblinShark(age=1) @@ -30,7 +31,7 @@ async def test_put_model(client, valid_body): await client.put_model(valid_body) -@pytest.fixture +@pytest_asyncio.fixture async def valid_recursive_body(): return Salmon( { diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_not_discriminated_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_not_discriminated_async.py index 7e7ce096956..5ed075e3d50 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_not_discriminated_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_not_discriminated_async.py @@ -4,17 +4,18 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.notdiscriminated.aio import NotDiscriminatedClient from typetest.model.notdiscriminated.models import Siamese -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NotDiscriminatedClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def valid_body(): return Siamese(name="abc", age=32, smart=True) diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_recursive_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_recursive_async.py index aea6f1bb9e3..3056c2c40a5 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_recursive_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_recursive_async.py @@ -4,17 +4,18 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.recursive.aio import RecursiveClient from typetest.model.recursive.models import Extension -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RecursiveClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def expected(): return Extension( { diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_single_discriminator_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_single_discriminator_async.py index dc98cd81c9b..e6ddd9c44fc 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_inheritance_single_discriminator_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_inheritance_single_discriminator_async.py @@ -4,17 +4,18 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.singlediscriminator.aio import SingleDiscriminatorClient from typetest.model.singlediscriminator.models import Sparrow, Eagle, Bird, Dinosaur -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SingleDiscriminatorClient() as client: yield client -@pytest.fixture +@pytest_asyncio.fixture async def valid_body(): return Sparrow(wingspan=1) @@ -29,7 +30,7 @@ async def test_put_model(client, valid_body): await client.put_model(valid_body) -@pytest.fixture +@pytest_asyncio.fixture async def recursive_body(): return Eagle( { diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_usage_async.py similarity index 95% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_usage_async.py index bcebeaec205..a7e00354034 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_usage_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_usage_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.usage import models from typetest.model.usage.aio import UsageClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with UsageClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_visibility_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_visibility_async.py index 27fb23df8aa..62827695819 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_model_visibility_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_model_visibility_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.model.visibility.aio import VisibilityClient from typetest.model.visibility import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with VisibilityClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_additionalproperties_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_additionalproperties_async.py index 2109ea31791..3784156bfeb 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_additionalproperties_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_additionalproperties_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.property.additionalproperties import models from typetest.property.additionalproperties.aio import AdditionalPropertiesClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with AdditionalPropertiesClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_nullable_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_nullable_async.py index a5dc1322110..f54cafb464a 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_nullable_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_nullable_async.py @@ -6,6 +6,7 @@ # -------------------------------------------------------------------------- import json import pytest +import pytest_asyncio from typetest.property.nullable import models from typetest.property.nullable.aio import NullableClient from typetest.property.nullable._utils.model_base import ( # pylint: disable=protected-access @@ -18,7 +19,7 @@ from azure.core.serialization import NULL -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NullableClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_optional_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_optional_async.py index e7ec09d0059..51d8bd362e9 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_optional_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_optional_async.py @@ -6,11 +6,12 @@ # -------------------------------------------------------------------------- from typing import Any import pytest +import pytest_asyncio from typetest.property.optional import models from typetest.property.optional.aio import OptionalClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with OptionalClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_valuetypes_async.py similarity index 99% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_valuetypes_async.py index 1b7566c5739..15a3e794e1e 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_property_valuetypes_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_property_valuetypes_async.py @@ -7,12 +7,13 @@ import decimal import pytest +import pytest_asyncio import datetime from typetest.property.valuetypes import models from typetest.property.valuetypes.aio import ValueTypesClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ValueTypesClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_scalar_async.py similarity index 97% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_scalar_async.py index 3e2b308f8ba..674ee0e0d4d 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_scalar_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_scalar_async.py @@ -7,10 +7,11 @@ from functools import reduce import pytest +import pytest_asyncio from typetest.scalar.aio import ScalarClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ScalarClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_union_async.py similarity index 98% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_union_async.py index 9e738701f4f..18b5e1aba91 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_typetest_union_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_typetest_union_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from typetest.union.aio import UnionClient from typetest.union import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with UnionClient() as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_added_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_added_async.py index 27e78a8892d..8906113b96f 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_added_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_added_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.added.aio import AddedClient from versioning.added.models import ModelV1, ModelV2, EnumV1, EnumV2 -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with AddedClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_made_optional_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_made_optional_async.py index 27ec811cae2..c126d401167 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_made_optional_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_made_optional_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.madeoptional.aio import MadeOptionalClient from versioning.madeoptional.models import TestModel -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with MadeOptionalClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_removed_async.py similarity index 97% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_removed_async.py index 5442c56e6c9..22dab517fdf 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_removed_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_removed_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.removed.aio import RemovedClient from versioning.removed.models import ModelV2, EnumV2, ModelV3, EnumV3 -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RemovedClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_renamed_from_async.py similarity index 96% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_renamed_from_async.py index 46ef588f65d..1e738c21326 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_renamed_from_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_renamed_from_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.renamedfrom.aio import RenamedFromClient from versioning.renamedfrom.models import NewModel, NewEnum -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with RenamedFromClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_return_type_changed_from_async.py similarity index 93% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_return_type_changed_from_async.py index 80eefecbe22..e6234f69607 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_return_type_changed_from_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_return_type_changed_from_async.py @@ -4,10 +4,11 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.returntypechangedfrom.aio import ReturnTypeChangedFromClient -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ReturnTypeChangedFromClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_type_changed_from_async.py similarity index 94% rename from packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py rename to packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_type_changed_from_async.py index 2374bd1f550..6bf75a87be0 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/asynctests/test_versioning_type_changed_from_async.py +++ b/packages/http-client-python/tests/mock_api/shared/asynctests/test_versioning_type_changed_from_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from versioning.typechangedfrom.aio import TypeChangedFromClient from versioning.typechangedfrom.models import TestModel -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with TypeChangedFromClient(endpoint="http://localhost:3000", version="v2") as client: yield client diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/conftest.py b/packages/http-client-python/tests/mock_api/shared/conftest.py similarity index 87% rename from packages/http-client-python/generator/test/generic_mock_api_tests/conftest.py rename to packages/http-client-python/tests/mock_api/shared/conftest.py index 00de709f440..727f986ae44 100644 --- a/packages/http-client-python/generator/test/generic_mock_api_tests/conftest.py +++ b/packages/http-client-python/tests/mock_api/shared/conftest.py @@ -28,10 +28,14 @@ def start_server_process(): def terminate_server_process(process): - if os.name == "nt": - process.kill() - else: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + try: + if os.name == "nt": + process.kill() + else: + os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + except ProcessLookupError: + # Process already terminated, which is fine + pass @pytest.fixture(scope="session", autouse=True) diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/data/image.jpg b/packages/http-client-python/tests/mock_api/shared/data/image.jpg similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/data/image.jpg rename to packages/http-client-python/tests/mock_api/shared/data/image.jpg diff --git a/packages/http-client-python/generator/test/data/image.png b/packages/http-client-python/tests/mock_api/shared/data/image.png similarity index 100% rename from packages/http-client-python/generator/test/data/image.png rename to packages/http-client-python/tests/mock_api/shared/data/image.png diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_authentication.py b/packages/http-client-python/tests/mock_api/shared/test_authentication.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_authentication.py rename to packages/http-client-python/tests/mock_api/shared/test_authentication.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_array.py b/packages/http-client-python/tests/mock_api/shared/test_encode_array.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_array.py rename to packages/http-client-python/tests/mock_api/shared/test_encode_array.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_bytes.py b/packages/http-client-python/tests/mock_api/shared/test_encode_bytes.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_bytes.py rename to packages/http-client-python/tests/mock_api/shared/test_encode_bytes.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_datetime.py b/packages/http-client-python/tests/mock_api/shared/test_encode_datetime.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_encode_datetime.py rename to packages/http-client-python/tests/mock_api/shared/test_encode_datetime.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_headasboolean.py b/packages/http-client-python/tests/mock_api/shared/test_headasboolean.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_headasboolean.py rename to packages/http-client-python/tests/mock_api/shared/test_headasboolean.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_body_optionality.py b/packages/http-client-python/tests/mock_api/shared/test_parameters_body_optionality.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_body_optionality.py rename to packages/http-client-python/tests/mock_api/shared/test_parameters_body_optionality.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_collection_format.py b/packages/http-client-python/tests/mock_api/shared/test_parameters_collection_format.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_collection_format.py rename to packages/http-client-python/tests/mock_api/shared/test_parameters_collection_format.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_path.py b/packages/http-client-python/tests/mock_api/shared/test_parameters_path.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_path.py rename to packages/http-client-python/tests/mock_api/shared/test_parameters_path.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_query.py b/packages/http-client-python/tests/mock_api/shared/test_parameters_query.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_parameters_query.py rename to packages/http-client-python/tests/mock_api/shared/test_parameters_query.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py b/packages/http-client-python/tests/mock_api/shared/test_payload_json_merge_patch.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_json_merge_patch.py rename to packages/http-client-python/tests/mock_api/shared/test_payload_json_merge_patch.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_media_type.py b/packages/http-client-python/tests/mock_api/shared/test_payload_media_type.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_media_type.py rename to packages/http-client-python/tests/mock_api/shared/test_payload_media_type.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_pageable.py b/packages/http-client-python/tests/mock_api/shared/test_payload_pageable.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_pageable.py rename to packages/http-client-python/tests/mock_api/shared/test_payload_pageable.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py b/packages/http-client-python/tests/mock_api/shared/test_payload_xml.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_payload_xml.py rename to packages/http-client-python/tests/mock_api/shared/test_payload_xml.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_response_status_code_range.py b/packages/http-client-python/tests/mock_api/shared/test_response_status_code_range.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_response_status_code_range.py rename to packages/http-client-python/tests/mock_api/shared/test_response_status_code_range.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_routes.py b/packages/http-client-python/tests/mock_api/shared/test_routes.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_routes.py rename to packages/http-client-python/tests/mock_api/shared/test_routes.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_server_endpoint_not_defined.py b/packages/http-client-python/tests/mock_api/shared/test_server_endpoint_not_defined.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_server_endpoint_not_defined.py rename to packages/http-client-python/tests/mock_api/shared/test_server_endpoint_not_defined.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_server_path_multiple.py b/packages/http-client-python/tests/mock_api/shared/test_server_path_multiple.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_server_path_multiple.py rename to packages/http-client-python/tests/mock_api/shared/test_server_path_multiple.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_server_path_single.py b/packages/http-client-python/tests/mock_api/shared/test_server_path_single.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_server_path_single.py rename to packages/http-client-python/tests/mock_api/shared/test_server_path_single.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_server_versions_not_versioned.py b/packages/http-client-python/tests/mock_api/shared/test_server_versions_not_versioned.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_server_versions_not_versioned.py rename to packages/http-client-python/tests/mock_api/shared/test_server_versions_not_versioned.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_server_versions_versioned.py b/packages/http-client-python/tests/mock_api/shared/test_server_versions_versioned.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_server_versions_versioned.py rename to packages/http-client-python/tests/mock_api/shared/test_server_versions_versioned.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_special_headers_conditional_request.py b/packages/http-client-python/tests/mock_api/shared/test_special_headers_conditional_request.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_special_headers_conditional_request.py rename to packages/http-client-python/tests/mock_api/shared/test_special_headers_conditional_request.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_special_headers_repeatability.py b/packages/http-client-python/tests/mock_api/shared/test_special_headers_repeatability.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_special_headers_repeatability.py rename to packages/http-client-python/tests/mock_api/shared/test_special_headers_repeatability.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_specs_documentation.py b/packages/http-client-python/tests/mock_api/shared/test_specs_documentation.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_specs_documentation.py rename to packages/http-client-python/tests/mock_api/shared/test_specs_documentation.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_streaming_jsonl.py b/packages/http-client-python/tests/mock_api/shared/test_streaming_jsonl.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_streaming_jsonl.py rename to packages/http-client-python/tests/mock_api/shared/test_streaming_jsonl.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_array.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_array.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_array.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_array.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_dictionary.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_dictionary.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_dictionary.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_dictionary.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_enum_extensible.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_enum_extensible.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_enum_extensible.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_enum_extensible.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_enum_fixed.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_enum_fixed.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_enum_fixed.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_enum_fixed.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_file.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_file.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_file.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_file.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_empty.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_empty.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_empty.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_empty.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_enum_discriminator.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_enum_discriminator.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_enum_discriminator.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_enum_discriminator.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_nested_discriminator.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_nested_discriminator.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_nested_discriminator.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_nested_discriminator.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_not_discriminated.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_not_discriminated.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_not_discriminated.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_not_discriminated.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_recursive.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_recursive.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_recursive.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_recursive.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_single_discriminator.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_single_discriminator.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_inheritance_single_discriminator.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_inheritance_single_discriminator.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_usage.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_usage.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_usage.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_usage.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_visibility.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_model_visibility.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_model_visibility.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_model_visibility.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_additionalproperties.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_property_additionalproperties.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_additionalproperties.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_property_additionalproperties.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_property_nullable.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_nullable.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_property_nullable.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_optional.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_property_optional.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_optional.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_property_optional.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_valuetypes.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_property_valuetypes.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_property_valuetypes.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_property_valuetypes.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_scalar.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_scalar.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_scalar.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_scalar.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_union.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_union.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_union.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_union.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_union_discriminated.py b/packages/http-client-python/tests/mock_api/shared/test_typetest_union_discriminated.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_typetest_union_discriminated.py rename to packages/http-client-python/tests/mock_api/shared/test_typetest_union_discriminated.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_added.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_added.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_added.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_added.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_made_optional.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_made_optional.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_made_optional.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_made_optional.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_removed.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_removed.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_removed.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_removed.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_renamed_from.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_renamed_from.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_renamed_from.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_renamed_from.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_return_type_changed_from.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_return_type_changed_from.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_return_type_changed_from.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_return_type_changed_from.py diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_type_changed_from.py b/packages/http-client-python/tests/mock_api/shared/test_versioning_type_changed_from.py similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/test_versioning_type_changed_from.py rename to packages/http-client-python/tests/mock_api/shared/test_versioning_type_changed_from.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_auth_flow_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_auth_flow_async.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_auth_flow_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_auth_flow_async.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_duration_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_duration_async.py similarity index 98% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_duration_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_duration_async.py index f14c436a8f8..2b0716dc98b 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_duration_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_duration_async.py @@ -6,6 +6,7 @@ import datetime import pytest +import pytest_asyncio from encode.duration.aio import DurationClient from encode.duration.property.models import ( Int32SecondsDurationProperty, @@ -16,7 +17,7 @@ ) -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with DurationClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_numeric_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_numeric_async.py similarity index 96% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_numeric_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_numeric_async.py index 19e4f619f2c..244f2ee0e12 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_encode_numeric_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_encode_numeric_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from encode.numeric.aio import NumericClient from encode.numeric.property import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with NumericClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_basic_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_basic_async.py similarity index 94% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_basic_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_basic_async.py index 81a0deecdd5..f6d8c58a938 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_basic_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_basic_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.basic.aio import BasicClient from parameters.basic.explicitbody.models import User -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with BasicClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_spread_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_spread_async.py similarity index 98% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_spread_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_spread_async.py index 89f3cec4819..57de584d843 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_parameters_spread_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_parameters_spread_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from parameters.spread.aio import SpreadClient from parameters.spread.model.models import BodyParameter -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SpreadClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_content_negotiation_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_content_negotiation_async.py similarity index 97% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_content_negotiation_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_content_negotiation_async.py index 27db476d9c5..3dd1cc324b6 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_content_negotiation_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_content_negotiation_async.py @@ -5,11 +5,12 @@ # -------------------------------------------------------------------------- import base64 import pytest +import pytest_asyncio from payload.contentnegotiation.aio import ContentNegotiationClient from payload.contentnegotiation.differentbody.models import PngImageAsJson -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ContentNegotiationClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_multipart_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_multipart_async.py similarity index 99% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_multipart_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_multipart_async.py index 4a1a6a9cedf..b5197313bff 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_payload_multipart_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_payload_multipart_async.py @@ -5,6 +5,7 @@ # -------------------------------------------------------------------------- from pathlib import Path import pytest +import pytest_asyncio from payload.multipart import models from payload.multipart.aio import MultiPartClient from payload.multipart.formdata.httpparts.nonstring.models import FloatRequest @@ -14,7 +15,7 @@ PNG = Path(__file__).parent.parent / "data/image.png" -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with MultiPartClient(endpoint="http://localhost:3000") as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_serialization_encoded_name_json_async.py similarity index 94% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_serialization_encoded_name_json_async.py index 7234c7e253a..c03899fe7e3 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_serialization_encoded_name_json_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_serialization_encoded_name_json_async.py @@ -4,11 +4,12 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from serialization.encodedname.json.aio import JsonClient from serialization.encodedname.json.property import models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with JsonClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_special_words_async.py similarity index 98% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_special_words_async.py index 112533fa2db..c1e3bc0a8f2 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_special_words_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_special_words_async.py @@ -4,13 +4,14 @@ # license information. # -------------------------------------------------------------------------- import pytest +import pytest_asyncio from specialwords.aio import SpecialWordsClient from specialwords.models import models from specialwords.modelproperties import models as model_properties_models from specialwords.extensiblestrings import models as extensible_strings_models -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with SpecialWordsClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_unbranded_async.py similarity index 93% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py rename to packages/http-client-python/tests/mock_api/unbranded/asynctests/test_unbranded_async.py index 1ba8cc5750d..0218d8578ef 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/asynctests/test_unbranded_async.py +++ b/packages/http-client-python/tests/mock_api/unbranded/asynctests/test_unbranded_async.py @@ -4,11 +4,12 @@ # ------------------------------------ import traceback import pytest +import pytest_asyncio from typetest.scalar.aio import ScalarClient from corehttp.exceptions import HttpResponseError -@pytest.fixture +@pytest_asyncio.fixture async def client(): async with ScalarClient() as client: yield client diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/conftest.py b/packages/http-client-python/tests/mock_api/unbranded/conftest.py similarity index 84% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/conftest.py rename to packages/http-client-python/tests/mock_api/unbranded/conftest.py index 78b45a295a0..5d190ae0bd4 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/conftest.py +++ b/packages/http-client-python/tests/mock_api/unbranded/conftest.py @@ -14,7 +14,7 @@ def start_server_process(): - http_path = Path(os.path.dirname(__file__)) / Path("../../../../node_modules/@typespec/http-specs") + http_path = Path(os.path.dirname(__file__)) / Path("../../../node_modules/@typespec/http-specs") os.chdir(http_path.resolve()) cmd = "tsp-spector serve ./specs" if os.name == "nt": @@ -23,10 +23,14 @@ def start_server_process(): def terminate_server_process(process): - if os.name == "nt": - process.kill() - else: - os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + try: + if os.name == "nt": + process.kill() + else: + os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send the signal to all the process groups + except ProcessLookupError: + # Process already terminated, which is fine + pass @pytest.fixture(scope="session", autouse=True) diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/data/image.jpg b/packages/http-client-python/tests/mock_api/unbranded/data/image.jpg similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/data/image.jpg rename to packages/http-client-python/tests/mock_api/unbranded/data/image.jpg diff --git a/packages/http-client-python/generator/test/generic_mock_api_tests/data/image.png b/packages/http-client-python/tests/mock_api/unbranded/data/image.png similarity index 100% rename from packages/http-client-python/generator/test/generic_mock_api_tests/data/image.png rename to packages/http-client-python/tests/mock_api/unbranded/data/image.png diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_auth_flow.py b/packages/http-client-python/tests/mock_api/unbranded/test_auth_flow.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_auth_flow.py rename to packages/http-client-python/tests/mock_api/unbranded/test_auth_flow.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_encode_duration.py b/packages/http-client-python/tests/mock_api/unbranded/test_encode_duration.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_encode_duration.py rename to packages/http-client-python/tests/mock_api/unbranded/test_encode_duration.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_encode_numeric.py b/packages/http-client-python/tests/mock_api/unbranded/test_encode_numeric.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_encode_numeric.py rename to packages/http-client-python/tests/mock_api/unbranded/test_encode_numeric.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_parameters_basic.py b/packages/http-client-python/tests/mock_api/unbranded/test_parameters_basic.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_parameters_basic.py rename to packages/http-client-python/tests/mock_api/unbranded/test_parameters_basic.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_parameters_spread.py b/packages/http-client-python/tests/mock_api/unbranded/test_parameters_spread.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_parameters_spread.py rename to packages/http-client-python/tests/mock_api/unbranded/test_parameters_spread.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_payload_content_negotiation.py b/packages/http-client-python/tests/mock_api/unbranded/test_payload_content_negotiation.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_payload_content_negotiation.py rename to packages/http-client-python/tests/mock_api/unbranded/test_payload_content_negotiation.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_payload_multipart.py b/packages/http-client-python/tests/mock_api/unbranded/test_payload_multipart.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_payload_multipart.py rename to packages/http-client-python/tests/mock_api/unbranded/test_payload_multipart.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_serialization_encoded_name_json.py b/packages/http-client-python/tests/mock_api/unbranded/test_serialization_encoded_name_json.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_serialization_encoded_name_json.py rename to packages/http-client-python/tests/mock_api/unbranded/test_serialization_encoded_name_json.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py b/packages/http-client-python/tests/mock_api/unbranded/test_special_words.py similarity index 100% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_special_words.py rename to packages/http-client-python/tests/mock_api/unbranded/test_special_words.py diff --git a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_unbranded.py b/packages/http-client-python/tests/mock_api/unbranded/test_unbranded.py similarity index 95% rename from packages/http-client-python/generator/test/unbranded/mock_api_tests/test_unbranded.py rename to packages/http-client-python/tests/mock_api/unbranded/test_unbranded.py index 19d767860f8..e1b32751ff3 100644 --- a/packages/http-client-python/generator/test/unbranded/mock_api_tests/test_unbranded.py +++ b/packages/http-client-python/tests/mock_api/unbranded/test_unbranded.py @@ -51,7 +51,7 @@ def check_sensitive_word(folder: Path, word: str) -> str: def test_sensitive_word(): - check_folder = (Path(os.path.dirname(__file__)) / "../generated").resolve() + check_folder = (Path(os.path.dirname(__file__)) / "../../generated/unbranded").resolve() assert [] == check_sensitive_word(check_folder, "azure") # after update spector, it shall also equal to [] expected = [ diff --git a/packages/http-client-python/tests/requirements/azure.txt b/packages/http-client-python/tests/requirements/azure.txt new file mode 100644 index 00000000000..0d5e793d16f --- /dev/null +++ b/packages/http-client-python/tests/requirements/azure.txt @@ -0,0 +1,4 @@ +# Azure SDK dependencies +-r base.txt +azure-core>=1.37.0 +azure-mgmt-core==1.6.0 diff --git a/packages/http-client-python/tests/requirements/base.txt b/packages/http-client-python/tests/requirements/base.txt new file mode 100644 index 00000000000..441007cce76 --- /dev/null +++ b/packages/http-client-python/tests/requirements/base.txt @@ -0,0 +1,10 @@ +# Base test dependencies +pytest==8.3.2 +pytest-asyncio>=0.14.0 +aiohttp +coverage==7.6.1 +colorama==0.4.6 +isodate>=0.6.1 +typing-extensions>=4.6.0 +tox>=4.16.0 +tox-uv>=1.0.0 diff --git a/packages/http-client-python/tests/requirements/docs.txt b/packages/http-client-python/tests/requirements/docs.txt new file mode 100644 index 00000000000..c92e47a60d6 --- /dev/null +++ b/packages/http-client-python/tests/requirements/docs.txt @@ -0,0 +1,7 @@ +# Documentation dependencies +-r base.txt +sphinx>=7.0.0 +sphinx_rtd_theme>=2.0.0 +myst_parser>=2.0.0 +sphinxcontrib-jquery>=4.1 +apiview-stub-generator>=0.3.19 --index-url=https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/ diff --git a/packages/http-client-python/tests/requirements/lint.txt b/packages/http-client-python/tests/requirements/lint.txt new file mode 100644 index 00000000000..2a9896f8d75 --- /dev/null +++ b/packages/http-client-python/tests/requirements/lint.txt @@ -0,0 +1,4 @@ +# Linting dependencies +-r base.txt +pylint==4.0.4 +black==24.8.0 diff --git a/packages/http-client-python/tests/requirements/typecheck.txt b/packages/http-client-python/tests/requirements/typecheck.txt new file mode 100644 index 00000000000..6e09ee898c7 --- /dev/null +++ b/packages/http-client-python/tests/requirements/typecheck.txt @@ -0,0 +1,5 @@ +# Type checking dependencies +-r base.txt +pyright==1.1.407 +mypy==1.19.1 +types-PyYAML==6.0.12.8 diff --git a/packages/http-client-python/tests/requirements/unbranded.txt b/packages/http-client-python/tests/requirements/unbranded.txt new file mode 100644 index 00000000000..73749e218c0 --- /dev/null +++ b/packages/http-client-python/tests/requirements/unbranded.txt @@ -0,0 +1,3 @@ +# Unbranded SDK dependencies +-r base.txt +corehttp[requests] diff --git a/packages/http-client-python/tests/tox.ini b/packages/http-client-python/tests/tox.ini new file mode 100644 index 00000000000..f68944f3d64 --- /dev/null +++ b/packages/http-client-python/tests/tox.ini @@ -0,0 +1,207 @@ +[tox] +envlist = test-{azure,unbranded}, lint-{azure,unbranded}, mypy-{azure,unbranded}, pyright-{azure,unbranded}, unittest +skipsdist = True +isolated_build = True +requires = tox-uv + +[testenv] +deps = + -r {tox_root}/requirements/base.txt +setenv = + PYTHONPATH = {tox_root}/../generator + FLAVOR = {envname} +passenv = + FOLDER + +# ============================================================================= +# Test environments +# ============================================================================= + +[testenv:test-azure] +description = Run tests for Azure flavor +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + {[testenv]deps} + -r {tox_root}/requirements/azure.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py azure {tox_root} + pytest mock_api/azure mock_api/shared -v {posargs} + +[testenv:test-unbranded] +description = Run tests for unbranded flavor +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + {[testenv]deps} + -r {tox_root}/requirements/unbranded.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + pytest mock_api/unbranded mock_api/shared -v {posargs} + +[testenv:unittest] +description = Run unit tests for pygen internals +deps = + {[testenv]deps} + -r {tox_root}/requirements/unbranded.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + pytest unit/ -v -n auto {posargs} + +# ============================================================================= +# Lint environments +# ============================================================================= + +[testenv:lint-azure] +description = Run linting for Azure flavor +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + -r {tox_root}/requirements/lint.txt + -r {tox_root}/requirements/azure.txt + -e {tox_root}/../generator +commands = + uv pip install azure-pylint-guidelines-checker==0.5.2 --index-url="https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-python/pypi/simple/" + python {tox_root}/install_packages.py azure {tox_root} + python {tox_root}/../eng/scripts/ci/run_pylint.py -t azure -s generated {posargs} + +[testenv:lint-unbranded] +description = Run linting for unbranded flavor +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + -r {tox_root}/requirements/lint.txt + -r {tox_root}/requirements/unbranded.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + python {tox_root}/../eng/scripts/ci/run_pylint.py -t unbranded -s generated {posargs} + +# ============================================================================= +# Type checking environments (separate mypy and pyright) +# ============================================================================= + +[testenv:mypy-azure] +description = Run mypy type checking for Azure flavor +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + -r {tox_root}/requirements/typecheck.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py azure {tox_root} + python {tox_root}/../eng/scripts/ci/run_mypy.py -t azure -s generated {posargs} + +[testenv:mypy-unbranded] +description = Run mypy type checking for unbranded flavor +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + -r {tox_root}/requirements/typecheck.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + python {tox_root}/../eng/scripts/ci/run_mypy.py -t unbranded -s generated {posargs} + +[testenv:pyright-azure] +description = Run pyright type checking for Azure flavor +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + -r {tox_root}/requirements/typecheck.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py azure {tox_root} + python {tox_root}/../eng/scripts/ci/run_pyright.py -t azure -s generated {posargs} + +[testenv:pyright-unbranded] +description = Run pyright type checking for unbranded flavor +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + -r {tox_root}/requirements/typecheck.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + python {tox_root}/../eng/scripts/ci/run_pyright.py -t unbranded -s generated {posargs} + +# ============================================================================= +# Documentation environments +# ============================================================================= + +[testenv:docs-azure] +description = Run documentation validation for Azure flavor +basepython = python3.10 +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + -r {tox_root}/requirements/docs.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py azure {tox_root} + python {tox_root}/../eng/scripts/ci/run_apiview.py -t azure -s generated {posargs} + python {tox_root}/../eng/scripts/ci/run_sphinx_build.py -t azure -s generated {posargs} + +[testenv:docs-unbranded] +description = Run documentation validation for unbranded flavor +basepython = python3.10 +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + -r {tox_root}/requirements/docs.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + python {tox_root}/../eng/scripts/ci/run_apiview.py -t unbranded -s generated {posargs} + python {tox_root}/../eng/scripts/ci/run_sphinx_build.py -t unbranded -s generated {posargs} + +# ============================================================================= +# CI environments (combines all checks) +# ============================================================================= + +[testenv:ci-azure] +description = Run full CI for Azure flavor +setenv = + {[testenv]setenv} + FLAVOR = azure +deps = + -r {tox_root}/requirements/lint.txt + -r {tox_root}/requirements/typecheck.txt + -r {tox_root}/requirements/azure.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py azure {tox_root} + pytest mock_api/azure mock_api/shared -v + python {tox_root}/../eng/scripts/ci/run_pylint.py -t azure -s generated + python {tox_root}/../eng/scripts/ci/run_mypy.py -t azure -s generated + python {tox_root}/../eng/scripts/ci/run_pyright.py -t azure -s generated + +[testenv:ci-unbranded] +description = Run full CI for unbranded flavor +setenv = + {[testenv]setenv} + FLAVOR = unbranded +deps = + -r {tox_root}/requirements/lint.txt + -r {tox_root}/requirements/typecheck.txt + -r {tox_root}/requirements/unbranded.txt + -e {tox_root}/../generator +commands = + python {tox_root}/install_packages.py unbranded {tox_root} + pytest mock_api/unbranded mock_api/shared -v + python {tox_root}/../eng/scripts/ci/run_pylint.py -t unbranded -s generated + python {tox_root}/../eng/scripts/ci/run_mypy.py -t unbranded -s generated + python {tox_root}/../eng/scripts/ci/run_pyright.py -t unbranded -s generated diff --git a/packages/http-client-python/generator/test/unittests/conftest.py b/packages/http-client-python/tests/unit/conftest.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/conftest.py rename to packages/http-client-python/tests/unit/conftest.py diff --git a/packages/http-client-python/generator/test/unittests/requirements.txt b/packages/http-client-python/tests/unit/requirements.txt similarity index 100% rename from packages/http-client-python/generator/test/unittests/requirements.txt rename to packages/http-client-python/tests/unit/requirements.txt diff --git a/packages/http-client-python/generator/test/unittests/test_enums.py b/packages/http-client-python/tests/unit/test_enums.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_enums.py rename to packages/http-client-python/tests/unit/test_enums.py diff --git a/packages/http-client-python/generator/test/unittests/test_model_base_serialization.py b/packages/http-client-python/tests/unit/test_model_base_serialization.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_model_base_serialization.py rename to packages/http-client-python/tests/unit/test_model_base_serialization.py diff --git a/packages/http-client-python/generator/test/unittests/test_model_base_xml_serialization.py b/packages/http-client-python/tests/unit/test_model_base_xml_serialization.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_model_base_xml_serialization.py rename to packages/http-client-python/tests/unit/test_model_base_xml_serialization.py diff --git a/packages/http-client-python/generator/test/unittests/test_name_converter.py b/packages/http-client-python/tests/unit/test_name_converter.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_name_converter.py rename to packages/http-client-python/tests/unit/test_name_converter.py diff --git a/packages/http-client-python/generator/test/unittests/test_optional_return_type.py b/packages/http-client-python/tests/unit/test_optional_return_type.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_optional_return_type.py rename to packages/http-client-python/tests/unit/test_optional_return_type.py diff --git a/packages/http-client-python/generator/test/unittests/test_parameter_ordering.py b/packages/http-client-python/tests/unit/test_parameter_ordering.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_parameter_ordering.py rename to packages/http-client-python/tests/unit/test_parameter_ordering.py diff --git a/packages/http-client-python/generator/test/unittests/test_sort_schema.py b/packages/http-client-python/tests/unit/test_sort_schema.py similarity index 100% rename from packages/http-client-python/generator/test/unittests/test_sort_schema.py rename to packages/http-client-python/tests/unit/test_sort_schema.py diff --git a/packages/http-client-python/generator/test/unittests/tox.ini b/packages/http-client-python/tests/unit/tox.ini similarity index 100% rename from packages/http-client-python/generator/test/unittests/tox.ini rename to packages/http-client-python/tests/unit/tox.ini