xhtm 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {xhtm-0.2.1 → xhtm-0.3.0}/PKG-INFO +1 -1
  2. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/PKG-INFO +1 -1
  3. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/SOURCES.txt +8 -1
  4. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/attribute.py +1 -1
  5. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/element/doc.py +1 -1
  6. xhtm-0.3.0/xhtml/unittest/__init__.py +0 -0
  7. xhtm-0.3.0/xhtml/unittest/test_element.py +108 -0
  8. xhtm-0.3.0/xhtml/unittest/test_flask.py +78 -0
  9. xhtm-0.3.0/xhtml/unittest/test_header.py +58 -0
  10. xhtm-0.3.0/xhtml/unittest/test_request.py +44 -0
  11. xhtm-0.3.0/xhtml/unittest/test_resource.py +59 -0
  12. xhtm-0.3.0/xhtml/unittest/test_template.py +33 -0
  13. {xhtm-0.2.1 → xhtm-0.3.0}/LICENSE +0 -0
  14. {xhtm-0.2.1 → xhtm-0.3.0}/README.md +0 -0
  15. {xhtm-0.2.1 → xhtm-0.3.0}/setup.cfg +0 -0
  16. {xhtm-0.2.1 → xhtm-0.3.0}/setup.py +0 -0
  17. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/dependency_links.txt +0 -0
  18. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/requires.txt +0 -0
  19. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/top_level.txt +0 -0
  20. {xhtm-0.2.1 → xhtm-0.3.0}/xhtm.egg-info/zip-safe +0 -0
  21. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/__init__.py +0 -0
  22. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/element/__init__.py +0 -0
  23. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/element/attr.py +0 -0
  24. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/element/css.py +0 -0
  25. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/element/tag.py +0 -0
  26. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/flask/__init__.py +0 -0
  27. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/flask/proxy.py +0 -0
  28. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/header/__init__.py +0 -0
  29. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/header/accept.py +0 -0
  30. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/header/content.py +0 -0
  31. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/request/__init__.py +0 -0
  32. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/request/stream.py +0 -0
  33. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/resource/__init__.py +0 -0
  34. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/resource/favicon.ico +0 -0
  35. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/resource/logo.svg +0 -0
  36. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/template/__init__.py +0 -0
  37. {xhtm-0.2.1 → xhtm-0.3.0}/xhtml/template/hello.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xhtm
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Rendering HTML Text
5
5
  Home-page: https://github.com/bondbox/xhtm
6
6
  Author: Mingzhe Zou
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xhtm
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Rendering HTML Text
5
5
  Home-page: https://github.com/bondbox/xhtm
6
6
  Author: Mingzhe Zou
@@ -26,4 +26,11 @@ xhtml/resource/__init__.py
26
26
  xhtml/resource/favicon.ico
27
27
  xhtml/resource/logo.svg
28
28
  xhtml/template/__init__.py
29
- xhtml/template/hello.html
29
+ xhtml/template/hello.html
30
+ xhtml/unittest/__init__.py
31
+ xhtml/unittest/test_element.py
32
+ xhtml/unittest/test_flask.py
33
+ xhtml/unittest/test_header.py
34
+ xhtml/unittest/test_request.py
35
+ xhtml/unittest/test_resource.py
36
+ xhtml/unittest/test_template.py
@@ -3,7 +3,7 @@
3
3
  from urllib.parse import urljoin
4
4
 
5
5
  __project__ = "xhtm"
6
- __version__ = "0.2.1"
6
+ __version__ = "0.3.0"
7
7
  __description__ = "Rendering HTML Text"
8
8
  __urlhome__ = "https://github.com/bondbox/xhtm"
9
9
  __urlcode__ = __urlhome__
@@ -9,7 +9,7 @@ class HtmlDoc(Html):
9
9
  super().__init__()
10
10
 
11
11
  def __str__(self) -> str:
