.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
searx.plugins.unit_converter Namespace Reference

Functions

 symbol_to_si ()
 
 _parse_text_and_convert (search, from_query, to_query)
 
 post_search (_request, search)
 

Variables

str name = "Unit converter plugin"
 
 description = gettext("Convert between units")
 
bool default_on = True
 
str plugin_id = "unit_converter"
 
str preference_section = "general"
 
list CONVERT_KEYWORDS = ["in", "to", "as"]
 
str RE_MEASURE
 
list ADDITIONAL_UNITS
 
dict ALIAS_SYMBOLS
 
list SYMBOL_TO_SI = []
 

Detailed Description

A plugin for converting measured values from one unit to another unit (a
unit converter).

The plugin looks up the symbols (given in the query term) in a list of
converters, each converter is one item in the list (compare
:py:obj:`ADDITIONAL_UNITS`).  If the symbols are ambiguous, the matching units
of measurement are evaluated.  The weighting in the evaluation results from the
sorting of the :py:obj:`list of unit converters<symbol_to_si>`.

Enable in ``settings.yml``:

.. code:: yaml

  enabled_plugins:
    ..
    - 'Unit converter plugin'

Function Documentation

◆ _parse_text_and_convert()

searx.plugins.unit_converter._parse_text_and_convert ( search,
from_query,
to_query )
protected

Definition at line 174 of file unit_converter.py.

174def _parse_text_and_convert(search, from_query, to_query):
175
176 # pylint: disable=too-many-branches, too-many-locals
177
178 if not (from_query and to_query):
179 return
180
181 measured = re.match(RE_MEASURE, from_query, re.VERBOSE)
182 if not (measured and measured.group('number'), measured.group('unit')):
183 return
184
185 # Symbols are not unique, if there are several hits for the from-unit, then
186 # the correct one must be determined by comparing it with the to-unit
187 # https://github.com/searxng/searxng/pull/3378#issuecomment-2080974863
188
189 # first: collecting possible units
190
191 source_list, target_list = [], []
192
193 for symbol, si_name, from_si, to_si, orig_symbol in symbol_to_si():
194
195 if symbol == measured.group('unit'):
196 source_list.append((si_name, to_si))
197 if symbol == to_query:
198 target_list.append((si_name, from_si, orig_symbol))
199
200 if not (source_list and target_list):
201 return
202
203 source_to_si = target_from_si = target_symbol = None
204
205 # second: find the right unit by comparing list of from-units with list of to-units
206
207 for source in source_list:
208 for target in target_list:
209 if source[0] == target[0]: # compare si_name
210 source_to_si = source[1]
211 target_from_si = target[1]
212 target_symbol = target[2]
213
214 if not (source_to_si and target_from_si):
215 return
216
217 _locale = get_locale() or 'en_US'
218
219 value = measured.group('sign') + measured.group('number') + (measured.group('E') or '')
220 value = babel.numbers.parse_decimal(value, locale=_locale)
221
222 # convert value to SI unit
223
224 if isinstance(source_to_si, (float, int)):
225 value = float(value) * source_to_si
226 else:
227 value = source_to_si(float(value))
228
229 # convert value from SI unit to target unit
230
231 if isinstance(target_from_si, (float, int)):
232 value = float(value) * target_from_si
233 else:
234 value = target_from_si(float(value))
235
236 if measured.group('E'):
237 # when incomming notation is scientific, outgoing notation is scientific
238 result = babel.numbers.format_scientific(value, locale=_locale)
239 else:
240 result = babel.numbers.format_decimal(value, locale=_locale, format='#,##0.##########;-#')
241
242 search.result_container.answers['conversion'] = {'answer': f'{result} {target_symbol}'}
243
244

References searx.plugins.unit_converter.symbol_to_si().

Referenced by searx.plugins.unit_converter.post_search().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ post_search()

searx.plugins.unit_converter.post_search ( _request,
search )

Definition at line 245 of file unit_converter.py.

245def post_search(_request, search):
246 # only convert between units on the first page
247 if search.search_query.pageno > 1:
248 return True
249
250 query = search.search_query.query
251 query_parts = query.split(" ")
252
253 if len(query_parts) < 3:
254 return True
255
256 for query_part in query_parts:
257 for keyword in CONVERT_KEYWORDS:
258 if query_part == keyword:
259 from_query, to_query = query.split(keyword, 1)
260 _parse_text_and_convert(search, from_query.strip(), to_query.strip())
261 return True
262
263 return True

References searx.plugins.unit_converter._parse_text_and_convert().

+ Here is the call graph for this function:

◆ symbol_to_si()

searx.plugins.unit_converter.symbol_to_si ( )
Generates a list of tuples, each tuple is a measure unit and the fields
in the tuple are:

0. Symbol of the measure unit (e.g. 'mi' for measure unit 'miles' Q253276)

1. SI name of the measure unit (e.g. Q11573 for SI unit 'metre')

2. Factor to get SI value from measure unit (e.g. 1mi is equal to SI 1m
   multiplied by 1609.344)

3. Factor to get measure value from from SI value (e.g. SI 100m is equal to
   100mi divided by 1609.344)

The returned list is sorted, the first items are created from
``WIKIDATA_UNITS``, the second group of items is build from
:py:obj:`ADDITIONAL_UNITS` and items created from :py:obj:`ALIAS_SYMBOLS`.

