diff --git a/ruff.toml b/ruff.toml index 5ebeee3197..75c69dfa24 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,3 +1,25 @@ +# default excludes minus "dist" +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "node_modules", + "venv"] + line-length = 99 target-version = "py311" diff --git a/source/tools/dist/build-osx-bundle.py b/source/tools/dist/build-osx-bundle.py index 7f16545402..a6a51290c7 100755 --- a/source/tools/dist/build-osx-bundle.py +++ b/source/tools/dist/build-osx-bundle.py @@ -1,38 +1,41 @@ #!/usr/bin/python3 -""" -Builds the OSX bundle from existing elements. +"""Build the OSX bundle from existing elements. + App bundles are intended to be self-contained and portable. An SDK is required, usually included with Xcode. The SDK ensures that only those system libraries are used which are available on the chosen target and compatible systems. -This is Python because plistlib is extremely strict about what it accepts +This is Python because plistlib is extremely strict about what it accepts, and it's used by dmgbuild, and saving the Plist doesn't really work otherwise. """ + import argparse -import datetime import glob import os import plistlib import shutil import subprocess +import sys +from datetime import datetime import dmgbuild + parser = argparse.ArgumentParser() -parser.add_argument('bundle_version', help='Bundle version') -parser.add_argument('--architecture', help='aarch64 (arm64) or x86_64 (amd64)', - default='aarch64') -parser.add_argument('--min_osx', help='Minimum supported OSX version', - default='10.12') -parser.add_argument('--bundle_identifier', help='Bundle identifier', - default='com.wildfiregames.play0ad') -parser.add_argument('-s', '--signkey', help='Signature key sha sum') -parser.add_argument('--notarytool_user', help='Apple ID user for notarization') -parser.add_argument('--notarytool_team', help='Team ID for notarization') -parser.add_argument('--notarytool_password', help='App password for notarization') -parser.add_argument('--dev', help='Turn on dev mode, which isn\'t fit for release but faster', - action="store_true") +parser.add_argument("bundle_version", help="Bundle version") +parser.add_argument("--architecture", help="aarch64 (arm64) or x86_64 (amd64)", default="aarch64") +parser.add_argument("--min_osx", help="Minimum supported OSX version", default="10.12") +parser.add_argument( + "--bundle_identifier", help="Bundle identifier", default="com.wildfiregames.play0ad" +) +parser.add_argument("-s", "--signkey", help="Signature key sha sum") +parser.add_argument("--notarytool_user", help="Apple ID user for notarization") +parser.add_argument("--notarytool_team", help="Team ID for notarization") +parser.add_argument("--notarytool_password", help="App password for notarization") +parser.add_argument( + "--dev", help="Turn on dev mode, which isn't fit for release but faster", action="store_true" +) args = parser.parse_args() ARCH = args.architecture @@ -77,9 +80,18 @@ shutil.copy("binaries/system/libMoltenVK.dylib", BUNDLE_FRAMEWORKS) if not args.dev: print("Signing libs") - subprocess.run(["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libAtlasUI.dylib"], check=True) - subprocess.run(["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libCollada.dylib"], check=True) - subprocess.run(["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libMoltenVK.dylib"], check=True) + subprocess.run( + ["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libAtlasUI.dylib"], + check=True, + ) + subprocess.run( + ["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libCollada.dylib"], + check=True, + ) + subprocess.run( + ["codesign", "-s", SIGNKEY, "-f", "--timestamp", BUNDLE_FRAMEWORKS + "/libMoltenVK.dylib"], + check=True, + ) if not args.dev: print("Copying archived game data from archives/") @@ -112,50 +124,72 @@ shutil.copy("libraries/LICENSE.txt", BUNDLE_RESOURCES + "/LIB_LICENSE.txt") print("Creating Info.plist") -with open(BUNDLE_CONTENTS + "/Info.plist", 'wb') as f: - plistlib.dump({ - 'CFBundleName': '0 A.D.', - 'CFBundleIdentifier': BUNDLE_IDENTIFIER, - 'CFBundleVersion': BUNDLE_VERSION, - 'CFBundlePackageType': 'APPL', - 'CFBundleSignature': 'none', - 'CFBundleExecutable': 'pyrogenesis', - 'CFBundleShortVersionString': BUNDLE_VERSION, - 'CFBundleDevelopmentRegion': 'English', - 'CFBundleInfoDictionaryVersion': '6.0', - 'CFBundleIconFile': '0ad', - 'LSHasLocalizedDisplayName': True, - 'LSMinimumSystemVersion': BUNDLE_MIN_OSX_VERSION, - 'NSHumanReadableCopyright': f'Copyright © {datetime.datetime.now().year} Wildfire Games', - 'UTExportedTypeDeclarations': [{ - 'UTTypeIdentifier': BUNDLE_IDENTIFIER, - 'UTTypeTagSpecification': { - 'public.filename-extension': ["pyromod"], - }, - 'UTTypeConformsTo': ['public.zip-archive'], - 'UTTypeDescription': '0 A.D. Zipped Mod', - 'UTTypeIconFile': '0ad' - }], - 'CFBundleDocumentTypes': [{ - 'CFBundleTypeExtensions': ['pyromod'], - 'CFBundleTypeRole': 'Editor', - 'CFBundleTypeIconFile': '0ad', - 'LSHandlerRank': 'Owner' - }, +with open(BUNDLE_CONTENTS + "/Info.plist", "wb") as f: + plistlib.dump( { - 'CFBundleTypeExtensions': ['zip'], - 'CFBundleTypeRole': 'Viewer', - 'CFBundleTypeIconFile': '0ad', - 'LSHandlerRank': 'Alternate' - }], - }, f) + "CFBundleName": "0 A.D.", + "CFBundleIdentifier": BUNDLE_IDENTIFIER, + "CFBundleVersion": BUNDLE_VERSION, + "CFBundlePackageType": "APPL", + "CFBundleSignature": "none", + "CFBundleExecutable": "pyrogenesis", + "CFBundleShortVersionString": BUNDLE_VERSION, + "CFBundleDevelopmentRegion": "English", + "CFBundleInfoDictionaryVersion": "6.0", + "CFBundleIconFile": "0ad", + "LSHasLocalizedDisplayName": True, + "LSMinimumSystemVersion": BUNDLE_MIN_OSX_VERSION, + "NSHumanReadableCopyright": f"Copyright © {datetime.now(tz=datetime.UTC).year} " + f"Wildfire Games", + "UTExportedTypeDeclarations": [ + { + "UTTypeIdentifier": BUNDLE_IDENTIFIER, + "UTTypeTagSpecification": { + "public.filename-extension": ["pyromod"], + }, + "UTTypeConformsTo": ["public.zip-archive"], + "UTTypeDescription": "0 A.D. Zipped Mod", + "UTTypeIconFile": "0ad", + } + ], + "CFBundleDocumentTypes": [ + { + "CFBundleTypeExtensions": ["pyromod"], + "CFBundleTypeRole": "Editor", + "CFBundleTypeIconFile": "0ad", + "LSHandlerRank": "Owner", + }, + { + "CFBundleTypeExtensions": ["zip"], + "CFBundleTypeRole": "Viewer", + "CFBundleTypeIconFile": "0ad", + "LSHandlerRank": "Alternate", + }, + ], + }, + f, + ) if args.dev: print(f"Dev mode bundle complete, located at {BUNDLE_OUTPUT}") - exit(0) + sys.exit(0) print("Signing bundle") -subprocess.run(["codesign", "-s", SIGNKEY, "-f", "--timestamp", "-o", "runtime", "--entitlements", "source/tools/dist/0ad.entitlements", BUNDLE_OUTPUT], check=True) +subprocess.run( + [ + "codesign", + "-s", + SIGNKEY, + "-f", + "--timestamp", + "-o", + "runtime", + "--entitlements", + "source/tools/dist/0ad.entitlements", + BUNDLE_OUTPUT, + ], + check=True, +) print("Creating .dmg") @@ -167,14 +201,42 @@ dmgbuild.build_dmg( defines={ "app": BUNDLE_OUTPUT, "background": "build/resources/dmgbackground.png", - "icon": "build/resources/0ad.icns" - }) + "icon": "build/resources/0ad.icns", + }, +) print("Signing .dmg") -subprocess.run(["codesign", "-s", SIGNKEY, "-f", "--timestamp", "-i", BUNDLE_IDENTIFIER, BUNDLE_DMG_NAME + ".dmg"], check=True) +subprocess.run( + [ + "codesign", + "-s", + SIGNKEY, + "-f", + "--timestamp", + "-i", + BUNDLE_IDENTIFIER, + BUNDLE_DMG_NAME + ".dmg", + ], + check=True, +) print("Notarizing .dmg") -subprocess.run(["xcrun", "notarytool", "submit", BUNDLE_DMG_NAME + ".dmg", "--apple-id", NOTARYTOOL_USER, "--team-id", NOTARYTOOL_TEAM, "--password", NOTARYTOOL_PASSWORD, "--wait"], check=True) +subprocess.run( + [ + "xcrun", + "notarytool", + "submit", + BUNDLE_DMG_NAME + ".dmg", + "--apple-id", + NOTARYTOOL_USER, + "--team-id", + NOTARYTOOL_TEAM, + "--password", + NOTARYTOOL_PASSWORD, + "--wait", + ], + check=True, +) print("Stapling notarization ticket") subprocess.run(["xcrun", "stapler", "staple", BUNDLE_DMG_NAME + ".dmg"], check=True) diff --git a/source/tools/dist/dmgbuild-settings.py b/source/tools/dist/dmgbuild-settings.py index 9e934fe563..bba886b317 100644 --- a/source/tools/dist/dmgbuild-settings.py +++ b/source/tools/dist/dmgbuild-settings.py @@ -1,27 +1,31 @@ +"""0 A.D. settings file for dmgbuild. + +Use like this: + + dmgbuild -s settings.py -D app=/path/to/My.app \ + -D background=/path/to/background.png "My Application" MyApp.dmg +""" + +# ruff: noqa: A001,F821,INP001 + import os.path -# -# 0 A.D. settings file for dmgbuild -# -# Use like this: -# dmgbuild -s settings.py -D app=/path/to/My.app -D background=/path/to/background.png "My Application" MyApp.dmg - -application = defines.get('app') +application = defines.get("app") # .. Basics .................................................................... # Volume format (see hdiutil create -help) -format = defines.get('format', 'UDBZ') +format = defines.get("format", "UDBZ") # Volume size -size = defines.get('size', '4G') +size = defines.get("size", "4G") # Files to include -files = [ application ] +files = [application] # Symlinks to create -symlinks = { 'Applications': '/Applications' } +symlinks = {"Applications": "/Applications"} # Volume icon # @@ -29,18 +33,15 @@ symlinks = { 'Applications': '/Applications' } # image, *or* you can define badge_icon, in which case the icon file you specify # will be used to badge the system's Removable Disk icon # -badge_icon = defines.get('icon') +badge_icon = defines.get("icon") # Where to put the icons -icon_locations = { - os.path.basename(application): (125, 170), - 'Applications': (475, 170) -} +icon_locations = {os.path.basename(application): (125, 170), "Applications": (475, 170)} # .. Window configuration ...................................................... # Background -background = defines.get('background') +background = defines.get("background") show_status_bar = False show_tab_view = False @@ -54,20 +55,20 @@ window_rect = ((0, 0), (600, 393)) # Select the default view; must be one of # -# 'icon-view' -# 'list-view' -# 'column-view' -# 'coverflow' +# "icon-view" +# "list-view" +# "column-view" +# "coverflow" # -default_view = 'icon-view' +default_view = "icon-view" # General view configuration show_icon_preview = False # Set these to True to force inclusion of icon/list view settings (otherwise # we only include settings for the default view) -include_icon_view_settings = 'auto' -include_list_view_settings = 'auto' +include_icon_view_settings = "auto" +include_list_view_settings = "auto" # .. Icon view configuration ................................................... @@ -75,7 +76,7 @@ arrange_by = None grid_offset = (0, 0) grid_spacing = 100 scroll_position = (0, 0) -label_pos = 'bottom' # or 'right' +label_pos = "bottom" # or "right" text_size = 12 icon_size = 90 @@ -97,33 +98,33 @@ icon_size = 90 list_icon_size = 16 list_text_size = 12 list_scroll_position = (0, 0) -list_sort_by = 'name' +list_sort_by = "name" list_use_relative_dates = True -list_calculate_all_sizes = False, -list_columns = ('name', 'date-modified', 'size', 'kind', 'date-added') +list_calculate_all_sizes = False +list_columns = ("name", "date-modified", "size", "kind", "date-added") list_column_widths = { - 'name': 300, - 'date-modified': 181, - 'date-created': 181, - 'date-added': 181, - 'date-last-opened': 181, - 'size': 97, - 'kind': 115, - 'label': 100, - 'version': 75, - 'comments': 300, + "name": 300, + "date-modified": 181, + "date-created": 181, + "date-added": 181, + "date-last-opened": 181, + "size": 97, + "kind": 115, + "label": 100, + "version": 75, + "comments": 300, } list_column_sort_directions = { - 'name': 'ascending', - 'date-modified': 'descending', - 'date-created': 'descending', - 'date-added': 'descending', - 'date-last-opened': 'descending', - 'size': 'descending', - 'kind': 'ascending', - 'label': 'ascending', - 'version': 'ascending', - 'comments': 'ascending', + "name": "ascending", + "date-modified": "descending", + "date-created": "descending", + "date-added": "descending", + "date-last-opened": "descending", + "size": "descending", + "kind": "ascending", + "label": "ascending", + "version": "ascending", + "comments": "ascending", } # .. License configuration .....................................................