From 438f2607c1f28c3bd159a945cece17b31539682d Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 16:23:27 +0100 Subject: [PATCH 1/9] Adopt schemaver --- menuinst/_schema.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/menuinst/_schema.py b/menuinst/_schema.py index 1c15d135..56bec39b 100644 --- a/menuinst/_schema.py +++ b/menuinst/_schema.py @@ -27,7 +27,8 @@ log = getLogger(__name__) SCHEMA_DIALECT = "http://json-schema.org/draft-07/schema#" -SCHEMA_VERSION = "1" +# We follow schemaver +SCHEMA_VERSION = "1-1-0" SCHEMA_URL = f"https://schemas.conda.org/menuinst-{SCHEMA_VERSION}.schema.json" @@ -702,6 +703,7 @@ class Config(BaseModel.Config): schema_extra = { "$schema": SCHEMA_DIALECT, "$id": SCHEMA_URL, + "$version": SCHEMA_VERSION, } id_: constr(min_length=1) = Field( @@ -712,7 +714,7 @@ class Config(BaseModel.Config): ) schema_: constr(min_length=1) = Field( SCHEMA_URL, - description="Version of the menuinst schema.", + description="Version of the menuinst schema to validate against.", alias="$schema", ) menu_name: constr(min_length=1) = Field( From 12b82b698f2ef769d9c844a0aa83857f39fe44e8 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 16:23:55 +0100 Subject: [PATCH 2/9] Provide all schemas to date, versioned according to schemaver --- menuinst/data/menuinst-1-0-0.default.json | 66 ++ menuinst/data/menuinst-1-0-0.schema.json | 676 ++++++++++++++++ menuinst/data/menuinst-1-0-1.default.json | 68 ++ menuinst/data/menuinst-1-0-1.schema.json | 731 ++++++++++++++++++ ...fault.json => menuinst-1-0-2.default.json} | 0 ...schema.json => menuinst-1-0-2.schema.json} | 0 ...fault.json => menuinst-1-1-0.default.json} | 2 +- ...schema.json => menuinst-1-1-0.schema.json} | 11 +- 8 files changed, 1548 insertions(+), 6 deletions(-) create mode 100644 menuinst/data/menuinst-1-0-0.default.json create mode 100644 menuinst/data/menuinst-1-0-0.schema.json create mode 100644 menuinst/data/menuinst-1-0-1.default.json create mode 100644 menuinst/data/menuinst-1-0-1.schema.json rename menuinst/data/{menuinst.default.json => menuinst-1-0-2.default.json} (100%) rename menuinst/data/{menuinst.schema.json => menuinst-1-0-2.schema.json} (100%) rename menuinst/data/{menuinst-1.default.json => menuinst-1-1-0.default.json} (96%) rename menuinst/data/{menuinst-1.schema.json => menuinst-1-1-0.schema.json} (99%) diff --git a/menuinst/data/menuinst-1-0-0.default.json b/menuinst/data/menuinst-1-0-0.default.json new file mode 100644 index 00000000..b220ad39 --- /dev/null +++ b/menuinst/data/menuinst-1-0-0.default.json @@ -0,0 +1,66 @@ +{ + "id_": "https://schemas.conda.io/menuinst-1.schema.json", + "schema_": "https://json-schema.org/draft-07/schema", + "menu_name": "REQUIRED", + "menu_items": [ + { + "name": "REQUIRED", + "description": "REQUIRED", + "command": [ + "REQUIRED" + ], + "icon": null, + "precommand": null, + "precreate": null, + "working_dir": null, + "activate": true, + "terminal": false, + "platforms": { + "linux": { + "Categories": null, + "DBusActivatable": null, + "GenericName": null, + "Hidden": null, + "Implements": null, + "Keywords": null, + "MimeType": null, + "NoDisplay": null, + "NotShowIn": null, + "OnlyShowIn": null, + "PrefersNonDefaultGPU": null, + "StartupNotify": null, + "StartupWMClass": null, + "TryExec": null, + "glob_patterns": null + }, + "osx": { + "CFBundleDisplayName": null, + "CFBundleIdentifier": null, + "CFBundleName": null, + "CFBundleSpokenName": null, + "CFBundleVersion": null, + "CFBundleURLTypes": null, + "CFBundleDocumentTypes": null, + "LSApplicationCategoryType": null, + "LSBackgroundOnly": null, + "LSEnvironment": null, + "LSMinimumSystemVersion": null, + "LSMultipleInstancesProhibited": null, + "LSRequiresNativeExecution": null, + "UTExportedTypeDeclarations": null, + "UTImportedTypeDeclarations": null, + "entitlements": null, + "link_in_bundle": null, + "event_handler": null + }, + "win": { + "desktop": true, + "quicklaunch": true, + "url_protocols": null, + "file_extensions": null, + "app_user_model_id": null + } + } + } + ] +} diff --git a/menuinst/data/menuinst-1-0-0.schema.json b/menuinst/data/menuinst-1-0-0.schema.json new file mode 100644 index 00000000..b76b8ba7 --- /dev/null +++ b/menuinst/data/menuinst-1-0-0.schema.json @@ -0,0 +1,676 @@ +{ + "title": "MenuInstSchema", + "description": "Metadata required to create menu items across operating systems with ``menuinst``.", + "type": "object", + "properties": { + "$id": { + "title": "$Id", + "description": "Version of the menuinst schema.", + "enum": [ + "https://schemas.conda.io/menuinst-1.schema.json" + ], + "type": "string" + }, + "$schema": { + "title": "$Schema", + "description": "Standard of the JSON schema we adhere to.", + "enum": [ + "https://json-schema.org/draft-07/schema" + ], + "type": "string" + }, + "menu_name": { + "title": "Menu Name", + "minLength": 1, + "type": "string" + }, + "menu_items": { + "title": "Menu Items", + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/definitions/MenuItem" + } + } + }, + "required": [ + "$id", + "$schema", + "menu_name", + "menu_items" + ], + "additionalProperties": false, + "definitions": { + "Linux": { + "title": "Linux", + "description": "Linux-specific instructions.\n\nCheck the `Desktop entry specification `__ for more details.\n\n.. desktop-entry-spec: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#recognized-keys", + "type": "object", + "properties": { + "name": { + "title": "Name", + "minLength": 1, + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "Categories": { + "title": "Categories", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "DBusActivatable": { + "title": "Dbusactivatable", + "type": "boolean" + }, + "GenericName": { + "title": "Genericname", + "type": "string" + }, + "Hidden": { + "title": "Hidden", + "type": "boolean" + }, + "Implements": { + "title": "Implements", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "Keywords": { + "title": "Keywords", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "MimeType": { + "title": "Mimetype", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "NoDisplay": { + "title": "Nodisplay", + "type": "boolean" + }, + "NotShowIn": { + "title": "Notshowin", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "OnlyShowIn": { + "title": "Onlyshowin", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "PrefersNonDefaultGPU": { + "title": "Prefersnondefaultgpu", + "type": "boolean" + }, + "StartupNotify": { + "title": "Startupnotify", + "type": "boolean" + }, + "StartupWMClass": { + "title": "Startupwmclass", + "type": "string" + }, + "TryExec": { + "title": "Tryexec", + "type": "string" + }, + "glob_patterns": { + "title": "Glob Patterns", + "type": "object", + "additionalProperties": { + "type": "string", + "pattern": ".*\\*.*" + } + } + }, + "additionalProperties": false + }, + "CFBundleURLTypesModel": { + "title": "CFBundleURLTypesModel", + "description": "Describes a URL scheme associated with the app.", + "type": "object", + "properties": { + "CFBundleTypeRole": { + "title": "Cfbundletyperole", + "enum": [ + "Editor", + "Viewer", + "Shell", + "None" + ], + "type": "string" + }, + "CFBundleURLSchemes": { + "title": "Cfbundleurlschemes", + "type": "array", + "items": { + "type": "string" + } + }, + "CFBundleURLName": { + "title": "Cfbundleurlname", + "type": "string" + }, + "CFBundleURLIconFile": { + "title": "Cfbundleurliconfile", + "type": "string" + } + }, + "required": [ + "CFBundleURLSchemes" + ], + "additionalProperties": false + }, + "CFBundleDocumentTypesModel": { + "title": "CFBundleDocumentTypesModel", + "description": "Describes a document type associated with the app.", + "type": "object", + "properties": { + "CFBundleTypeIconFile": { + "title": "Cfbundletypeiconfile", + "type": "string" + }, + "CFBundleTypeName": { + "title": "Cfbundletypename", + "type": "string" + }, + "CFBundleTypeRole": { + "title": "Cfbundletyperole", + "enum": [ + "Editor", + "Viewer", + "Shell", + "None" + ], + "type": "string" + }, + "LSItemContentTypes": { + "title": "Lsitemcontenttypes", + "type": "array", + "items": { + "type": "string" + } + }, + "LSHandlerRank": { + "title": "Lshandlerrank", + "enum": [ + "Owner", + "Default", + "Alternate" + ], + "type": "string" + } + }, + "required": [ + "CFBundleTypeName", + "LSItemContentTypes", + "LSHandlerRank" + ], + "additionalProperties": false + }, + "UTTypeDeclarationModel": { + "title": "UTTypeDeclarationModel", + "type": "object", + "properties": { + "UTTypeConformsTo": { + "title": "Uttypeconformsto", + "type": "array", + "items": { + "type": "string" + } + }, + "UTTypeDescription": { + "title": "Uttypedescription", + "type": "string" + }, + "UTTypeIconFile": { + "title": "Uttypeiconfile", + "type": "string" + }, + "UTTypeIdentifier": { + "title": "Uttypeidentifier", + "type": "string" + }, + "UTTypeReferenceURL": { + "title": "Uttypereferenceurl", + "type": "string" + }, + "UTTypeTagSpecification": { + "title": "Uttypetagspecification", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "UTTypeConformsTo", + "UTTypeIdentifier", + "UTTypeTagSpecification" + ], + "additionalProperties": false + }, + "MacOS": { + "title": "MacOS", + "description": "Mac-specific instructions. Check these URLs for more info:\n\n- ``CF*`` keys: see `Core Foundation Keys `_\n- ``LS*`` keys: see `Launch Services Keys `_\n- ``entitlements``: see `entitlements docs `_\n\n.. _cf-keys: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html\n.. _ls-keys: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html\n.. _entitlements-docs: https://developer.apple.com/documentation/bundleresources/entitlements.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "minLength": 1, + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "CFBundleDisplayName": { + "title": "Cfbundledisplayname", + "type": "string" + }, + "CFBundleIdentifier": { + "title": "Cfbundleidentifier", + "pattern": "^[A-z0-9\\-\\.]+$", + "type": "string" + }, + "CFBundleName": { + "title": "Cfbundlename", + "maxLength": 16, + "type": "string" + }, + "CFBundleSpokenName": { + "title": "Cfbundlespokenname", + "type": "string" + }, + "CFBundleVersion": { + "title": "Cfbundleversion", + "pattern": "^\\S+$", + "type": "string" + }, + "CFBundleURLTypes": { + "title": "Cfbundleurltypes", + "type": "array", + "items": { + "$ref": "#/definitions/CFBundleURLTypesModel" + } + }, + "CFBundleDocumentTypes": { + "title": "Cfbundledocumenttypes", + "type": "array", + "items": { + "$ref": "#/definitions/CFBundleDocumentTypesModel" + } + }, + "LSApplicationCategoryType": { + "title": "Lsapplicationcategorytype", + "pattern": "^public\\.app-category\\.\\S+$", + "type": "string" + }, + "LSBackgroundOnly": { + "title": "Lsbackgroundonly", + "type": "boolean" + }, + "LSEnvironment": { + "title": "Lsenvironment", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "LSMinimumSystemVersion": { + "title": "Lsminimumsystemversion", + "pattern": "^\\d+\\.\\d+\\.\\d+$", + "type": "string" + }, + "LSMultipleInstancesProhibited": { + "title": "Lsmultipleinstancesprohibited", + "type": "boolean" + }, + "LSRequiresNativeExecution": { + "title": "Lsrequiresnativeexecution", + "type": "boolean" + }, + "UTExportedTypeDeclarations": { + "title": "Utexportedtypedeclarations", + "type": "array", + "items": { + "$ref": "#/definitions/UTTypeDeclarationModel" + } + }, + "UTImportedTypeDeclarations": { + "title": "Utimportedtypedeclarations", + "type": "array", + "items": { + "$ref": "#/definitions/UTTypeDeclarationModel" + } + }, + "entitlements": { + "title": "Entitlements", + "type": "array", + "items": { + "type": "string", + "pattern": "[a-z0-9\\.\\-]+" + } + }, + "link_in_bundle": { + "title": "Link In Bundle", + "type": "object", + "additionalProperties": { + "type": "string", + "pattern": "^(?!\\/)(?!\\.\\./).*" + } + }, + "event_handler": { + "title": "Event Handler", + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + }, + "Windows": { + "title": "Windows", + "description": "Windows-specific instructions. You can override global keys here if needed", + "type": "object", + "properties": { + "name": { + "title": "Name", + "minLength": 1, + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "desktop": { + "title": "Desktop", + "default": true, + "type": "boolean" + }, + "quicklaunch": { + "title": "Quicklaunch", + "default": true, + "type": "boolean" + }, + "url_protocols": { + "title": "Url Protocols", + "type": "array", + "items": { + "type": "string", + "pattern": "\\S+" + } + }, + "file_extensions": { + "title": "File Extensions", + "type": "array", + "items": { + "type": "string", + "pattern": "\\.\\S*" + } + }, + "app_user_model_id": { + "title": "App User Model Id", + "maxLength": 128, + "pattern": "\\S+\\.\\S+", + "type": "string" + } + }, + "additionalProperties": false + }, + "Platforms": { + "title": "Platforms", + "description": "Platform specific options.\n\nNote each of these fields supports the same keys as the top-level :class:`MenuItem`\n(sans ``platforms`` itself), in case overrides are needed.", + "type": "object", + "properties": { + "linux": { + "$ref": "#/definitions/Linux" + }, + "osx": { + "$ref": "#/definitions/MacOS" + }, + "win": { + "$ref": "#/definitions/Windows" + } + }, + "additionalProperties": false + }, + "MenuItem": { + "title": "MenuItem", + "description": "Instructions to create a menu item across operating systems.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "minLength": 1, + "type": "string" + }, + "description": { + "title": "Description", + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "default": true, + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "default": false, + "type": "boolean" + }, + "platforms": { + "$ref": "#/definitions/Platforms" + } + }, + "required": [ + "name", + "description", + "command", + "platforms" + ], + "additionalProperties": false + } + } +} diff --git a/menuinst/data/menuinst-1-0-1.default.json b/menuinst/data/menuinst-1-0-1.default.json new file mode 100644 index 00000000..c9acad43 --- /dev/null +++ b/menuinst/data/menuinst-1-0-1.default.json @@ -0,0 +1,68 @@ +{ + "id_": "https://schemas.conda.io/menuinst-1.schema.json", + "schema_": "https://json-schema.org/draft-07/schema", + "menu_name": "REQUIRED", + "menu_items": [ + { + "name": "REQUIRED", + "description": "REQUIRED", + "command": [ + "REQUIRED" + ], + "icon": null, + "precommand": null, + "precreate": null, + "working_dir": null, + "activate": true, + "terminal": false, + "platforms": { + "linux": { + "Categories": null, + "DBusActivatable": null, + "GenericName": null, + "Hidden": null, + "Implements": null, + "Keywords": null, + "MimeType": null, + "NoDisplay": null, + "NotShowIn": null, + "OnlyShowIn": null, + "PrefersNonDefaultGPU": null, + "StartupNotify": null, + "StartupWMClass": null, + "TryExec": null, + "glob_patterns": null + }, + "osx": { + "CFBundleDisplayName": null, + "CFBundleIdentifier": null, + "CFBundleName": null, + "CFBundleSpokenName": null, + "CFBundleVersion": null, + "CFBundleURLTypes": null, + "CFBundleDocumentTypes": null, + "LSApplicationCategoryType": null, + "LSBackgroundOnly": null, + "LSEnvironment": null, + "LSMinimumSystemVersion": null, + "LSMultipleInstancesProhibited": null, + "LSRequiresNativeExecution": null, + "NSSupportsAutomaticGraphicsSwitching": null, + "UTExportedTypeDeclarations": null, + "UTImportedTypeDeclarations": null, + "entitlements": null, + "link_in_bundle": null, + "event_handler": null + }, + "win": { + "desktop": true, + "quicklaunch": true, + "terminal_profile": null, + "url_protocols": null, + "file_extensions": null, + "app_user_model_id": null + } + } + } + ] +} diff --git a/menuinst/data/menuinst-1-0-1.schema.json b/menuinst/data/menuinst-1-0-1.schema.json new file mode 100644 index 00000000..9e49980b --- /dev/null +++ b/menuinst/data/menuinst-1-0-1.schema.json @@ -0,0 +1,731 @@ +{ + "title": "MenuInstSchema", + "description": "Metadata required to create menu items across operating systems with ``menuinst``.", + "type": "object", + "properties": { + "$id": { + "title": "$Id", + "description": "Version of the menuinst schema.", + "enum": [ + "https://schemas.conda.io/menuinst-1.schema.json" + ], + "type": "string" + }, + "$schema": { + "title": "$Schema", + "description": "Standard of the JSON schema we adhere to.", + "enum": [ + "https://json-schema.org/draft-07/schema" + ], + "type": "string" + }, + "menu_name": { + "title": "Menu Name", + "minLength": 1, + "type": "string" + }, + "menu_items": { + "title": "Menu Items", + "minItems": 1, + "type": "array", + "items": { + "$ref": "#/definitions/MenuItem" + } + } + }, + "required": [ + "$id", + "$schema", + "menu_name", + "menu_items" + ], + "additionalProperties": false, + "definitions": { + "MenuItemNameDict": { + "title": "MenuItemNameDict", + "description": "Variable menu item name.\nUse this dictionary if the menu item name depends on installation parameters\nsuch as the target environment.", + "type": "object", + "properties": { + "target_environment_is_base": { + "title": "Target Environment Is Base", + "minLength": 1, + "type": "string" + }, + "target_environment_is_not_base": { + "title": "Target Environment Is Not Base", + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + }, + "Linux": { + "title": "Linux", + "description": "Linux-specific instructions.\n\nCheck the `Desktop entry specification\n`__\nfor more details.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "$ref": "#/definitions/MenuItemNameDict" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "Categories": { + "title": "Categories", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "DBusActivatable": { + "title": "Dbusactivatable", + "type": "boolean" + }, + "GenericName": { + "title": "Genericname", + "type": "string" + }, + "Hidden": { + "title": "Hidden", + "type": "boolean" + }, + "Implements": { + "title": "Implements", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "Keywords": { + "title": "Keywords", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "MimeType": { + "title": "Mimetype", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "NoDisplay": { + "title": "Nodisplay", + "type": "boolean" + }, + "NotShowIn": { + "title": "Notshowin", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "OnlyShowIn": { + "title": "Onlyshowin", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^.+;$" + } + ] + }, + "PrefersNonDefaultGPU": { + "title": "Prefersnondefaultgpu", + "type": "boolean" + }, + "StartupNotify": { + "title": "Startupnotify", + "type": "boolean" + }, + "StartupWMClass": { + "title": "Startupwmclass", + "type": "string" + }, + "TryExec": { + "title": "Tryexec", + "type": "string" + }, + "glob_patterns": { + "title": "Glob Patterns", + "type": "object", + "additionalProperties": { + "type": "string", + "pattern": ".*\\*.*" + } + } + }, + "additionalProperties": false + }, + "CFBundleURLTypesModel": { + "title": "CFBundleURLTypesModel", + "description": "Describes a URL scheme associated with the app.", + "type": "object", + "properties": { + "CFBundleTypeRole": { + "title": "Cfbundletyperole", + "enum": [ + "Editor", + "Viewer", + "Shell", + "None" + ], + "type": "string" + }, + "CFBundleURLSchemes": { + "title": "Cfbundleurlschemes", + "type": "array", + "items": { + "type": "string" + } + }, + "CFBundleURLName": { + "title": "Cfbundleurlname", + "type": "string" + }, + "CFBundleURLIconFile": { + "title": "Cfbundleurliconfile", + "type": "string" + } + }, + "required": [ + "CFBundleURLSchemes" + ], + "additionalProperties": false + }, + "CFBundleDocumentTypesModel": { + "title": "CFBundleDocumentTypesModel", + "description": "Describes a document type associated with the app.", + "type": "object", + "properties": { + "CFBundleTypeIconFile": { + "title": "Cfbundletypeiconfile", + "type": "string" + }, + "CFBundleTypeName": { + "title": "Cfbundletypename", + "type": "string" + }, + "CFBundleTypeRole": { + "title": "Cfbundletyperole", + "enum": [ + "Editor", + "Viewer", + "Shell", + "None" + ], + "type": "string" + }, + "LSItemContentTypes": { + "title": "Lsitemcontenttypes", + "type": "array", + "items": { + "type": "string" + } + }, + "LSHandlerRank": { + "title": "Lshandlerrank", + "enum": [ + "Owner", + "Default", + "Alternate" + ], + "type": "string" + } + }, + "required": [ + "CFBundleTypeName", + "LSItemContentTypes", + "LSHandlerRank" + ], + "additionalProperties": false + }, + "UTTypeDeclarationModel": { + "title": "UTTypeDeclarationModel", + "type": "object", + "properties": { + "UTTypeConformsTo": { + "title": "Uttypeconformsto", + "type": "array", + "items": { + "type": "string" + } + }, + "UTTypeDescription": { + "title": "Uttypedescription", + "type": "string" + }, + "UTTypeIconFile": { + "title": "Uttypeiconfile", + "type": "string" + }, + "UTTypeIdentifier": { + "title": "Uttypeidentifier", + "type": "string" + }, + "UTTypeReferenceURL": { + "title": "Uttypereferenceurl", + "type": "string" + }, + "UTTypeTagSpecification": { + "title": "Uttypetagspecification", + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "UTTypeConformsTo", + "UTTypeIdentifier", + "UTTypeTagSpecification" + ], + "additionalProperties": false + }, + "MacOS": { + "title": "MacOS", + "description": "Mac-specific instructions. Check these URLs for more info:\n\n- ``CF*`` keys: see `Core Foundation Keys `__\n- ``LS*`` keys: see `Launch Services Keys `__\n- ``entitlements``: see `Entitlements documentation `__", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "$ref": "#/definitions/MenuItemNameDict" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "CFBundleDisplayName": { + "title": "Cfbundledisplayname", + "type": "string" + }, + "CFBundleIdentifier": { + "title": "Cfbundleidentifier", + "pattern": "^[A-z0-9\\-\\.]+$", + "type": "string" + }, + "CFBundleName": { + "title": "Cfbundlename", + "maxLength": 16, + "type": "string" + }, + "CFBundleSpokenName": { + "title": "Cfbundlespokenname", + "type": "string" + }, + "CFBundleVersion": { + "title": "Cfbundleversion", + "pattern": "^\\S+$", + "type": "string" + }, + "CFBundleURLTypes": { + "title": "Cfbundleurltypes", + "type": "array", + "items": { + "$ref": "#/definitions/CFBundleURLTypesModel" + } + }, + "CFBundleDocumentTypes": { + "title": "Cfbundledocumenttypes", + "type": "array", + "items": { + "$ref": "#/definitions/CFBundleDocumentTypesModel" + } + }, + "LSApplicationCategoryType": { + "title": "Lsapplicationcategorytype", + "pattern": "^public\\.app-category\\.\\S+$", + "type": "string" + }, + "LSBackgroundOnly": { + "title": "Lsbackgroundonly", + "type": "boolean" + }, + "LSEnvironment": { + "title": "Lsenvironment", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "LSMinimumSystemVersion": { + "title": "Lsminimumsystemversion", + "pattern": "^\\d+\\.\\d+\\.\\d+$", + "type": "string" + }, + "LSMultipleInstancesProhibited": { + "title": "Lsmultipleinstancesprohibited", + "type": "boolean" + }, + "LSRequiresNativeExecution": { + "title": "Lsrequiresnativeexecution", + "type": "boolean" + }, + "NSSupportsAutomaticGraphicsSwitching": { + "title": "Nssupportsautomaticgraphicsswitching", + "type": "boolean" + }, + "UTExportedTypeDeclarations": { + "title": "Utexportedtypedeclarations", + "type": "array", + "items": { + "$ref": "#/definitions/UTTypeDeclarationModel" + } + }, + "UTImportedTypeDeclarations": { + "title": "Utimportedtypedeclarations", + "type": "array", + "items": { + "$ref": "#/definitions/UTTypeDeclarationModel" + } + }, + "entitlements": { + "title": "Entitlements", + "type": "array", + "items": { + "type": "string", + "pattern": "[a-z0-9\\.\\-]+" + } + }, + "link_in_bundle": { + "title": "Link In Bundle", + "type": "object", + "additionalProperties": { + "type": "string", + "pattern": "^(?!\\/)(?!\\.\\./).*" + } + }, + "event_handler": { + "title": "Event Handler", + "minLength": 1, + "type": "string" + } + }, + "additionalProperties": false + }, + "Windows": { + "title": "Windows", + "description": "Windows-specific instructions. You can override global keys here if needed", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "$ref": "#/definitions/MenuItemNameDict" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "type": "boolean" + }, + "desktop": { + "title": "Desktop", + "default": true, + "type": "boolean" + }, + "quicklaunch": { + "title": "Quicklaunch", + "default": true, + "type": "boolean" + }, + "terminal_profile": { + "title": "Terminal Profile", + "minLength": 1, + "type": "string" + }, + "url_protocols": { + "title": "Url Protocols", + "type": "array", + "items": { + "type": "string", + "pattern": "\\S+" + } + }, + "file_extensions": { + "title": "File Extensions", + "type": "array", + "items": { + "type": "string", + "pattern": "\\.\\S*" + } + }, + "app_user_model_id": { + "title": "App User Model Id", + "maxLength": 128, + "pattern": "\\S+\\.\\S+", + "type": "string" + } + }, + "additionalProperties": false + }, + "Platforms": { + "title": "Platforms", + "description": "Platform specific options.\n\nNote each of these fields supports the same keys as the top-level :class:`MenuItem`\n(sans ``platforms`` itself), in case overrides are needed.", + "type": "object", + "properties": { + "linux": { + "$ref": "#/definitions/Linux" + }, + "osx": { + "$ref": "#/definitions/MacOS" + }, + "win": { + "$ref": "#/definitions/Windows" + } + }, + "additionalProperties": false + }, + "MenuItem": { + "title": "MenuItem", + "description": "Instructions to create a menu item across operating systems.", + "type": "object", + "properties": { + "name": { + "title": "Name", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "$ref": "#/definitions/MenuItemNameDict" + } + ] + }, + "description": { + "title": "Description", + "type": "string" + }, + "command": { + "title": "Command", + "minItems": 1, + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "title": "Icon", + "minLength": 1, + "type": "string" + }, + "precommand": { + "title": "Precommand", + "minLength": 1, + "type": "string" + }, + "precreate": { + "title": "Precreate", + "minLength": 1, + "type": "string" + }, + "working_dir": { + "title": "Working Dir", + "minLength": 1, + "type": "string" + }, + "activate": { + "title": "Activate", + "default": true, + "type": "boolean" + }, + "terminal": { + "title": "Terminal", + "default": false, + "type": "boolean" + }, + "platforms": { + "$ref": "#/definitions/Platforms" + } + }, + "required": [ + "name", + "description", + "command", + "platforms" + ], + "additionalProperties": false + } + } +} diff --git a/menuinst/data/menuinst.default.json b/menuinst/data/menuinst-1-0-2.default.json similarity index 100% rename from menuinst/data/menuinst.default.json rename to menuinst/data/menuinst-1-0-2.default.json diff --git a/menuinst/data/menuinst.schema.json b/menuinst/data/menuinst-1-0-2.schema.json similarity index 100% rename from menuinst/data/menuinst.schema.json rename to menuinst/data/menuinst-1-0-2.schema.json diff --git a/menuinst/data/menuinst-1.default.json b/menuinst/data/menuinst-1-1-0.default.json similarity index 96% rename from menuinst/data/menuinst-1.default.json rename to menuinst/data/menuinst-1-1-0.default.json index 0f0efd32..ab13c3e5 100644 --- a/menuinst/data/menuinst-1.default.json +++ b/menuinst/data/menuinst-1-1-0.default.json @@ -64,5 +64,5 @@ } } ], - "$schema": "https://schemas.conda.org/menuinst-1.schema.json" + "$schema": "https://schemas.conda.org/menuinst-1-1-0.schema.json" } diff --git a/menuinst/data/menuinst-1.schema.json b/menuinst/data/menuinst-1-1-0.schema.json similarity index 99% rename from menuinst/data/menuinst-1.schema.json rename to menuinst/data/menuinst-1-1-0.schema.json index 7e7e8f09..6c815e64 100644 --- a/menuinst/data/menuinst-1.schema.json +++ b/menuinst/data/menuinst-1-1-0.schema.json @@ -6,7 +6,7 @@ "$id": { "title": "$Id", "description": "DEPRECATED. Use ``$schema``.", - "default": "https://schemas.conda.org/menuinst-1.schema.json", + "default": "https://schemas.conda.org/menuinst-1-1-0.schema.json", "deprecated": true, "markdownDescription": "DEPRECATED. Use ``$schema``.", "minLength": 1, @@ -14,9 +14,9 @@ }, "$schema": { "title": "$Schema", - "description": "Version of the menuinst schema.", - "default": "https://schemas.conda.org/menuinst-1.schema.json", - "markdownDescription": "Version of the menuinst schema.", + "description": "Version of the menuinst schema to validate against.", + "default": "https://schemas.conda.org/menuinst-1-1-0.schema.json", + "markdownDescription": "Version of the menuinst schema to validate against.", "minLength": 1, "type": "string" }, @@ -44,7 +44,8 @@ ], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://schemas.conda.org/menuinst-1.schema.json", + "$id": "https://schemas.conda.org/menuinst-1-1-0.schema.json", + "$version": "1-1-0", "definitions": { "MenuItemNameDict": { "title": "MenuItemNameDict", From 2b764215d209d00bbd626cd106522d42e5db07f3 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 16:27:32 +0100 Subject: [PATCH 3/9] symlink versionless schema to latest 1-0-x schema --- menuinst/data/menuinst.schema.json | 1 + 1 file changed, 1 insertion(+) create mode 120000 menuinst/data/menuinst.schema.json diff --git a/menuinst/data/menuinst.schema.json b/menuinst/data/menuinst.schema.json new file mode 120000 index 00000000..7036ac9a --- /dev/null +++ b/menuinst/data/menuinst.schema.json @@ -0,0 +1 @@ +menuinst-1-0-2.schema.json \ No newline at end of file From ad984515aea63f32e055e1b700711ad1c60eaae1 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:11:55 +0100 Subject: [PATCH 4/9] define here too --- menuinst/platforms/base.py | 3 ++- tests/test_data.py | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/menuinst/platforms/base.py b/menuinst/platforms/base.py index d3119e6b..c7e7926c 100644 --- a/menuinst/platforms/base.py +++ b/menuinst/platforms/base.py @@ -22,6 +22,7 @@ ) log = getLogger(__name__) +SCHEMA_VERSION = "1-1-0" class Menu: @@ -266,5 +267,5 @@ def platform_key(platform: str = sys.platform) -> str: menuitem_defaults = json.loads( - (Path(__file__).parents[1] / "data" / "menuinst.default.json").read_text() + (Path(__file__).parents[1] / "data" / f"menuinst-{SCHEMA_VERSION}.default.json").read_text() )["menu_items"][0] diff --git a/tests/test_data.py b/tests/test_data.py index 55628bc4..759f71f9 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -2,6 +2,7 @@ import json +from menuinst.platforms.base import SCHEMA_VERSION as SCHEMA_VERSION_BASE from menuinst._schema import SCHEMA_VERSION, dump_default_to_json, dump_schema_to_json from menuinst.utils import data_path @@ -18,3 +19,11 @@ def test_defaults_are_up_to_date(): in_file = json.load(f) in_code = dump_default_to_json(write=False) assert in_file == in_code + + +def test_schema_versions_in_sync(): + assert SCHEMA_VERSION_BASE == SCHEMA_VERSION, ( + "meninst._schema and menuinst.platforms.base must " + "have the same 'SCHEMA_VERSION' value" + ) + \ No newline at end of file From e163f7cc4f6200dfb1cdb86cef04fb25b2d5e124 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:12:24 +0100 Subject: [PATCH 5/9] pre-commit --- tests/test_data.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_data.py b/tests/test_data.py index 759f71f9..fa4b6ce5 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -2,8 +2,8 @@ import json -from menuinst.platforms.base import SCHEMA_VERSION as SCHEMA_VERSION_BASE from menuinst._schema import SCHEMA_VERSION, dump_default_to_json, dump_schema_to_json +from menuinst.platforms.base import SCHEMA_VERSION as SCHEMA_VERSION_BASE from menuinst.utils import data_path @@ -23,7 +23,5 @@ def test_defaults_are_up_to_date(): def test_schema_versions_in_sync(): assert SCHEMA_VERSION_BASE == SCHEMA_VERSION, ( - "meninst._schema and menuinst.platforms.base must " - "have the same 'SCHEMA_VERSION' value" + "meninst._schema and menuinst.platforms.base must " "have the same 'SCHEMA_VERSION' value" ) - \ No newline at end of file From 9f94e46d782c7afd3ab12f7aaa64e4f2103c6cc2 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:15:31 +0100 Subject: [PATCH 6/9] add news --- news/288-schemaver | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 news/288-schemaver diff --git a/news/288-schemaver b/news/288-schemaver new file mode 100644 index 00000000..3f6327ca --- /dev/null +++ b/news/288-schemaver @@ -0,0 +1,19 @@ +### Enhancements + +* Version the JSON schema using SchemaVer. Current version is `1-1-0`. Previous versions are still available as `1-0-0` (as published in menuinst v2.0.0), `1-0-1` (as published in menuinst v2.1.0), and `1-0-2` (as published in menuinst v2.2.0) (#288) + +### Bug fixes + +* + +### Deprecations + +* + +### Docs + +* + +### Other + +* From dea52e3a5d9918481a15926a74543cb312455d99 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:16:44 +0100 Subject: [PATCH 7/9] and here --- menuinst/platforms/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menuinst/platforms/base.py b/menuinst/platforms/base.py index c7e7926c..7b1c6c3b 100644 --- a/menuinst/platforms/base.py +++ b/menuinst/platforms/base.py @@ -218,7 +218,7 @@ def _paths(self) -> Iterable[os.PathLike]: @staticmethod def _initialize_on_defaults(data) -> Dict: - with open(data_path("menuinst.default.json")) as f: + with open(data_path(f"menuinst-{SCHEMA_VERSION}.default.json")) as f: defaults = json.load(f)["menu_items"][0] return deep_update(defaults, data) From def336af5f65298214c7fc1e17c1b3680fad1d2e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:40:15 +0100 Subject: [PATCH 8/9] fix docs --- docs/source/conf.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 4148b3a4..77da7171 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -52,12 +52,11 @@ "tasklist", ] myst_linkify_fuzzy_links = False -default_config_payload = json.dumps( - json.loads( - (Path(__file__).parents[2] / "menuinst" / "data" / "menuinst.default.json").read_text() - ), - indent=2, -) +latest_default = sorted( + (Path(__file__).parents[2] / "menuinst" / "data").glob("*-*.default.json"), + key=lambda path: [int(x) for x in path.name.split(".")[0].rsplit("-", 3)[-3:]] +)[-1] +default_config_payload = json.dumps(json.loads(latest_default.read_text()), indent=2) myst_substitutions = { "default_schema_json": f"```json\n{default_config_payload}\n```", } From e39299e3daa823c53f6a0e67220690b0062a791f Mon Sep 17 00:00:00 2001 From: jaimergp Date: Sat, 14 Dec 2024 17:41:14 +0100 Subject: [PATCH 9/9] pre-commit --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 77da7171..f84687be 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -54,7 +54,7 @@ myst_linkify_fuzzy_links = False latest_default = sorted( (Path(__file__).parents[2] / "menuinst" / "data").glob("*-*.default.json"), - key=lambda path: [int(x) for x in path.name.split(".")[0].rsplit("-", 3)[-3:]] + key=lambda path: [int(x) for x in path.name.split(".")[0].rsplit("-", 3)[-3:]], )[-1] default_config_payload = json.dumps(json.loads(latest_default.read_text()), indent=2) myst_substitutions = {