From 6e221dab9b29c16ea0dc9b1570252197921c116d Mon Sep 17 00:00:00 2001 From: John Vert Date: Mon, 10 Jul 2023 11:21:47 -0700 Subject: [PATCH 01/10] add support for windowShadeLevel capabaility (#72) * update aiohttp to 3.8.4 to fix build issue * add support for windowShadeLevel capability and setShadeLevel command. Fixes #67 * support shade_level attribute * add some set_window_shade_level tests * update black version to fix error due to click * update README to include set_window_shade_level() documentation * add shade_level property tests --- README.md | 7 +++ pysmartthings/capability.py | 2 + pysmartthings/device.py | 35 +++++++++++ requirements.txt | 2 +- test-requirements.txt | 2 +- .../device_command_post_set_shade_level.json | 10 ++++ tests/test_device.py | 59 +++++++++++++++++++ 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 tests/json/device_command_post_set_shade_level.json diff --git a/README.md b/README.md index 641bf46..8a645e9 100644 --- a/README.md +++ b/README.md @@ -141,3 +141,10 @@ Devices with the `switchLevel` capability have the following function that sets result = await device.set_level(75, 2) assert result == True ``` + +Devices with the `windowShadeLevel` capability have the following function that sets the target shade level. + +```pythonstub + result = await device.set_window_shade_level(50) + assert result == True +``` diff --git a/pysmartthings/capability.py b/pysmartthings/capability.py index 5e87f8b..23e019c 100644 --- a/pysmartthings/capability.py +++ b/pysmartthings/capability.py @@ -241,6 +241,7 @@ class Capability: washer_operating_state = "washerOperatingState" water_sensor = "waterSensor" window_shade = "windowShade" + window_shade_level = "windowShadeLevel" class Attribute: @@ -336,6 +337,7 @@ class Attribute: rssi = "rssi" saturation = "saturation" schedule = "schedule" + shade_level = "shadeLevel" smoke = "smoke" sound = "sound" st = "st" diff --git a/pysmartthings/device.py b/pysmartthings/device.py index a5d92f1..918f3fc 100644 --- a/pysmartthings/device.py +++ b/pysmartthings/device.py @@ -67,6 +67,7 @@ class Command: set_saturation = "setSaturation" set_thermostat_fan_mode = "setThermostatFanMode" set_thermostat_mode = "setThermostatMode" + set_shade_level = "setShadeLevel" unlock = "unlock" mute = "mute" unmute = "unmute" @@ -727,6 +728,18 @@ def media_title(self) -> bool: """Get the trackDescription attribute.""" return self._attributes["trackDescription"].value + @property + def shade_level(self) -> int: + """Get the shadeLevel attribute, scaled 0-100.""" + return int(self._attributes[Attribute.shade_level].value or 0) + + @shade_level.setter + def shade_level(self, value: int): + """Set the level of the attribute, scaled 0-100.""" + if not 0 <= value <= 100: + raise ValueError("value must be scaled between 0-100.") + self.update_attribute_value(Attribute.shade_level, value) + class DeviceStatus(DeviceStatusBase): """Define the device status.""" @@ -1390,6 +1403,28 @@ async def channel_down( component_id, Capability.tv_channel, Command.channel_down ) + async def set_window_shade_level( + self, + level: int, + set_status: bool = False, + *, + component_id: str = "main", + ) -> bool: + """Call the set shade level device command.""" + if not 0 <= level <= 100: + raise ValueError("level must be scaled between 0-100.") + + result = await self.command( + component_id, + Capability.window_shade_level, + Command.set_shade_level, + [level], + ) + if result and set_status: + self.status.shade_level = level + self.status.switch = level > 0 + return result + @property def status(self): """Get the status entity of the device.""" diff --git a/requirements.txt b/requirements.txt index 448801e..9a8a7f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -aiohttp==3.8.0 \ No newline at end of file +aiohttp==3.8.4 \ No newline at end of file diff --git a/test-requirements.txt b/test-requirements.txt index c9ebce7..8e881d8 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -black==21.10b0 +black==22.3.0 coveralls==3.3.0 flake8==4.0.1 flake8-docstrings==1.6.0 diff --git a/tests/json/device_command_post_set_shade_level.json b/tests/json/device_command_post_set_shade_level.json new file mode 100644 index 0000000..5524eaf --- /dev/null +++ b/tests/json/device_command_post_set_shade_level.json @@ -0,0 +1,10 @@ +{ + "commands": [ + { + "component": "main", + "capability": "windowShadeLevel", + "command": "setShadeLevel", + "arguments": [75] + } + ] +} \ No newline at end of file diff --git a/tests/test_device.py b/tests/test_device.py index a1f9e19..db477fc 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1210,6 +1210,44 @@ async def test_channel_down(api): # Assert assert result + @staticmethod + @pytest.mark.asyncio + async def test_set_window_shade_level(api): + """Tests the set_window_shade_level method.""" + # Arrange + device = DeviceEntity(api, device_id=DEVICE_ID) + # Act + result = await device.set_window_shade_level(75) + # Assert + assert result + assert device.status.level == 0 + assert not device.status.switch + + @staticmethod + @pytest.mark.asyncio + async def test_set_window_shade_level_invalid(api): + """Tests the set_window_shade_level method invalid values.""" + # Arrange + device = DeviceEntity(api, device_id=DEVICE_ID) + # Assert level + levels = [-1, 101] + for level in levels: + with pytest.raises(ValueError): + await device.set_window_shade_level(level) + + @staticmethod + @pytest.mark.asyncio + async def test_set_window_shade_level_update(api): + """Tests the set_window_shade_level method.""" + # Arrange + device = DeviceEntity(api, device_id=DEVICE_ID) + # Act + result = await device.set_window_shade_level(75, True) + # Assert + assert result + assert device.status.shade_level == 75 + assert device.status.switch + class TestDeviceStatus: """Tests for the DeviceStatus class.""" @@ -1655,3 +1693,24 @@ def test_well_known_power_consumption_attributes(): assert status.power_consumption_energy_saved is None assert status.power_consumption_persisted_energy is None assert status.power_consumption_power_energy is None + + @staticmethod + def test_shade_level(): + """Tests the shade_level property.""" + # Arrange + status = DeviceStatus(None, device_id=DEVICE_ID) + # Act + status.shade_level = 50 + # Assert + assert status.shade_level == 50 + + @staticmethod + def test_shade_level_range(): + """Tests the shade_level property's range.""" + # Arrange + status = DeviceStatus(None, device_id=DEVICE_ID) + # Act/Assert + values = [-1, 101] + for value in values: + with pytest.raises(ValueError): + status.shade_level = value From 397ee76f7d0325ba3a4af1169777a0d1465a14a4 Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:58:10 -0500 Subject: [PATCH 02/10] Update requirements --- test-requirements.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index 8e881d8..ca66949 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,12 +1,12 @@ -black==22.3.0 -coveralls==3.3.0 -flake8==4.0.1 -flake8-docstrings==1.6.0 -pydocstyle==6.1.1 -isort==5.10.1 -pylint==2.11.1 -pytest==6.2.5 -pytest-asyncio==0.16.0 -pytest-cov==3.0.0 -pytest-timeout==2.0.1 -yarl==1.7.2 \ No newline at end of file +black==23.3.0 +coveralls==3.3.1 +flake8==6.0.0 +flake8-docstrings==1.7.0 +pydocstyle==6.3.0 +isort==5.12.0 +pylint==2.17.4 +pytest==7.4.0 +pytest-asyncio==0.21.0 +pytest-cov==4.1.0 +pytest-timeout==2.1.0 +yarl==1.9.2 \ No newline at end of file From be3bb8347a395ebe7f0989e9e3a1eeca3c47355b Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:04:19 -0500 Subject: [PATCH 03/10] Fixexd pylint issues --- .vscode/settings.json | 5 ++++- pylintrc | 2 -- pysmartthings/app.py | 4 +--- pysmartthings/device.py | 2 +- tests/test_device.py | 6 +++--- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6422c07..17ee738 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "python.linting.pylintEnabled": true, "python.linting.enabled": true, - "python.formatting.provider": "black", + "python.formatting.provider": "none", "editor.formatOnPaste": false, "editor.formatOnSave": true, "editor.formatOnType": true, @@ -16,5 +16,8 @@ "when": "$(basename).py" }, "**/__pycache__": true + }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" } } \ No newline at end of file diff --git a/pylintrc b/pylintrc index cb31740..204c9b2 100644 --- a/pylintrc +++ b/pylintrc @@ -16,7 +16,6 @@ # unnecessary-pass - readability for functions which only contain pass disable= format, - abstract-class-little-used, abstract-method, cyclic-import, duplicate-code, @@ -25,7 +24,6 @@ disable= locally-disabled, not-an-iterable, not-context-manager, - redefined-variable-type, too-few-public-methods, too-many-arguments, too-many-branches, diff --git a/pysmartthings/app.py b/pysmartthings/app.py index ee64f70..bf27acd 100644 --- a/pysmartthings/app.py +++ b/pysmartthings/app.py @@ -177,9 +177,7 @@ def app_type(self) -> str: def app_type(self, value: str): """Set the app type.""" if value not in (APP_TYPE_LAMBDA, APP_TYPE_WEBHOOK): - raise ValueError( - "value must be 'LAMBDA_SMART_APP' " "or 'WEBHOOK_SMART_APP'" - ) + raise ValueError("value must be 'LAMBDA_SMART_APP' or 'WEBHOOK_SMART_APP'") self._app_type = value @property diff --git a/pysmartthings/device.py b/pysmartthings/device.py index 918f3fc..e98a043 100644 --- a/pysmartthings/device.py +++ b/pysmartthings/device.py @@ -861,7 +861,7 @@ async def set_color( if color_hex: if not COLOR_HEX_MATCHER.match(color_hex): raise ValueError( - "color_hex was not a properly formatted " "color hex, i.e. #000000." + "color_hex was not a properly formatted color hex, i.e. #000000." ) color_map["hex"] = color_hex else: diff --git a/tests/test_device.py b/tests/test_device.py index db477fc..77ea633 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -26,8 +26,8 @@ def test_init(): device = Device() # Assert assert device.type == DEVICE_TYPE_UNKNOWN - assert device.capabilities == [] - assert device.components == {} + assert not device.capabilities + assert not device.components @staticmethod def test_apply_data(): @@ -1259,7 +1259,7 @@ def test_init(): status = DeviceStatus(None, device_id=DEVICE_ID) # Assert assert status.device_id == DEVICE_ID - assert status.attributes == {} + assert not status.attributes assert not status.switch assert not status.motion assert status.level == 0 From 278afa82e1588917f84820c1e96dc8efbde02872 Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:10:14 -0500 Subject: [PATCH 04/10] Update python versions --- .github/workflows/ci.yaml | 6 +++--- .github/workflows/publish.yaml | 2 +- setup.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9520013..e69a6f2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} @@ -40,7 +40,7 @@ jobs: needs: lint strategy: matrix: - python-version: [3.8, 3.9] + python-version: [3.10, 3.11] steps: - uses: actions/checkout@v2 - name: Set up Python @@ -67,7 +67,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 7cd8132..5044915 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -14,7 +14,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} diff --git a/setup.py b/setup.py index ab965a1..efaa405 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ author_email="andrew@sayre.net", license="ASL 2.0", packages=find_packages(exclude=("tests*",)), - install_requires=["aiohttp>=3.8.0,<4.0.0"], + install_requires=["aiohttp>=3.8.4,<4.0.0"], tests_require=[], platforms=["any"], keywords="smartthings", @@ -36,7 +36,7 @@ "Operating System :: OS Independent", "Topic :: Software Development :: Libraries", "Topic :: Home Automation", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", ], ) From 7ecfb65f5e1d8d3e836721381fb1ad70c00d629e Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:21:46 -0500 Subject: [PATCH 05/10] Update action versions --- .github/workflows/ci.yaml | 18 +++++++++--------- .github/workflows/publish.yaml | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e69a6f2..b5c3ebf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,12 +12,12 @@ jobs: name: "Check style and lint" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.11 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test-requirements.txt') }} @@ -42,12 +42,12 @@ jobs: matrix: python-version: [3.10, 3.11] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test-requirements.txt') }} @@ -63,12 +63,12 @@ jobs: runs-on: ubuntu-latest needs: lint steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.11 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test-requirements.txt') }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 5044915..0e7c291 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -12,14 +12,14 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.11 - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test-requirements.txt') }} - - name: Install dependencies + - name: Install dependenciesgit run: | python -m pip install --upgrade pip pip install -r requirements.txt -r test-requirements.txt --upgrade --upgrade-strategy eager From 4b8eb771424724a8ad4436dc03facf256cd1c841 Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:29:42 -0500 Subject: [PATCH 06/10] Convert versions to strings --- .github/workflows/ci.yaml | 6 +++--- .github/workflows/publish.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b5c3ebf..c88ce98 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: "3.11" - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} @@ -40,7 +40,7 @@ jobs: needs: lint strategy: matrix: - python-version: [3.10, 3.11] + python-version: ["3.10", "3.11"] steps: - uses: actions/checkout@v3 - name: Set up Python @@ -67,7 +67,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.11 + python-version: "3.11" - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 0e7c291..181398d 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -10,12 +10,12 @@ jobs: name: "Package and Publish" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.11 - - uses: actions/cache@v2 + python-version: "3.11" + - uses: actions/cache@v3 with: path: ${{ env.pythonLocation }} key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('test-requirements.txt') }} From 80e8d0e1fb4d8742e0f2a91f3e4f512418194c9d Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:35:35 -0500 Subject: [PATCH 07/10] One more string conversion --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c88ce98..af99dad 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,7 @@ jobs: needs: lint strategy: matrix: - python-version: ["3.10", "3.11"] + python-version: "['3.10', '3.11']" steps: - uses: actions/checkout@v3 - name: Set up Python From efc98799c8dc83289ceb892b8e211ae393c1f1ba Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Mon, 10 Jul 2023 15:43:24 -0500 Subject: [PATCH 08/10] Fix version string and update codecov --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index af99dad..acd8acd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,7 @@ jobs: needs: lint strategy: matrix: - python-version: "['3.10', '3.11']" + python-version: ["3.10", "3.11"] steps: - uses: actions/checkout@v3 - name: Set up Python @@ -79,6 +79,6 @@ jobs: - name: Run pytest on ${{ matrix.python-version }} run: pytest --cov=./ --cov-report=xml - name: "Upload coverage to Codecov" - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: - fail_ci_if_error: true + fail_ci_if_error: true \ No newline at end of file From 0e2c90ab2d662b9602e544a70c488512c7110ba3 Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:59:16 -0500 Subject: [PATCH 09/10] Updated capabilities --- pysmartthings/capability.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pysmartthings/capability.py b/pysmartthings/capability.py index 23e019c..b410d85 100644 --- a/pysmartthings/capability.py +++ b/pysmartthings/capability.py @@ -147,6 +147,8 @@ ], "waterSensor": ["water"], "windowShade": ["windowShade"], + "windowShadeLevel": ["shadeLevel"], + "windowShadePreset": ["presetPosition"], } CAPABILITIES = list(CAPABILITIES_TO_ATTRIBUTES) ATTRIBUTES = { @@ -242,6 +244,7 @@ class Capability: water_sensor = "waterSensor" window_shade = "windowShade" window_shade_level = "windowShadeLevel" + window_shade_preset = "windowShadePreset" class Attribute: @@ -328,6 +331,7 @@ class Attribute: power_consumption = "powerConsumption" power_source = "powerSource" presence = "presence" + preset_position = "presetPosition" progress = "progress" rapid_cooling = "rapidCooling" refrigeration_setpoint = "refrigerationSetpoint" @@ -344,6 +348,7 @@ class Attribute: supported_ac_fan_modes = "supportedAcFanModes" supported_ac_modes = "supportedAcModes" supported_button_values = "supportedButtonValues" + supported_fan_oscillation_modes = "supportedFanOscillationModes" supported_input_sources = "supportedInputSources" supported_machine_states = "supportedMachineStates" supported_playback_commands = "supportedPlaybackCommands" From ca4917e4eca01126d9f1a0db3862ceac115f2359 Mon Sep 17 00:00:00 2001 From: andrewsayre <6730289+andrewsayre@users.noreply.github.com> Date: Tue, 11 Jul 2023 20:32:34 -0500 Subject: [PATCH 10/10] Version bump --- pysmartthings/const.py | 2 +- script/generate_attributes.py | 2 +- script/generate_capabilities.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pysmartthings/const.py b/pysmartthings/const.py index 18f33ea..10a11f2 100644 --- a/pysmartthings/const.py +++ b/pysmartthings/const.py @@ -1,4 +1,4 @@ """Define consts for the pysmartthings package.""" __title__ = "pysmartthings" -__version__ = "0.7.7" +__version__ = "0.7.8" diff --git a/script/generate_attributes.py b/script/generate_attributes.py index 058dba6..f2735cb 100644 --- a/script/generate_attributes.py +++ b/script/generate_attributes.py @@ -12,7 +12,7 @@ def main(): attribs = [a for a in ATTRIBUTES] attribs.sort() for a in attribs: - print("{} = '{}'".format(re.sub(r"([A-Z])", r"_\1", a).lower(), a)) + print('{} = "{}"'.format(re.sub(r"([A-Z])", r"_\1", a).lower(), a)) if __name__ == "__main__": diff --git a/script/generate_capabilities.py b/script/generate_capabilities.py index 71e557e..8b38c0f 100644 --- a/script/generate_capabilities.py +++ b/script/generate_capabilities.py @@ -12,7 +12,7 @@ def main(): capabilities = CAPABILITIES.copy() capabilities.sort() for c in capabilities: - print("{} = '{}'".format(re.sub(r"([A-Z])", r"_\1", c).lower(), c)) + print('{} = "{}"'.format(re.sub(r"([A-Z])", r"_\1", c).lower(), c)) if __name__ == "__main__":