Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use unicode slugify #19192

Merged
merged 20 commits into from Dec 17, 2018
1 change: 1 addition & 0 deletions homeassistant/package_constraints.txt
Expand Up @@ -9,6 +9,7 @@ jinja2>=2.10
PyJWT==1.6.4
cryptography==2.3.1
pip>=8.0.3
python-slugify==1.2.6
pytz>=2018.04
pyyaml>=3.13,<4
requests==2.20.1
Expand Down
15 changes: 3 additions & 12 deletions homeassistant/util/__init__.py
Expand Up @@ -10,10 +10,11 @@
import string
from functools import wraps
from types import MappingProxyType
from unicodedata import normalize
from typing import (Any, Optional, TypeVar, Callable, KeysView, Union, # noqa
Iterable, List, Dict, Iterator, Coroutine, MutableSet)

import slugify as unicode_slug

from .dt import as_local, utcnow

# pylint: disable=invalid-name
Expand All @@ -24,10 +25,6 @@

RE_SANITIZE_FILENAME = re.compile(r'(~|\.\.|/|\\)')
RE_SANITIZE_PATH = re.compile(r'(~|\.(\.)+)')
RE_SLUGIFY = re.compile(r'[^a-z0-9_]+')
TBL_SLUGIFY = {
ord('ß'): 'ss'
}


def sanitize_filename(filename: str) -> str:
Expand All @@ -42,13 +39,7 @@ def sanitize_path(path: str) -> str:

def slugify(text: str) -> str:
"""Slugify a given text."""
text = normalize('NFKD', text)
text = text.lower()
text = text.replace(" ", "_")
text = text.translate(TBL_SLUGIFY)
text = RE_SLUGIFY.sub("", text)

return text
return unicode_slug.slugify(text, separator='_') # type: ignore


def repr_helper(inp: Any) -> str:
Expand Down
1 change: 1 addition & 0 deletions requirements_all.txt
Expand Up @@ -10,6 +10,7 @@ jinja2>=2.10
PyJWT==1.6.4
cryptography==2.3.1
pip>=8.0.3
python-slugify==1.2.6
pytz>=2018.04
pyyaml>=3.13,<4
requests==2.20.1
Expand Down
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -45,6 +45,7 @@
# PyJWT has loose dependency. We want the latest one.
'cryptography==2.3.1',
'pip>=8.0.3',
'python-slugify==1.2.6',
'pytz>=2018.04',
'pyyaml>=3.13,<4',
'requests==2.20.1',
Expand Down
4 changes: 2 additions & 2 deletions tests/components/device_tracker/test_init.py
Expand Up @@ -408,10 +408,10 @@ async def test_see_state(hass, yaml_devices):
timedelta(seconds=0))
assert len(config) == 1

state = hass.states.get('device_tracker.examplecom')
state = hass.states.get('device_tracker.example_com')
attrs = state.attributes
assert state.state == 'Work'
assert state.object_id == 'examplecom'
assert state.object_id == 'example_com'
assert state.name == 'example.com'
assert attrs['friendly_name'] == 'example.com'
assert attrs['battery'] == 100
Expand Down
90 changes: 42 additions & 48 deletions tests/components/device_tracker/test_meraki.py
Expand Up @@ -15,15 +15,19 @@
@pytest.fixture
def meraki_client(loop, hass, hass_client):
"""Meraki mock client."""
assert loop.run_until_complete(async_setup_component(
hass, device_tracker.DOMAIN, {
device_tracker.DOMAIN: {
CONF_PLATFORM: 'meraki',
CONF_VALIDATOR: 'validator',
CONF_SECRET: 'secret'

}
}))
assert loop.run_until_complete(
async_setup_component(
hass,
device_tracker.DOMAIN,
{
device_tracker.DOMAIN: {
CONF_PLATFORM: "meraki",
CONF_VALIDATOR: "validator",
CONF_SECRET: "secret",
}
},
)
)

yield loop.run_until_complete(hass_client())

Expand All @@ -34,53 +38,41 @@ def test_invalid_or_missing_data(mock_device_tracker_conf, meraki_client):
req = yield from meraki_client.get(URL)
text = yield from req.text()
assert req.status == 200
assert text == 'validator'
assert text == "validator"

req = yield from meraki_client.post(URL, data=b"invalid")
text = yield from req.json()
assert req.status == 400
assert text['message'] == 'Invalid JSON'
assert text["message"] == "Invalid JSON"

req = yield from meraki_client.post(URL, data=b"{}")
text = yield from req.json()
assert req.status == 422
assert text['message'] == 'No secret'
assert text["message"] == "No secret"

