def test_exceptions_str(self):
        incorrect = [
            {'remote': {'networking': {'nic': "eth0", "firewall": {"open_ports":[1,2,3, 'a']}}}},
            {'remote': {'networking': {'nic': "eth0", "firewall": {"closed_ports": [], "open_ports":[1,2,3]}}}},
            {'remote': {'networking': {'noc': "eth0", "firewall": {"open_ports":[2,3]}}}},
            {'romote': {'networking': {'nic': "eth0", "firewall": {"open_ports":[2,3]}}}},
            {'remote': {'nitworking': {'nic': "eth0", "firewall": {"open_ports":[2,3]}}}},
        ]

        paths = []
        for i in incorrect:
            try:
                load(i, Config, basiccast=False, failonextra=True)
                assert False
            except exceptions.TypedloadException as e:
                for i in e.exceptions:
                    paths.append(e._path(e.trace) + '.' + i._path(i.trace[1:]))
        #1st object
        assert paths[0] == '.remote.networking.firewall.open_ports.[3]'
        assert paths[1] == '.remote.'
        #2nd object
        assert paths[2] == '.remote.networking.firewall'
        assert paths[3] == '.remote.'
        #3rd object
        assert paths[4] == '.remote.networking'
        assert paths[5] == '.remote.'
        #4th object
        # Nothing because of no sub-exceptions, fails before the union
        #5th object
        assert paths[6] == '.remote.'
        assert paths[7] == '.remote.'
        assert len(paths) == 8
Example #2
0
    def test_nestedload(self):
        @dataclass
        class A:
            a: int
            b: str

        @dataclass
        class B:
            a: A
            b: List[A]

        assert load({
            'a': {
                'a': 101,
                'b': 'ciao'
            },
            'b': []
        }, B) == B(A(101, 'ciao'), [])
        assert load(
            {
                'a': {
                    'a': 101,
                    'b': 'ciao'
                },
                'b': [{
                    'a': 1,
                    'b': 'a'
                }, {
                    'a': 0,
                    'b': 'b'
                }]
            }, B) == B(A(101, 'ciao'), [A(1, 'a'), A(0, 'b')])
Example #3
0
    def test_correct_exception_when_mangling(self):
        @dataclass
        class A:
            a: str = field(metadata={'name': 'q'})

        with self.assertRaises(exceptions.TypedloadAttributeError):
            load(1, A)
Example #4
0
    def test_correct_exception_when_mangling(self):
        @attrs
        class A:
            a = attrib(type=str, metadata={'name': 'q'})

        with self.assertRaises(exceptions.TypedloadAttributeError):
            load(1, A)
Example #5
0
    async def channels(self, refresh: bool = False) -> List[Channel]:
        """
        Returns the list of slack channels

        if refresh is set, the local cache is cleared
        """
        if refresh:
            self._channelscache.clear()

        if self._channelscache:
            return self._channelscache

        cursor = None
        while True:
            r = await self.client.api_call(
                'conversations.list',
                cursor=cursor,
                exclude_archived=True,
                types='public_channel,private_channel,mpim',
                limit=1000, # In vain hope that slack would not ignore this
            )
            response = load(r, Response)

            if response.ok:
                conv = load(r, Conversations)
                self._channelscache += conv.channels
                # For this API, slack sends an empty string as next cursor, just to show off their programming "skillz"
                if not conv.response_metadata or not conv.response_metadata.next_cursor:
                    break
                cursor = conv.response_metadata.next_cursor
            else:
                raise ResponseException(response.error)
        return self._channelscache
Example #6
0
    def test_factory_load(self):
        @dataclass
        class A:
            a: List[int] = field(default_factory=list)

        assert load({'a': [1, 2, 3]}, A) == A([1, 2, 3])
        assert load({'a': []}, A) == A()
        assert load({}, A) == A()
Example #7
0
    def test_mangle_extra(self):
        @dataclass
        class Mangle:
            value: int = field(metadata={'name': 'Value'})

        assert load({'value': 12, 'Value': 12}, Mangle) == Mangle(12)
        with self.assertRaises(exceptions.TypedloadValueError):
            load({'value': 12, 'Value': 12}, Mangle, failonextra=True)
Example #8
0
    def test_defaultvalue(self):
        @dataclass
        class A:
            a: int
            b: Optional[str] = None

        assert load({'a': 1}, A) == A(1)
        assert load({'a': 1, 'b': 'io'}, A) == A(1, 'io')
Example #9
0
 def get_members(self, id_: str) -> List[str]:
     r = self.client.api_call('conversations.members',
                              channel=id_,
                              limit=5000)
     response = load(r, Response)
     if response.ok:
         return load(r['members'], List[str])
     raise ResponseException(response)