12
- return f"<!DOCTYPE {self.__doctype}>\n{super().__str__()}"
12
+ return f"<!DOCTYPE {self.doctype}>\n{super().__str__()}"
13
13
 
14
14
  @property
15
15
  def doctype(self) -> str:
File without changes
@@ -0,0 +1,108 @@
1
+ # coding:utf-8
2
+
3
+ import unittest
4
+
5
+ from xhtml.element.doc import HtmlDoc
6
+ from xhtml.element.tag import Br
7
+ from xhtml.element.tag import Div
8
+ from xhtml.element.tag import Form
9
+ from xhtml.element.tag import Input
10
+ from xhtml.element.tag import Span
11
+
12
+
13
+ class TestHtmlDoc(unittest.TestCase):
14
+
15
+ @classmethod
16
+ def setUpClass(cls):
17
+ cls.title: str = "Login"
18
+ cls.html: HtmlDoc = HtmlDoc()
19
+ cls.html.head.title.text = cls.title
20
+ cls.user: Input = Input({"type": "text", "name": "username", "placeholder": "Username"}) # noqa:E501
21
+ cls.user.attrs.std_style.width.v = "200px"
22
+ cls.user.attrs.std_style.height.v = "30px"
23
+ cls.word: Input = Input({"type": "password", "name": "password", "placeholder": "Password"}) # noqa:E501
24
+ cls.word.attrs.std_style.width.v = "200px"
25
+ cls.word.attrs.std_style.height.v = "30px"
26
+ cls.post: Input = Input({"type": "submit", "value": "Submit"})
27
+ cls.post.attrs.std_style.width.v = "200px"
28
+ cls.post.attrs.std_style.height.v = "30px"
29
+ cls.form: Form = Form({"method": "post"})
30
+ cls.form.add(Div(attrs={"style": "text-align: center;"}, child=[cls.user, Br()])) # noqa: E501
31
+ cls.form.add(Span(attrs={"style": "display: block; margin-bottom: 10px;"})) # noqa: E501
32
+ cls.form.add(Div(attrs={"style": "text-align: center;"}, child=[cls.word, Br()])) # noqa: E501
33
+ cls.form.add(Span(attrs={"style": "display: block; margin-bottom: 20px;"})) # noqa: E501
34
+ cls.form.add(Div(attrs={"style": "text-align: center;"}, child=[cls.post, Br()])) # noqa: E501
35
+ cls.root: Div = Div()
36
+ cls.root.add(cls.form)
37
+ cls.root.attrs.std_style.height.v = "60vh"
38
+ cls.root.attrs.std_style.display.v = "grid"
39
+ cls.root.attrs.std_style.place_items.v = "center"
40
+ cls.html.body.add(cls.root)
41
+
42
+ @classmethod
43
+ def tearDownClass(cls):
44
+ pass
45
+
46
+ def setUp(self):
47
+ pass
48
+
49
+ def tearDown(self):
50
+ pass
51
+
52
+ def test_html(self):
53
+ self.assertIsInstance(str(self.html), str)
54
+
55
+ def test_std_attrs(self):
56
+ self.assertEqual(len(self.html.attrs), 0)
57
+ self.assertEqual(self.html.attrs.xmlns.v, "")
58
+ self.assertEqual(self.html.attrs.std_accesskey.v, "")
59
+ self.assertEqual(self.html.attrs.std_class.v, "")
60
+ self.assertEqual(self.html.attrs.std_contenteditable.v, "")
61
+ self.assertEqual(self.html.attrs.std_contextmenu.v, "")
62
+ self.assertEqual(self.html.attrs.std_dir.v, "")
63
+ self.assertEqual(self.html.attrs.std_draggable.v, "")
64
+ self.assertEqual(self.html.attrs.std_dropzone.v, "")
65
+ self.assertEqual(self.html.attrs.std_enterkeyhint.v, "")
66
+ self.assertEqual(self.html.attrs.std_hidden.v, "")
67
+ self.assertEqual(self.html.attrs.std_id.v, "")
68
+ self.assertEqual(self.html.attrs.std_inert.v, "")
69
+ self.assertEqual(self.html.attrs.std_inputmode.v, "")
70
+ self.assertEqual(self.html.attrs.std_lang.v, "")
71
+ self.assertEqual(self.html.attrs.std_popover.v, "")
72
+ self.assertEqual(self.html.attrs.std_spellcheck.v, "")
73
+ self.assertEqual(self.html.attrs.std_tabindex.v, "")
74
+ self.assertEqual(self.html.attrs.std_title.v, "")
75
+ self.assertEqual(self.html.attrs.std_translate.v, "")
76
+ self.assertNotIn("test", self.html.attrs)
77
+ self.html.attrs["test"] = "unit"
78
+ self.assertEqual(self.html.attrs["test"].v, "unit")
79
+ self.assertEqual(len(self.html.attrs), 20)
80
+ self.assertIsInstance(self.html.attrs.keys(), tuple)
81
+ self.assertIsInstance(self.html.attrs.values(), tuple)
82
+ self.assertIsInstance(self.html.attrs.items(), tuple)
83
+ self.assertNotIn("unit", self.html.attrs)
84
+ self.html.attrs.hit("unit", "test")
85
+ self.assertEqual(self.html.attrs["unit"].v, "test")
86
+ self.assertEqual(len(self.html.attrs), 21)
87
+
88
+ def test_css_style(self):
89
+ self.assertEqual(self.root.attrs.std_style.margin.v, "")
90
+ self.assertEqual(self.root.attrs.std_style.margin_top.v, "")
91
+ self.assertEqual(self.root.attrs.std_style.margin_bottom.v, "")
92
+ self.assertEqual(self.root.attrs.std_style.margin_left.v, "")
93
+ self.assertEqual(self.root.attrs.std_style.margin_right.v, "")
94
+ self.assertEqual(self.root.attrs.std_style.text_align.v, "")
95
+ self.assertEqual(self.root.attrs.std_style.vertical_align.v, "")
96
+
97
+ def test_form(self):
98
+ self.assertEqual(self.form.attrs.method.v, "post")
99
+
100
+ def test_input(self):
101
+ self.assertEqual(self.user.attrs.name.v, "username")
102
+ self.assertEqual(self.user.attrs.placeholder.v, "Username")
103
+ self.assertEqual(self.user.attrs.type.v, "text")
104
+ self.assertEqual(self.user.attrs.value.v, "")
105
+
106
+
107
+ if __name__ == "__main__":
108
+ unittest.main()
@@ -0,0 +1,78 @@
1
+ # coding:utf-8
2
+
3
+ import unittest
4
+ from unittest.mock import MagicMock
5
+ from unittest.mock import patch
6
+
7
+ from flask import Request
8
+ from werkzeug.test import EnvironBuilder
9
+
10
+ from xhtml.flask import proxy
11
+
12
+
13
+ class TestFlaskProxy(unittest.TestCase):
14
+
15
+ @classmethod
16
+ def setUpClass(cls):
17
+ cls.cookie = MagicMock()
18
+ cls.cookie.name = "test"
19
+ cls.cookie.value = "unittest"
20
+ cls.cookie.expires = 1000
21
+ cls.cookie.path = "/"
22
+ cls.cookie.domain = "example.com"
23
+ cls.cookie.secure = True
24
+
25
+ @classmethod
26
+ def tearDownClass(cls):
27
+ pass
28
+
29
+ def setUp(self):
30
+ self.proxy = proxy.FlaskProxy("http://example.com")
31
+
32
+ def tearDown(self):
33
+ pass
34
+
35
+ @patch.object(proxy.requests, "get")
36
+ @patch.object(proxy, "stream_with_context")
37
+ def test_request_get_success(self, mock_stream_with_context, mock_get):
38
+ fake_response = MagicMock()
39
+ fake_response.status_code = 200
40
+ fake_response.raw.headers = {"Content-Type": "text/html"}
41
+ fake_response.cookies = [self.cookie]
42
+ mock_get.return_value = fake_response
43
+ mock_stream_with_context.side_effect = ["unittest"]
44
+ request = Request(EnvironBuilder().get_environ())
45
+ response = self.proxy.request(request)
46
+ self.assertEqual(response.status_code, 200)
47
+ self.assertEqual(response.headers["Content-Type"], "text/html")
48
+
49
+ @patch.object(proxy.requests, "post")
50
+ @patch.object(proxy, "stream_with_context")
51
+ def test_request_post_success(self, mock_stream_with_context, mock_post):
52
+ fake_response = MagicMock()
53
+ fake_response.status_code = 201
54
+ fake_response.raw.headers = {"Content-Type": "application/json"}
55
+ fake_response.cookies = [self.cookie]
56
+ mock_post.return_value = fake_response
57
+ mock_stream_with_context.side_effect = ["unittest"]
58
+ request = Request(EnvironBuilder(method="post").get_environ())
59
+ response = self.proxy.request(request)
60
+ self.assertEqual(response.status_code, 201)
61
+ self.assertEqual(response.headers["Content-Type"], "application/json")
62
+
63
+ @patch.object(proxy.requests, "get")
64
+ def test_request_UnsupportedMethod(self, mock_get):
65
+ request = Request(EnvironBuilder(method="put").get_environ())
66
+ response = self.proxy.request(request)
67
+ self.assertEqual(response.status_code, 405)
68
+
69
+ @patch.object(proxy.requests, "get")
70
+ def test_request_ConnectionError(self, mock_get):
71
+ mock_get.side_effect = proxy.requests.ConnectionError
72
+ request = Request(EnvironBuilder().get_environ())
73
+ response = self.proxy.request(request)
74
+ self.assertEqual(response.status_code, 502)
75
+
76
+
77
+ if __name__ == "__main__":
78
+ unittest.main()
@@ -0,0 +1,58 @@
1
+ # coding:utf-8
2
+
3
+ import unittest
4
+
5
+ from xhtml.header.accept import AcceptLanguage
6
+ from xhtml.header.accept import LanguageQ
7
+
8
+
9
+ class TestLanguageQ(unittest.TestCase):
10
+
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ cls.q: LanguageQ = LanguageQ("zh-CN,zh", 0.9)
14
+
15
+ @classmethod
16
+ def tearDownClass(cls):
17
+ pass
18
+
19
+ def setUp(self):
20
+ pass
21
+
22
+ def tearDown(self):
23
+ pass
24
+
25
+ def test_str(self):
26
+ self.assertEqual(str(self.q), "zh-CN,zh;q=0.9")
27
+
28
+ def test_len(self):
29
+ self.assertEqual(len(self.q), 2)
30
+
31
+
32
+ class TestAcceptLanguage(unittest.TestCase):
33
+
34
+ @classmethod
35
+ def setUpClass(cls):
36
+ cls.lang: AcceptLanguage = AcceptLanguage("zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6") # noqa:E501
37
+
38
+ @classmethod
39
+ def tearDownClass(cls):
40
+ pass
41
+
42
+ def setUp(self):
43
+ pass
44
+
45
+ def tearDown(self):
46
+ pass
47
+
48
+ def test_len_and_contains(self):
49
+ self.assertEqual(len(self.lang), 5)
50
+ self.assertNotIn("zh-TW", self.lang)
51
+ self.assertNotIn("zh-HK", self.lang)
52
+ self.assertIn("zh-CN", self.lang)
53
+ self.assertIn("zh", self.lang)
54
+ self.assertIn("en", self.lang)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ unittest.main()
@@ -0,0 +1,44 @@
1
+ # coding:utf-8
2
+
3
+ from typing import Generator
4
+ import unittest
5
+ from unittest.mock import MagicMock
6
+
7
+ from xhtml.request import stream
8
+
9
+
10
+ class TestStreamResponse(unittest.TestCase):
11
+
12
+ @classmethod
13
+ def setUpClass(cls):
14
+ cls.cookie = MagicMock()
15
+ cls.cookie.name = "test"
16
+ cls.cookie.value = "unittest"
17
+ cls.cookie.expires = 1000
18
+ cls.cookie.path = "/"
19
+ cls.cookie.domain = "example.com"
20
+ cls.cookie.secure = True
21
+
22
+ @classmethod
23
+ def tearDownClass(cls):
24
+ pass
25
+
26
+ def setUp(self):
27
+ fake_response = MagicMock()
28
+ fake_response.status_code = 200
29
+ fake_response.raw.headers = {"Content-Type": "text/html"}
30
+ fake_response.cookies = [self.cookie]
31
+ fake_response.iter_content.return_value = ["unittest", "unittest"]
32
+ self.stream = stream.StreamResponse(fake_response)
33
+
34
+ def tearDown(self):
35
+ pass
36
+
37
+ def test_generator(self):
38
+ self.assertIsInstance(self.stream.generator, Generator)
39
+ for chunk in self.stream.generator:
40
+ self.assertEqual(chunk, "unittest")
41
+
42
+
43
+ if __name__ == "__main__":
44
+ unittest.main()
@@ -0,0 +1,59 @@
1
+ # coding:utf-8
2
+
3
+ import unittest
4
+
5
+ from xhtml.resource import FileResource
6
+ from xhtml.resource import Resource
7
+
8
+
9
+ class TestFileResource(unittest.TestCase):
10
+
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ pass
14
+
15
+ @classmethod
16
+ def tearDownClass(cls):
17
+ pass
18
+
19
+ def setUp(self):
20
+ pass
21
+
22
+ def tearDown(self):
23
+ pass
24
+
25
+ def test_file_not_found(self):
26
+ self.assertRaises(FileNotFoundError, FileResource, "test.txt")
27
+
28
+
29
+ class TestResource(unittest.TestCase):
30
+
31
+ @classmethod
32
+ def setUpClass(cls):
33
+ cls.res: Resource = Resource()
34
+
35
+ @classmethod
36
+ def tearDownClass(cls):
37
+ pass
38
+
39
+ def setUp(self):
40
+ pass
41
+
42
+ def tearDown(self):
43
+ pass
44
+
45
+ def test_favicon(self):
46
+ self.assertIsInstance(self.res.favicon.loadb(), bytes)
47
+
48
+ def test_favicon_ext(self):
49
+ self.assertEqual(self.res.favicon.ext, ".ico")
50
+
51
+ def test_seek(self):
52
+ self.assertIsInstance(self.res.seek("logo.svg").loads(), str)
53
+
54
+ def test_seek_file_not_found(self):
55
+ self.assertRaises(FileNotFoundError, self.res.seek, "test.txt")
56
+
57
+
58
+ if __name__ == "__main__":
59
+ unittest.main()
@@ -0,0 +1,33 @@
1
+ # coding:utf-8
2
+
3
+ import os
4
+ import unittest
5
+
6
+ from xhtml.template import LocaleTemplate
7
+
8
+
9
+ class TestLocaleTemplate(unittest.TestCase):
10
+
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ cls.base: str = os.path.dirname(os.path.abspath(__file__))
14
+ cls.template: LocaleTemplate = LocaleTemplate(cls.base)
15
+
16
+ @classmethod
17
+ def tearDownClass(cls):
18
+ pass
19
+
20
+ def setUp(self):
21
+ pass
22
+
23
+ def tearDown(self):
24
+ pass
25
+
26
+ def test_search(self):
27
+ self.assertEqual(self.template.search("zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "login").lang.tag, "zh-Hans") # noqa:E501
28
+ self.assertEqual(self.template.search("en", "login").lang.tag, "en")
29
+ self.assertEqual(self.template.search("fr", "login").lang.tag, "en")
30
+
31
+
32
+ if __name__ == "__main__":
33
+ unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes