diff --git a/.gitignore b/.gitignore index 090eda8..3c5e847 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ target/ # Virtualenv env/ +.python-version diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..21f9f3a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: python +python: + - "3.6" +script: + - python tests.py \ No newline at end of file diff --git a/README.md b/README.md index 5787d32..b678ac5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # sms-counter-python ---- +[![Build Status](https://travis-ci.com/uralov/sms-counter-python.svg?branch=master)](https://travis-ci.com/uralov/sms-counter-python) **sms-counter-python** is a lib that help to count characters of SMS messages. diff --git a/sms_counter/main.py b/sms_counter/main.py index 257aa85..90950cd 100644 --- a/sms_counter/main.py +++ b/sms_counter/main.py @@ -1,8 +1,8 @@ # -*- coding: utf8 -*- -''' +""" Created on Jul 10, 2016 @author: Dayo -''' +""" from math import ceil @@ -45,17 +45,15 @@ class SMSCounter(object): def _detect_encoding(cls, plaintext): rf = cls._text_to_unicode_pointcode_list(plaintext) - utf16chars = set(rf).difference(set(cls._get_gsm_7bit_map())) + non_gsm_7bit_chars = set(rf) - set(cls._get_gsm_7bit_map()) + if not non_gsm_7bit_chars: + return cls.GSM_7BIT - if len(utf16chars): - return cls.UTF16 - - exchars = set(rf).intersection(set(cls._get_added_gsm_7bit_ex_map())) - - if len(exchars): + non_gsm_7bit_ex_chars = non_gsm_7bit_chars - set(cls._get_added_gsm_7bit_ex_map()) + if not non_gsm_7bit_ex_chars: return cls.GSM_7BIT_EX - return cls.GSM_7BIT + return cls.UTF16 @classmethod def count(cls, plaintext): diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..4424414 --- /dev/null +++ b/tests.py @@ -0,0 +1,58 @@ +from unittest import TestCase + +from sms_counter import SMSCounter + + +class SMSCounterTestCase(TestCase): + """ Tests for sms counting """ + GSM_7BIT_LEN = 160 + GSM_7BIT_LEN_MULTIPART = 153 + UTF16_LEN = 70 + UTF16_LEN_MULTIPART = 67 + GSM_7BIT_CHAR_MAP = list(map(chr, SMSCounter._get_gsm_7bit_map())) + GSM_7BIT_EX_CHAR_MAP = list(map(chr, SMSCounter._get_added_gsm_7bit_ex_map())) + + def _check_gsm_7bit_sms_length(self, counter, message, message_max_length=GSM_7BIT_LEN): + length_error = 'Message length should be less than {} symbols'.format(message_max_length) + self.assertLessEqual(len(message), counter.get('per_message'), length_error) + self.assertEqual(len(message), counter.get('length')) + self.assertEqual(counter.get('messages'), 1, 'Message is not multipart') + + def test_gsm_7bit_chars(self): + message = self.GSM_7BIT_CHAR_MAP[:self.GSM_7BIT_LEN] + counter = SMSCounter.count(message) + self._check_gsm_7bit_sms_length(counter, message) + self.assertEqual(counter.get('encoding'), SMSCounter.GSM_7BIT) + + def test_gsm_7bit_ex_chars(self): + message = self.GSM_7BIT_CHAR_MAP + self.GSM_7BIT_EX_CHAR_MAP + message = message[:self.GSM_7BIT_LEN] + counter = SMSCounter.count(message) + self._check_gsm_7bit_sms_length(counter, message) + self.assertEqual(counter.get('encoding'), SMSCounter.GSM_7BIT_EX) + + def test_utf_chars(self): + utf_message = ['£', 'ф', '±'] + self.GSM_7BIT_CHAR_MAP + utf_message = utf_message[:self.UTF16_LEN] + counter = SMSCounter.count(utf_message) + self._check_gsm_7bit_sms_length(counter, utf_message, self.UTF16_LEN) + self.assertEqual(counter.get('encoding'), SMSCounter.UTF16) + + def test_multipart_sms_gsm_7bit(self): + message = self.GSM_7BIT_CHAR_MAP + self.GSM_7BIT_EX_CHAR_MAP + double_message = message[:self.GSM_7BIT_LEN_MULTIPART] * 2 + counter = SMSCounter.count(double_message) + self.assertEqual(counter.get('encoding'), SMSCounter.GSM_7BIT_EX) + self.assertEqual(counter.get('messages'), 2, 'Message must contains from 2 parts') + + def test_multipart_sms_utf(self): + utf_message = ['£', 'ф', '±'] + self.GSM_7BIT_CHAR_MAP + double_utf_message = utf_message[:self.UTF16_LEN_MULTIPART] * 2 + counter = SMSCounter.count(double_utf_message) + self.assertEqual(counter.get('encoding'), SMSCounter.UTF16) + self.assertEqual(counter.get('messages'), 2, 'Message must contains from 2 parts') + + +if __name__ == '__main__': + import unittest + unittest.main()