Example #10
0
    def test_loadperson(self):
        o = {'name': 'pino', 'age': 1.1}
        assert load(o, Person) == o
        assert load({'val': 3}, A) == {'val': '3'}

        with self.assertRaises(ValueError):
            o.pop('age')
            load(o, Person)
Example #11
0
    def test_mangle_extra(self):
        @attrs
        class Mangle:
            value = attrib(metadata={'name': 'Value'}, type=int)

        assert load({'value': 12, 'Value': 12}, Mangle) == Mangle(12)
        with self.assertRaises(exceptions.TypedloadValueError):
            load({'value': 12, 'Value': 12}, Mangle, failonextra=True)
Example #12
0
    def test_case(self):
        @dataclass
        class Mangle:
            value: int = field(metadata={'name': 'Value'})

        assert load({'Value': 1}, Mangle) == Mangle(1)
        assert 'Value' in dump(Mangle(1))
        with self.assertRaises(ValueError):
            load({'value': 1}, Mangle)
    def test_nestedlegacyload(self):
        A = NamedTuple('A', [('a', int), ('b', str)])
        B = NamedTuple('B', [('a', A), ('b', List[A])])

        assert load({'a': {'a': 101, 'b': 'ciao'}, 'b': []}, B) == B(A(101, 'ciao'), [])
        assert load(
            {'a': {'a': 101, 'b': 'ciao'}, 'b': [{'a': 1, 'b': 'a'},{'a': 0, 'b': 'b'}]},
            B
        ) == B(A(101, 'ciao'), [A(1, 'a'),A(0, 'b')])
Example #14
0
    def test_case(self):
        @attrs
        class Mangle:
            value = attrib(type=int, metadata={'name': 'Value'})

        assert load({'Value': 1}, Mangle) == Mangle(1)
        assert 'Value' in dump(Mangle(1))
        with self.assertRaises(TypeError):
            load({'value': 1}, Mangle)
Example #15
0
 def prefetch_users(self) -> None:
     """
     Prefetch all team members for the slack team.
     """
     r = self.client.api_call("users.list")
     response = load(r, Response)
     if response.ok:
         for user in load(r['members'], List[User]):
             self._usercache[user.id] = user
             self._usermapcache[user.name] = user
Example #16
0
    def events_iter(self) -> Iterator[Optional[SlackEvent]]:
        """
        This yields an event or None. Don't call it without sleeps
        """
        if self.client.rtm_connect():
            while True:
                try:
                    events = self.client.rtm_read()
                except:
                    if not self.client.rtm_connect():
                        sleep(10)
                    events = []

                for event in events:
                    t = event.get('type')
                    subt = event.get('subtype')

                    try:
                        if t == 'message' and not subt:
                            yield _loadwrapper(event, Message)
                        elif t == 'message' and subt == 'slackbot_response':
                            yield _loadwrapper(event, Message)
                        elif t == 'message' and subt == 'file_share':
                            yield _loadwrapper(event, MessageFileShare)
                        elif t == 'message' and subt == 'message_changed':
                            event['message']['channel'] = event['channel']
                            event['previous_message']['channel'] = event[
                                'channel']
                            yield MessageEdit(
                                previous=load(event['previous_message'],
                                              Message),
                                current=load(event['message'], Message))
                        elif t == 'message' and subt == 'message_deleted':
                            event['previous_message']['channel'] = event[
                                'channel']
                            yield _loadwrapper(event['previous_message'],
                                               MessageDelete)
                        elif t == 'message' and subt == 'bot_message':
                            yield _loadwrapper(event, MessageBot)
                        elif t == 'user_change':
                            # Changes in the user, drop it from cache
                            u = load(event['user'], User)
                            if u.id in self._usercache:
                                del self._usercache[u.id]
                                #FIXME don't know if it is wise, maybe it gets lost forever del self._usermapcache[u.name]
                            #TODO make an event for this
                        elif t == 'file_deleted':
                            yield _loadwrapper(event, FileDeleted)
                        elif t in USELESS_EVENTS:
                            continue
                        else:
                            print(event)
                    except Exception as e:
                        print('Exception: %s' % e)
                yield None
Example #17
0
 def test_wrongtype_nested(self):
     data = {
         'course': 'how to be a corsair',
         'students': [{
             'name': 'Alfio'
         }, 3]
     }
     try:
         load(data, Students)
     except exceptions.TypedloadAttributeError as e:
         assert e.trace[-1].annotation[1] == 1
 def test_enum_exceptions_str(self):
     incorrect = [
         [1, 1],
         '3',
         12,
     ]
     for i in incorrect:
         try:
             load(i, Enumeration, basiccast=False, failonextra=True)
         except Exception as e:
             str(e)
