xhtm 0.2.0__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 (43) hide show
  1. {xhtm-0.2.0 → xhtm-0.3.0}/PKG-INFO +1 -1
  2. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/PKG-INFO +1 -1
  3. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/SOURCES.txt +8 -1
  4. xhtm-0.3.0/xhtml/__init__.py +11 -0
  5. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/attribute.py +1 -1
  6. xhtm-0.3.0/xhtml/element/__init__.py +20 -0
  7. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/element/css.py +3 -3
  8. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/element/doc.py +2 -2
  9. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/element/tag.py +6 -6
  10. xhtm-0.3.0/xhtml/flask/__init__.py +3 -0
  11. xhtm-0.3.0/xhtml/header/__init__.py +4 -0
  12. xhtm-0.3.0/xhtml/request/__init__.py +3 -0
  13. xhtm-0.3.0/xhtml/template/__init__.py +32 -0
  14. xhtm-0.3.0/xhtml/unittest/__init__.py +0 -0
  15. xhtm-0.3.0/xhtml/unittest/test_element.py +108 -0
  16. xhtm-0.3.0/xhtml/unittest/test_flask.py +78 -0
  17. xhtm-0.3.0/xhtml/unittest/test_header.py +58 -0
  18. xhtm-0.3.0/xhtml/unittest/test_request.py +44 -0
  19. xhtm-0.3.0/xhtml/unittest/test_resource.py +59 -0
  20. xhtm-0.3.0/xhtml/unittest/test_template.py +33 -0
  21. xhtm-0.2.0/xhtml/__init__.py +0 -10
  22. xhtm-0.2.0/xhtml/element/__init__.py +0 -20
  23. xhtm-0.2.0/xhtml/flask/__init__.py +0 -3
  24. xhtm-0.2.0/xhtml/header/__init__.py +0 -4
  25. xhtm-0.2.0/xhtml/request/__init__.py +0 -3
  26. xhtm-0.2.0/xhtml/template/__init__.py +0 -17
  27. {xhtm-0.2.0 → xhtm-0.3.0}/LICENSE +0 -0
  28. {xhtm-0.2.0 → xhtm-0.3.0}/README.md +0 -0
  29. {xhtm-0.2.0 → xhtm-0.3.0}/setup.cfg +0 -0
  30. {xhtm-0.2.0 → xhtm-0.3.0}/setup.py +0 -0
  31. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/dependency_links.txt +0 -0
  32. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/requires.txt +0 -0
  33. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/top_level.txt +0 -0
  34. {xhtm-0.2.0 → xhtm-0.3.0}/xhtm.egg-info/zip-safe +0 -0
  35. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/element/attr.py +0 -0
  36. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/flask/proxy.py +0 -0
  37. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/header/accept.py +0 -0
  38. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/header/content.py +0 -0
  39. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/request/stream.py +0 -0
  40. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/resource/__init__.py +0 -0
  41. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/resource/favicon.ico +0 -0
  42. {xhtm-0.2.0 → xhtm-0.3.0}/xhtml/resource/logo.svg +0 -0
  43. {xhtm-0.2.0 → 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.0
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.0
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
@@ -0,0 +1,11 @@
1
+ # coding:utf-8
2
+
3
+ from xhtml.element import * # noqa:F401,F403
4
+ from xhtml.flask import FlaskProxy # noqa:F401
5
+ from xhtml.header import AcceptLanguage # noqa:F401
6
+ from xhtml.header import LanguageQ # noqa:F401
7
+ from xhtml.request import StreamResponse # noqa:F401
8
+ from xhtml.resource import FileResource # noqa:F401
9
+ from xhtml.resource import Resource # noqa:F401
10
+ from xhtml.template import LocaleTemplate # noqa:F401
11
+ from xhtml.template import Template # noqa:F401
@@ -3,7 +3,7 @@
3
3
  from urllib.parse import urljoin
4
4
 
5
5
  __project__ = "xhtm"
6
- __version__ = "0.2.0"
6
+ __version__ = "0.3.0"
7
7
  __description__ = "Rendering HTML Text"
8
8
  __urlhome__ = "https://github.com/bondbox/xhtm"
9
9
  __urlcode__ = __urlhome__
@@ -0,0 +1,20 @@
1
+ # coding:utf-8
2
+
3
+ from xhtml.element.attr import Attr # noqa:F401
4
+ from xhtml.element.css import StyleCSS # noqa:F401
5
+ from xhtml.element.doc import HtmlDoc # noqa:F401
6
+ from xhtml.element.tag import Body # noqa:F401
7
+ from xhtml.element.tag import Br # noqa:F401
8
+ from xhtml.element.tag import Div # noqa:F401
9
+ from xhtml.element.tag import EmptyTag # noqa:F401
10
+ from xhtml.element.tag import Form # noqa:F401
11
+ from xhtml.element.tag import FormAttrs # noqa:F401
12
+ from xhtml.element.tag import Head # noqa:F401
13
+ from xhtml.element.tag import Html # noqa:F401
14
+ from xhtml.element.tag import HtmlAttrs # noqa:F401
15
+ from xhtml.element.tag import Input # noqa:F401
16
+ from xhtml.element.tag import InputAttrs # noqa:F401
17
+ from xhtml.element.tag import Span # noqa:F401
18
+ from xhtml.element.tag import Tag # noqa:F401
19
+ from xhtml.element.tag import TextTag # noqa:F401
20
+ from xhtml.element.tag import Title # noqa:F401
@@ -1,8 +1,8 @@
1
1
  # coding:utf-8
2
2
 
3
- from .attr import Args
4
- from .attr import Arguments
5
- from .attr import Attr
3
+ from xhtml.element.attr import Args
4
+ from xhtml.element.attr import Arguments
5
+ from xhtml.element.attr import Attr
6
6
 
7
7
 
8
8
  class StyleCSS(Attr):
@@ -1,6 +1,6 @@
1
1
  # coding:utf-8
2
2
 
3
- from .tag import Html
3
+ from xhtml.element.tag import Html
4
4
 
5
5
 
6
6
  class HtmlDoc(Html):
@@ -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:
@@ -6,12 +6,12 @@ from typing import List
6
6
  from typing import Optional
7
7
  from typing import TypeVar
8
8
 
9
- from ..attribute import __description__
10
- from ..attribute import __project__
11
- from .attr import Args
12
- from .attr import Arguments
13
- from .attr import Attr
14
- from .css import StyleCSS
9
+ from xhtml.attribute import __description__
10
+ from xhtml.attribute import __project__
11
+ from xhtml.element.attr import Args
12
+ from xhtml.element.attr import Arguments
13
+ from xhtml.element.attr import Attr
14
+ from xhtml.element.css import StyleCSS
15
15
 
16
16
 
17
17
  class Attrs(Args):
@@ -0,0 +1,3 @@
1
+ # coding:utf-8
2
+
3
+ from xhtml.flask.proxy import FlaskProxy # noqa:F401
@@ -0,0 +1,4 @@
1
+ # coding:utf-8
2
+
3
+ from xhtml.header.accept import AcceptLanguage # noqa:F401
4
+ from xhtml.header.accept import LanguageQ # noqa:F401
@@ -0,0 +1,3 @@
1
+ # coding:utf-8
2
+
3
+ from xhtml.request.stream import StreamResponse # noqa:F401
@@ -0,0 +1,32 @@
1
+ # coding:utf-8
2
+
3
+ from os.path import abspath
4
+ from os.path import dirname
5
+ from os.path import isdir
6
+ from os.path import join
7
+ from typing import Optional
8
+
9
+ from xlc import Message
10
+ from xlc import Section
11
+
12
+ from xhtml.header import AcceptLanguage
13
+ from xhtml.resource import Resource
14
+
15
+ BASE_DIR = dirname(abspath(__file__))
16
+
17
+
18
+ class Template(Resource):
19
+ FAVICON: str = "favicon.ico"
20
+
21
+ def __init__(self, base: Optional[str] = None):
22
+ super().__init__(base if base and isdir(base) else BASE_DIR)
23
+
24
+
25
+ class LocaleTemplate(Template):
26
+ def __init__(self, base: str):
27
+ self.__message: Message = Message.load(join(base, "locale"))
28
+ super().__init__(base)
29
+
30
+ def search(self, accept_language: str, section: str) -> Section:
31
+ language: AcceptLanguage = AcceptLanguage(accept_language)
32
+ return language.choice(self.__message).seek(section)
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()
@@ -1,10 +0,0 @@
1
- # coding:utf-8
2
-
3
- from .element import * # noqa:F401,F403
4
- from .flask import FlaskProxy # noqa:F401
5
- from .header import AcceptLanguage # noqa:F401
6
- from .header import LanguageQ # noqa:F401
7
- from .request import StreamResponse # noqa:F401
8
- from .resource import FileResource # noqa:F401
9
- from .resource import Resource # noqa:F401
10
- from .template import Template # noqa:F401
@@ -1,20 +0,0 @@
1
- # coding:utf-8
2
-
3
- from .attr import Attr # noqa:F401
4
- from .css import StyleCSS # noqa:F401
5
- from .doc import HtmlDoc # noqa:F401
6
- from .tag import Body # noqa:F401
7
- from .tag import Br # noqa:F401
8
- from .tag import Div # noqa:F401
9
- from .tag import EmptyTag # noqa:F401
10
- from .tag import Form # noqa:F401
11
- from .tag import FormAttrs # noqa:F401
12
- from .tag import Head # noqa:F401
13
- from .tag import Html # noqa:F401
14
- from .tag import HtmlAttrs # noqa:F401
15
- from .tag import Input # noqa:F401
16
- from .tag import InputAttrs # noqa:F401
17
- from .tag import Span # noqa:F401
18
- from .tag import Tag # noqa:F401
19
- from .tag import TextTag # noqa:F401
20
- from .tag import Title # noqa:F401
@@ -1,3 +0,0 @@
1
- # coding:utf-8
2
-
3
- from .proxy import FlaskProxy # noqa:F401
@@ -1,4 +0,0 @@
1
- # coding:utf-8
2
-
3
- from .accept import AcceptLanguage # noqa:F401
4
- from .accept import LanguageQ # noqa:F401
@@ -1,3 +0,0 @@
1
- # coding:utf-8
2
-
3
- from .stream import StreamResponse # noqa:F401
@@ -1,17 +0,0 @@
1
- # coding:utf-8
2
-
3
- from os.path import abspath
4
- from os.path import dirname
5
- from os.path import isdir
6
- from typing import Optional
7
-
8
- from xhtml.resource import Resource
9
-
10
- BASE_DIR = dirname(abspath(__file__))
11
-
12
-
13
- class Template(Resource):
14
- FAVICON: str = "favicon.ico"
15
-
16
- def __init__(self, base: Optional[str] = None):
17
- super().__init__(base if base and isdir(base) else BASE_DIR)
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