Skip to content

Commit

Permalink
refactor: scripts/update_schema.py
Browse files Browse the repository at this point in the history
Signed-off-by: Jack Cherng <jfcherng@gmail.com>
  • Loading branch information
jfcherng committed Dec 13, 2023
1 parent 5bc8004 commit 2af1cb2
Showing 1 changed file with 70 additions and 63 deletions.
133 changes: 70 additions & 63 deletions scripts/update_schema.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,83 @@
from json import dump, dumps, load
from typing import Any, Dict, List, Optional, Tuple
from collections.abc import Generator
from typing import Any
from urllib.request import urlopen
import os
from pathlib import Path
import json

DIRNAME = os.path.dirname(os.path.abspath(__file__))
PYRIGHTCONFIG_SCHEMA_ID = 'sublime://pyrightconfig'
PYRIGHT_CONFIGURATION_SCHEMA_URL = 'https://raw.githubusercontent.com/microsoft/pyright/main/packages/vscode-pyright/schemas/pyrightconfig.schema.json' # noqa: E501
SUBLIME_PACKAGE_JSON_PATH = os.path.join(DIRNAME, '..', 'sublime-package.json')
PACKAGE_NAME = "LSP-pyright"

PROJECT_ROOT = Path(__file__).parents[1]
PYRIGHTCONFIG_SCHEMA_ID = "sublime://pyrightconfig"
PYRIGHT_CONFIGURATION_SCHEMA_URL = "https://raw.githubusercontent.com/microsoft/pyright/main/packages/vscode-pyright/schemas/pyrightconfig.schema.json" # noqa: E501
SUBLIME_PACKAGE_JSON_PATH = PROJECT_ROOT / "sublime-package.json"
# Keys that are in the pyrightconfig.json schema but should not raise a comment when not present in the LSP schema.
IGNORED_PYRIGHTCONFIG_KEYS = [
'defineConstant',
'exclude',
'executionEnvironments',
'ignore',
'include',
'pythonPlatform',
'pythonVersion',
'strict',
'typeshedPath',
'venv',
'verboseOutput',
]
IGNORED_PYRIGHTCONFIG_KEYS = {
"defineConstant",
"exclude",
"executionEnvironments",
"ignore",
"include",
"pythonPlatform",
"pythonVersion",
"strict",
"typeshedPath",
"venv",
"verboseOutput",
}

JSON = Dict[str, Any]
JsonDict = dict[str, Any]


def main() -> None:
json_dump_kwargs = {"indent": 2, "ensure_ascii": False, "sort_keys": True}
pyrightconfig_schema_json, sublime_package_schema_json = read_sublime_package_json()
before = dumps(sublime_package_schema_json)
new_schema_keys = update_schema(sublime_package_schema_json, pyrightconfig_schema_json)
after = dumps(sublime_package_schema_json)
before = json.dumps(sublime_package_schema_json, **json_dump_kwargs)
new_schema_keys = sorted(update_schema(sublime_package_schema_json, pyrightconfig_schema_json))
after = json.dumps(sublime_package_schema_json, **json_dump_kwargs)
if before != after:
with open(SUBLIME_PACKAGE_JSON_PATH, 'w', encoding='utf-8') as f:
dump(sublime_package_schema_json, f, indent=2)
print('sublime-package.json schema updated.')
SUBLIME_PACKAGE_JSON_PATH.write_text(after, encoding="utf-8")
print("sublime-package.json schema updated.")
else:
print('No updates done to sublime-package.json.')
print("No updates done to sublime-package.json.")
if new_schema_keys:
print('\nThe following new keys were found in the latest pyrightconfig.json schema: {}\n\n'.format(
'\n - '.join(new_schema_keys)))
print('Ensure that those are added to the sublime-package.json manually, if relevant.')
new_schema_keys_text = "\n - ".join(new_schema_keys)
print(f"\nNew keys found in the latest pyrightconfig.json schema: {new_schema_keys_text}\n\n")
print("Ensure that those are added to the sublime-package.json manually, if relevant.")


def read_sublime_package_json() -> Tuple[JSON, JSON]:
def read_sublime_package_json() -> tuple[JsonDict, JsonDict]:
with urlopen(PYRIGHT_CONFIGURATION_SCHEMA_URL) as response:
pyrightconfig_schema_json = load(response)
with open(SUBLIME_PACKAGE_JSON_PATH, 'r', encoding='utf-8') as f:
sublime_package_schema_json = load(f)
pyrightconfig_schema_json: JsonDict = json.load(response)
sublime_package_schema_json: JsonDict = json.loads(SUBLIME_PACKAGE_JSON_PATH.read_bytes())
return (pyrightconfig_schema_json, sublime_package_schema_json)