Example #19
0
 def get_file(self, f: Union[FileShared, str]) -> File:
     """
     Returns a file object
     """
     fileid = f if isinstance(f, str) else f.file_id
     r = self.client.api_call("files.info", file=fileid)
     response = load(r, Response)
     if response.ok:
         return load(r['file'], File)
     else:
         raise KeyError(response)
Example #20
0
    def test_uuid(self):
        import uuid

        @attrs
        class A:
            a = attrib(type=int)
            uuid_value = attrib(type=str, init=False)

            def __attrs_post_init__(self):
                self.uuid_value = str(uuid.uuid4())

        assert type(load({'a': 1}, A).uuid_value) == str
        assert load({'a': 1}, A) != load({'a': 1}, A)
Example #21
0
    def get_ims(self) -> List[IM]:
        """
        Returns a list of the IMs

        Some bullshit slack invented because 1 to 1 conversations
        need to have an ID to send to, you can't send directly to
        a user.
        """
        r = self.client.api_call("im.list", )
        response = load(r, Response)
        if response.ok:
            return load(r['ims'], List[IM])
        raise ResponseException(response)
 def test_tuple_exceptions_str(self):
     incorrect = [
         [1, 1],
         [1, 1, 1],
         [1],
         [1, 1.2],
         [1, None],
         [1, None, 1],
     ]
     for i in incorrect:
         try:
             load(i, Tuple[int, int], basiccast=False, failonextra=True)
         except Exception as e:
             str(e)
Example #23
0
 def channels(self) -> List[Channel]:
     """
     Returns the list of slack channels
     """
     result = []  # type: List[Channel]
     r = self.client.api_call("conversations.list",
                              exclude_archived=True,
                              types='public_channel,private_channel,mpim',
                              limit=1000)
     response = load(r, Response)
     if response.ok:
         return load(r['channels'], List[Channel])
     else:
         raise ResponseException(response)
Example #24
0
    def get_ims(self) -> List[IM]:
        """
        Returns a list of the IMs

        Some bullshit slack invented because 1 to 1 conversations
        need to have an ID to send to, you can't send directly to
        a user.
        """
        r = self.client.api_call("conversations.list",
                                 exclude_archived=True,
                                 types='im',
                                 limit=1000)
        response = load(r, Response)
        if response.ok:
            return load(r['channels'], List[IM])
        raise ResponseException(response)
Example #25
0
 def kick(self, channel: Channel, user: User) -> None:
     r = self.client.api_call('conversations.kick',
                              channel=channel.id,
                              user=user.id)
     response = load(r, Response)
     if not response.ok:
         raise ResponseException(response)
Example #26
0
 def topic(self, channel: Channel, topic: str) -> None:
     r = self.client.api_call('conversations.setTopic',
                              channel=channel.id,
                              topic=topic)
     response = load(r, Response)
     if not response.ok:
         raise ResponseException(response)
Example #27
0
    def test_weird_mangle(self):
        @attrs
        class Mangle:
            a = attrib(type=int, metadata={'name': 'b', 'alt': 'q'})
            b = attrib(type=str, metadata={'name': 'a'})

        assert load({'b': 1, 'a': 'ciao'}, Mangle) == Mangle(1, 'ciao')
        assert load({
            'q': 1,
            'b': 'ciao'
        }, Mangle, mangle_key='alt') == Mangle(1, 'ciao')
        assert dump(Mangle(1, 'ciao')) == {'b': 1, 'a': 'ciao'}
        assert dump(Mangle(1, 'ciao'), mangle_key='alt') == {
            'q': 1,
            'b': 'ciao'
        }
Example #28
0
    def __init__(self, token: str, cookie: Optional[str], previous_status: Optional[bytes]) -> None:
        """
        A slack client object.

        token: The slack token
        cookie: If the slack instance also uses a cookie, it must be passed here
        previous_status: Opaque bytestring to restore internal status
                from a different object. Obtained from get_status()
        """
        self.client = SlackClient(token, cookie)
        self._usercache: Dict[str, User] = {}
        self._usermapcache: Dict[str, User] = {}
        self._usermapcache_keys: List[str]
        self._imcache: Dict[str, str] = {}
        self._channelscache: List[Channel] = []
        self._get_members_cache: Dict[str, Set[str]] = {}
        self._get_members_cache_cursor: Dict[str, Optional[str]] = {}
        self._internalevents: List[SlackEvent] = []
        self._sent_by_self: Set[float] = set()
        self._wsblock: int = 0 # Semaphore to block the socket and avoid events being received before their API call ended.
        self.login_info: Optional[LoginInfo] = None
        if previous_status is None:
            self._status = SlackStatus()
        else:
            self._status = load(json.loads(previous_status), SlackStatus)
