Add script to generate Nuspec wrapper library.

This tool will help facilitate development of nupkg and chocolately
processors and associated libraries. The generated output is included in
this commit.
This commit is contained in:
Brian Smith
2020-06-26 16:43:52 -07:00
parent 8e7db9b9c9
commit 55956e4d17
5 changed files with 4490 additions and 1 deletions
+1
View File
@@ -18,6 +18,7 @@ ignore = E127, E128, E203, E265, E266, E402, E501, E722, P207, P208, W503
exclude =
.git,
.hg,
Code/nupkg/generated/*,
# This will be fine-tuned over time
max-complexity = 65
# Ignore the line length limits on tests, where we have in-line plist strings
+1
View File
@@ -1,3 +1,4 @@
exclude: '^Code/nuget/generated/.*$'
repos:
- repo: https://github.com/python/black
rev: 19.10b0
File diff suppressed because it is too large Load Diff
+119
View File
@@ -0,0 +1,119 @@
#!/usr/local/autopkg/python
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Regenerates the NuSpec XML schema Python wrapper module from upstream source.
Downloads the latest NuSpec XSD from the GitHub NuGet/NuGet.Client Git repository,
and creates a wrapper library using the `generateDS` utility.
"""
import os
import sys
# isort: off
# Ensure that we can find autopkglib no matter where we run this.
AUTOPKG_TOP: str = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "Code")
)
sys.path.insert(0, AUTOPKG_TOP)
# isort: on
import ssl
import subprocess
from argparse import ArgumentParser
from typing import List
from urllib.request import urlopen
from autopkglib import find_binary
SCHEMA_SOURCE_URL: str = (
"https://raw.githubusercontent.com/NuGet/NuGet.Client"
"/dev/src/NuGet.Core/NuGet.Packaging/compiler/resources/nuspec.xsd"
)
# Latest known version of the Nuspec XML schema namespace. Found by running `choco new`.
# Used because the schema source contains placeholders for the namespace.
SCHEMA_XMLNS: bytes = b"http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd"
def get_schema_source(url: str, xmlns: bytes = SCHEMA_XMLNS) -> bytes:
"""Fetch the latest XML schema and replace `{0}` with the given XML namespace."""
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
with urlopen(SCHEMA_SOURCE_URL, context=context) as res:
return res.read().replace(b"{0}", xmlns)
def run_generateds(generateds_binary: str, output_path: str, schema_source: bytes):
"""Generate python wrapper library around the provided XML schema."""
call_res = subprocess.run(
[
generateds_binary,
# Enable using Python __slots__ object annotation to improve performance.
"--member-specs=dict",
"--enable-slots",
# Generate methods to write to files and validate objects.
"--export=write validate",
# Do not prompt and force overwrite existing files.
"--no-questions",
"-f",
"-o",
output_path,
"-",
],
input=schema_source,
)
return call_res.returncode
def main(input_args: List[str]) -> int:
parser = ArgumentParser(
description="Regenerate the python wrapper library around the nuget xml schema."
)
parser.add_argument(
"--output-path",
help=(
"Full path to the output file. "
"Intermediate directories are created as needed."
),
required=True,
)
parser.add_argument(
"--generateds-binary",
help="Path to generateDS. If not specified, defaults to looking in $env:PATH",
default=None,
)
args = parser.parse_args(input_args)
if args.generateds_binary is None:
args.generateds_binary = find_binary("generateDS")
if args.generateds_binary is None:
print("ERROR: Unable to locate generateDS! Try passing --generateds-binary.")
return 1
# Create any directories as needed.
output_dir = os.path.abspath(os.path.dirname(args.output_path))
print(f"Generated output is being written to: {output_dir}")
os.makedirs(output_dir, exist_ok=True)
return run_generateds(
args.generateds_binary, args.output_path, get_schema_source(SCHEMA_SOURCE_URL)
)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
+5 -1
View File
@@ -147,4 +147,8 @@ pyobjc-framework-VideoSubscriberAccount==6.0.1; sys_platform == 'darwin'
pyobjc-framework-VideoToolbox==6.0.1; sys_platform == 'darwin'
pyobjc-framework-Vision==6.0.1; sys_platform == 'darwin'
pyobjc-framework-WebKit==6.0.1; sys_platform == 'darwin'
pyobjc==6.0.1; sys_platform == 'darwin'
pyobjc==6.0.1; sys_platform == 'darwin'
#
# Windows Requirements
#
generateDS==2.35.24; sys_platform == 'win32'