symbolfyi 0.1.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.
- symbolfyi-0.1.0/.gitignore +15 -0
- symbolfyi-0.1.0/LICENSE +21 -0
- symbolfyi-0.1.0/PKG-INFO +123 -0
- symbolfyi-0.1.0/README.md +94 -0
- symbolfyi-0.1.0/pyproject.toml +64 -0
- symbolfyi-0.1.0/src/symbolfyi/__init__.py +58 -0
- symbolfyi-0.1.0/src/symbolfyi/engine.py +256 -0
- symbolfyi-0.1.0/src/symbolfyi/py.typed +0 -0
- symbolfyi-0.1.0/tests/test_symbolfyi.py +211 -0
- symbolfyi-0.1.0/uv.lock +402 -0
symbolfyi-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FYI-Dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
symbolfyi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: symbolfyi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pure Python symbol & character encoding toolkit — 11 encoding formats, Unicode properties, HTML entities.
|
|
5
|
+
Project-URL: Homepage, https://symbolfyi.com
|
|
6
|
+
Project-URL: Documentation, https://symbolfyi.com/developers/
|
|
7
|
+
Project-URL: Repository, https://github.com/fyipedia/symbolfyi
|
|
8
|
+
Project-URL: Issues, https://github.com/fyipedia/symbolfyi/issues
|
|
9
|
+
Author: FYIPedia
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: character,codepoint,encoding,html-entity,symbol,unicode,utf16,utf8
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Topic :: Text Processing :: General
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Provides-Extra: full
|
|
27
|
+
Requires-Dist: fonttools>=4.50; extra == 'full'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# symbolfyi
|
|
31
|
+
|
|
32
|
+
[](https://pypi.org/project/symbolfyi/)
|
|
33
|
+
[](https://pypi.org/project/symbolfyi/)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
|
|
36
|
+
Pure Python symbol & character encoding toolkit. Compute 11 encoding representations and full Unicode properties for any character. Includes 51 HTML entity mappings.
|
|
37
|
+
|
|
38
|
+
> Look up any symbol at [symbolfyi.com](https://symbolfyi.com/)
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install symbolfyi # Core (zero deps)
|
|
44
|
+
pip install "symbolfyi[full]" # + fonttools for Unicode block/script
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from symbolfyi import get_encodings, get_info, lookup_html_entity
|
|
51
|
+
|
|
52
|
+
# Encode any character (11 formats)
|
|
53
|
+
enc = get_encodings("→")
|
|
54
|
+
print(enc.unicode) # U+2192
|
|
55
|
+
print(enc.html_entity) # →
|
|
56
|
+
print(enc.css) # \2192
|
|
57
|
+
print(enc.javascript) # \u{2192}
|
|
58
|
+
print(enc.utf8_bytes) # e2 86 92
|
|
59
|
+
print(enc.url_encoded) # %E2%86%92
|
|
60
|
+
|
|
61
|
+
# Full Unicode properties (requires fonttools for block/script)
|
|
62
|
+
info = get_info("♠")
|
|
63
|
+
print(info.name) # BLACK SPADE SUIT
|
|
64
|
+
print(info.category_name) # Other Symbol
|
|
65
|
+
print(info.block) # Miscellaneous Symbols
|
|
66
|
+
print(info.script) # Common
|
|
67
|
+
|
|
68
|
+
# HTML entity reverse lookup
|
|
69
|
+
char = lookup_html_entity("♥")
|
|
70
|
+
print(char) # ♥
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## API Reference
|
|
74
|
+
|
|
75
|
+
### Core Functions
|
|
76
|
+
|
|
77
|
+
| Function | Description |
|
|
78
|
+
|----------|-------------|
|
|
79
|
+
| `get_encodings(char) -> EncodingInfo` | Compute 11 encoding representations |
|
|
80
|
+
| `get_info(char) -> SymbolInfo \| None` | Full Unicode properties + encodings |
|
|
81
|
+
| `get_category_name(code) -> str` | Category code to human name |
|
|
82
|
+
| `lookup_html_entity(entity) -> str \| None` | Entity string to character |
|
|
83
|
+
|
|
84
|
+
### Data Types
|
|
85
|
+
|
|
86
|
+
- **`EncodingInfo`** — 11-field NamedTuple: unicode, html_decimal, html_hex, html_entity, css, javascript, python, java, utf8_bytes, utf16_bytes, url_encoded
|
|
87
|
+
- **`SymbolInfo`** — 12-field NamedTuple: codepoint, character, name, category, category_name, block, script, bidirectional, combining, mirrored, decomposition, encodings
|
|
88
|
+
|
|
89
|
+
### Constants
|
|
90
|
+
|
|
91
|
+
| Constant | Description |
|
|
92
|
+
|----------|-------------|
|
|
93
|
+
| `GENERAL_CATEGORIES` | 27 Unicode category codes with names |
|
|
94
|
+
| `HTML_ENTITIES` | 51 codepoint-to-entity mappings |
|
|
95
|
+
| `HTML_ENTITY_TO_CHAR` | 51 entity-to-character reverse mappings |
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
- **11 encoding types**: Unicode, HTML decimal/hex/entity, CSS, JavaScript, Python, Java, UTF-8/UTF-16 bytes, URL-encoded
|
|
100
|
+
- **Unicode properties**: name, category, block, script, bidirectional, combining, mirrored, decomposition
|
|
101
|
+
- **51 HTML entities**: Common entities with bidirectional lookup
|
|
102
|
+
- **Zero required deps**: Core uses only stdlib (`unicodedata`, `urllib.parse`)
|
|
103
|
+
- **Optional fonttools**: Install `symbolfyi[full]` for Unicode block and script info
|
|
104
|
+
- **Type-safe**: Full type annotations, `py.typed` marker (PEP 561)
|
|
105
|
+
|
|
106
|
+
## Related Packages
|
|
107
|
+
|
|
108
|
+
| Package | Description |
|
|
109
|
+
|---------|-------------|
|
|
110
|
+
| [unicodefyi](https://github.com/fyipedia/unicodefyi) | Extended Unicode toolkit with 17 encodings + character search |
|
|
111
|
+
| [colorfyi](https://github.com/fyipedia/colorfyi) | Color conversion, contrast, harmonies, shades |
|
|
112
|
+
| [emojifyi](https://github.com/fyipedia/emojifyi) | Emoji encoding & metadata for 3,781 emojis |
|
|
113
|
+
| [fontfyi](https://github.com/fyipedia/fontfyi) | Google Fonts metadata, CSS helpers, font pairings |
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- [Symbol Browser](https://symbolfyi.com/) — Look up any symbol online
|
|
118
|
+
- [API Documentation](https://symbolfyi.com/developers/) — REST API with free access
|
|
119
|
+
- [Source Code](https://github.com/fyipedia/symbolfyi)
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# symbolfyi
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/symbolfyi/)
|
|
4
|
+
[](https://pypi.org/project/symbolfyi/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
Pure Python symbol & character encoding toolkit. Compute 11 encoding representations and full Unicode properties for any character. Includes 51 HTML entity mappings.
|
|
8
|
+
|
|
9
|
+
> Look up any symbol at [symbolfyi.com](https://symbolfyi.com/)
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install symbolfyi # Core (zero deps)
|
|
15
|
+
pip install "symbolfyi[full]" # + fonttools for Unicode block/script
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from symbolfyi import get_encodings, get_info, lookup_html_entity
|
|
22
|
+
|
|
23
|
+
# Encode any character (11 formats)
|
|
24
|
+
enc = get_encodings("→")
|
|
25
|
+
print(enc.unicode) # U+2192
|
|
26
|
+
print(enc.html_entity) # →
|
|
27
|
+
print(enc.css) # \2192
|
|
28
|
+
print(enc.javascript) # \u{2192}
|
|
29
|
+
print(enc.utf8_bytes) # e2 86 92
|
|
30
|
+
print(enc.url_encoded) # %E2%86%92
|
|
31
|
+
|
|
32
|
+
# Full Unicode properties (requires fonttools for block/script)
|
|
33
|
+
info = get_info("♠")
|
|
34
|
+
print(info.name) # BLACK SPADE SUIT
|
|
35
|
+
print(info.category_name) # Other Symbol
|
|
36
|
+
print(info.block) # Miscellaneous Symbols
|
|
37
|
+
print(info.script) # Common
|
|
38
|
+
|
|
39
|
+
# HTML entity reverse lookup
|
|
40
|
+
char = lookup_html_entity("♥")
|
|
41
|
+
print(char) # ♥
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API Reference
|
|
45
|
+
|
|
46
|
+
### Core Functions
|
|
47
|
+
|
|
48
|
+
| Function | Description |
|
|
49
|
+
|----------|-------------|
|
|
50
|
+
| `get_encodings(char) -> EncodingInfo` | Compute 11 encoding representations |
|
|
51
|
+
| `get_info(char) -> SymbolInfo \| None` | Full Unicode properties + encodings |
|
|
52
|
+
| `get_category_name(code) -> str` | Category code to human name |
|
|
53
|
+
| `lookup_html_entity(entity) -> str \| None` | Entity string to character |
|
|
54
|
+
|
|
55
|
+
### Data Types
|
|
56
|
+
|
|
57
|
+
- **`EncodingInfo`** — 11-field NamedTuple: unicode, html_decimal, html_hex, html_entity, css, javascript, python, java, utf8_bytes, utf16_bytes, url_encoded
|
|
58
|
+
- **`SymbolInfo`** — 12-field NamedTuple: codepoint, character, name, category, category_name, block, script, bidirectional, combining, mirrored, decomposition, encodings
|
|
59
|
+
|
|
60
|
+
### Constants
|
|
61
|
+
|
|
62
|
+
| Constant | Description |
|
|
63
|
+
|----------|-------------|
|
|
64
|
+
| `GENERAL_CATEGORIES` | 27 Unicode category codes with names |
|
|
65
|
+
| `HTML_ENTITIES` | 51 codepoint-to-entity mappings |
|
|
66
|
+
| `HTML_ENTITY_TO_CHAR` | 51 entity-to-character reverse mappings |
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- **11 encoding types**: Unicode, HTML decimal/hex/entity, CSS, JavaScript, Python, Java, UTF-8/UTF-16 bytes, URL-encoded
|
|
71
|
+
- **Unicode properties**: name, category, block, script, bidirectional, combining, mirrored, decomposition
|
|
72
|
+
- **51 HTML entities**: Common entities with bidirectional lookup
|
|
73
|
+
- **Zero required deps**: Core uses only stdlib (`unicodedata`, `urllib.parse`)
|
|
74
|
+
- **Optional fonttools**: Install `symbolfyi[full]` for Unicode block and script info
|
|
75
|
+
- **Type-safe**: Full type annotations, `py.typed` marker (PEP 561)
|
|
76
|
+
|
|
77
|
+
## Related Packages
|
|
78
|
+
|
|
79
|
+
| Package | Description |
|
|
80
|
+
|---------|-------------|
|
|
81
|
+
| [unicodefyi](https://github.com/fyipedia/unicodefyi) | Extended Unicode toolkit with 17 encodings + character search |
|
|
82
|
+
| [colorfyi](https://github.com/fyipedia/colorfyi) | Color conversion, contrast, harmonies, shades |
|
|
83
|
+
| [emojifyi](https://github.com/fyipedia/emojifyi) | Emoji encoding & metadata for 3,781 emojis |
|
|
84
|
+
| [fontfyi](https://github.com/fyipedia/fontfyi) | Google Fonts metadata, CSS helpers, font pairings |
|
|
85
|
+
|
|
86
|
+
## Links
|
|
87
|
+
|
|
88
|
+
- [Symbol Browser](https://symbolfyi.com/) — Look up any symbol online
|
|
89
|
+
- [API Documentation](https://symbolfyi.com/developers/) — REST API with free access
|
|
90
|
+
- [Source Code](https://github.com/fyipedia/symbolfyi)
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "symbolfyi"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Pure Python symbol & character encoding toolkit — 11 encoding formats, Unicode properties, HTML entities."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [{ name = "FYIPedia" }]
|
|
9
|
+
keywords = ["unicode", "symbol", "encoding", "html-entity", "utf8", "utf16", "character", "codepoint"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 4 - Beta",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"Programming Language :: Python :: 3.13",
|
|
19
|
+
"Programming Language :: Python :: 3.14",
|
|
20
|
+
"Topic :: Text Processing :: General",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = []
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
full = ["fonttools>=4.50"]
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://symbolfyi.com"
|
|
31
|
+
Documentation = "https://symbolfyi.com/developers/"
|
|
32
|
+
Repository = "https://github.com/fyipedia/symbolfyi"
|
|
33
|
+
Issues = "https://github.com/fyipedia/symbolfyi/issues"
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["hatchling"]
|
|
37
|
+
build-backend = "hatchling.build"
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.wheel]
|
|
40
|
+
packages = ["src/symbolfyi"]
|
|
41
|
+
|
|
42
|
+
[tool.pytest.ini_options]
|
|
43
|
+
testpaths = ["tests"]
|
|
44
|
+
addopts = "-v --tb=short"
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
target-version = "py310"
|
|
48
|
+
line-length = 100
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
|
|
52
|
+
ignore = ["RUF022"]
|
|
53
|
+
|
|
54
|
+
[tool.mypy]
|
|
55
|
+
python_version = "3.10"
|
|
56
|
+
strict = true
|
|
57
|
+
|
|
58
|
+
[dependency-groups]
|
|
59
|
+
dev = [
|
|
60
|
+
"fonttools>=4.50",
|
|
61
|
+
"mypy>=1.19.1",
|
|
62
|
+
"pytest>=9.0.2",
|
|
63
|
+
"ruff>=0.15.4",
|
|
64
|
+
]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""symbolfyi — Pure Python symbol & character encoding toolkit.
|
|
2
|
+
|
|
3
|
+
Compute 11 encoding representations (Unicode, HTML, CSS, JavaScript,
|
|
4
|
+
Python, Java, UTF-8, UTF-16, URL) and Unicode properties for any character.
|
|
5
|
+
Includes 47 HTML entity mappings.
|
|
6
|
+
|
|
7
|
+
Zero required dependencies. Optional ``fonttools`` for block/script info.
|
|
8
|
+
|
|
9
|
+
Usage::
|
|
10
|
+
|
|
11
|
+
from symbolfyi import get_encodings, get_info, lookup_html_entity
|
|
12
|
+
|
|
13
|
+
# Encode any character
|
|
14
|
+
enc = get_encodings("→")
|
|
15
|
+
print(enc.unicode) # U+2192
|
|
16
|
+
print(enc.html_entity) # →
|
|
17
|
+
print(enc.css) # \\2192
|
|
18
|
+
print(enc.utf8_bytes) # e2 86 92
|
|
19
|
+
|
|
20
|
+
# Full Unicode properties
|
|
21
|
+
info = get_info("♠")
|
|
22
|
+
print(info.name) # BLACK SPADE SUIT
|
|
23
|
+
print(info.block) # Miscellaneous Symbols (requires fonttools)
|
|
24
|
+
print(info.category_name) # Other Symbol
|
|
25
|
+
|
|
26
|
+
# HTML entity lookup
|
|
27
|
+
char = lookup_html_entity("♥")
|
|
28
|
+
print(char) # ♥
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from symbolfyi.engine import (
|
|
32
|
+
GENERAL_CATEGORIES,
|
|
33
|
+
HTML_ENTITIES,
|
|
34
|
+
HTML_ENTITY_TO_CHAR,
|
|
35
|
+
EncodingInfo,
|
|
36
|
+
SymbolInfo,
|
|
37
|
+
get_category_name,
|
|
38
|
+
get_encodings,
|
|
39
|
+
get_info,
|
|
40
|
+
lookup_html_entity,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__version__ = "0.1.0"
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
# Data types
|
|
47
|
+
"EncodingInfo",
|
|
48
|
+
"SymbolInfo",
|
|
49
|
+
# Core functions
|
|
50
|
+
"get_encodings",
|
|
51
|
+
"get_info",
|
|
52
|
+
"get_category_name",
|
|
53
|
+
"lookup_html_entity",
|
|
54
|
+
# Data
|
|
55
|
+
"GENERAL_CATEGORIES",
|
|
56
|
+
"HTML_ENTITIES",
|
|
57
|
+
"HTML_ENTITY_TO_CHAR",
|
|
58
|
+
]
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Symbol encoding and Unicode property engine — stateless, <1ms per call.
|
|
2
|
+
|
|
3
|
+
Computes 11 encoding representations and Unicode properties for any character.
|
|
4
|
+
Uses stdlib ``unicodedata`` for core properties; ``fontTools`` (optional) for
|
|
5
|
+
Unicode block and script data.
|
|
6
|
+
|
|
7
|
+
Zero required dependencies. Install ``fonttools`` for block/script info::
|
|
8
|
+
|
|
9
|
+
pip install symbolfyi[full]
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import unicodedata
|
|
15
|
+
from typing import NamedTuple
|
|
16
|
+
from urllib.parse import quote
|
|
17
|
+
|
|
18
|
+
# Try fontTools for block/script (optional dependency)
|
|
19
|
+
try:
|
|
20
|
+
from fontTools.unicodedata import block as ft_block
|
|
21
|
+
from fontTools.unicodedata import script as ft_script
|
|
22
|
+
|
|
23
|
+
_HAS_FONTTOOLS = True
|
|
24
|
+
except ImportError:
|
|
25
|
+
_HAS_FONTTOOLS = False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ─── Unicode general category names ──────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
GENERAL_CATEGORIES: dict[str, str] = {
|
|
31
|
+
"Lu": "Uppercase Letter",
|
|
32
|
+
"Ll": "Lowercase Letter",
|
|
33
|
+
"Lt": "Titlecase Letter",
|
|
34
|
+
"Lm": "Modifier Letter",
|
|
35
|
+
"Lo": "Other Letter",
|
|
36
|
+
"Mn": "Nonspacing Mark",
|
|
37
|
+
"Mc": "Spacing Mark",
|
|
38
|
+
"Me": "Enclosing Mark",
|
|
39
|
+
"Nd": "Decimal Number",
|
|
40
|
+
"Nl": "Letter Number",
|
|
41
|
+
"No": "Other Number",
|
|
42
|
+
"Pc": "Connector Punctuation",
|
|
43
|
+
"Pd": "Dash Punctuation",
|
|
44
|
+
"Ps": "Open Punctuation",
|
|
45
|
+
"Pe": "Close Punctuation",
|
|
46
|
+
"Pi": "Initial Punctuation",
|
|
47
|
+
"Pf": "Final Punctuation",
|
|
48
|
+
"Po": "Other Punctuation",
|
|
49
|
+
"Sm": "Math Symbol",
|
|
50
|
+
"Sc": "Currency Symbol",
|
|
51
|
+
"Sk": "Modifier Symbol",
|
|
52
|
+
"So": "Other Symbol",
|
|
53
|
+
"Zs": "Space Separator",
|
|
54
|
+
"Zl": "Line Separator",
|
|
55
|
+
"Zp": "Paragraph Separator",
|
|
56
|
+
"Cc": "Control",
|
|
57
|
+
"Cf": "Format",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ─── HTML entity mappings ────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
HTML_ENTITIES: dict[int, str] = {
|
|
64
|
+
0x0026: "&",
|
|
65
|
+
0x003C: "<",
|
|
66
|
+
0x003E: ">",
|
|
67
|
+
0x0022: """,
|
|
68
|
+
0x00A9: "©",
|
|
69
|
+
0x00AE: "®",
|
|
70
|
+
0x2122: "™",
|
|
71
|
+
0x00A3: "£",
|
|
72
|
+
0x00A5: "¥",
|
|
73
|
+
0x20AC: "€",
|
|
74
|
+
0x00B0: "°",
|
|
75
|
+
0x00B1: "±",
|
|
76
|
+
0x00D7: "×",
|
|
77
|
+
0x00F7: "÷",
|
|
78
|
+
0x2190: "←",
|
|
79
|
+
0x2191: "↑",
|
|
80
|
+
0x2192: "→",
|
|
81
|
+
0x2193: "↓",
|
|
82
|
+
0x2194: "↔",
|
|
83
|
+
0x21D0: "⇐",
|
|
84
|
+
0x21D2: "⇒",
|
|
85
|
+
0x21D4: "⇔",
|
|
86
|
+
0x2200: "∀",
|
|
87
|
+
0x2202: "∂",
|
|
88
|
+
0x2203: "∃",
|
|
89
|
+
0x2205: "∅",
|
|
90
|
+
0x2207: "∇",
|
|
91
|
+
0x2208: "∈",
|
|
92
|
+
0x2209: "∉",
|
|
93
|
+
0x220B: "∋",
|
|
94
|
+
0x220F: "∏",
|
|
95
|
+
0x2211: "∑",
|
|
96
|
+
0x221A: "√",
|
|
97
|
+
0x221E: "∞",
|
|
98
|
+
0x2227: "∧",
|
|
99
|
+
0x2228: "∨",
|
|
100
|
+
0x2229: "∩",
|
|
101
|
+
0x222A: "∪",
|
|
102
|
+
0x222B: "∫",
|
|
103
|
+
0x2260: "≠",
|
|
104
|
+
0x2264: "≤",
|
|
105
|
+
0x2265: "≥",
|
|
106
|
+
0x2282: "⊂",
|
|
107
|
+
0x2283: "⊃",
|
|
108
|
+
0x2286: "⊆",
|
|
109
|
+
0x2287: "⊇",
|
|
110
|
+
0x25CA: "◊",
|
|
111
|
+
0x2660: "♠",
|
|
112
|
+
0x2663: "♣",
|
|
113
|
+
0x2665: "♥",
|
|
114
|
+
0x2666: "♦",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Reverse mapping: entity string → character
|
|
118
|
+
HTML_ENTITY_TO_CHAR: dict[str, str] = {v: chr(k) for k, v in HTML_ENTITIES.items()}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# ─── Data types ──────────────────────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class EncodingInfo(NamedTuple):
|
|
125
|
+
"""11 encoding representations for a character."""
|
|
126
|
+
|
|
127
|
+
unicode: str
|
|
128
|
+
html_decimal: str
|
|
129
|
+
html_hex: str
|
|
130
|
+
html_entity: str
|
|
131
|
+
css: str
|
|
132
|
+
javascript: str
|
|
133
|
+
python: str
|
|
134
|
+
java: str
|
|
135
|
+
utf8_bytes: str
|
|
136
|
+
utf16_bytes: str
|
|
137
|
+
url_encoded: str
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class SymbolInfo(NamedTuple):
|
|
141
|
+
"""Full Unicode properties + encodings for a character."""
|
|
142
|
+
|
|
143
|
+
codepoint: int
|
|
144
|
+
character: str
|
|
145
|
+
name: str
|
|
146
|
+
category: str
|
|
147
|
+
category_name: str
|
|
148
|
+
block: str
|
|
149
|
+
script: str
|
|
150
|
+
bidirectional: str
|
|
151
|
+
combining: int
|
|
152
|
+
mirrored: bool
|
|
153
|
+
decomposition: str
|
|
154
|
+
encodings: EncodingInfo
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# ─── Core functions ──────────────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_encodings(char: str) -> EncodingInfo:
|
|
161
|
+
"""Compute 11 encoding representations for a single character.
|
|
162
|
+
|
|
163
|
+
>>> enc = get_encodings("♠")
|
|
164
|
+
>>> enc.unicode
|
|
165
|
+
'U+2660'
|
|
166
|
+
>>> enc.html_entity
|
|
167
|
+
'♠'
|
|
168
|
+
>>> enc.utf8_bytes
|
|
169
|
+
'e2 99 a0'
|
|
170
|
+
"""
|
|
171
|
+
cp = ord(char)
|
|
172
|
+
if cp <= 0xFFFF:
|
|
173
|
+
python_repr = f"\\u{cp:04x}"
|
|
174
|
+
java_repr = f"\\u{cp:04X}"
|
|
175
|
+
else:
|
|
176
|
+
python_repr = f"\\U{cp:08x}"
|
|
177
|
+
high = 0xD800 + ((cp - 0x10000) >> 10)
|
|
178
|
+
low = 0xDC00 + ((cp - 0x10000) & 0x3FF)
|
|
179
|
+
java_repr = f"\\u{high:04X}\\u{low:04X}"
|
|
180
|
+
|
|
181
|
+
return EncodingInfo(
|
|
182
|
+
unicode=f"U+{cp:04X}",
|
|
183
|
+
html_decimal=f"&#{cp};",
|
|
184
|
+
html_hex=f"&#x{cp:X};",
|
|
185
|
+
html_entity=HTML_ENTITIES.get(cp, ""),
|
|
186
|
+
css=f"\\{cp:04X}",
|
|
187
|
+
javascript=f"\\u{{{cp:X}}}",
|
|
188
|
+
python=python_repr,
|
|
189
|
+
java=java_repr,
|
|
190
|
+
utf8_bytes=char.encode("utf-8").hex(" "),
|
|
191
|
+
utf16_bytes=char.encode("utf-16-be").hex(" "),
|
|
192
|
+
url_encoded=quote(char),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def get_info(char: str) -> SymbolInfo | None:
|
|
197
|
+
"""Get full Unicode properties and encodings for a character.
|
|
198
|
+
|
|
199
|
+
Returns ``None`` if the character has no Unicode name (control chars, etc.).
|
|
200
|
+
|
|
201
|
+
>>> info = get_info("→")
|
|
202
|
+
>>> info.name if info else None
|
|
203
|
+
'RIGHTWARDS ARROW'
|
|
204
|
+
>>> info.block if info else None # requires fonttools
|
|
205
|
+
'Arrows'
|
|
206
|
+
"""
|
|
207
|
+
try:
|
|
208
|
+
cp = ord(char)
|
|
209
|
+
name = unicodedata.name(char, None)
|
|
210
|
+
if name is None:
|
|
211
|
+
return None
|
|
212
|
+
cat = unicodedata.category(char)
|
|
213
|
+
|
|
214
|
+
if _HAS_FONTTOOLS:
|
|
215
|
+
block = ft_block(cp)
|
|
216
|
+
script = ft_script(cp)
|
|
217
|
+
else:
|
|
218
|
+
block = ""
|
|
219
|
+
script = ""
|
|
220
|
+
|
|
221
|
+
return SymbolInfo(
|
|
222
|
+
codepoint=cp,
|
|
223
|
+
character=char,
|
|
224
|
+
name=name,
|
|
225
|
+
category=cat,
|
|
226
|
+
category_name=GENERAL_CATEGORIES.get(cat, cat),
|
|
227
|
+
block=block,
|
|
228
|
+
script=script,
|
|
229
|
+
bidirectional=unicodedata.bidirectional(char),
|
|
230
|
+
combining=unicodedata.combining(char),
|
|
231
|
+
mirrored=bool(unicodedata.mirrored(char)),
|
|
232
|
+
decomposition=unicodedata.decomposition(char),
|
|
233
|
+
encodings=get_encodings(char),
|
|
234
|
+
)
|
|
235
|
+
except (ValueError, OverflowError):
|
|
236
|
+
return None
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def get_category_name(category_code: str) -> str:
|
|
240
|
+
"""Get the full name for a Unicode general category code.
|
|
241
|
+
|
|
242
|
+
>>> get_category_name("Sm")
|
|
243
|
+
'Math Symbol'
|
|
244
|
+
"""
|
|
245
|
+
return GENERAL_CATEGORIES.get(category_code, category_code)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def lookup_html_entity(entity: str) -> str | None:
|
|
249
|
+
"""Look up the character for an HTML entity string.
|
|
250
|
+
|
|
251
|
+
>>> lookup_html_entity("&")
|
|
252
|
+
'&'
|
|
253
|
+
>>> lookup_html_entity("♥")
|
|
254
|
+
'♥'
|
|
255
|
+
"""
|
|
256
|
+
return HTML_ENTITY_TO_CHAR.get(entity)
|
|
File without changes
|