Example #29
0
 async def _thread_history(self, channel: str, thread_id: str) -> List[Union[HistoryMessage, HistoryBotMessage]]:
     r: List[Union[HistoryMessage, HistoryBotMessage]] = []
     cursor = None
     log('Thread history', channel, thread_id)
     while True:
         log('Cursor')
         p = await self.client.api_call(
             'conversations.replies',
             channel=channel,
             ts=thread_id,
             limit=1000,
             cursor=cursor,
         )
         try:
             response = load(p, History)
         except Exception as e:
                 log('Failed to parse', e)
                 log(p)
                 break
         r += [i for i in response.messages if i.ts != i.thread_ts]
         if response.has_more and response.response_metadata:
             cursor = response.response_metadata.next_cursor
         else:
             break
     log('Thread fetched')
     r[0].thread_ts = None
     return r
def test_home_config_convert():
    config = typedload.load(
        {
            'accounts': [{
                'id': '1',
                'name': 'peter',
                'port': 8080,
                'ssl': False,
                'username': '',
                'host': 'deepkit.ai',
                'token': 'abc'
            }, {
                'id': '2',
                'name': 'localhost',
                'port': 8080,
                'ssl': False,
                'username': '',
                'host': 'deepkit.ai',
                'token': 'abc'
            }],
            'folderLinks': []
        }, HomeConfig)

    assert config.get_account_for_id('1').name == 'peter'
    assert config.get_account_for_id('2').name == 'localhost'
Example #31
0
    def location(self, user_input) -> Stops:
        '''Returns a list of Stop objects, completing from the user input'''
        a = self._request(
            "location.name", urllib.parse.urlencode({'input': user_input}))
        c = a["LocationList"]['StopLocation']

        if isinstance(c, dict):
            c = [c]
        return load(c, Stops)
Example #32
0
def _get_token(key: str) -> str:
    if hasattr(_get_token, 'token') and monotonic() < _get_token.obtained + _get_token.token.expires_in:
            return _get_token.token.access_token
    url = "https://api.vasttrafik.se:443/token"
    req = urllib.request.Request(url)
    req.data = b'grant_type=client_credentials'
    req.headers['Authorization'] = 'Basic ' + key
    with urllib.request.urlopen(req) as f:
        token = load(json.load(f), Token)
    _get_token.token = token
    _get_token.obtained = monotonic()
    return token.access_token
Example #33
0
    def trip(self, originCoord=None, originId=None, originCoordName=None, destCoord=None, destId=None, destCoordName=None, viaId=None, datetime_obj=None) -> 'Trips':
        '''
        originCoord = a tuple with origin coordinates (lat,lon)
        originId = stop id
        originCoordName = address

        destCoord
        destId
        destCoordName

        viaId = pass by a certain stop

        datetime_obj = search from this moment
        '''

        service = 'trip'
        params = {}

        if originCoord != None:
            params['originCoordLat'] = originCoord[0]
            params['originCoordLong'] = originCoord[1]
        elif originId != None:
            params['originId'] = originId
        elif originCoordName != None:
            params['originCoordName'] = originCoordName

        if destCoord != None:
            params['destCoordLat'] = destCoord[0]
            params['destCoordLong'] = destCoord[1]
        elif destId != None:
            params['destId'] = destId
        elif destCoordName != None:
            params['destCoordName'] = destCoordName

        if viaId != None:
            params['viaId'] = viaId

        if datetime_obj != None:
            params['date'] = '%04d-%02d-%02d' % (
                datetime_obj.year, datetime_obj.month, datetime_obj.day)
            params['time'] = '%02d:%02d' % (
                datetime_obj.hour, datetime_obj.minute)

        # Request
        b = self._request(service, urllib.parse.urlencode(params))
        c = b['TripList']

        self.datetime_obj = to_datetime(c['serverdate'], c['servertime'])

        return load(c['Trip'], Trips)
Example #34
0
    def nearby(self, lat: float, lon: float, stops: int = 10, dist: Optional[int] = None) -> Stops:
        '''
        Returns the list of stops close to a certain location

        lat = latitude
        lon = longitude

        stops = maximum number of stops to return
        dist = maximum distance in meters
        '''
        params = 'originCoordLat=%s&originCoordLong=%s&maxNo=%d' % (
            str(lat), str(lon), stops)
        if dist != None:
            params += '&maxDist=%d' % dist

        b = self._request('location.nearbystops', params)
        c = b["LocationList"]['StopLocation']

        return load(c, Stops)