If you search this list for a symbol, then a match with a symbol from
Wikidata has the highest weighting (first hit in the list), followed by the
symbols from the :py:obj:`ADDITIONAL_UNITS` and the lowest weighting is
given to the symbols resulting from the aliases :py:obj:`ALIAS_SYMBOLS`.

Definition at line 102 of file unit_converter.py.

102def symbol_to_si():
103 """Generates a list of tuples, each tuple is a measure unit and the fields
104 in the tuple are:
105
106 0. Symbol of the measure unit (e.g. 'mi' for measure unit 'miles' Q253276)
107
108 1. SI name of the measure unit (e.g. Q11573 for SI unit 'metre')
109
110 2. Factor to get SI value from measure unit (e.g. 1mi is equal to SI 1m
111 multiplied by 1609.344)
112
113 3. Factor to get measure value from from SI value (e.g. SI 100m is equal to
114 100mi divided by 1609.344)
115
116 The returned list is sorted, the first items are created from
117 ``WIKIDATA_UNITS``, the second group of items is build from
118 :py:obj:`ADDITIONAL_UNITS` and items created from :py:obj:`ALIAS_SYMBOLS`.
119
120 If you search this list for a symbol, then a match with a symbol from
121 Wikidata has the highest weighting (first hit in the list), followed by the
122 symbols from the :py:obj:`ADDITIONAL_UNITS` and the lowest weighting is
123 given to the symbols resulting from the aliases :py:obj:`ALIAS_SYMBOLS`.
124
125 """
126
127 global SYMBOL_TO_SI # pylint: disable=global-statement
128 if SYMBOL_TO_SI:
129 return SYMBOL_TO_SI
130
131 # filter out units which can't be normalized to a SI unit and filter out
132 # units without a symbol / arcsecond does not have a symbol
133 # https://www.wikidata.org/wiki/Q829073
134
135 for item in data.WIKIDATA_UNITS.values():
136 if item['to_si_factor'] and item['symbol']:
137 SYMBOL_TO_SI.append(
138 (
139 item['symbol'],
140 item['si_name'],
141 1 / item['to_si_factor'], # from_si
142 item['to_si_factor'], # to_si
143 item['symbol'],
144 )
145 )
146
147 for item in ADDITIONAL_UNITS:
148 SYMBOL_TO_SI.append(
149 (
150 item['symbol'],
151 item['si_name'],
152 item['from_si'],
153 item['to_si'],
154 item['symbol'],
155 )
156 )
157
158 alias_items = []
159 for item in SYMBOL_TO_SI:
160 for alias in ALIAS_SYMBOLS.get(item[0], ()):
161 alias_items.append(
162 (
163 alias,
164 item[1],
165 item[2], # from_si
166 item[3], # to_si
167 item[0], # origin unit
168 )
169 )
170 SYMBOL_TO_SI = SYMBOL_TO_SI + alias_items
171 return SYMBOL_TO_SI
172
173

Referenced by searx.plugins.unit_converter._parse_text_and_convert().

+ Here is the caller graph for this function:

Variable Documentation

◆ ADDITIONAL_UNITS

list searx.plugins.unit_converter.ADDITIONAL_UNITS
Initial value:
1= [
2 {
3 "si_name": "Q11579",
4 "symbol": "°C",
5 "to_si": lambda val: val + 273.15,
6 "from_si": lambda val: val - 273.15,
7 },
8 {
9 "si_name": "Q11579",
10 "symbol": "°F",
11 "to_si": lambda val: (val + 459.67) * 5 / 9,
12 "from_si": lambda val: (val * 9 / 5) - 459.67,
13 },
14]

Definition at line 48 of file unit_converter.py.

◆ ALIAS_SYMBOLS

dict searx.plugins.unit_converter.ALIAS_SYMBOLS
Initial value:
1= {
2 '°C': ('C',),
3 '°F': ('F',),
4 'mi': ('L',),
5}

Definition at line 86 of file unit_converter.py.

◆ CONVERT_KEYWORDS

list searx.plugins.unit_converter.CONVERT_KEYWORDS = ["in", "to", "as"]

Definition at line 35 of file unit_converter.py.

◆ default_on

bool searx.plugins.unit_converter.default_on = True

Definition at line 30 of file unit_converter.py.

◆ description

searx.plugins.unit_converter.description = gettext("Convert between units")

Definition at line 29 of file unit_converter.py.

◆ name

str searx.plugins.unit_converter.name = "Unit converter plugin"

Definition at line 28 of file unit_converter.py.

◆ plugin_id

str searx.plugins.unit_converter.plugin_id = "unit_converter"

Definition at line 32 of file unit_converter.py.

◆ preference_section

str searx.plugins.unit_converter.preference_section = "general"

Definition at line 33 of file unit_converter.py.

◆ RE_MEASURE

str searx.plugins.unit_converter.RE_MEASURE
Initial value:
1= r'''
2(?P<sign>[-+]?) # +/- or nothing for positive
3(\s*) # separator: white space or nothing
4(?P<number>[\d\.,]*) # number: 1,000.00 (en) or 1.000,00 (de)
5(?P<E>[eE][-+]?\d+)? # scientific notation: e(+/-)2 (*10^2)
6(\s*) # separator: white space or nothing
7(?P<unit>\S+) # unit of measure
8'''

Definition at line 38 of file unit_converter.py.

◆ SYMBOL_TO_SI

list searx.plugins.unit_converter.SYMBOL_TO_SI = []

Definition at line 99 of file unit_converter.py.