compute-wer 0.1.3__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 彭震东
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.
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: compute-wer
3
+ Version: 0.1.3
4
+ Summary: Compute WER
5
+ Author-email: Zhendong Peng <pzd17@tsinghua.org.cn>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/pengzhendong/compute-wer
8
+ Project-URL: Documentation, https://github.com/pengzhendong/compute-wer#readme
9
+ Project-URL: BugTracker, https://github.com/pengzhendong/compute-wer/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: click>=8.1.7
16
+ Requires-Dist: contractions>=0.1.73
17
+ Requires-Dist: edit-distance>=1.0.6
18
+ Requires-Dist: wetext>=0.0.7
19
+ Dynamic: license-file
20
+
21
+ # compute-wer
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ $ pip install compute-wer
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ $ cat ref.txt
33
+
34
+ /path/to/audio1 莫愁前路无知己
35
+ /path/to/audio2 天下谁人不识君
36
+ ```
37
+
38
+ ```bash
39
+ $ cat hyp.txt
40
+
41
+ /path/to/audio1 海内存知己
42
+ /path/to/audio2 天下谁人不识君
43
+ ```
44
+
45
+ ```bash
46
+ $ compute-wer ref.txt hyp.txt wer.txt
47
+ ```
48
+
49
+ ```bash
50
+ $ compute-wer "莫愁前路无知己" "海内存知己"
51
+ ```
52
+
53
+ ## Help
54
+
55
+ ```bash
56
+ $ compute-wer --help
57
+ ```
@@ -0,0 +1,37 @@
1
+ # compute-wer
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ $ pip install compute-wer
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```bash
12
+ $ cat ref.txt
13
+
14
+ /path/to/audio1 莫愁前路无知己
15
+ /path/to/audio2 天下谁人不识君
16
+ ```
17
+
18
+ ```bash
19
+ $ cat hyp.txt
20
+
21
+ /path/to/audio1 海内存知己
22
+ /path/to/audio2 天下谁人不识君
23
+ ```
24
+
25
+ ```bash
26
+ $ compute-wer ref.txt hyp.txt wer.txt
27
+ ```
28
+
29
+ ```bash
30
+ $ compute-wer "莫愁前路无知己" "海内存知己"
31
+ ```
32
+
33
+ ## Help
34
+
35
+ ```bash
36
+ $ compute-wer --help
37
+ ```
@@ -0,0 +1 @@
1
+ 0.1.3
@@ -0,0 +1,17 @@
1
+ # Copyright (c) 2023 Zhendong Peng (pzd17@tsinghua.org.cn)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from compute_wer.calculator import Calculator
16
+
17
+ __all__ = ["Calculator"]
@@ -0,0 +1,172 @@
1
+ # Copyright (c) 2025, Zhendong Peng (pzd17@tsinghua.org.cn)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import sys
16
+ from collections import defaultdict
17
+
18
+ import contractions
19
+ from edit_distance import DELETE, EQUAL, INSERT, REPLACE, SequenceMatcher
20
+ from wetext import Normalizer
21
+
22
+ from compute_wer.utils import characterize, default_cluster, strip_tags, width
23
+
24
+
25
+ class WER:
26
+ def __init__(self):
27
+ self.equal = 0
28
+ self.replace = 0
29
+ self.delete = 0
30
+ self.insert = 0
31
+
32
+ def __getitem__(self, key):
33
+ return self.__dict__[key]
34
+
35
+ def __setitem__(self, key, value):
36
+ self.__dict__[key] = value
37
+
38
+ @property
39
+ def all(self):
40
+ return self.equal + self.replace + self.delete
41
+
42
+ @property
43
+ def wer(self):
44
+ if self.all == 0:
45
+ return 0
46
+ return (self.replace + self.delete + self.insert) / self.all
47
+
48
+ def __str__(self):
49
+ return f"{self.wer * 100:4.2f} % N={self.all} C={self.equal} S={self.replace} D={self.delete} I={self.insert}"
50
+
51
+ @staticmethod
52
+ def overall(wers):
53
+ overall = WER()
54
+ for wer in wers:
55
+ if wer is None:
56
+ continue
57
+ for key in (EQUAL, REPLACE, DELETE, INSERT):
58
+ overall[key] += wer[key]
59
+ return overall
60
+
61
+
62
+ class SER:
63
+ def __init__(self):
64
+ self.cor = 0
65
+ self.err = 0
66
+
67
+ @property
68
+ def all(self):
69
+ return self.cor + self.err
70
+
71
+ @property
72
+ def ser(self):
73
+ return self.err / self.all if self.all != 0 else 0
74
+
75
+ def __str__(self):
76
+ return f"{self.ser * 100:4.2f} % N={self.all} C={self.cor} E={self.err}"
77
+
78
+
79
+ class Calculator:
80
+
81
+ def __init__(
82
+ self,
83
+ tochar: bool = False,
84
+ case_sensitive: bool = False,
85
+ remove_tag: bool = False,
86
+ ignore_words: set = set(),
87
+ operator: str = None,
88
+ max_wer: float = sys.maxsize,
89
+ ):
90
+ self.tochar = tochar
91
+ self.case_sensitive = case_sensitive
92
+ self.remove_tag = remove_tag
93
+ self.ignore_words = ignore_words
94
+ self.normalizer = None if operator is None else Normalizer(operator=operator)
95
+
96
+ self.clusters = defaultdict(set)
97
+ self.data = {}
98
+ self.max_wer = max_wer
99
+ self.ser = SER()
100
+
101
+ def normalize(self, text):
102
+ """
103
+ Normalize the input text.
104
+ Args:
105
+ text: input text
106
+ Returns:
107
+ list of normalized tokens
108
+ """
109
+ text = contractions.fix(text)
110
+ if self.normalizer is not None:
111
+ text = self.normalizer.normalize(text)
112
+ tokens = characterize(text, self.tochar)
113
+ tokens = (strip_tags(token) if self.remove_tag else token for token in tokens)
114
+ tokens = (token.upper() if not self.case_sensitive else token for token in tokens)
115
+ return [token for token in tokens if token and token not in self.ignore_words]
116
+
117
+ def calculate(self, ref, hyp):
118
+ """
119
+ Calculate the WER and align the reference and hypothesis.
120
+ Args:
121
+ ref: reference text
122
+ hyp: hypothesis text
123
+ Returns:
124
+ result: result of the WER calculation
125
+ """
126
+ ref = self.normalize(ref)
127
+ hyp = self.normalize(hyp)
128
+ for token in set(ref + hyp):
129
+ if token not in self.data:
130
+ self.data[token] = WER()
131
+ self.clusters[default_cluster(token)].add(token)
132
+ opcodes = SequenceMatcher(ref, hyp).get_opcodes()
133
+
134
+ result = {"ref": [], "hyp": [], "wer": WER()}
135
+ for op, i, _, j, _ in opcodes:
136
+ result["wer"][op] += 1
137
+ ref_token = ref[i] if op != INSERT else ""
138
+ hyp_token = hyp[j] if op != DELETE else ""
139
+ diff = width(hyp_token) - width(ref_token)
140
+ result["ref"].append(ref_token + " " * diff)
141
+ result["hyp"].append(hyp_token + " " * -diff)
142
+
143
+ self.ser.cor += result["wer"].wer == 0
144
+ if result["wer"].wer < self.max_wer:
145
+ for op, i, _, j, _ in opcodes:
146
+ self.data[ref[i] if op != INSERT else hyp[j]][op] += 1
147
+ self.ser.err += result["wer"].wer > 0
148
+ return result
149
+
150
+ def cluster(self, data):
151
+ """
152
+ Calculate the WER for a cluster.
153
+ Args:
154
+ data: list of tokens
155
+ Returns:
156
+ WER for the cluster
157
+ """
158
+ return WER.overall((self.data.get(token) for token in data))
159
+
160
+ def overall(self):
161
+ """
162
+ Calculate the overall WER and the WER for each cluster.
163
+ Returns:
164
+ overall WER
165
+ WER for each cluster
166
+ """
167
+ cluster_wers = {}
168
+ for name, cluster in self.clusters.items():
169
+ wer = self.cluster(cluster)
170
+ if wer.all > 0:
171
+ cluster_wers[name] = wer
172
+ return WER.overall(self.data.values()), cluster_wers
@@ -0,0 +1,121 @@
1
+ # Copyright (c) 2025, Zhendong Peng (pzd17@tsinghua.org.cn)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import codecs
16
+ import logging
17
+ import os
18
+ import sys
19
+
20
+ import click
21
+
22
+ from compute_wer.calculator import Calculator
23
+
24
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
25
+
26
+
27
+ @click.command(help="Compute Word Error Rate (WER) and align recognition results with references.")
28
+ @click.argument("ref")
29
+ @click.argument("hyp")
30
+ @click.argument("output-file", type=click.Path(dir_okay=False), required=False)
31
+ @click.option("--align-to-ref", is_flag=True, help="If set, align to reference (default: align to hypothesis)")
32
+ @click.option("--char", "-c", is_flag=True, help="Use character-level WER instead of word-level WER.")
33
+ @click.option("--sort", "-s", is_flag=True, help="Sort the hypotheses by WER in ascending order.")
34
+ @click.option("--case-sensitive", "-cs", is_flag=True, help="Use case-sensitive matching.")
35
+ @click.option("--remove-tag", "-rt", is_flag=True, default=True, help="Remove tags from the reference and hypothesis.")
36
+ @click.option("--ignore-file", "-ig", type=click.Path(exists=True, dir_okay=False), help="Path to the ignore file.")
37
+ @click.option("--operator", "-o", type=click.Choice(["tn", "itn"], case_sensitive=False), help="Normalizer operator.")
38
+ @click.option("--verbose", "-v", is_flag=True, default=True, help="Print verbose output.")
39
+ @click.option("--max-wer", "-mw", type=float, default=sys.maxsize, help="Filter hypotheses with WER <= this value.")
40
+ def main(
41
+ ref, hyp, output_file, align_to_ref, char, sort, case_sensitive, remove_tag, ignore_file, operator, verbose, max_wer
42
+ ):
43
+ input_is_file = False
44
+ if os.path.exists(ref):
45
+ assert os.path.exists(hyp)
46
+ input_is_file = True
47
+
48
+ ignore_words = set()
49
+ if ignore_file is not None:
50
+ for line in codecs.open(ignore_file, encoding="utf-8"):
51
+ word = line.strip()
52
+ if len(word) > 0:
53
+ ignore_words.add(word if case_sensitive else word.upper())
54
+ calculator = Calculator(char, case_sensitive, remove_tag, ignore_words, operator, max_wer)
55
+
56
+ if input_is_file:
57
+ hyp_set = {}
58
+ for line in codecs.open(hyp, encoding="utf-8"):
59
+ array = line.strip().split(maxsplit=1)
60
+ if len(array) == 0:
61
+ continue
62
+ utt, hyp = array[0], array[1] if len(array) > 1 else ""
63
+ if utt in hyp_set:
64
+ if hyp != hyp_set[utt]:
65
+ raise ValueError(f"Conflicting hypotheses found:\n{utt}\t{hyp}\n{utt}\t{hyp_set[utt]}")
66
+ logging.warning("Skip duplicate hypothesis: %s\t%s", utt, hyp)
67
+ hyp_set[utt] = hyp
68
+
69
+ results = []
70
+ if input_is_file:
71
+ ref_set = {}
72
+ for line in codecs.open(ref, encoding="utf-8"):
73
+ array = line.strip().split(maxsplit=1)
74
+ if len(array) == 0:
75
+ continue
76
+ utt, ref = array[0], array[1] if len(array) > 1 else ""
77
+ if utt in ref_set:
78
+ if ref != ref_set[utt]:
79
+ raise ValueError(f"Conflicting references found:\n{utt}\t{ref}\n{utt}\t{ref_set[utt]}")
80
+ logging.warning("Skip duplicate reference: %s\t%s", utt, ref)
81
+ ref_set[utt] = ref
82
+ if not (utt in hyp_set or align_to_ref):
83
+ hyp_set[utt] = ""
84
+ logging.warning("No hypothesis found for %s, use empty string as hypothesis.", utt)
85
+ else:
86
+ continue
87
+ result = calculator.calculate(ref, hyp_set[utt])
88
+ if result["wer"].wer < max_wer:
89
+ results.append((utt, result))
90
+ else:
91
+ results.append((None, calculator.calculate(ref, hyp)))
92
+
93
+ fout = sys.stdout
94
+ if output_file is None:
95
+ fout.write("\n")
96
+ else:
97
+ fout = codecs.open(output_file, "w", encoding="utf-8")
98
+
99
+ if verbose:
100
+ if sort:
101
+ results = sorted(results, key=lambda x: x[1]["wer"].wer)
102
+ for utt, result in results:
103
+ if utt is not None:
104
+ fout.write(f"utt: {utt}\n")
105
+ fout.write(f"WER: {result['wer']}\n")
106
+ for key in ("ref", "hyp"):
107
+ fout.write(f"{key}: {' '.join(result[key])}\n")
108
+ fout.write("\n")
109
+ fout.write("===========================================================================\n")
110
+ wer, cluster_wers = calculator.overall()
111
+ fout.write(f"Overall -> {wer}\n")
112
+ for cluster, wer in cluster_wers.items():
113
+ fout.write(f"{cluster} -> {wer}\n")
114
+ if input_is_file:
115
+ fout.write(f"SER -> {calculator.ser}\n")
116
+ fout.write("===========================================================================\n")
117
+ fout.close()
118
+
119
+
120
+ if __name__ == "__main__":
121
+ main()
@@ -0,0 +1,141 @@
1
+ # Copyright (c) 2025, Zhendong Peng (pzd17@tsinghua.org.cn)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import unicodedata
16
+ from unicodedata import category, east_asian_width
17
+
18
+ spacelist = [" ", "\t", "\r", "\n"]
19
+ puncts = ["!", ",", ".", "?", "-", "、", "。", "!", ",", ";", "?", ":", "「", "」", "︰", "『", "』", "《", "》"]
20
+
21
+
22
+ def characterize(text, tochar):
23
+ """
24
+ Characterize the text.
25
+ Args:
26
+ text: text to characterize
27
+ tochar: whether to characterize to character
28
+ Returns:
29
+ list of characterized tokens
30
+ """
31
+ res = []
32
+ i = 0
33
+ length = len(text)
34
+ while i < length:
35
+ char = text[i]
36
+ if char in puncts or char in spacelist:
37
+ i += 1
38
+ continue
39
+ cat = category(char)
40
+ # https://unicodebook.readthedocs.io/unicode.html#unicode-categories
41
+ if cat in {"Zs", "Cn"}: # space or not assigned
42
+ i += 1
43
+ elif cat == "Lo": # Letter-other (Chinese letter)
44
+ res.append(char)
45
+ i += 1
46
+ elif tochar and cat.startswith(("L", "N")):
47
+ res.append(char)
48
+ i += 1
49
+ else:
50
+ # some input looks like: <unk><noise>, we want to separate it to two words.
51
+ sep = ">" if char == "<" else " "
52
+ j = i + 1
53
+ while j < length:
54
+ c = text[j]
55
+ if ord(c) >= 128 or c in spacelist or c == sep:
56
+ break
57
+ j += 1
58
+ if j < length and text[j] == ">":
59
+ j += 1
60
+ res.append(text[i:j])
61
+ i = j
62
+ return res
63
+
64
+
65
+ def default_cluster(word):
66
+ """
67
+ Get the default cluster of a word.
68
+ Args:
69
+ word: word to get the default cluster
70
+ Returns:
71
+ default cluster
72
+ """
73
+ replacements = {
74
+ "DIGIT": "Number",
75
+ "CJK UNIFIED IDEOGRAPH": "Chinese",
76
+ "CJK COMPATIBILITY IDEOGRAPH": "Chinese",
77
+ "LATIN CAPITAL LETTER": "English",
78
+ "LATIN SMALL LETTER": "English",
79
+ "HIRAGANA LETTER": "Japanese",
80
+ }
81
+ ignored_prefixes = (
82
+ "AMPERSAND",
83
+ "APOSTROPHE",
84
+ "COMMERCIAL AT",
85
+ "DEGREE CELSIUS",
86
+ "EQUALS SIGN",
87
+ "FULL STOP",
88
+ "HYPHEN-MINUS",
89
+ "LOW LINE",
90
+ "NUMBER SIGN",
91
+ "PLUS SIGN",
92
+ "SEMICOLON",
93
+ )
94
+ clusters = set()
95
+ for name in [unicodedata.name(char) for char in word]:
96
+ if any(name.startswith(prefix) for prefix in ignored_prefixes):
97
+ continue
98
+ cluster = "Other"
99
+ for key, value in replacements.items():
100
+ if name.startswith(key):
101
+ cluster = value
102
+ break
103
+ clusters.add(cluster or "Other")
104
+ return clusters.pop() if len(clusters) == 1 else "Other"
105
+
106
+
107
+ def strip_tags(token):
108
+ """
109
+ Strip the tags from the token.
110
+ Args:
111
+ token: token to strip the tags
112
+ Returns:
113
+ token without tags
114
+ """
115
+ if not token:
116
+ return ""
117
+ chars = []
118
+ i = 0
119
+ while i < len(token):
120
+ if token[i] == "<":
121
+ end = token.find(">", i) + 1
122
+ if end == 0:
123
+ chars.append(token[i])
124
+ i += 1
125
+ else:
126
+ i = end
127
+ else:
128
+ chars.append(token[i])
129
+ i += 1
130
+ return "".join(chars)
131
+
132
+
133
+ def width(str):
134
+ """
135
+ Get the width of a string.
136
+ Args:
137
+ str: string to get the width
138
+ Returns:
139
+ width of the string
140
+ """
141
+ return sum(1 + (east_asian_width(char) in "AFW") for char in str)
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: compute-wer
3
+ Version: 0.1.3
4
+ Summary: Compute WER
5
+ Author-email: Zhendong Peng <pzd17@tsinghua.org.cn>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/pengzhendong/compute-wer
8
+ Project-URL: Documentation, https://github.com/pengzhendong/compute-wer#readme
9
+ Project-URL: BugTracker, https://github.com/pengzhendong/compute-wer/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: click>=8.1.7
16
+ Requires-Dist: contractions>=0.1.73
17
+ Requires-Dist: edit-distance>=1.0.6
18
+ Requires-Dist: wetext>=0.0.7
19
+ Dynamic: license-file
20
+
21
+ # compute-wer
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ $ pip install compute-wer
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ $ cat ref.txt
33
+
34
+ /path/to/audio1 莫愁前路无知己
35
+ /path/to/audio2 天下谁人不识君
36
+ ```
37
+
38
+ ```bash
39
+ $ cat hyp.txt
40
+
41
+ /path/to/audio1 海内存知己
42
+ /path/to/audio2 天下谁人不识君
43
+ ```
44
+
45
+ ```bash
46
+ $ compute-wer ref.txt hyp.txt wer.txt
47
+ ```
48
+
49
+ ```bash
50
+ $ compute-wer "莫愁前路无知己" "海内存知己"
51
+ ```
52
+
53
+ ## Help
54
+
55
+ ```bash
56
+ $ compute-wer --help
57
+ ```
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ VERSION
4
+ pyproject.toml
5
+ compute_wer/__init__.py
6
+ compute_wer/calculator.py
7
+ compute_wer/cli.py
8
+ compute_wer/utils.py
9
+ compute_wer.egg-info/PKG-INFO
10
+ compute_wer.egg-info/SOURCES.txt
11
+ compute_wer.egg-info/dependency_links.txt
12
+ compute_wer.egg-info/entry_points.txt
13
+ compute_wer.egg-info/requires.txt
14
+ compute_wer.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ compute-wer = compute_wer.cli:main
@@ -0,0 +1,4 @@
1
+ click>=8.1.7
2
+ contractions>=0.1.73
3
+ edit-distance>=1.0.6
4
+ wetext>=0.0.7
@@ -0,0 +1 @@
1
+ compute_wer
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "compute-wer"
7
+ authors = [{ name = "Zhendong Peng", email = "pzd17@tsinghua.org.cn" }]
8
+ description = "Compute WER"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.8"
12
+ dynamic = ["version"]
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+ dependencies = [
18
+ "click>=8.1.7",
19
+ "contractions>=0.1.73",
20
+ "edit-distance>=1.0.6",
21
+ "wetext>=0.0.7",
22
+ ]
23
+
24
+ [project.scripts]
25
+ compute-wer = "compute_wer.cli:main"
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/pengzhendong/compute-wer"
29
+ Documentation = "https://github.com/pengzhendong/compute-wer#readme"
30
+ BugTracker = "https://github.com/pengzhendong/compute-wer/issues"
31
+
32
+ [tool.setuptools.dynamic]
33
+ version = { file = "VERSION" }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+