def update_schema(sublime_package_json: JSON, pyrightconfig_schema_json: JSON) -> List[str]:
pyrightconfig_contribution: Optional[JSON] = None
lsp_pyright_contribution: Optional[JSON] = None
for contribution in sublime_package_json['contributions']['settings']:
if '/pyrightconfig.json' in contribution['file_patterns']:
def update_schema(sublime_package_json: JsonDict, pyrightconfig_schema_json: JsonDict) -> Generator[str, None, None]:
pyrightconfig_contribution: JsonDict | None = None
lsp_pyright_contribution: JsonDict | None = None
for contribution in sublime_package_json["contributions"]["settings"]:
if "/pyrightconfig.json" in contribution["file_patterns"]:
pyrightconfig_contribution = contribution
elif '/LSP-pyright.sublime-settings' in contribution['file_patterns']:
elif f"/{PACKAGE_NAME}.sublime-settings" in contribution["file_patterns"]:
lsp_pyright_contribution = contribution
if not pyrightconfig_contribution or not lsp_pyright_contribution:
raise Exception('Expected contributions not found in sublime-package.json!')
if not (pyrightconfig_contribution and lsp_pyright_contribution):
raise Exception("Expected contributions not found in sublime-package.json!")
# Update to latest pyrightconfig schema.
pyrightconfig_contribution['schema'] = pyrightconfig_schema_json
pyrightconfig_contribution["schema"] = pyrightconfig_schema_json
# Add ID.
pyrightconfig_contribution['schema']['$id'] = PYRIGHTCONFIG_SCHEMA_ID
pyrightconfig_contribution["schema"]["$id"] = PYRIGHTCONFIG_SCHEMA_ID
# Update LSP settings to reference options from the pyrightconfig schema.
settings_properties: JSON = lsp_pyright_contribution['schema']['definitions']['PluginConfig']['properties']['settings']['properties'] # noqa: E501
pyrightconfig_properties: JSON = pyrightconfig_contribution['schema']['properties']
# fmt: off
settings_properties: JsonDict = lsp_pyright_contribution["schema"]["definitions"]["PluginConfig"]["properties"]["settings"]["properties"] # noqa: E501
# fmt: on
pyrightconfig_properties: JsonDict = pyrightconfig_contribution["schema"]["properties"]
for setting_key, setting_value in settings_properties.items():
# get last dotted component.
last_component_key = setting_key.split('.').pop()
last_component_key = setting_key.rpartition(".")[2]
if last_component_key in pyrightconfig_properties:
update_property_ref(last_component_key, setting_value, pyrightconfig_properties)
if setting_key == 'python.analysis.diagnosticSeverityOverrides':
overrides_properties: JSON = setting_value['properties']
if setting_key == "python.analysis.diagnosticSeverityOverrides":
overrides_properties: JsonDict = setting_value["properties"]
for override_key, override_value in overrides_properties.items():
if override_key in pyrightconfig_properties:
update_property_ref(override_key, override_value, pyrightconfig_properties)
Expand All @@ -82,22 +86,25 @@ def update_schema(sublime_package_json: JSON, pyrightconfig_schema_json: JSON) -
# Check if there are any properties that might need to be added to the LSP properties.
# If the property is neither in `diagnosticSeverityOverrides`, the root LSP settings nor in ignored keys
# then it might have to be added manually.
all_settings_keys = list(map(lambda k: k.split('.').pop(), settings_properties.keys()))
all_overrides_keys = settings_properties['python.analysis.diagnosticSeverityOverrides']['properties'].keys()
new_schema_keys = []
for pyrightconfig_key in pyrightconfig_properties.keys():
if pyrightconfig_key not in all_settings_keys \
and pyrightconfig_key not in all_overrides_keys \
and pyrightconfig_key not in IGNORED_PYRIGHTCONFIG_KEYS:
new_schema_keys.append(pyrightconfig_key)
return new_schema_keys
all_settings_keys = [key.rpartition(".")[2] for key in settings_properties.keys()]
all_overrides_keys = settings_properties["python.analysis.diagnosticSeverityOverrides"]["properties"].keys()

yield from (
pyrightconfig_key
for pyrightconfig_key in pyrightconfig_properties.keys()
if not (
pyrightconfig_key in all_settings_keys
or pyrightconfig_key in all_overrides_keys
or pyrightconfig_key in IGNORED_PYRIGHTCONFIG_KEYS
)
)


def update_property_ref(property_key: str, property_schema: JSON, pyrightconfig_properties: JSON) -> None:
def update_property_ref(property_key: str, property_schema: JsonDict, pyrightconfig_properties: JsonDict) -> None:
property_schema.clear()
pyrightconfig_property_id: str = pyrightconfig_properties[property_key]['$id']
property_schema['$ref'] = PYRIGHTCONFIG_SCHEMA_ID + pyrightconfig_property_id
pyrightconfig_property_id: str = pyrightconfig_properties[property_key]["$id"]
property_schema["$ref"] = PYRIGHTCONFIG_SCHEMA_ID + pyrightconfig_property_id


if __name__ == '__main__':
if __name__ == "__main__":
main()

0 comments on commit 2af1cb2

Please sign in to comment.