data = {
"version": "1.0",
"secret": "secret"
}
data = {"version": "1.0", "secret": "secret"}
req = yield from meraki_client.post(URL, data=json.dumps(data))
text = yield from req.json()
assert req.status == 422
assert text['message'] == 'Invalid version'
assert text["message"] == "Invalid version"

data = {
"version": "2.0",
"secret": "invalid"
}
data = {"version": "2.0", "secret": "invalid"}
req = yield from meraki_client.post(URL, data=json.dumps(data))
text = yield from req.json()
assert req.status == 422
assert text['message'] == 'Invalid secret'
assert text["message"] == "Invalid secret"

data = {
"version": "2.0",
"secret": "secret",
"type": "InvalidType"
}
data = {"version": "2.0", "secret": "secret", "type": "InvalidType"}
req = yield from meraki_client.post(URL, data=json.dumps(data))
text = yield from req.json()
assert req.status == 422
assert text['message'] == 'Invalid device type'
assert text["message"] == "Invalid device type"

data = {
"version": "2.0",
"secret": "secret",
"type": "BluetoothDevicesSeen",
"data": {
"observations": []
}
"data": {"observations": []},
}
req = yield from meraki_client.post(URL, data=json.dumps(data))
assert req.status == 200
Expand All @@ -102,13 +94,13 @@ def test_data_will_be_saved(mock_device_tracker_conf, hass, meraki_client):
"unc": "46.3610585",
},
"seenTime": "2016-09-12T16:23:13Z",
"ssid": 'ssid',
"os": 'HA',
"ipv6": '2607:f0d0:1002:51::4/64',
"ssid": "ssid",
"os": "HA",
"ipv6": "2607:f0d0:1002:51::4/64",
"clientMac": "00:26:ab:b8:a9:a4",
"seenEpoch": "147369739",
"rssi": "20",
"manufacturer": "Seiko Epson"
"manufacturer": "Seiko Epson",
},
{
"location": {
Expand All @@ -117,24 +109,26 @@ def test_data_will_be_saved(mock_device_tracker_conf, hass, meraki_client):
"unc": "46.3610585",
},
"seenTime": "2016-09-12T16:21:13Z",
"ssid": 'ssid',
"os": 'HA',
"ipv4": '192.168.0.1',
"ssid": "ssid",
"os": "HA",
"ipv4": "192.168.0.1",
"clientMac": "00:26:ab:b8:a9:a5",
"seenEpoch": "147369750",
"rssi": "20",
"manufacturer": "Seiko Epson"
}
"manufacturer": "Seiko Epson",
},
]
}
},
}
req = yield from meraki_client.post(URL, data=json.dumps(data))
assert req.status == 200
yield from hass.async_block_till_done()
state_name = hass.states.get('{}.{}'.format('device_tracker',
'0026abb8a9a4')).state
assert 'home' == state_name

state_name = hass.states.get('{}.{}'.format('device_tracker',
'0026abb8a9a5')).state
assert 'home' == state_name
state_name = hass.states.get(
"{}.{}".format("device_tracker", "00_26_ab_b8_a9_a4")
).state
assert "home" == state_name

state_name = hass.states.get(
"{}.{}".format("device_tracker", "00_26_ab_b8_a9_a5")
).state
assert "home" == state_name
10 changes: 5 additions & 5 deletions tests/components/device_tracker/test_owntracks.py
Expand Up @@ -252,10 +252,10 @@ def build_message(test_params, default_params):
}

WAYPOINT_ENTITY_NAMES = [
'zone.greg_phone__exp_wayp1',
'zone.greg_phone__exp_wayp2',
'zone.ram_phone__exp_wayp1',
'zone.ram_phone__exp_wayp2',
'zone.greg_phone_exp_wayp1',
'zone.greg_phone_exp_wayp2',
'zone.ram_phone_exp_wayp1',
'zone.ram_phone_exp_wayp2',
]

LWT_MESSAGE = {
Expand Down Expand Up @@ -405,7 +405,7 @@ def assert_mobile_tracker_accuracy(hass, accuracy, beacon=IBEACON_DEVICE):
async def test_location_invalid_devid(hass, context):
"""Test the update of a location."""
await send_message(hass, 'owntracks/paulus/nexus-5x', LOCATION_MESSAGE)
state = hass.states.get('device_tracker.paulus_nexus5x')
state = hass.states.get('device_tracker.paulus_nexus_5x')
assert state.state == 'outer'


Expand Down