├── .gitignore
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs
├── Makefile
├── _build
│ ├── doctrees
│ │ ├── docs
│ │ │ └── index.doctree
│ │ ├── environment.pickle
│ │ └── index.doctree
│ └── html
│ │ ├── .buildinfo
│ │ ├── _sources
│ │ ├── docs
│ │ │ └── index.rst.txt
│ │ └── index.rst.txt
│ │ ├── _static
│ │ ├── ajax-loader.gif
│ │ ├── alabaster.css
│ │ ├── basic.css
│ │ ├── comment-bright.png
│ │ ├── comment-close.png
│ │ ├── comment.png
│ │ ├── custom.css
│ │ ├── doctools.js
│ │ ├── documentation_options.js
│ │ ├── down-pressed.png
│ │ ├── down.png
│ │ ├── file.png
│ │ ├── jquery-3.2.1.js
│ │ ├── jquery.js
│ │ ├── language_data.js
│ │ ├── minus.png
│ │ ├── plus.png
│ │ ├── pygments.css
│ │ ├── searchtools.js
│ │ ├── underscore-1.3.1.js
│ │ ├── underscore.js
│ │ ├── up-pressed.png
│ │ ├── up.png
│ │ └── websupport.js
│ │ ├── docs
│ │ └── index.html
│ │ ├── genindex.html
│ │ ├── index.html
│ │ ├── objects.inv
│ │ ├── py-modindex.html
│ │ ├── search.html
│ │ └── searchindex.js
├── conf.py
├── index.rst
└── make.bat
├── pylintrc
├── pytrie.py
├── setup.py
└── tests
├── __init__.py
├── test_mapping.py
└── test_trie.py
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.pyc
3 | PyTrie.egg-info/
4 | .eggs/
5 | *.egg
6 | build/
7 | dist/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009, George Sakkis
2 |
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 | * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
15 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include LICENSE
2 | include tests/*.py
3 | include README.md
4 | recursive-include docs *
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pytrie
2 |
3 | `pytrie` is a a pure Python 3 implementation of the trie data structure.
4 |
5 | A _trie_ is an ordered tree data structure that is used to store a mapping
6 | where the keys are sequences, usually strings over an alphabet. In addition to
7 | implementing the mapping interface, tries allow finding the items for a given
8 | prefix, and vice versa, finding the items whose keys are prefixes of a given key.
9 |
10 | To install run:
11 |
12 | pip install pytrie
13 |
14 | Documentation is available at [Read the Docs](https://pytrie.readthedocs.io/).
15 |
16 | ## Changelog
17 |
18 | ### 0.4.0
19 |
20 | * Drop Python 2 support
21 |
22 | ### 0.3.1
23 |
24 | * Fixed iteritems/itervalues for SortedDicts in Python 2.7.
25 |
26 | ### 0.3
27 |
28 | * Fixed bug for tries with zero-length keys.
29 | * Added `__bool__` (`__nonzero__`) and `__cmp__` methods to `Trie`.
30 | * Added `sortedcontainers` dependency.
31 | * Linting.
32 | * Converted from Mercurial to Git.
33 |
34 | ### 0.2
35 |
36 | * Initial Python 3 support (thanks Dmitrijs Milajevs)
37 |
38 | ### 0.1
39 |
40 | * Initial release
41 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = _build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/_build/doctrees/docs/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/doctrees/docs/index.doctree
--------------------------------------------------------------------------------
/docs/_build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/_build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/_build/html/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: c836f18e6a7021619792fe2482a16499
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/docs/index.rst.txt:
--------------------------------------------------------------------------------
1 | .. PyTrie documentation master file, created by
2 | sphinx-quickstart on Sat Dec 26 19:56:21 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to PyTrie's documentation!
7 | ==================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | .. automodule:: pytrie
14 |
15 | Reference documentation
16 | -----------------------
17 |
18 | Classes
19 | ~~~~~~~
20 | .. autoclass:: Trie
21 | :show-inheritance:
22 | :members: __init__, fromkeys, KeyFactory, NodeFactory
23 | .. autoclass:: StringTrie
24 | :show-inheritance:
25 | .. autoclass:: SortedTrie
26 | :show-inheritance:
27 | .. autoclass:: SortedStringTrie
28 | :show-inheritance:
29 |
30 | Trie methods
31 | ~~~~~~~~~~~~
32 | The following methods are specific to tries; they are not part of the mapping API.
33 |
34 | .. automethod:: Trie.longest_prefix(key[, default])
35 | .. automethod:: Trie.longest_prefix_value(key[, default])
36 | .. automethod:: Trie.longest_prefix_item(key[, default])
37 | .. automethod:: Trie.iter_prefixes
38 | .. automethod:: Trie.iter_prefix_values
39 | .. automethod:: Trie.iter_prefix_items
40 |
41 | Extended mapping API methods
42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 | The following methods extend the respective mapping API methods with an optional
44 | ``prefix`` parameter. If not ``None``, only keys (or associated values/items)
45 | that start with ``prefix`` are returned.
46 |
47 | .. automethod:: Trie.keys
48 | .. automethod:: Trie.values
49 | .. automethod:: Trie.items
50 | .. automethod:: Trie.iterkeys
51 | .. automethod:: Trie.itervalues
52 | .. automethod:: Trie.iteritems
53 |
54 | Original mapping API methods
55 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 | The following methods have the standard mapping signature and semantics.
57 |
58 | .. automethod:: Trie.__len__
59 | .. automethod:: Trie.__bool__
60 | .. automethod:: Trie.__iter__
61 | .. automethod:: Trie.__contains__
62 | .. automethod:: Trie.__getitem__
63 | .. automethod:: Trie.__setitem__
64 | .. automethod:: Trie.__delitem__
65 | .. automethod:: Trie.__repr__
66 | .. automethod:: Trie.clear
67 | .. automethod:: Trie.copy
68 |
69 | Internals
70 | ~~~~~~~~~
71 | Tries are implemented as trees of :class:`Node` instances. You don't need to
72 | worry about them unless unless you want to extend or replace :class:`Node` with
73 | a new node factory and bind it to :attr:`Trie.NodeFactory`.
74 |
75 | .. autoclass:: Node
76 | :show-inheritance:
77 | :members:
78 |
79 | Indices and tables
80 | ==================
81 |
82 | * :ref:`genindex`
83 | * :ref:`modindex`
84 | * :ref:`search`
85 |
--------------------------------------------------------------------------------
/docs/_build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | .. PyTrie documentation master file, created by
2 | sphinx-quickstart on Sat Dec 26 19:56:21 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to PyTrie's documentation!
7 | ==================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | .. automodule:: pytrie
14 |
15 | Reference documentation
16 | -----------------------
17 |
18 | Classes
19 | ~~~~~~~
20 | .. autoclass:: Trie
21 | :show-inheritance:
22 | :members: __init__, fromkeys, KeyFactory, NodeFactory
23 | .. autoclass:: StringTrie
24 | :show-inheritance:
25 | .. autoclass:: SortedTrie
26 | :show-inheritance:
27 | .. autoclass:: SortedStringTrie
28 | :show-inheritance:
29 |
30 | Trie methods
31 | ~~~~~~~~~~~~
32 | The following methods are specific to tries; they are not part of the mapping API.
33 |
34 | .. automethod:: Trie.longest_prefix(key[, default])
35 | .. automethod:: Trie.longest_prefix_value(key[, default])
36 | .. automethod:: Trie.longest_prefix_item(key[, default])
37 | .. automethod:: Trie.iter_prefixes
38 | .. automethod:: Trie.iter_prefix_values
39 | .. automethod:: Trie.iter_prefix_items
40 |
41 | Extended mapping API methods
42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 | The following methods extend the respective mapping API methods with an optional
44 | ``prefix`` parameter. If not ``None``, only keys (or associated values/items)
45 | that start with ``prefix`` are returned.
46 |
47 | .. automethod:: Trie.keys
48 | .. automethod:: Trie.values
49 | .. automethod:: Trie.items
50 | .. automethod:: Trie.iterkeys
51 | .. automethod:: Trie.itervalues
52 | .. automethod:: Trie.iteritems
53 |
54 | Original mapping API methods
55 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 | The following methods have the standard mapping signature and semantics.
57 |
58 | .. automethod:: Trie.__len__
59 | .. automethod:: Trie.__bool__
60 | .. automethod:: Trie.__iter__
61 | .. automethod:: Trie.__contains__
62 | .. automethod:: Trie.__getitem__
63 | .. automethod:: Trie.__setitem__
64 | .. automethod:: Trie.__delitem__
65 | .. automethod:: Trie.__repr__
66 | .. automethod:: Trie.clear
67 | .. automethod:: Trie.copy
68 |
69 | Internals
70 | ~~~~~~~~~
71 | Tries are implemented as trees of :class:`Node` instances. You don't need to
72 | worry about them unless unless you want to extend or replace :class:`Node` with
73 | a new node factory and bind it to :attr:`Trie.NodeFactory`.
74 |
75 | .. autoclass:: Node
76 | :show-inheritance:
77 | :members:
78 |
79 | Indices and tables
80 | ==================
81 |
82 | * :ref:`genindex`
83 | * :ref:`modindex`
84 | * :ref:`search`
85 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/_build/html/_static/alabaster.css:
--------------------------------------------------------------------------------
1 | @import url("basic.css");
2 |
3 | /* -- page layout ----------------------------------------------------------- */
4 |
5 | body {
6 | font-family: Georgia, serif;
7 | font-size: 17px;
8 | background-color: #fff;
9 | color: #000;
10 | margin: 0;
11 | padding: 0;
12 | }
13 |
14 |
15 | div.document {
16 | width: 940px;
17 | margin: 30px auto 0 auto;
18 | }
19 |
20 | div.documentwrapper {
21 | float: left;
22 | width: 100%;
23 | }
24 |
25 | div.bodywrapper {
26 | margin: 0 0 0 220px;
27 | }
28 |
29 | div.sphinxsidebar {
30 | width: 220px;
31 | font-size: 14px;
32 | line-height: 1.5;
33 | }
34 |
35 | hr {
36 | border: 1px solid #B1B4B6;
37 | }
38 |
39 | div.body {
40 | background-color: #fff;
41 | color: #3E4349;
42 | padding: 0 30px 0 30px;
43 | }
44 |
45 | div.body > .section {
46 | text-align: left;
47 | }
48 |
49 | div.footer {
50 | width: 940px;
51 | margin: 20px auto 30px auto;
52 | font-size: 14px;
53 | color: #888;
54 | text-align: right;
55 | }
56 |
57 | div.footer a {
58 | color: #888;
59 | }
60 |
61 | p.caption {
62 | font-family: inherit;
63 | font-size: inherit;
64 | }
65 |
66 |
67 | div.relations {
68 | display: none;
69 | }
70 |
71 |
72 | div.sphinxsidebar a {
73 | color: #444;
74 | text-decoration: none;
75 | border-bottom: 1px dotted #999;
76 | }
77 |
78 | div.sphinxsidebar a:hover {
79 | border-bottom: 1px solid #999;
80 | }
81 |
82 | div.sphinxsidebarwrapper {
83 | padding: 18px 10px;
84 | }
85 |
86 | div.sphinxsidebarwrapper p.logo {
87 | padding: 0;
88 | margin: -10px 0 0 0px;
89 | text-align: center;
90 | }
91 |
92 | div.sphinxsidebarwrapper h1.logo {
93 | margin-top: -10px;
94 | text-align: center;
95 | margin-bottom: 5px;
96 | text-align: left;
97 | }
98 |
99 | div.sphinxsidebarwrapper h1.logo-name {
100 | margin-top: 0px;
101 | }
102 |
103 | div.sphinxsidebarwrapper p.blurb {
104 | margin-top: 0;
105 | font-style: normal;
106 | }
107 |
108 | div.sphinxsidebar h3,
109 | div.sphinxsidebar h4 {
110 | font-family: Georgia, serif;
111 | color: #444;
112 | font-size: 24px;
113 | font-weight: normal;
114 | margin: 0 0 5px 0;
115 | padding: 0;
116 | }
117 |
118 | div.sphinxsidebar h4 {
119 | font-size: 20px;
120 | }
121 |
122 | div.sphinxsidebar h3 a {
123 | color: #444;
124 | }
125 |
126 | div.sphinxsidebar p.logo a,
127 | div.sphinxsidebar h3 a,
128 | div.sphinxsidebar p.logo a:hover,
129 | div.sphinxsidebar h3 a:hover {
130 | border: none;
131 | }
132 |
133 | div.sphinxsidebar p {
134 | color: #555;
135 | margin: 10px 0;
136 | }
137 |
138 | div.sphinxsidebar ul {
139 | margin: 10px 0;
140 | padding: 0;
141 | color: #000;
142 | }
143 |
144 | div.sphinxsidebar ul li.toctree-l1 > a {
145 | font-size: 120%;
146 | }
147 |
148 | div.sphinxsidebar ul li.toctree-l2 > a {
149 | font-size: 110%;
150 | }
151 |
152 | div.sphinxsidebar input {
153 | border: 1px solid #CCC;
154 | font-family: Georgia, serif;
155 | font-size: 1em;
156 | }
157 |
158 | div.sphinxsidebar hr {
159 | border: none;
160 | height: 1px;
161 | color: #AAA;
162 | background: #AAA;
163 |
164 | text-align: left;
165 | margin-left: 0;
166 | width: 50%;
167 | }
168 |
169 | div.sphinxsidebar .badge {
170 | border-bottom: none;
171 | }
172 |
173 | div.sphinxsidebar .badge:hover {
174 | border-bottom: none;
175 | }
176 |
177 | /* To address an issue with donation coming after search */
178 | div.sphinxsidebar h3.donation {
179 | margin-top: 10px;
180 | }
181 |
182 | /* -- body styles ----------------------------------------------------------- */
183 |
184 | a {
185 | color: #004B6B;
186 | text-decoration: underline;
187 | }
188 |
189 | a:hover {
190 | color: #6D4100;
191 | text-decoration: underline;
192 | }
193 |
194 | div.body h1,
195 | div.body h2,
196 | div.body h3,
197 | div.body h4,
198 | div.body h5,
199 | div.body h6 {
200 | font-family: Georgia, serif;
201 | font-weight: normal;
202 | margin: 30px 0px 10px 0px;
203 | padding: 0;
204 | }
205 |
206 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
207 | div.body h2 { font-size: 180%; }
208 | div.body h3 { font-size: 150%; }
209 | div.body h4 { font-size: 130%; }
210 | div.body h5 { font-size: 100%; }
211 | div.body h6 { font-size: 100%; }
212 |
213 | a.headerlink {
214 | color: #DDD;
215 | padding: 0 4px;
216 | text-decoration: none;
217 | }
218 |
219 | a.headerlink:hover {
220 | color: #444;
221 | background: #EAEAEA;
222 | }
223 |
224 | div.body p, div.body dd, div.body li {
225 | line-height: 1.4em;
226 | }
227 |
228 | div.admonition {
229 | margin: 20px 0px;
230 | padding: 10px 30px;
231 | background-color: #EEE;
232 | border: 1px solid #CCC;
233 | }
234 |
235 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
236 | background-color: #FBFBFB;
237 | border-bottom: 1px solid #fafafa;
238 | }
239 |
240 | div.admonition p.admonition-title {
241 | font-family: Georgia, serif;
242 | font-weight: normal;
243 | font-size: 24px;
244 | margin: 0 0 10px 0;
245 | padding: 0;
246 | line-height: 1;
247 | }
248 |
249 | div.admonition p.last {
250 | margin-bottom: 0;
251 | }
252 |
253 | div.highlight {
254 | background-color: #fff;
255 | }
256 |
257 | dt:target, .highlight {
258 | background: #FAF3E8;
259 | }
260 |
261 | div.warning {
262 | background-color: #FCC;
263 | border: 1px solid #FAA;
264 | }
265 |
266 | div.danger {
267 | background-color: #FCC;
268 | border: 1px solid #FAA;
269 | -moz-box-shadow: 2px 2px 4px #D52C2C;
270 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
271 | box-shadow: 2px 2px 4px #D52C2C;
272 | }
273 |
274 | div.error {
275 | background-color: #FCC;
276 | border: 1px solid #FAA;
277 | -moz-box-shadow: 2px 2px 4px #D52C2C;
278 | -webkit-box-shadow: 2px 2px 4px #D52C2C;
279 | box-shadow: 2px 2px 4px #D52C2C;
280 | }
281 |
282 | div.caution {
283 | background-color: #FCC;
284 | border: 1px solid #FAA;
285 | }
286 |
287 | div.attention {
288 | background-color: #FCC;
289 | border: 1px solid #FAA;
290 | }
291 |
292 | div.important {
293 | background-color: #EEE;
294 | border: 1px solid #CCC;
295 | }
296 |
297 | div.note {
298 | background-color: #EEE;
299 | border: 1px solid #CCC;
300 | }
301 |
302 | div.tip {
303 | background-color: #EEE;
304 | border: 1px solid #CCC;
305 | }
306 |
307 | div.hint {
308 | background-color: #EEE;
309 | border: 1px solid #CCC;
310 | }
311 |
312 | div.seealso {
313 | background-color: #EEE;
314 | border: 1px solid #CCC;
315 | }
316 |
317 | div.topic {
318 | background-color: #EEE;
319 | }
320 |
321 | p.admonition-title {
322 | display: inline;
323 | }
324 |
325 | p.admonition-title:after {
326 | content: ":";
327 | }
328 |
329 | pre, tt, code {
330 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
331 | font-size: 0.9em;
332 | }
333 |
334 | .hll {
335 | background-color: #FFC;
336 | margin: 0 -12px;
337 | padding: 0 12px;
338 | display: block;
339 | }
340 |
341 | img.screenshot {
342 | }
343 |
344 | tt.descname, tt.descclassname, code.descname, code.descclassname {
345 | font-size: 0.95em;
346 | }
347 |
348 | tt.descname, code.descname {
349 | padding-right: 0.08em;
350 | }
351 |
352 | img.screenshot {
353 | -moz-box-shadow: 2px 2px 4px #EEE;
354 | -webkit-box-shadow: 2px 2px 4px #EEE;
355 | box-shadow: 2px 2px 4px #EEE;
356 | }
357 |
358 | table.docutils {
359 | border: 1px solid #888;
360 | -moz-box-shadow: 2px 2px 4px #EEE;
361 | -webkit-box-shadow: 2px 2px 4px #EEE;
362 | box-shadow: 2px 2px 4px #EEE;
363 | }
364 |
365 | table.docutils td, table.docutils th {
366 | border: 1px solid #888;
367 | padding: 0.25em 0.7em;
368 | }
369 |
370 | table.field-list, table.footnote {
371 | border: none;
372 | -moz-box-shadow: none;
373 | -webkit-box-shadow: none;
374 | box-shadow: none;
375 | }
376 |
377 | table.footnote {
378 | margin: 15px 0;
379 | width: 100%;
380 | border: 1px solid #EEE;
381 | background: #FDFDFD;
382 | font-size: 0.9em;
383 | }
384 |
385 | table.footnote + table.footnote {
386 | margin-top: -15px;
387 | border-top: none;
388 | }
389 |
390 | table.field-list th {
391 | padding: 0 0.8em 0 0;
392 | }
393 |
394 | table.field-list td {
395 | padding: 0;
396 | }
397 |
398 | table.field-list p {
399 | margin-bottom: 0.8em;
400 | }
401 |
402 | /* Cloned from
403 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
404 | */
405 | .field-name {
406 | -moz-hyphens: manual;
407 | -ms-hyphens: manual;
408 | -webkit-hyphens: manual;
409 | hyphens: manual;
410 | }
411 |
412 | table.footnote td.label {
413 | width: .1px;
414 | padding: 0.3em 0 0.3em 0.5em;
415 | }
416 |
417 | table.footnote td {
418 | padding: 0.3em 0.5em;
419 | }
420 |
421 | dl {
422 | margin: 0;
423 | padding: 0;
424 | }
425 |
426 | dl dd {
427 | margin-left: 30px;
428 | }
429 |
430 | blockquote {
431 | margin: 0 0 0 30px;
432 | padding: 0;
433 | }
434 |
435 | ul, ol {
436 | /* Matches the 30px from the narrow-screen "li > ul" selector below */
437 | margin: 10px 0 10px 30px;
438 | padding: 0;
439 | }
440 |
441 | pre {
442 | background: #EEE;
443 | padding: 7px 30px;
444 | margin: 15px 0px;
445 | line-height: 1.3em;
446 | }
447 |
448 | div.viewcode-block:target {
449 | background: #ffd;
450 | }
451 |
452 | dl pre, blockquote pre, li pre {
453 | margin-left: 0;
454 | padding-left: 30px;
455 | }
456 |
457 | tt, code {
458 | background-color: #ecf0f3;
459 | color: #222;
460 | /* padding: 1px 2px; */
461 | }
462 |
463 | tt.xref, code.xref, a tt {
464 | background-color: #FBFBFB;
465 | border-bottom: 1px solid #fff;
466 | }
467 |
468 | a.reference {
469 | text-decoration: none;
470 | border-bottom: 1px dotted #004B6B;
471 | }
472 |
473 | /* Don't put an underline on images */
474 | a.image-reference, a.image-reference:hover {
475 | border-bottom: none;
476 | }
477 |
478 | a.reference:hover {
479 | border-bottom: 1px solid #6D4100;
480 | }
481 |
482 | a.footnote-reference {
483 | text-decoration: none;
484 | font-size: 0.7em;
485 | vertical-align: top;
486 | border-bottom: 1px dotted #004B6B;
487 | }
488 |
489 | a.footnote-reference:hover {
490 | border-bottom: 1px solid #6D4100;
491 | }
492 |
493 | a:hover tt, a:hover code {
494 | background: #EEE;
495 | }
496 |
497 |
498 | @media screen and (max-width: 870px) {
499 |
500 | div.sphinxsidebar {
501 | display: none;
502 | }
503 |
504 | div.document {
505 | width: 100%;
506 |
507 | }
508 |
509 | div.documentwrapper {
510 | margin-left: 0;
511 | margin-top: 0;
512 | margin-right: 0;
513 | margin-bottom: 0;
514 | }
515 |
516 | div.bodywrapper {
517 | margin-top: 0;
518 | margin-right: 0;
519 | margin-bottom: 0;
520 | margin-left: 0;
521 | }
522 |
523 | ul {
524 | margin-left: 0;
525 | }
526 |
527 | li > ul {
528 | /* Matches the 30px from the "ul, ol" selector above */
529 | margin-left: 30px;
530 | }
531 |
532 | .document {
533 | width: auto;
534 | }
535 |
536 | .footer {
537 | width: auto;
538 | }
539 |
540 | .bodywrapper {
541 | margin: 0;
542 | }
543 |
544 | .footer {
545 | width: auto;
546 | }
547 |
548 | .github {
549 | display: none;
550 | }
551 |
552 |
553 |
554 | }
555 |
556 |
557 |
558 | @media screen and (max-width: 875px) {
559 |
560 | body {
561 | margin: 0;
562 | padding: 20px 30px;
563 | }
564 |
565 | div.documentwrapper {
566 | float: none;
567 | background: #fff;
568 | }
569 |
570 | div.sphinxsidebar {
571 | display: block;
572 | float: none;
573 | width: 102.5%;
574 | margin: 50px -30px -20px -30px;
575 | padding: 10px 20px;
576 | background: #333;
577 | color: #FFF;
578 | }
579 |
580 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
581 | div.sphinxsidebar h3 a {
582 | color: #fff;
583 | }
584 |
585 | div.sphinxsidebar a {
586 | color: #AAA;
587 | }
588 |
589 | div.sphinxsidebar p.logo {
590 | display: none;
591 | }
592 |
593 | div.document {
594 | width: 100%;
595 | margin: 0;
596 | }
597 |
598 | div.footer {
599 | display: none;
600 | }
601 |
602 | div.bodywrapper {
603 | margin: 0;
604 | }
605 |
606 | div.body {
607 | min-height: 0;
608 | padding: 0;
609 | }
610 |
611 | .rtd_doc_footer {
612 | display: none;
613 | }
614 |
615 | .document {
616 | width: auto;
617 | }
618 |
619 | .footer {
620 | width: auto;
621 | }
622 |
623 | .footer {
624 | width: auto;
625 | }
626 |
627 | .github {
628 | display: none;
629 | }
630 | }
631 |
632 |
633 | /* misc. */
634 |
635 | .revsys-inline {
636 | display: none!important;
637 | }
638 |
639 | /* Make nested-list/multi-paragraph items look better in Releases changelog
640 | * pages. Without this, docutils' magical list fuckery causes inconsistent
641 | * formatting between different release sub-lists.
642 | */
643 | div#changelog > div.section > ul > li > p:only-child {
644 | margin-bottom: 0;
645 | }
646 |
647 | /* Hide fugly table cell borders in ..bibliography:: directive output */
648 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
649 | border: none;
650 | /* Below needed in some edge cases; if not applied, bottom shadows appear */
651 | -moz-box-shadow: none;
652 | -webkit-box-shadow: none;
653 | box-shadow: none;
654 | }
655 |
656 |
657 | /* relbar */
658 |
659 | .related {
660 | line-height: 30px;
661 | width: 100%;
662 | font-size: 0.9rem;
663 | }
664 |
665 | .related.top {
666 | border-bottom: 1px solid #EEE;
667 | margin-bottom: 20px;
668 | }
669 |
670 | .related.bottom {
671 | border-top: 1px solid #EEE;
672 | }
673 |
674 | .related ul {
675 | padding: 0;
676 | margin: 0;
677 | list-style: none;
678 | }
679 |
680 | .related li {
681 | display: inline;
682 | }
683 |
684 | nav#rellinks {
685 | float: right;
686 | }
687 |
688 | nav#rellinks li+li:before {
689 | content: "|";
690 | }
691 |
692 | nav#breadcrumbs li+li:before {
693 | content: "\00BB";
694 | }
695 |
696 | /* Hide certain items when printing */
697 | @media print {
698 | div.related {
699 | display: none;
700 | }
701 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /* -- main layout ----------------------------------------------------------- */
13 |
14 | div.clearer {
15 | clear: both;
16 | }
17 |
18 | /* -- relbar ---------------------------------------------------------------- */
19 |
20 | div.related {
21 | width: 100%;
22 | font-size: 90%;
23 | }
24 |
25 | div.related h3 {
26 | display: none;
27 | }
28 |
29 | div.related ul {
30 | margin: 0;
31 | padding: 0 0 0 10px;
32 | list-style: none;
33 | }
34 |
35 | div.related li {
36 | display: inline;
37 | }
38 |
39 | div.related li.right {
40 | float: right;
41 | margin-right: 5px;
42 | }
43 |
44 | /* -- sidebar --------------------------------------------------------------- */
45 |
46 | div.sphinxsidebarwrapper {
47 | padding: 10px 5px 0 10px;
48 | }
49 |
50 | div.sphinxsidebar {
51 | float: left;
52 | width: 230px;
53 | margin-left: -100%;
54 | font-size: 90%;
55 | word-wrap: break-word;
56 | overflow-wrap : break-word;
57 | }
58 |
59 | div.sphinxsidebar ul {
60 | list-style: none;
61 | }
62 |
63 | div.sphinxsidebar ul ul,
64 | div.sphinxsidebar ul.want-points {
65 | margin-left: 20px;
66 | list-style: square;
67 | }
68 |
69 | div.sphinxsidebar ul ul {
70 | margin-top: 0;
71 | margin-bottom: 0;
72 | }
73 |
74 | div.sphinxsidebar form {
75 | margin-top: 10px;
76 | }
77 |
78 | div.sphinxsidebar input {
79 | border: 1px solid #98dbcc;
80 | font-family: sans-serif;
81 | font-size: 1em;
82 | }
83 |
84 | div.sphinxsidebar #searchbox form.search {
85 | overflow: hidden;
86 | }
87 |
88 | div.sphinxsidebar #searchbox input[type="text"] {
89 | float: left;
90 | width: 80%;
91 | padding: 0.25em;
92 | box-sizing: border-box;
93 | }
94 |
95 | div.sphinxsidebar #searchbox input[type="submit"] {
96 | float: left;
97 | width: 20%;
98 | border-left: none;
99 | padding: 0.25em;
100 | box-sizing: border-box;
101 | }
102 |
103 |
104 | img {
105 | border: 0;
106 | max-width: 100%;
107 | }
108 |
109 | /* -- search page ----------------------------------------------------------- */
110 |
111 | ul.search {
112 | margin: 10px 0 0 20px;
113 | padding: 0;
114 | }
115 |
116 | ul.search li {
117 | padding: 5px 0 5px 20px;
118 | background-image: url(file.png);
119 | background-repeat: no-repeat;
120 | background-position: 0 7px;
121 | }
122 |
123 | ul.search li a {
124 | font-weight: bold;
125 | }
126 |
127 | ul.search li div.context {
128 | color: #888;
129 | margin: 2px 0 0 30px;
130 | text-align: left;
131 | }
132 |
133 | ul.keywordmatches li.goodmatch a {
134 | font-weight: bold;
135 | }
136 |
137 | /* -- index page ------------------------------------------------------------ */
138 |
139 | table.contentstable {
140 | width: 90%;
141 | margin-left: auto;
142 | margin-right: auto;
143 | }
144 |
145 | table.contentstable p.biglink {
146 | line-height: 150%;
147 | }
148 |
149 | a.biglink {
150 | font-size: 1.3em;
151 | }
152 |
153 | span.linkdescr {
154 | font-style: italic;
155 | padding-top: 5px;
156 | font-size: 90%;
157 | }
158 |
159 | /* -- general index --------------------------------------------------------- */
160 |
161 | table.indextable {
162 | width: 100%;
163 | }
164 |
165 | table.indextable td {
166 | text-align: left;
167 | vertical-align: top;
168 | }
169 |
170 | table.indextable ul {
171 | margin-top: 0;
172 | margin-bottom: 0;
173 | list-style-type: none;
174 | }
175 |
176 | table.indextable > tbody > tr > td > ul {
177 | padding-left: 0em;
178 | }
179 |
180 | table.indextable tr.pcap {
181 | height: 10px;
182 | }
183 |
184 | table.indextable tr.cap {
185 | margin-top: 10px;
186 | background-color: #f2f2f2;
187 | }
188 |
189 | img.toggler {
190 | margin-right: 3px;
191 | margin-top: 3px;
192 | cursor: pointer;
193 | }
194 |
195 | div.modindex-jumpbox {
196 | border-top: 1px solid #ddd;
197 | border-bottom: 1px solid #ddd;
198 | margin: 1em 0 1em 0;
199 | padding: 0.4em;
200 | }
201 |
202 | div.genindex-jumpbox {
203 | border-top: 1px solid #ddd;
204 | border-bottom: 1px solid #ddd;
205 | margin: 1em 0 1em 0;
206 | padding: 0.4em;
207 | }
208 |
209 | /* -- domain module index --------------------------------------------------- */
210 |
211 | table.modindextable td {
212 | padding: 2px;
213 | border-collapse: collapse;
214 | }
215 |
216 | /* -- general body styles --------------------------------------------------- */
217 |
218 | div.body {
219 | min-width: 450px;
220 | max-width: 800px;
221 | }
222 |
223 | div.body p, div.body dd, div.body li, div.body blockquote {
224 | -moz-hyphens: auto;
225 | -ms-hyphens: auto;
226 | -webkit-hyphens: auto;
227 | hyphens: auto;
228 | }
229 |
230 | a.headerlink {
231 | visibility: hidden;
232 | }
233 |
234 | h1:hover > a.headerlink,
235 | h2:hover > a.headerlink,
236 | h3:hover > a.headerlink,
237 | h4:hover > a.headerlink,
238 | h5:hover > a.headerlink,
239 | h6:hover > a.headerlink,
240 | dt:hover > a.headerlink,
241 | caption:hover > a.headerlink,
242 | p.caption:hover > a.headerlink,
243 | div.code-block-caption:hover > a.headerlink {
244 | visibility: visible;
245 | }
246 |
247 | div.body p.caption {
248 | text-align: inherit;
249 | }
250 |
251 | div.body td {
252 | text-align: left;
253 | }
254 |
255 | .first {
256 | margin-top: 0 !important;
257 | }
258 |
259 | p.rubric {
260 | margin-top: 30px;
261 | font-weight: bold;
262 | }
263 |
264 | img.align-left, .figure.align-left, object.align-left {
265 | clear: left;
266 | float: left;
267 | margin-right: 1em;
268 | }
269 |
270 | img.align-right, .figure.align-right, object.align-right {
271 | clear: right;
272 | float: right;
273 | margin-left: 1em;
274 | }
275 |
276 | img.align-center, .figure.align-center, object.align-center {
277 | display: block;
278 | margin-left: auto;
279 | margin-right: auto;
280 | }
281 |
282 | .align-left {
283 | text-align: left;
284 | }
285 |
286 | .align-center {
287 | text-align: center;
288 | }
289 |
290 | .align-right {
291 | text-align: right;
292 | }
293 |
294 | /* -- sidebars -------------------------------------------------------------- */
295 |
296 | div.sidebar {
297 | margin: 0 0 0.5em 1em;
298 | border: 1px solid #ddb;
299 | padding: 7px 7px 0 7px;
300 | background-color: #ffe;
301 | width: 40%;
302 | float: right;
303 | }
304 |
305 | p.sidebar-title {
306 | font-weight: bold;
307 | }
308 |
309 | /* -- topics ---------------------------------------------------------------- */
310 |
311 | div.topic {
312 | border: 1px solid #ccc;
313 | padding: 7px 7px 0 7px;
314 | margin: 10px 0 10px 0;
315 | }
316 |
317 | p.topic-title {
318 | font-size: 1.1em;
319 | font-weight: bold;
320 | margin-top: 10px;
321 | }
322 |
323 | /* -- admonitions ----------------------------------------------------------- */
324 |
325 | div.admonition {
326 | margin-top: 10px;
327 | margin-bottom: 10px;
328 | padding: 7px;
329 | }
330 |
331 | div.admonition dt {
332 | font-weight: bold;
333 | }
334 |
335 | div.admonition dl {
336 | margin-bottom: 0;
337 | }
338 |
339 | p.admonition-title {
340 | margin: 0px 10px 5px 0px;
341 | font-weight: bold;
342 | }
343 |
344 | div.body p.centered {
345 | text-align: center;
346 | margin-top: 25px;
347 | }
348 |
349 | /* -- tables ---------------------------------------------------------------- */
350 |
351 | table.docutils {
352 | border: 0;
353 | border-collapse: collapse;
354 | }
355 |
356 | table.align-center {
357 | margin-left: auto;
358 | margin-right: auto;
359 | }
360 |
361 | table caption span.caption-number {
362 | font-style: italic;
363 | }
364 |
365 | table caption span.caption-text {
366 | }
367 |
368 | table.docutils td, table.docutils th {
369 | padding: 1px 8px 1px 5px;
370 | border-top: 0;
371 | border-left: 0;
372 | border-right: 0;
373 | border-bottom: 1px solid #aaa;
374 | }
375 |
376 | table.footnote td, table.footnote th {
377 | border: 0 !important;
378 | }
379 |
380 | th {
381 | text-align: left;
382 | padding-right: 5px;
383 | }
384 |
385 | table.citation {
386 | border-left: solid 1px gray;
387 | margin-left: 1px;
388 | }
389 |
390 | table.citation td {
391 | border-bottom: none;
392 | }
393 |
394 | /* -- figures --------------------------------------------------------------- */
395 |
396 | div.figure {
397 | margin: 0.5em;
398 | padding: 0.5em;
399 | }
400 |
401 | div.figure p.caption {
402 | padding: 0.3em;
403 | }
404 |
405 | div.figure p.caption span.caption-number {
406 | font-style: italic;
407 | }
408 |
409 | div.figure p.caption span.caption-text {
410 | }
411 |
412 | /* -- field list styles ----------------------------------------------------- */
413 |
414 | table.field-list td, table.field-list th {
415 | border: 0 !important;
416 | }
417 |
418 | .field-list ul {
419 | margin: 0;
420 | padding-left: 1em;
421 | }
422 |
423 | .field-list p {
424 | margin: 0;
425 | }
426 |
427 | .field-name {
428 | -moz-hyphens: manual;
429 | -ms-hyphens: manual;
430 | -webkit-hyphens: manual;
431 | hyphens: manual;
432 | }
433 |
434 | /* -- hlist styles ---------------------------------------------------------- */
435 |
436 | table.hlist td {
437 | vertical-align: top;
438 | }
439 |
440 |
441 | /* -- other body styles ----------------------------------------------------- */
442 |
443 | ol.arabic {
444 | list-style: decimal;
445 | }
446 |
447 | ol.loweralpha {
448 | list-style: lower-alpha;
449 | }
450 |
451 | ol.upperalpha {
452 | list-style: upper-alpha;
453 | }
454 |
455 | ol.lowerroman {
456 | list-style: lower-roman;
457 | }
458 |
459 | ol.upperroman {
460 | list-style: upper-roman;
461 | }
462 |
463 | dl {
464 | margin-bottom: 15px;
465 | }
466 |
467 | dd p {
468 | margin-top: 0px;
469 | }
470 |
471 | dd ul, dd table {
472 | margin-bottom: 10px;
473 | }
474 |
475 | dd {
476 | margin-top: 3px;
477 | margin-bottom: 10px;
478 | margin-left: 30px;
479 | }
480 |
481 | dt:target, span.highlighted {
482 | background-color: #fbe54e;
483 | }
484 |
485 | rect.highlighted {
486 | fill: #fbe54e;
487 | }
488 |
489 | dl.glossary dt {
490 | font-weight: bold;
491 | font-size: 1.1em;
492 | }
493 |
494 | .optional {
495 | font-size: 1.3em;
496 | }
497 |
498 | .sig-paren {
499 | font-size: larger;
500 | }
501 |
502 | .versionmodified {
503 | font-style: italic;
504 | }
505 |
506 | .system-message {
507 | background-color: #fda;
508 | padding: 5px;
509 | border: 3px solid red;
510 | }
511 |
512 | .footnote:target {
513 | background-color: #ffa;
514 | }
515 |
516 | .line-block {
517 | display: block;
518 | margin-top: 1em;
519 | margin-bottom: 1em;
520 | }
521 |
522 | .line-block .line-block {
523 | margin-top: 0;
524 | margin-bottom: 0;
525 | margin-left: 1.5em;
526 | }
527 |
528 | .guilabel, .menuselection {
529 | font-family: sans-serif;
530 | }
531 |
532 | .accelerator {
533 | text-decoration: underline;
534 | }
535 |
536 | .classifier {
537 | font-style: oblique;
538 | }
539 |
540 | abbr, acronym {
541 | border-bottom: dotted 1px;
542 | cursor: help;
543 | }
544 |
545 | /* -- code displays --------------------------------------------------------- */
546 |
547 | pre {
548 | overflow: auto;
549 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
550 | }
551 |
552 | span.pre {
553 | -moz-hyphens: none;
554 | -ms-hyphens: none;
555 | -webkit-hyphens: none;
556 | hyphens: none;
557 | }
558 |
559 | td.linenos pre {
560 | padding: 5px 0px;
561 | border: 0;
562 | background-color: transparent;
563 | color: #aaa;
564 | }
565 |
566 | table.highlighttable {
567 | margin-left: 0.5em;
568 | }
569 |
570 | table.highlighttable td {
571 | padding: 0 0.5em 0 0.5em;
572 | }
573 |
574 | div.code-block-caption {
575 | padding: 2px 5px;
576 | font-size: small;
577 | }
578 |
579 | div.code-block-caption code {
580 | background-color: transparent;
581 | }
582 |
583 | div.code-block-caption + div > div.highlight > pre {
584 | margin-top: 0;
585 | }
586 |
587 | div.code-block-caption span.caption-number {
588 | padding: 0.1em 0.3em;
589 | font-style: italic;
590 | }
591 |
592 | div.code-block-caption span.caption-text {
593 | }
594 |
595 | div.literal-block-wrapper {
596 | padding: 1em 1em 0;
597 | }
598 |
599 | div.literal-block-wrapper div.highlight {
600 | margin: 0;
601 | }
602 |
603 | code.descname {
604 | background-color: transparent;
605 | font-weight: bold;
606 | font-size: 1.2em;
607 | }
608 |
609 | code.descclassname {
610 | background-color: transparent;
611 | }
612 |
613 | code.xref, a code {
614 | background-color: transparent;
615 | font-weight: bold;
616 | }
617 |
618 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
619 | background-color: transparent;
620 | }
621 |
622 | .viewcode-link {
623 | float: right;
624 | }
625 |
626 | .viewcode-back {
627 | float: right;
628 | font-family: sans-serif;
629 | }
630 |
631 | div.viewcode-block:target {
632 | margin: -1px -10px;
633 | padding: 0 10px;
634 | }
635 |
636 | /* -- math display ---------------------------------------------------------- */
637 |
638 | img.math {
639 | vertical-align: middle;
640 | }
641 |
642 | div.body div.math p {
643 | text-align: center;
644 | }
645 |
646 | span.eqno {
647 | float: right;
648 | }
649 |
650 | span.eqno a.headerlink {
651 | position: relative;
652 | left: 0px;
653 | z-index: 1;
654 | }
655 |
656 | div.math:hover a.headerlink {
657 | visibility: visible;
658 | }
659 |
660 | /* -- printout stylesheet --------------------------------------------------- */
661 |
662 | @media print {
663 | div.document,
664 | div.documentwrapper,
665 | div.bodywrapper {
666 | margin: 0 !important;
667 | width: 100%;
668 | }
669 |
670 | div.sphinxsidebar,
671 | div.related,
672 | div.footer,
673 | #top-link {
674 | display: none;
675 | }
676 | }
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/comment.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/doctools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * doctools.js
3 | * ~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for all documentation.
6 | *
7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /**
13 | * select a different prefix for underscore
14 | */
15 | $u = _.noConflict();
16 |
17 | /**
18 | * make the code below compatible with browsers without
19 | * an installed firebug like debugger
20 | if (!window.console || !console.firebug) {
21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
23 | "profile", "profileEnd"];
24 | window.console = {};
25 | for (var i = 0; i < names.length; ++i)
26 | window.console[names[i]] = function() {};
27 | }
28 | */
29 |
30 | /**
31 | * small helper function to urldecode strings
32 | */
33 | jQuery.urldecode = function(x) {
34 | return decodeURIComponent(x).replace(/\+/g, ' ');
35 | };
36 |
37 | /**
38 | * small helper function to urlencode strings
39 | */
40 | jQuery.urlencode = encodeURIComponent;
41 |
42 | /**
43 | * This function returns the parsed url parameters of the
44 | * current request. Multiple values per key are supported,
45 | * it will always return arrays of strings for the value parts.
46 | */
47 | jQuery.getQueryParameters = function(s) {
48 | if (typeof s === 'undefined')
49 | s = document.location.search;
50 | var parts = s.substr(s.indexOf('?') + 1).split('&');
51 | var result = {};
52 | for (var i = 0; i < parts.length; i++) {
53 | var tmp = parts[i].split('=', 2);
54 | var key = jQuery.urldecode(tmp[0]);
55 | var value = jQuery.urldecode(tmp[1]);
56 | if (key in result)
57 | result[key].push(value);
58 | else
59 | result[key] = [value];
60 | }
61 | return result;
62 | };
63 |
64 | /**
65 | * highlight a given string on a jquery object by wrapping it in
66 | * span elements with the given class name.
67 | */
68 | jQuery.fn.highlightText = function(text, className) {
69 | function highlight(node, addItems) {
70 | if (node.nodeType === 3) {
71 | var val = node.nodeValue;
72 | var pos = val.toLowerCase().indexOf(text);
73 | if (pos >= 0 &&
74 | !jQuery(node.parentNode).hasClass(className) &&
75 | !jQuery(node.parentNode).hasClass("nohighlight")) {
76 | var span;
77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
78 | if (isInSVG) {
79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
80 | } else {
81 | span = document.createElement("span");
82 | span.className = className;
83 | }
84 | span.appendChild(document.createTextNode(val.substr(pos, text.length)));
85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore(
86 | document.createTextNode(val.substr(pos + text.length)),
87 | node.nextSibling));
88 | node.nodeValue = val.substr(0, pos);
89 | if (isInSVG) {
90 | var bbox = span.getBBox();
91 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
92 | rect.x.baseVal.value = bbox.x;
93 | rect.y.baseVal.value = bbox.y;
94 | rect.width.baseVal.value = bbox.width;
95 | rect.height.baseVal.value = bbox.height;
96 | rect.setAttribute('class', className);
97 | var parentOfText = node.parentNode.parentNode;
98 | addItems.push({
99 | "parent": node.parentNode,
100 | "target": rect});
101 | }
102 | }
103 | }
104 | else if (!jQuery(node).is("button, select, textarea")) {
105 | jQuery.each(node.childNodes, function() {
106 | highlight(this, addItems);
107 | });
108 | }
109 | }
110 | var addItems = [];
111 | var result = this.each(function() {
112 | highlight(this, addItems);
113 | });
114 | for (var i = 0; i < addItems.length; ++i) {
115 | jQuery(addItems[i].parent).before(addItems[i].target);
116 | }
117 | return result;
118 | };
119 |
120 | /*
121 | * backward compatibility for jQuery.browser
122 | * This will be supported until firefox bug is fixed.
123 | */
124 | if (!jQuery.browser) {
125 | jQuery.uaMatch = function(ua) {
126 | ua = ua.toLowerCase();
127 |
128 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
129 | /(webkit)[ \/]([\w.]+)/.exec(ua) ||
130 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
131 | /(msie) ([\w.]+)/.exec(ua) ||
132 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
133 | [];
134 |
135 | return {
136 | browser: match[ 1 ] || "",
137 | version: match[ 2 ] || "0"
138 | };
139 | };
140 | jQuery.browser = {};
141 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
142 | }
143 |
144 | /**
145 | * Small JavaScript module for the documentation.
146 | */
147 | var Documentation = {
148 |
149 | init : function() {
150 | this.fixFirefoxAnchorBug();
151 | this.highlightSearchWords();
152 | this.initIndexTable();
153 | if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
154 | this.initOnKeyListeners();
155 | }
156 | },
157 |
158 | /**
159 | * i18n support
160 | */
161 | TRANSLATIONS : {},
162 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
163 | LOCALE : 'unknown',
164 |
165 | // gettext and ngettext don't access this so that the functions
166 | // can safely bound to a different name (_ = Documentation.gettext)
167 | gettext : function(string) {
168 | var translated = Documentation.TRANSLATIONS[string];
169 | if (typeof translated === 'undefined')
170 | return string;
171 | return (typeof translated === 'string') ? translated : translated[0];
172 | },
173 |
174 | ngettext : function(singular, plural, n) {
175 | var translated = Documentation.TRANSLATIONS[singular];
176 | if (typeof translated === 'undefined')
177 | return (n == 1) ? singular : plural;
178 | return translated[Documentation.PLURALEXPR(n)];
179 | },
180 |
181 | addTranslations : function(catalog) {
182 | for (var key in catalog.messages)
183 | this.TRANSLATIONS[key] = catalog.messages[key];
184 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
185 | this.LOCALE = catalog.locale;
186 | },
187 |
188 | /**
189 | * add context elements like header anchor links
190 | */
191 | addContextElements : function() {
192 | $('div[id] > :header:first').each(function() {
193 | $('').
194 | attr('href', '#' + this.id).
195 | attr('title', _('Permalink to this headline')).
196 | appendTo(this);
197 | });
198 | $('dt[id]').each(function() {
199 | $('').
200 | attr('href', '#' + this.id).
201 | attr('title', _('Permalink to this definition')).
202 | appendTo(this);
203 | });
204 | },
205 |
206 | /**
207 | * workaround a firefox stupidity
208 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
209 | */
210 | fixFirefoxAnchorBug : function() {
211 | if (document.location.hash && $.browser.mozilla)
212 | window.setTimeout(function() {
213 | document.location.href += '';
214 | }, 10);
215 | },
216 |
217 | /**
218 | * highlight the search words provided in the url in the text
219 | */
220 | highlightSearchWords : function() {
221 | var params = $.getQueryParameters();
222 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
223 | if (terms.length) {
224 | var body = $('div.body');
225 | if (!body.length) {
226 | body = $('body');
227 | }
228 | window.setTimeout(function() {
229 | $.each(terms, function() {
230 | body.highlightText(this.toLowerCase(), 'highlighted');
231 | });
232 | }, 10);
233 | $('
' + _('Hide Search Matches') + '
')
235 | .appendTo($('#searchbox'));
236 | }
237 | },
238 |
239 | /**
240 | * init the domain index toggle buttons
241 | */
242 | initIndexTable : function() {
243 | var togglers = $('img.toggler').click(function() {
244 | var src = $(this).attr('src');
245 | var idnum = $(this).attr('id').substr(7);
246 | $('tr.cg-' + idnum).toggle();
247 | if (src.substr(-9) === 'minus.png')
248 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
249 | else
250 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
251 | }).css('display', '');
252 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
253 | togglers.click();
254 | }
255 | },
256 |
257 | /**
258 | * helper function to hide the search marks again
259 | */
260 | hideSearchWords : function() {
261 | $('#searchbox .highlight-link').fadeOut(300);
262 | $('span.highlighted').removeClass('highlighted');
263 | },
264 |
265 | /**
266 | * make the url absolute
267 | */
268 | makeURL : function(relativeURL) {
269 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
270 | },
271 |
272 | /**
273 | * get the current relative url
274 | */
275 | getCurrentURL : function() {
276 | var path = document.location.pathname;
277 | var parts = path.split(/\//);
278 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
279 | if (this === '..')
280 | parts.pop();
281 | });
282 | var url = parts.join('/');
283 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
284 | },
285 |
286 | initOnKeyListeners: function() {
287 | $(document).keyup(function(event) {
288 | var activeElementType = document.activeElement.tagName;
289 | // don't navigate when in search box or textarea
290 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
291 | switch (event.keyCode) {
292 | case 37: // left
293 | var prevHref = $('link[rel="prev"]').prop('href');
294 | if (prevHref) {
295 | window.location.href = prevHref;
296 | return false;
297 | }
298 | case 39: // right
299 | var nextHref = $('link[rel="next"]').prop('href');
300 | if (nextHref) {
301 | window.location.href = nextHref;
302 | return false;
303 | }
304 | }
305 | }
306 | });
307 | }
308 | };
309 |
310 | // quick alias for translations
311 | _ = Documentation.gettext;
312 |
313 | $(document).ready(function() {
314 | Documentation.init();
315 | });
316 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | var DOCUMENTATION_OPTIONS = {
2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
3 | VERSION: '0.4.0',
4 | LANGUAGE: 'None',
5 | COLLAPSE_INDEX: false,
6 | FILE_SUFFIX: '.html',
7 | HAS_SOURCE: true,
8 | SOURCELINK_SUFFIX: '.txt',
9 | NAVIGATION_WITH_KEYS: false,
10 | };
--------------------------------------------------------------------------------
/docs/_build/html/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/down-pressed.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/down.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/language_data.js:
--------------------------------------------------------------------------------
1 | /*
2 | * language_data.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * This script contains the language-specific data used by searchtools.js,
6 | * namely the list of stopwords, stemmer, scorer and splitter.
7 | *
8 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
9 | * :license: BSD, see LICENSE for details.
10 | *
11 | */
12 |
13 | var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
14 |
15 |
16 | /* Non-minified version JS is _stemmer.js if file is provided */
17 | /**
18 | * Porter Stemmer
19 | */
20 | var Stemmer = function() {
21 |
22 | var step2list = {
23 | ational: 'ate',
24 | tional: 'tion',
25 | enci: 'ence',
26 | anci: 'ance',
27 | izer: 'ize',
28 | bli: 'ble',
29 | alli: 'al',
30 | entli: 'ent',
31 | eli: 'e',
32 | ousli: 'ous',
33 | ization: 'ize',
34 | ation: 'ate',
35 | ator: 'ate',
36 | alism: 'al',
37 | iveness: 'ive',
38 | fulness: 'ful',
39 | ousness: 'ous',
40 | aliti: 'al',
41 | iviti: 'ive',
42 | biliti: 'ble',
43 | logi: 'log'
44 | };
45 |
46 | var step3list = {
47 | icate: 'ic',
48 | ative: '',
49 | alize: 'al',
50 | iciti: 'ic',
51 | ical: 'ic',
52 | ful: '',
53 | ness: ''
54 | };
55 |
56 | var c = "[^aeiou]"; // consonant
57 | var v = "[aeiouy]"; // vowel
58 | var C = c + "[^aeiouy]*"; // consonant sequence
59 | var V = v + "[aeiou]*"; // vowel sequence
60 |
61 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
62 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
63 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
64 | var s_v = "^(" + C + ")?" + v; // vowel in stem
65 |
66 | this.stemWord = function (w) {
67 | var stem;
68 | var suffix;
69 | var firstch;
70 | var origword = w;
71 |
72 | if (w.length < 3)
73 | return w;
74 |
75 | var re;
76 | var re2;
77 | var re3;
78 | var re4;
79 |
80 | firstch = w.substr(0,1);
81 | if (firstch == "y")
82 | w = firstch.toUpperCase() + w.substr(1);
83 |
84 | // Step 1a
85 | re = /^(.+?)(ss|i)es$/;
86 | re2 = /^(.+?)([^s])s$/;
87 |
88 | if (re.test(w))
89 | w = w.replace(re,"$1$2");
90 | else if (re2.test(w))
91 | w = w.replace(re2,"$1$2");
92 |
93 | // Step 1b
94 | re = /^(.+?)eed$/;
95 | re2 = /^(.+?)(ed|ing)$/;
96 | if (re.test(w)) {
97 | var fp = re.exec(w);
98 | re = new RegExp(mgr0);
99 | if (re.test(fp[1])) {
100 | re = /.$/;
101 | w = w.replace(re,"");
102 | }
103 | }
104 | else if (re2.test(w)) {
105 | var fp = re2.exec(w);
106 | stem = fp[1];
107 | re2 = new RegExp(s_v);
108 | if (re2.test(stem)) {
109 | w = stem;
110 | re2 = /(at|bl|iz)$/;
111 | re3 = new RegExp("([^aeiouylsz])\\1$");
112 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
113 | if (re2.test(w))
114 | w = w + "e";
115 | else if (re3.test(w)) {
116 | re = /.$/;
117 | w = w.replace(re,"");
118 | }
119 | else if (re4.test(w))
120 | w = w + "e";
121 | }
122 | }
123 |
124 | // Step 1c
125 | re = /^(.+?)y$/;
126 | if (re.test(w)) {
127 | var fp = re.exec(w);
128 | stem = fp[1];
129 | re = new RegExp(s_v);
130 | if (re.test(stem))
131 | w = stem + "i";
132 | }
133 |
134 | // Step 2
135 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
136 | if (re.test(w)) {
137 | var fp = re.exec(w);
138 | stem = fp[1];
139 | suffix = fp[2];
140 | re = new RegExp(mgr0);
141 | if (re.test(stem))
142 | w = stem + step2list[suffix];
143 | }
144 |
145 | // Step 3
146 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
147 | if (re.test(w)) {
148 | var fp = re.exec(w);
149 | stem = fp[1];
150 | suffix = fp[2];
151 | re = new RegExp(mgr0);
152 | if (re.test(stem))
153 | w = stem + step3list[suffix];
154 | }
155 |
156 | // Step 4
157 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
158 | re2 = /^(.+?)(s|t)(ion)$/;
159 | if (re.test(w)) {
160 | var fp = re.exec(w);
161 | stem = fp[1];
162 | re = new RegExp(mgr1);
163 | if (re.test(stem))
164 | w = stem;
165 | }
166 | else if (re2.test(w)) {
167 | var fp = re2.exec(w);
168 | stem = fp[1] + fp[2];
169 | re2 = new RegExp(mgr1);
170 | if (re2.test(stem))
171 | w = stem;
172 | }
173 |
174 | // Step 5
175 | re = /^(.+?)e$/;
176 | if (re.test(w)) {
177 | var fp = re.exec(w);
178 | stem = fp[1];
179 | re = new RegExp(mgr1);
180 | re2 = new RegExp(meq1);
181 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
182 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
183 | w = stem;
184 | }
185 | re = /ll$/;
186 | re2 = new RegExp(mgr1);
187 | if (re.test(w) && re2.test(w)) {
188 | re = /.$/;
189 | w = w.replace(re,"");
190 | }
191 |
192 | // and turn initial Y back to y
193 | if (firstch == "y")
194 | w = firstch.toLowerCase() + w.substr(1);
195 | return w;
196 | }
197 | }
198 |
199 |
200 |
201 |
202 |
203 | var splitChars = (function() {
204 | var result = {};
205 | var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
206 | 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
207 | 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
208 | 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
209 | 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
210 | 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
211 | 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
212 | 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
213 | 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
214 | 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
215 | var i, j, start, end;
216 | for (i = 0; i < singles.length; i++) {
217 | result[singles[i]] = true;
218 | }
219 | var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
220 | [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
221 | [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
222 | [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
223 | [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
224 | [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
225 | [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
226 | [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
227 | [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
228 | [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
229 | [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
230 | [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
231 | [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
232 | [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
233 | [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
234 | [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
235 | [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
236 | [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
237 | [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
238 | [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
239 | [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
240 | [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
241 | [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
242 | [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
243 | [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
244 | [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
245 | [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
246 | [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
247 | [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
248 | [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
249 | [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
250 | [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
251 | [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
252 | [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
253 | [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
254 | [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
255 | [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
256 | [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
257 | [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
258 | [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
259 | [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
260 | [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
261 | [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
262 | [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
263 | [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
264 | [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
265 | [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
266 | [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
267 | [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
268 | for (i = 0; i < ranges.length; i++) {
269 | start = ranges[i][0];
270 | end = ranges[i][1];
271 | for (j = start; j <= end; j++) {
272 | result[j] = true;
273 | }
274 | }
275 | return result;
276 | })();
277 |
278 | function splitQuery(query) {
279 | var result = [];
280 | var start = -1;
281 | for (var i = 0; i < query.length; i++) {
282 | if (splitChars[query.charCodeAt(i)]) {
283 | if (start !== -1) {
284 | result.push(query.slice(start, i));
285 | start = -1;
286 | }
287 | } else if (start === -1) {
288 | start = i;
289 | }
290 | }
291 | if (start !== -1) {
292 | result.push(query.slice(start));
293 | }
294 | return result;
295 | }
296 |
297 |
298 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/pygments.css:
--------------------------------------------------------------------------------
1 | pre { line-height: 125%; }
2 | td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
3 | span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }
4 | td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
5 | span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
6 | .highlight .hll { background-color: #ffffcc }
7 | .highlight { background: #f8f8f8; }
8 | .highlight .c { color: #8f5902; font-style: italic } /* Comment */
9 | .highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
10 | .highlight .g { color: #000000 } /* Generic */
11 | .highlight .k { color: #004461; font-weight: bold } /* Keyword */
12 | .highlight .l { color: #000000 } /* Literal */
13 | .highlight .n { color: #000000 } /* Name */
14 | .highlight .o { color: #582800 } /* Operator */
15 | .highlight .x { color: #000000 } /* Other */
16 | .highlight .p { color: #000000; font-weight: bold } /* Punctuation */
17 | .highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */
18 | .highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
19 | .highlight .cp { color: #8f5902 } /* Comment.Preproc */
20 | .highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */
21 | .highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
22 | .highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */
23 | .highlight .gd { color: #a40000 } /* Generic.Deleted */
24 | .highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
25 | .highlight .gr { color: #ef2929 } /* Generic.Error */
26 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
27 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
28 | .highlight .go { color: #888888 } /* Generic.Output */
29 | .highlight .gp { color: #745334 } /* Generic.Prompt */
30 | .highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */
31 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
32 | .highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
33 | .highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */
34 | .highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */
35 | .highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */
36 | .highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */
37 | .highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */
38 | .highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */
39 | .highlight .ld { color: #000000 } /* Literal.Date */
40 | .highlight .m { color: #990000 } /* Literal.Number */
41 | .highlight .s { color: #4e9a06 } /* Literal.String */
42 | .highlight .na { color: #c4a000 } /* Name.Attribute */
43 | .highlight .nb { color: #004461 } /* Name.Builtin */
44 | .highlight .nc { color: #000000 } /* Name.Class */
45 | .highlight .no { color: #000000 } /* Name.Constant */
46 | .highlight .nd { color: #888888 } /* Name.Decorator */
47 | .highlight .ni { color: #ce5c00 } /* Name.Entity */
48 | .highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
49 | .highlight .nf { color: #000000 } /* Name.Function */
50 | .highlight .nl { color: #f57900 } /* Name.Label */
51 | .highlight .nn { color: #000000 } /* Name.Namespace */
52 | .highlight .nx { color: #000000 } /* Name.Other */
53 | .highlight .py { color: #000000 } /* Name.Property */
54 | .highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */
55 | .highlight .nv { color: #000000 } /* Name.Variable */
56 | .highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */
57 | .highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
58 | .highlight .mb { color: #990000 } /* Literal.Number.Bin */
59 | .highlight .mf { color: #990000 } /* Literal.Number.Float */
60 | .highlight .mh { color: #990000 } /* Literal.Number.Hex */
61 | .highlight .mi { color: #990000 } /* Literal.Number.Integer */
62 | .highlight .mo { color: #990000 } /* Literal.Number.Oct */
63 | .highlight .sa { color: #4e9a06 } /* Literal.String.Affix */
64 | .highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */
65 | .highlight .sc { color: #4e9a06 } /* Literal.String.Char */
66 | .highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */
67 | .highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
68 | .highlight .s2 { color: #4e9a06 } /* Literal.String.Double */
69 | .highlight .se { color: #4e9a06 } /* Literal.String.Escape */
70 | .highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */
71 | .highlight .si { color: #4e9a06 } /* Literal.String.Interpol */
72 | .highlight .sx { color: #4e9a06 } /* Literal.String.Other */
73 | .highlight .sr { color: #4e9a06 } /* Literal.String.Regex */
74 | .highlight .s1 { color: #4e9a06 } /* Literal.String.Single */
75 | .highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */
76 | .highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
77 | .highlight .fm { color: #000000 } /* Name.Function.Magic */
78 | .highlight .vc { color: #000000 } /* Name.Variable.Class */
79 | .highlight .vg { color: #000000 } /* Name.Variable.Global */
80 | .highlight .vi { color: #000000 } /* Name.Variable.Instance */
81 | .highlight .vm { color: #000000 } /* Name.Variable.Magic */
82 | .highlight .il { color: #990000 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/docs/_build/html/_static/searchtools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * searchtools.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for the full-text search.
6 | *
7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | if (!Scorer) {
13 | /**
14 | * Simple result scoring code.
15 | */
16 | var Scorer = {
17 | // Implement the following function to further tweak the score for each result
18 | // The function takes a result array [filename, title, anchor, descr, score]
19 | // and returns the new score.
20 | /*
21 | score: function(result) {
22 | return result[4];
23 | },
24 | */
25 |
26 | // query matches the full name of an object
27 | objNameMatch: 11,
28 | // or matches in the last dotted part of the object name
29 | objPartialMatch: 6,
30 | // Additive scores depending on the priority of the object
31 | objPrio: {0: 15, // used to be importantResults
32 | 1: 5, // used to be objectResults
33 | 2: -5}, // used to be unimportantResults
34 | // Used when the priority is not in the mapping.
35 | objPrioDefault: 0,
36 |
37 | // query found in title
38 | title: 15,
39 | // query found in terms
40 | term: 5
41 | };
42 | }
43 |
44 | if (!splitQuery) {
45 | function splitQuery(query) {
46 | return query.split(/\s+/);
47 | }
48 | }
49 |
50 | /**
51 | * Search Module
52 | */
53 | var Search = {
54 |
55 | _index : null,
56 | _queued_query : null,
57 | _pulse_status : -1,
58 |
59 | init : function() {
60 | var params = $.getQueryParameters();
61 | if (params.q) {
62 | var query = params.q[0];
63 | $('input[name="q"]')[0].value = query;
64 | this.performSearch(query);
65 | }
66 | },
67 |
68 | loadIndex : function(url) {
69 | $.ajax({type: "GET", url: url, data: null,
70 | dataType: "script", cache: true,
71 | complete: function(jqxhr, textstatus) {
72 | if (textstatus != "success") {
73 | document.getElementById("searchindexloader").src = url;
74 | }
75 | }});
76 | },
77 |
78 | setIndex : function(index) {
79 | var q;
80 | this._index = index;
81 | if ((q = this._queued_query) !== null) {
82 | this._queued_query = null;
83 | Search.query(q);
84 | }
85 | },
86 |
87 | hasIndex : function() {
88 | return this._index !== null;
89 | },
90 |
91 | deferQuery : function(query) {
92 | this._queued_query = query;
93 | },
94 |
95 | stopPulse : function() {
96 | this._pulse_status = 0;
97 | },
98 |
99 | startPulse : function() {
100 | if (this._pulse_status >= 0)
101 | return;
102 | function pulse() {
103 | var i;
104 | Search._pulse_status = (Search._pulse_status + 1) % 4;
105 | var dotString = '';
106 | for (i = 0; i < Search._pulse_status; i++)
107 | dotString += '.';
108 | Search.dots.text(dotString);
109 | if (Search._pulse_status > -1)
110 | window.setTimeout(pulse, 500);
111 | }
112 | pulse();
113 | },
114 |
115 | /**
116 | * perform a search for something (or wait until index is loaded)
117 | */
118 | performSearch : function(query) {
119 | // create the required interface elements
120 | this.out = $('#search-results');
121 | this.title = $('' + _('Searching') + ' ').appendTo(this.out);
122 | this.dots = $(' ').appendTo(this.title);
123 | this.status = $('
').appendTo(this.out);
124 | this.output = $('').appendTo(this.out);
125 |
126 | $('#search-progress').text(_('Preparing search...'));
127 | this.startPulse();
128 |
129 | // index already loaded, the browser was quick!
130 | if (this.hasIndex())
131 | this.query(query);
132 | else
133 | this.deferQuery(query);
134 | },
135 |
136 | /**
137 | * execute search (requires search index to be loaded)
138 | */
139 | query : function(query) {
140 | var i;
141 |
142 | // stem the searchterms and add them to the correct list
143 | var stemmer = new Stemmer();
144 | var searchterms = [];
145 | var excluded = [];
146 | var hlterms = [];
147 | var tmp = splitQuery(query);
148 | var objectterms = [];
149 | for (i = 0; i < tmp.length; i++) {
150 | if (tmp[i] !== "") {
151 | objectterms.push(tmp[i].toLowerCase());
152 | }
153 |
154 | if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
155 | tmp[i] === "") {
156 | // skip this "word"
157 | continue;
158 | }
159 | // stem the word
160 | var word = stemmer.stemWord(tmp[i].toLowerCase());
161 | // prevent stemmer from cutting word smaller than two chars
162 | if(word.length < 3 && tmp[i].length >= 3) {
163 | word = tmp[i];
164 | }
165 | var toAppend;
166 | // select the correct list
167 | if (word[0] == '-') {
168 | toAppend = excluded;
169 | word = word.substr(1);
170 | }
171 | else {
172 | toAppend = searchterms;
173 | hlterms.push(tmp[i].toLowerCase());
174 | }
175 | // only add if not already in the list
176 | if (!$u.contains(toAppend, word))
177 | toAppend.push(word);
178 | }
179 | var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
180 |
181 | // console.debug('SEARCH: searching for:');
182 | // console.info('required: ', searchterms);
183 | // console.info('excluded: ', excluded);
184 |
185 | // prepare search
186 | var terms = this._index.terms;
187 | var titleterms = this._index.titleterms;
188 |
189 | // array of [filename, title, anchor, descr, score]
190 | var results = [];
191 | $('#search-progress').empty();
192 |
193 | // lookup as object
194 | for (i = 0; i < objectterms.length; i++) {
195 | var others = [].concat(objectterms.slice(0, i),
196 | objectterms.slice(i+1, objectterms.length));
197 | results = results.concat(this.performObjectSearch(objectterms[i], others));
198 | }
199 |
200 | // lookup as search terms in fulltext
201 | results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
202 |
203 | // let the scorer override scores with a custom scoring function
204 | if (Scorer.score) {
205 | for (i = 0; i < results.length; i++)
206 | results[i][4] = Scorer.score(results[i]);
207 | }
208 |
209 | // now sort the results by score (in opposite order of appearance, since the
210 | // display function below uses pop() to retrieve items) and then
211 | // alphabetically
212 | results.sort(function(a, b) {
213 | var left = a[4];
214 | var right = b[4];
215 | if (left > right) {
216 | return 1;
217 | } else if (left < right) {
218 | return -1;
219 | } else {
220 | // same score: sort alphabetically
221 | left = a[1].toLowerCase();
222 | right = b[1].toLowerCase();
223 | return (left > right) ? -1 : ((left < right) ? 1 : 0);
224 | }
225 | });
226 |
227 | // for debugging
228 | //Search.lastresults = results.slice(); // a copy
229 | //console.info('search results:', Search.lastresults);
230 |
231 | // print the results
232 | var resultCount = results.length;
233 | function displayNextItem() {
234 | // results left, load the summary and display it
235 | if (results.length) {
236 | var item = results.pop();
237 | var listItem = $(' ');
238 | if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
239 | // dirhtml builder
240 | var dirname = item[0] + '/';
241 | if (dirname.match(/\/index\/$/)) {
242 | dirname = dirname.substring(0, dirname.length-6);
243 | } else if (dirname == 'index/') {
244 | dirname = '';
245 | }
246 | listItem.append($(' ').attr('href',
247 | DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
248 | highlightstring + item[2]).html(item[1]));
249 | } else {
250 | // normal html builders
251 | listItem.append($(' ').attr('href',
252 | item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
253 | highlightstring + item[2]).html(item[1]));
254 | }
255 | if (item[3]) {
256 | listItem.append($(' (' + item[3] + ') '));
257 | Search.output.append(listItem);
258 | listItem.slideDown(5, function() {
259 | displayNextItem();
260 | });
261 | } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
262 | var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
263 | if (suffix === undefined) {
264 | suffix = '.txt';
265 | }
266 | $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
267 | dataType: "text",
268 | complete: function(jqxhr, textstatus) {
269 | var data = jqxhr.responseText;
270 | if (data !== '' && data !== undefined) {
271 | listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
272 | }
273 | Search.output.append(listItem);
274 | listItem.slideDown(5, function() {
275 | displayNextItem();
276 | });
277 | }});
278 | } else {
279 | // no source available, just display title
280 | Search.output.append(listItem);
281 | listItem.slideDown(5, function() {
282 | displayNextItem();
283 | });
284 | }
285 | }
286 | // search finished, update title and status message
287 | else {
288 | Search.stopPulse();
289 | Search.title.text(_('Search Results'));
290 | if (!resultCount)
291 | Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
292 | else
293 | Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
294 | Search.status.fadeIn(500);
295 | }
296 | }
297 | displayNextItem();
298 | },
299 |
300 | /**
301 | * search for object names
302 | */
303 | performObjectSearch : function(object, otherterms) {
304 | var filenames = this._index.filenames;
305 | var docnames = this._index.docnames;
306 | var objects = this._index.objects;
307 | var objnames = this._index.objnames;
308 | var titles = this._index.titles;
309 |
310 | var i;
311 | var results = [];
312 |
313 | for (var prefix in objects) {
314 | for (var name in objects[prefix]) {
315 | var fullname = (prefix ? prefix + '.' : '') + name;
316 | if (fullname.toLowerCase().indexOf(object) > -1) {
317 | var score = 0;
318 | var parts = fullname.split('.');
319 | // check for different match types: exact matches of full name or
320 | // "last name" (i.e. last dotted part)
321 | if (fullname == object || parts[parts.length - 1] == object) {
322 | score += Scorer.objNameMatch;
323 | // matches in last name
324 | } else if (parts[parts.length - 1].indexOf(object) > -1) {
325 | score += Scorer.objPartialMatch;
326 | }
327 | var match = objects[prefix][name];
328 | var objname = objnames[match[1]][2];
329 | var title = titles[match[0]];
330 | // If more than one term searched for, we require other words to be
331 | // found in the name/title/description
332 | if (otherterms.length > 0) {
333 | var haystack = (prefix + ' ' + name + ' ' +
334 | objname + ' ' + title).toLowerCase();
335 | var allfound = true;
336 | for (i = 0; i < otherterms.length; i++) {
337 | if (haystack.indexOf(otherterms[i]) == -1) {
338 | allfound = false;
339 | break;
340 | }
341 | }
342 | if (!allfound) {
343 | continue;
344 | }
345 | }
346 | var descr = objname + _(', in ') + title;
347 |
348 | var anchor = match[3];
349 | if (anchor === '')
350 | anchor = fullname;
351 | else if (anchor == '-')
352 | anchor = objnames[match[1]][1] + '-' + fullname;
353 | // add custom score for some objects according to scorer
354 | if (Scorer.objPrio.hasOwnProperty(match[2])) {
355 | score += Scorer.objPrio[match[2]];
356 | } else {
357 | score += Scorer.objPrioDefault;
358 | }
359 | results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
360 | }
361 | }
362 | }
363 |
364 | return results;
365 | },
366 |
367 | /**
368 | * search for full-text terms in the index
369 | */
370 | performTermsSearch : function(searchterms, excluded, terms, titleterms) {
371 | var docnames = this._index.docnames;
372 | var filenames = this._index.filenames;
373 | var titles = this._index.titles;
374 |
375 | var i, j, file;
376 | var fileMap = {};
377 | var scoreMap = {};
378 | var results = [];
379 |
380 | // perform the search on the required terms
381 | for (i = 0; i < searchterms.length; i++) {
382 | var word = searchterms[i];
383 | var files = [];
384 | var _o = [
385 | {files: terms[word], score: Scorer.term},
386 | {files: titleterms[word], score: Scorer.title}
387 | ];
388 |
389 | // no match but word was a required one
390 | if ($u.every(_o, function(o){return o.files === undefined;})) {
391 | break;
392 | }
393 | // found search word in contents
394 | $u.each(_o, function(o) {
395 | var _files = o.files;
396 | if (_files === undefined)
397 | return
398 |
399 | if (_files.length === undefined)
400 | _files = [_files];
401 | files = files.concat(_files);
402 |
403 | // set score for the word in each file to Scorer.term
404 | for (j = 0; j < _files.length; j++) {
405 | file = _files[j];
406 | if (!(file in scoreMap))
407 | scoreMap[file] = {}
408 | scoreMap[file][word] = o.score;
409 | }
410 | });
411 |
412 | // create the mapping
413 | for (j = 0; j < files.length; j++) {
414 | file = files[j];
415 | if (file in fileMap)
416 | fileMap[file].push(word);
417 | else
418 | fileMap[file] = [word];
419 | }
420 | }
421 |
422 | // now check if the files don't contain excluded terms
423 | for (file in fileMap) {
424 | var valid = true;
425 |
426 | // check if all requirements are matched
427 | if (fileMap[file].length != searchterms.length)
428 | continue;
429 |
430 | // ensure that none of the excluded terms is in the search result
431 | for (i = 0; i < excluded.length; i++) {
432 | if (terms[excluded[i]] == file ||
433 | titleterms[excluded[i]] == file ||
434 | $u.contains(terms[excluded[i]] || [], file) ||
435 | $u.contains(titleterms[excluded[i]] || [], file)) {
436 | valid = false;
437 | break;
438 | }
439 | }
440 |
441 | // if we have still a valid result we can add it to the result list
442 | if (valid) {
443 | // select one (max) score for the file.
444 | // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
445 | var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
446 | results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
447 | }
448 | }
449 | return results;
450 | },
451 |
452 | /**
453 | * helper function to return a node containing the
454 | * search summary for a given text. keywords is a list
455 | * of stemmed words, hlwords is the list of normal, unstemmed
456 | * words. the first one is used to find the occurrence, the
457 | * latter for highlighting it.
458 | */
459 | makeSearchSummary : function(text, keywords, hlwords) {
460 | var textLower = text.toLowerCase();
461 | var start = 0;
462 | $.each(keywords, function() {
463 | var i = textLower.indexOf(this.toLowerCase());
464 | if (i > -1)
465 | start = i;
466 | });
467 | start = Math.max(start - 120, 0);
468 | var excerpt = ((start > 0) ? '...' : '') +
469 | $.trim(text.substr(start, 240)) +
470 | ((start + 240 - text.length) ? '...' : '');
471 | var rv = $('
').text(excerpt);
472 | $.each(hlwords, function() {
473 | rv = rv.highlightText(this, 'highlighted');
474 | });
475 | return rv;
476 | }
477 | };
478 |
479 | $(document).ready(function() {
480 | Search.init();
481 | });
482 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/underscore.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.3.1
2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
3 | // Underscore is freely distributable under the MIT license.
4 | // Portions of Underscore are inspired or borrowed from Prototype,
5 | // Oliver Steele's Functional, and John Resig's Micro-Templating.
6 | // For all details and documentation:
7 | // http://documentcloud.github.com/underscore
8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==
12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};
24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e /g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
32 |
--------------------------------------------------------------------------------
/docs/_build/html/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/_static/up.png
--------------------------------------------------------------------------------
/docs/_build/html/_static/websupport.js:
--------------------------------------------------------------------------------
1 | /*
2 | * websupport.js
3 | * ~~~~~~~~~~~~~
4 | *
5 | * sphinx.websupport utilities for all documentation.
6 | *
7 | * :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | (function($) {
13 | $.fn.autogrow = function() {
14 | return this.each(function() {
15 | var textarea = this;
16 |
17 | $.fn.autogrow.resize(textarea);
18 |
19 | $(textarea)
20 | .focus(function() {
21 | textarea.interval = setInterval(function() {
22 | $.fn.autogrow.resize(textarea);
23 | }, 500);
24 | })
25 | .blur(function() {
26 | clearInterval(textarea.interval);
27 | });
28 | });
29 | };
30 |
31 | $.fn.autogrow.resize = function(textarea) {
32 | var lineHeight = parseInt($(textarea).css('line-height'), 10);
33 | var lines = textarea.value.split('\n');
34 | var columns = textarea.cols;
35 | var lineCount = 0;
36 | $.each(lines, function() {
37 | lineCount += Math.ceil(this.length / columns) || 1;
38 | });
39 | var height = lineHeight * (lineCount + 1);
40 | $(textarea).css('height', height);
41 | };
42 | })(jQuery);
43 |
44 | (function($) {
45 | var comp, by;
46 |
47 | function init() {
48 | initEvents();
49 | initComparator();
50 | }
51 |
52 | function initEvents() {
53 | $(document).on("click", 'a.comment-close', function(event) {
54 | event.preventDefault();
55 | hide($(this).attr('id').substring(2));
56 | });
57 | $(document).on("click", 'a.vote', function(event) {
58 | event.preventDefault();
59 | handleVote($(this));
60 | });
61 | $(document).on("click", 'a.reply', function(event) {
62 | event.preventDefault();
63 | openReply($(this).attr('id').substring(2));
64 | });
65 | $(document).on("click", 'a.close-reply', function(event) {
66 | event.preventDefault();
67 | closeReply($(this).attr('id').substring(2));
68 | });
69 | $(document).on("click", 'a.sort-option', function(event) {
70 | event.preventDefault();
71 | handleReSort($(this));
72 | });
73 | $(document).on("click", 'a.show-proposal', function(event) {
74 | event.preventDefault();
75 | showProposal($(this).attr('id').substring(2));
76 | });
77 | $(document).on("click", 'a.hide-proposal', function(event) {
78 | event.preventDefault();
79 | hideProposal($(this).attr('id').substring(2));
80 | });
81 | $(document).on("click", 'a.show-propose-change', function(event) {
82 | event.preventDefault();
83 | showProposeChange($(this).attr('id').substring(2));
84 | });
85 | $(document).on("click", 'a.hide-propose-change', function(event) {
86 | event.preventDefault();
87 | hideProposeChange($(this).attr('id').substring(2));
88 | });
89 | $(document).on("click", 'a.accept-comment', function(event) {
90 | event.preventDefault();
91 | acceptComment($(this).attr('id').substring(2));
92 | });
93 | $(document).on("click", 'a.delete-comment', function(event) {
94 | event.preventDefault();
95 | deleteComment($(this).attr('id').substring(2));
96 | });
97 | $(document).on("click", 'a.comment-markup', function(event) {
98 | event.preventDefault();
99 | toggleCommentMarkupBox($(this).attr('id').substring(2));
100 | });
101 | }
102 |
103 | /**
104 | * Set comp, which is a comparator function used for sorting and
105 | * inserting comments into the list.
106 | */
107 | function setComparator() {
108 | // If the first three letters are "asc", sort in ascending order
109 | // and remove the prefix.
110 | if (by.substring(0,3) == 'asc') {
111 | var i = by.substring(3);
112 | comp = function(a, b) { return a[i] - b[i]; };
113 | } else {
114 | // Otherwise sort in descending order.
115 | comp = function(a, b) { return b[by] - a[by]; };
116 | }
117 |
118 | // Reset link styles and format the selected sort option.
119 | $('a.sel').attr('href', '#').removeClass('sel');
120 | $('a.by' + by).removeAttr('href').addClass('sel');
121 | }
122 |
123 | /**
124 | * Create a comp function. If the user has preferences stored in
125 | * the sortBy cookie, use those, otherwise use the default.
126 | */
127 | function initComparator() {
128 | by = 'rating'; // Default to sort by rating.
129 | // If the sortBy cookie is set, use that instead.
130 | if (document.cookie.length > 0) {
131 | var start = document.cookie.indexOf('sortBy=');
132 | if (start != -1) {
133 | start = start + 7;
134 | var end = document.cookie.indexOf(";", start);
135 | if (end == -1) {
136 | end = document.cookie.length;
137 | by = unescape(document.cookie.substring(start, end));
138 | }
139 | }
140 | }
141 | setComparator();
142 | }
143 |
144 | /**
145 | * Show a comment div.
146 | */
147 | function show(id) {
148 | $('#ao' + id).hide();
149 | $('#ah' + id).show();
150 | var context = $.extend({id: id}, opts);
151 | var popup = $(renderTemplate(popupTemplate, context)).hide();
152 | popup.find('textarea[name="proposal"]').hide();
153 | popup.find('a.by' + by).addClass('sel');
154 | var form = popup.find('#cf' + id);
155 | form.submit(function(event) {
156 | event.preventDefault();
157 | addComment(form);
158 | });
159 | $('#s' + id).after(popup);
160 | popup.slideDown('fast', function() {
161 | getComments(id);
162 | });
163 | }
164 |
165 | /**
166 | * Hide a comment div.
167 | */
168 | function hide(id) {
169 | $('#ah' + id).hide();
170 | $('#ao' + id).show();
171 | var div = $('#sc' + id);
172 | div.slideUp('fast', function() {
173 | div.remove();
174 | });
175 | }
176 |
177 | /**
178 | * Perform an ajax request to get comments for a node
179 | * and insert the comments into the comments tree.
180 | */
181 | function getComments(id) {
182 | $.ajax({
183 | type: 'GET',
184 | url: opts.getCommentsURL,
185 | data: {node: id},
186 | success: function(data, textStatus, request) {
187 | var ul = $('#cl' + id);
188 | var speed = 100;
189 | $('#cf' + id)
190 | .find('textarea[name="proposal"]')
191 | .data('source', data.source);
192 |
193 | if (data.comments.length === 0) {
194 | ul.html('No comments yet. ');
195 | ul.data('empty', true);
196 | } else {
197 | // If there are comments, sort them and put them in the list.
198 | var comments = sortComments(data.comments);
199 | speed = data.comments.length * 100;
200 | appendComments(comments, ul);
201 | ul.data('empty', false);
202 | }
203 | $('#cn' + id).slideUp(speed + 200);
204 | ul.slideDown(speed);
205 | },
206 | error: function(request, textStatus, error) {
207 | showError('Oops, there was a problem retrieving the comments.');
208 | },
209 | dataType: 'json'
210 | });
211 | }
212 |
213 | /**
214 | * Add a comment via ajax and insert the comment into the comment tree.
215 | */
216 | function addComment(form) {
217 | var node_id = form.find('input[name="node"]').val();
218 | var parent_id = form.find('input[name="parent"]').val();
219 | var text = form.find('textarea[name="comment"]').val();
220 | var proposal = form.find('textarea[name="proposal"]').val();
221 |
222 | if (text == '') {
223 | showError('Please enter a comment.');
224 | return;
225 | }
226 |
227 | // Disable the form that is being submitted.
228 | form.find('textarea,input').attr('disabled', 'disabled');
229 |
230 | // Send the comment to the server.
231 | $.ajax({
232 | type: "POST",
233 | url: opts.addCommentURL,
234 | dataType: 'json',
235 | data: {
236 | node: node_id,
237 | parent: parent_id,
238 | text: text,
239 | proposal: proposal
240 | },
241 | success: function(data, textStatus, error) {
242 | // Reset the form.
243 | if (node_id) {
244 | hideProposeChange(node_id);
245 | }
246 | form.find('textarea')
247 | .val('')
248 | .add(form.find('input'))
249 | .removeAttr('disabled');
250 | var ul = $('#cl' + (node_id || parent_id));
251 | if (ul.data('empty')) {
252 | $(ul).empty();
253 | ul.data('empty', false);
254 | }
255 | insertComment(data.comment);
256 | var ao = $('#ao' + node_id);
257 | ao.find('img').attr({'src': opts.commentBrightImage});
258 | if (node_id) {
259 | // if this was a "root" comment, remove the commenting box
260 | // (the user can get it back by reopening the comment popup)
261 | $('#ca' + node_id).slideUp();
262 | }
263 | },
264 | error: function(request, textStatus, error) {
265 | form.find('textarea,input').removeAttr('disabled');
266 | showError('Oops, there was a problem adding the comment.');
267 | }
268 | });
269 | }
270 |
271 | /**
272 | * Recursively append comments to the main comment list and children
273 | * lists, creating the comment tree.
274 | */
275 | function appendComments(comments, ul) {
276 | $.each(comments, function() {
277 | var div = createCommentDiv(this);
278 | ul.append($(document.createElement('li')).html(div));
279 | appendComments(this.children, div.find('ul.comment-children'));
280 | // To avoid stagnating data, don't store the comments children in data.
281 | this.children = null;
282 | div.data('comment', this);
283 | });
284 | }
285 |
286 | /**
287 | * After adding a new comment, it must be inserted in the correct
288 | * location in the comment tree.
289 | */
290 | function insertComment(comment) {
291 | var div = createCommentDiv(comment);
292 |
293 | // To avoid stagnating data, don't store the comments children in data.
294 | comment.children = null;
295 | div.data('comment', comment);
296 |
297 | var ul = $('#cl' + (comment.node || comment.parent));
298 | var siblings = getChildren(ul);
299 |
300 | var li = $(document.createElement('li'));
301 | li.hide();
302 |
303 | // Determine where in the parents children list to insert this comment.
304 | for(var i=0; i < siblings.length; i++) {
305 | if (comp(comment, siblings[i]) <= 0) {
306 | $('#cd' + siblings[i].id)
307 | .parent()
308 | .before(li.html(div));
309 | li.slideDown('fast');
310 | return;
311 | }
312 | }
313 |
314 | // If we get here, this comment rates lower than all the others,
315 | // or it is the only comment in the list.
316 | ul.append(li.html(div));
317 | li.slideDown('fast');
318 | }
319 |
320 | function acceptComment(id) {
321 | $.ajax({
322 | type: 'POST',
323 | url: opts.acceptCommentURL,
324 | data: {id: id},
325 | success: function(data, textStatus, request) {
326 | $('#cm' + id).fadeOut('fast');
327 | $('#cd' + id).removeClass('moderate');
328 | },
329 | error: function(request, textStatus, error) {
330 | showError('Oops, there was a problem accepting the comment.');
331 | }
332 | });
333 | }
334 |
335 | function deleteComment(id) {
336 | $.ajax({
337 | type: 'POST',
338 | url: opts.deleteCommentURL,
339 | data: {id: id},
340 | success: function(data, textStatus, request) {
341 | var div = $('#cd' + id);
342 | if (data == 'delete') {
343 | // Moderator mode: remove the comment and all children immediately
344 | div.slideUp('fast', function() {
345 | div.remove();
346 | });
347 | return;
348 | }
349 | // User mode: only mark the comment as deleted
350 | div
351 | .find('span.user-id:first')
352 | .text('[deleted]').end()
353 | .find('div.comment-text:first')
354 | .text('[deleted]').end()
355 | .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
356 | ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
357 | .remove();
358 | var comment = div.data('comment');
359 | comment.username = '[deleted]';
360 | comment.text = '[deleted]';
361 | div.data('comment', comment);
362 | },
363 | error: function(request, textStatus, error) {
364 | showError('Oops, there was a problem deleting the comment.');
365 | }
366 | });
367 | }
368 |
369 | function showProposal(id) {
370 | $('#sp' + id).hide();
371 | $('#hp' + id).show();
372 | $('#pr' + id).slideDown('fast');
373 | }
374 |
375 | function hideProposal(id) {
376 | $('#hp' + id).hide();
377 | $('#sp' + id).show();
378 | $('#pr' + id).slideUp('fast');
379 | }
380 |
381 | function showProposeChange(id) {
382 | $('#pc' + id).hide();
383 | $('#hc' + id).show();
384 | var textarea = $('#pt' + id);
385 | textarea.val(textarea.data('source'));
386 | $.fn.autogrow.resize(textarea[0]);
387 | textarea.slideDown('fast');
388 | }
389 |
390 | function hideProposeChange(id) {
391 | $('#hc' + id).hide();
392 | $('#pc' + id).show();
393 | var textarea = $('#pt' + id);
394 | textarea.val('').removeAttr('disabled');
395 | textarea.slideUp('fast');
396 | }
397 |
398 | function toggleCommentMarkupBox(id) {
399 | $('#mb' + id).toggle();
400 | }
401 |
402 | /** Handle when the user clicks on a sort by link. */
403 | function handleReSort(link) {
404 | var classes = link.attr('class').split(/\s+/);
405 | for (var i=0; iThank you! Your comment will show up '
558 | + 'once it is has been approved by a moderator.');
559 | }
560 | // Prettify the comment rating.
561 | comment.pretty_rating = comment.rating + ' point' +
562 | (comment.rating == 1 ? '' : 's');
563 | // Make a class (for displaying not yet moderated comments differently)
564 | comment.css_class = comment.displayed ? '' : ' moderate';
565 | // Create a div for this comment.
566 | var context = $.extend({}, opts, comment);
567 | var div = $(renderTemplate(commentTemplate, context));
568 |
569 | // If the user has voted on this comment, highlight the correct arrow.
570 | if (comment.vote) {
571 | var direction = (comment.vote == 1) ? 'u' : 'd';
572 | div.find('#' + direction + 'v' + comment.id).hide();
573 | div.find('#' + direction + 'u' + comment.id).show();
574 | }
575 |
576 | if (opts.moderator || comment.text != '[deleted]') {
577 | div.find('a.reply').show();
578 | if (comment.proposal_diff)
579 | div.find('#sp' + comment.id).show();
580 | if (opts.moderator && !comment.displayed)
581 | div.find('#cm' + comment.id).show();
582 | if (opts.moderator || (opts.username == comment.username))
583 | div.find('#dc' + comment.id).show();
584 | }
585 | return div;
586 | }
587 |
588 | /**
589 | * A simple template renderer. Placeholders such as <%id%> are replaced
590 | * by context['id'] with items being escaped. Placeholders such as <#id#>
591 | * are not escaped.
592 | */
593 | function renderTemplate(template, context) {
594 | var esc = $(document.createElement('div'));
595 |
596 | function handle(ph, escape) {
597 | var cur = context;
598 | $.each(ph.split('.'), function() {
599 | cur = cur[this];
600 | });
601 | return escape ? esc.text(cur || "").html() : cur;
602 | }
603 |
604 | return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
605 | return handle(arguments[2], arguments[1] == '%' ? true : false);
606 | });
607 | }
608 |
609 | /** Flash an error message briefly. */
610 | function showError(message) {
611 | $(document.createElement('div')).attr({'class': 'popup-error'})
612 | .append($(document.createElement('div'))
613 | .attr({'class': 'error-message'}).text(message))
614 | .appendTo('body')
615 | .fadeIn("slow")
616 | .delay(2000)
617 | .fadeOut("slow");
618 | }
619 |
620 | /** Add a link the user uses to open the comments popup. */
621 | $.fn.comment = function() {
622 | return this.each(function() {
623 | var id = $(this).attr('id').substring(1);
624 | var count = COMMENT_METADATA[id];
625 | var title = count + ' comment' + (count == 1 ? '' : 's');
626 | var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
627 | var addcls = count == 0 ? ' nocomment' : '';
628 | $(this)
629 | .append(
630 | $(document.createElement('a')).attr({
631 | href: '#',
632 | 'class': 'sphinx-comment-open' + addcls,
633 | id: 'ao' + id
634 | })
635 | .append($(document.createElement('img')).attr({
636 | src: image,
637 | alt: 'comment',
638 | title: title
639 | }))
640 | .click(function(event) {
641 | event.preventDefault();
642 | show($(this).attr('id').substring(2));
643 | })
644 | )
645 | .append(
646 | $(document.createElement('a')).attr({
647 | href: '#',
648 | 'class': 'sphinx-comment-close hidden',
649 | id: 'ah' + id
650 | })
651 | .append($(document.createElement('img')).attr({
652 | src: opts.closeCommentImage,
653 | alt: 'close',
654 | title: 'close'
655 | }))
656 | .click(function(event) {
657 | event.preventDefault();
658 | hide($(this).attr('id').substring(2));
659 | })
660 | );
661 | });
662 | };
663 |
664 | var opts = {
665 | processVoteURL: '/_process_vote',
666 | addCommentURL: '/_add_comment',
667 | getCommentsURL: '/_get_comments',
668 | acceptCommentURL: '/_accept_comment',
669 | deleteCommentURL: '/_delete_comment',
670 | commentImage: '/static/_static/comment.png',
671 | closeCommentImage: '/static/_static/comment-close.png',
672 | loadingImage: '/static/_static/ajax-loader.gif',
673 | commentBrightImage: '/static/_static/comment-bright.png',
674 | upArrow: '/static/_static/up.png',
675 | downArrow: '/static/_static/down.png',
676 | upArrowPressed: '/static/_static/up-pressed.png',
677 | downArrowPressed: '/static/_static/down-pressed.png',
678 | voting: false,
679 | moderator: false
680 | };
681 |
682 | if (typeof COMMENT_OPTIONS != "undefined") {
683 | opts = jQuery.extend(opts, COMMENT_OPTIONS);
684 | }
685 |
686 | var popupTemplate = '\
687 | ';
723 |
724 | var commentTemplate = '\
725 | \
768 | ';
769 |
770 | var replyTemplate = '\
771 | \
772 | \
773 | \
780 |
\
781 | ';
782 |
783 | $(document).ready(function() {
784 | init();
785 | });
786 | })(jQuery);
787 |
788 | $(document).ready(function() {
789 | // add comment anchors for all paragraphs that are commentable
790 | $('.sphinx-has-comment').comment();
791 |
792 | // highlight search words in search results
793 | $("div.context").each(function() {
794 | var params = $.getQueryParameters();
795 | var terms = (params.q) ? params.q[0].split(/\s+/) : [];
796 | var result = $(this);
797 | $.each(terms, function() {
798 | result.highlightText(this.toLowerCase(), 'highlighted');
799 | });
800 | });
801 |
802 | // directly open comment window if requested
803 | var anchor = document.location.hash;
804 | if (anchor.substring(0, 9) == '#comment-') {
805 | $('#ao' + anchor.substring(9)).click();
806 | document.location.hash = '#s' + anchor.substring(9);
807 | }
808 | });
809 |
--------------------------------------------------------------------------------
/docs/_build/html/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Welcome to PyTrie’s documentation! — PyTrie 0.4.0 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
Welcome to PyTrie’s documentation!
37 |
38 |
39 |
40 |
Reference documentation
41 |
42 |
Classes
43 |
44 |
45 |
Trie methods
46 |
The following methods are specific to tries; they are not part of the mapping API.
47 |
48 |
49 |
Extended mapping API methods
50 |
The following methods extend the respective mapping API methods with an optional
51 | prefix
parameter. If not None
, only keys (or associated values/items)
52 | that start with prefix
are returned.
53 |
54 |
55 |
Original mapping API methods
56 |
The following methods have the standard mapping signature and semantics.
57 |
58 |
59 |
Internals
60 |
Tries are implemented as trees of Node
instances. You don’t need to
61 | worry about them unless unless you want to extend or replace Node
with
62 | a new node factory and bind it to Trie.NodeFactory
.
63 |
64 |
65 |
66 |
67 |
Indices and tables
68 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
122 |
123 |
124 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/docs/_build/html/genindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 | Index — PyTrie 0.4.0 documentation
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
Index
38 |
39 |
40 |
_
41 | |
C
42 | |
F
43 | |
I
44 | |
K
45 | |
L
46 | |
N
47 | |
P
48 | |
S
49 | |
T
50 | |
V
51 |
52 |
53 |
_
54 |
78 |
79 |
C
80 |
92 |
93 |
F
94 |
100 |
101 |
I
102 |
122 |
123 |
K
124 |
134 |
135 |
L
136 |
148 |
149 |
N
150 |
160 |
161 |
P
162 |
168 |
169 |
S
170 |
182 |
183 |
T
184 |
190 |
191 |
V
192 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
247 |
248 |
249 |
257 |
258 |
259 |
260 |
261 |
262 |
--------------------------------------------------------------------------------
/docs/_build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/docs/_build/html/objects.inv
--------------------------------------------------------------------------------
/docs/_build/html/py-modindex.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Python Module Index — PyTrie 0.4.0 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
Python Module Index
44 |
45 |
48 |
49 |
50 |
51 |
52 | p
53 |
54 |
55 |
56 | pytrie
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/docs/_build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Search — PyTrie 0.4.0 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Search
45 |
46 |
47 |
48 | Please activate JavaScript to enable the search
49 | functionality.
50 |
51 |
52 |
53 | From here you can search these documents. Enter your search
54 | words into the box below and click "search". Note that the search
55 | function will automatically search for all of the words. Pages
56 | containing fewer words won't appear in the result list.
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
102 |
103 |
104 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/docs/_build/html/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:55},filenames:["index.rst"],objects:{"":{pytrie:[0,0,0,"-"]},"pytrie.Node":{ChildrenFactory:[0,2,1,""]},"pytrie.Trie":{KeyFactory:[0,2,1,""],NodeFactory:[0,2,1,""],__bool__:[0,3,1,""],__contains__:[0,3,1,""],__delitem__:[0,3,1,""],__getitem__:[0,3,1,""],__init__:[0,3,1,""],__iter__:[0,3,1,""],__len__:[0,3,1,""],__repr__:[0,3,1,""],__setitem__:[0,3,1,""],clear:[0,3,1,""],copy:[0,3,1,""],fromkeys:[0,4,1,""],items:[0,3,1,""],iter_prefix_items:[0,3,1,""],iter_prefix_values:[0,3,1,""],iter_prefixes:[0,3,1,""],iteritems:[0,3,1,""],iterkeys:[0,3,1,""],itervalues:[0,3,1,""],keys:[0,3,1,""],longest_prefix:[0,3,1,""],longest_prefix_item:[0,3,1,""],longest_prefix_value:[0,3,1,""],values:[0,3,1,""]},pytrie:{Node:[0,1,1,""],SortedStringTrie:[0,1,1,""],SortedTrie:[0,1,1,""],StringTrie:[0,1,1,""],Trie:[0,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","attribute","Python attribute"],"3":["py","method","Python method"],"4":["py","classmethod","Python class method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:attribute","3":"py:method","4":"py:classmethod"},terms:{"case":0,"default":0,"import":0,"new":0,"null":0,"return":0,The:0,Use:0,__bool__:0,__contains__:0,__delitem__:0,__getitem__:0,__init__:0,__iter__:0,__len__:0,__repr__:0,__setitem__:0,abc:0,about:0,addit:0,algorithm:0,alia:0,all:0,alloi:0,allot:0,allstar:0,alo:0,alphabet:0,alsa:0,also:0,ani:0,ant:0,antonym:0,appropri:0,area:0,arg:0,associ:0,base:0,binari:0,bind:0,both:0,bst:0,builtin:0,call:0,callabl:0,can:0,child:0,children:0,childrenfactori:0,classmethod:0,clear:0,collect:0,common:0,contain:0,copi:0,correspond:0,creat:0,current:0,data:0,dict:0,differ:0,doesn:0,don:0,effici:0,element:0,facilit:0,factori:0,few:0,find:0,finit:0,follow:0,from:0,fromkei:0,given:0,hash:0,hashabl:0,have:0,implement:0,index:0,instanc:0,interfac:0,item:0,iter:0,iter_prefix:0,iter_prefix_item:0,iter_prefix_valu:0,iteritem:0,iterkei:0,itervalu:0,its:0,kei:0,keyerror:0,keyfactori:0,kwarg:0,last:0,list:0,longest:0,longest_prefix:0,longest_prefix_item:0,longest_prefix_valu:0,lookup:0,mai:0,mani:0,memori:0,modul:0,more:0,most:0,mutablemap:0,necessarili:0,need:0,node:0,nodefactori:0,none:0,object:0,onli:0,option:0,otherwis:0,over:0,page:0,paramet:0,part:0,prefix:0,pure:0,python:0,rais:0,recent:0,regular:0,rel:0,remov:0,replac:0,repr:0,requir:0,respect:0,same:0,search:0,self:0,semant:0,sequenc:0,set:0,share:0,signatur:0,sort:0,sorteddict:0,sortedstringtri:0,sortedtri:0,special:0,specif:0,standard:0,start:0,store:0,string:0,stringtri:0,structur:0,subclass:0,support:0,than:0,thei:0,them:0,thi:0,time:0,traceback:0,tree:0,tri:0,tupl:0,unless:0,unlik:0,used:0,usual:0,valu:0,variabl:0,versa:0,vice:0,want:0,when:0,where:0,whose:0,worri:0,yield:0,you:0},titles:["Welcome to PyTrie\u2019s documentation!"],titleterms:{"class":0,api:0,document:0,extend:0,indic:0,intern:0,map:0,method:0,origin:0,pytri:0,refer:0,tabl:0,trie:0,usag:0,welcom:0}})
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Configuration file for the Sphinx documentation builder.
4 | #
5 | # This file does only contain a selection of the most common options. For a
6 | # full list see the documentation:
7 | # http://www.sphinx-doc.org/en/master/config
8 |
9 | # -- Path setup --------------------------------------------------------------
10 |
11 | # If extensions (or modules to document with autodoc) are in another directory,
12 | # add these directories to sys.path here. If the directory is relative to the
13 | # documentation root, use os.path.abspath to make it absolute, like shown here.
14 | #
15 | # import os
16 | # import sys
17 | # sys.path.insert(0, os.path.abspath('.'))
18 |
19 |
20 | # -- Project information -----------------------------------------------------
21 |
22 | project = 'PyTrie'
23 | copyright = '2020, George Sakkis'
24 | author = 'George Sakkis'
25 |
26 | # The short X.Y version
27 | version = ''
28 | # The full version, including alpha/beta/rc tags
29 | release = '0.4.0'
30 |
31 |
32 | # -- General configuration ---------------------------------------------------
33 |
34 | # If your documentation needs a minimal Sphinx version, state it here.
35 | #
36 | # needs_sphinx = '1.0'
37 |
38 | # Add any Sphinx extension module names here, as strings. They can be
39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
40 | # ones.
41 | extensions = ['sphinx.ext.autodoc']
42 |
43 | # Add any paths that contain templates here, relative to this directory.
44 | templates_path = ['_templates']
45 |
46 | # The suffix(es) of source filenames.
47 | # You can specify multiple suffix as a list of string:
48 | #
49 | # source_suffix = ['.rst', '.md']
50 | source_suffix = '.rst'
51 |
52 | # The master toctree document.
53 | master_doc = 'index'
54 |
55 | # The language for content autogenerated by Sphinx. Refer to documentation
56 | # for a list of supported languages.
57 | #
58 | # This is also used if you do content translation via gettext catalogs.
59 | # Usually you set "language" from the command line for these cases.
60 | language = None
61 |
62 | # List of patterns, relative to source directory, that match files and
63 | # directories to ignore when looking for source files.
64 | # This pattern also affects html_static_path and html_extra_path.
65 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
66 |
67 | # The name of the Pygments (syntax highlighting) style to use.
68 | pygments_style = None
69 |
70 |
71 | # -- Options for HTML output -------------------------------------------------
72 |
73 | # The theme to use for HTML and HTML Help pages. See the documentation for
74 | # a list of builtin themes.
75 | #
76 | html_theme = 'alabaster'
77 |
78 | # Theme options are theme-specific and customize the look and feel of a theme
79 | # further. For a list of options available for each theme, see the
80 | # documentation.
81 | #
82 | # html_theme_options = {}
83 |
84 | # Add any paths that contain custom static files (such as style sheets) here,
85 | # relative to this directory. They are copied after the builtin static files,
86 | # so a file named "default.css" will overwrite the builtin "default.css".
87 | html_static_path = ['_static']
88 |
89 | # Custom sidebar templates, must be a dictionary that maps document names
90 | # to template names.
91 | #
92 | # The default sidebars (for documents that don't match any pattern) are
93 | # defined by theme itself. Builtin themes are using these templates by
94 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
95 | # 'searchbox.html']``.
96 | #
97 | # html_sidebars = {}
98 |
99 |
100 | # -- Options for HTMLHelp output ---------------------------------------------
101 |
102 | # Output file base name for HTML help builder.
103 | htmlhelp_basename = 'PyTriedoc'
104 |
105 |
106 | # -- Options for LaTeX output ------------------------------------------------
107 |
108 | latex_elements = {
109 | # The paper size ('letterpaper' or 'a4paper').
110 | #
111 | # 'papersize': 'letterpaper',
112 |
113 | # The font size ('10pt', '11pt' or '12pt').
114 | #
115 | # 'pointsize': '10pt',
116 |
117 | # Additional stuff for the LaTeX preamble.
118 | #
119 | # 'preamble': '',
120 |
121 | # Latex figure (float) alignment
122 | #
123 | # 'figure_align': 'htbp',
124 | }
125 |
126 | # Grouping the document tree into LaTeX files. List of tuples
127 | # (source start file, target name, title,
128 | # author, documentclass [howto, manual, or own class]).
129 | latex_documents = [
130 | (master_doc, 'PyTrie.tex', 'PyTrie Documentation',
131 | 'George Sakkis', 'manual'),
132 | ]
133 |
134 |
135 | # -- Options for manual page output ------------------------------------------
136 |
137 | # One entry per manual page. List of tuples
138 | # (source start file, name, description, authors, manual section).
139 | man_pages = [
140 | (master_doc, 'pytrie', 'PyTrie Documentation',
141 | [author], 1)
142 | ]
143 |
144 |
145 | # -- Options for Texinfo output ----------------------------------------------
146 |
147 | # Grouping the document tree into Texinfo files. List of tuples
148 | # (source start file, target name, title, author,
149 | # dir menu entry, description, category)
150 | texinfo_documents = [
151 | (master_doc, 'PyTrie', 'PyTrie Documentation',
152 | author, 'PyTrie', 'One line description of project.',
153 | 'Miscellaneous'),
154 | ]
155 |
156 |
157 | # -- Options for Epub output -------------------------------------------------
158 |
159 | # Bibliographic Dublin Core info.
160 | epub_title = project
161 |
162 | # The unique identifier of the text. This can be a ISBN number
163 | # or the project homepage.
164 | #
165 | # epub_identifier = ''
166 |
167 | # A unique identification for the text.
168 | #
169 | # epub_uid = ''
170 |
171 | # A list of files that should not be packed into the epub file.
172 | epub_exclude_files = ['search.html']
173 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. PyTrie documentation master file, created by
2 | sphinx-quickstart on Sat Dec 26 19:56:21 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to PyTrie's documentation!
7 | ==================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | .. automodule:: pytrie
14 |
15 | Reference documentation
16 | -----------------------
17 |
18 | Classes
19 | ~~~~~~~
20 | .. autoclass:: Trie
21 | :show-inheritance:
22 | :members: __init__, fromkeys, KeyFactory, NodeFactory
23 | .. autoclass:: StringTrie
24 | :show-inheritance:
25 | .. autoclass:: SortedTrie
26 | :show-inheritance:
27 | .. autoclass:: SortedStringTrie
28 | :show-inheritance:
29 |
30 | Trie methods
31 | ~~~~~~~~~~~~
32 | The following methods are specific to tries; they are not part of the mapping API.
33 |
34 | .. automethod:: Trie.longest_prefix(key[, default])
35 | .. automethod:: Trie.longest_prefix_value(key[, default])
36 | .. automethod:: Trie.longest_prefix_item(key[, default])
37 | .. automethod:: Trie.iter_prefixes
38 | .. automethod:: Trie.iter_prefix_values
39 | .. automethod:: Trie.iter_prefix_items
40 |
41 | Extended mapping API methods
42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43 | The following methods extend the respective mapping API methods with an optional
44 | ``prefix`` parameter. If not ``None``, only keys (or associated values/items)
45 | that start with ``prefix`` are returned.
46 |
47 | .. automethod:: Trie.keys
48 | .. automethod:: Trie.values
49 | .. automethod:: Trie.items
50 | .. automethod:: Trie.iterkeys
51 | .. automethod:: Trie.itervalues
52 | .. automethod:: Trie.iteritems
53 |
54 | Original mapping API methods
55 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 | The following methods have the standard mapping signature and semantics.
57 |
58 | .. automethod:: Trie.__len__
59 | .. automethod:: Trie.__bool__
60 | .. automethod:: Trie.__iter__
61 | .. automethod:: Trie.__contains__
62 | .. automethod:: Trie.__getitem__
63 | .. automethod:: Trie.__setitem__
64 | .. automethod:: Trie.__delitem__
65 | .. automethod:: Trie.__repr__
66 | .. automethod:: Trie.clear
67 | .. automethod:: Trie.copy
68 |
69 | Internals
70 | ~~~~~~~~~
71 | Tries are implemented as trees of :class:`Node` instances. You don't need to
72 | worry about them unless unless you want to extend or replace :class:`Node` with
73 | a new node factory and bind it to :attr:`Trie.NodeFactory`.
74 |
75 | .. autoclass:: Node
76 | :show-inheritance:
77 | :members:
78 |
79 | Indices and tables
80 | ==================
81 |
82 | * :ref:`genindex`
83 | * :ref:`modindex`
84 | * :ref:`search`
85 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/pylintrc:
--------------------------------------------------------------------------------
1 | [MASTER]
2 |
3 | # Specify a configuration file.
4 | #rcfile=
5 |
6 | # Python code to execute, usually for sys.path manipulation such as
7 | # pygtk.require().
8 | #init-hook=
9 |
10 | # Profiled execution.
11 | profile=no
12 |
13 | # Add files or directories to the blacklist. They should be base names, not
14 | # paths.
15 | ignore=CVS
16 |
17 | # Pickle collected data for later comparisons.
18 | persistent=yes
19 |
20 | # List of plugins (as comma separated values of python modules names) to load,
21 | # usually to register additional checkers.
22 | load-plugins=
23 |
24 |
25 | [MESSAGES CONTROL]
26 |
27 | # Enable the message, report, category or checker with the given id(s). You can
28 | # either give multiple identifier separated by comma (,) or put this option
29 | # multiple time. See also the "--disable" option for examples.
30 | #enable=
31 |
32 | # Disable the message, report, category or checker with the given id(s). You
33 | # can either give multiple identifiers separated by comma (,) or put this
34 | # option multiple times (only on the command line, not in the configuration
35 | # file where it should appear only once).You can also use "--disable=all" to
36 | # disable everything first and then reenable specific checks. For example, if
37 | # you want to run only the similarities checker, you can use "--disable=all
38 | # --enable=similarities". If you want to run only the classes checker, but have
39 | # no Warning level messages displayed, use"--disable=all --enable=classes
40 | # --disable=W"
41 | disable=
42 | locally-disabled,
43 | missing-docstring,
44 | too-many-public-methods,
45 | too-few-public-methods,
46 |
47 | [REPORTS]
48 |
49 | # Set the output format. Available formats are text, parseable, colorized, msvs
50 | # (visual studio) and html. You can also give a reporter class, eg
51 | # mypackage.mymodule.MyReporterClass.
52 | output-format=text
53 |
54 | # Put messages in a separate file for each module / package specified on the
55 | # command line instead of printing them on stdout. Reports (if any) will be
56 | # written in a file name "pylint_global.[txt|html]".
57 | files-output=no
58 |
59 | # Tells whether to display a full report or only the messages
60 | reports=no
61 |
62 | # Python expression which should return a note less than 10 (10 is the highest
63 | # note). You have access to the variables errors warning, statement which
64 | # respectively contain the number of errors / warnings messages and the total
65 | # number of statements analyzed. This is used by the global evaluation report
66 | # (RP0004).
67 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
68 |
69 | # Add a comment according to your evaluation note. This is used by the global
70 | # evaluation report (RP0004).
71 | comment=no
72 |
73 | # Template used to display messages. This is a python new-style format string
74 | # used to format the message information. See doc for all details
75 | #msg-template=
76 |
77 |
78 | [SIMILARITIES]
79 |
80 | # Minimum lines number of a similarity.
81 | min-similarity-lines=4
82 |
83 | # Ignore comments when computing similarities.
84 | ignore-comments=yes
85 |
86 | # Ignore docstrings when computing similarities.
87 | ignore-docstrings=yes
88 |
89 | # Ignore imports when computing similarities.
90 | ignore-imports=no
91 |
92 |
93 | [BASIC]
94 |
95 | # Required attributes for module, separated by a comma
96 | required-attributes=
97 |
98 | # List of builtins function names that should not be used, separated by a comma
99 | bad-functions=map,filter,apply,input
100 |
101 | # Regular expression which should only match correct module names
102 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
103 |
104 | # Regular expression which should only match correct module level names
105 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
106 |
107 | # Regular expression which should only match correct class names
108 | class-rgx=[A-Z_][a-zA-Z0-9]+$
109 |
110 | # Regular expression which should only match correct function names
111 | function-rgx=[a-z_][a-z0-9_]{2,30}$
112 |
113 | # Regular expression which should only match correct method names
114 | method-rgx=[a-z_][a-z0-9_]{2,30}$
115 |
116 | # Regular expression which should only match correct instance attribute names
117 | attr-rgx=[a-z_][a-z0-9_]{2,30}$
118 |
119 | # Regular expression which should only match correct argument names
120 | argument-rgx=[a-z_][a-z0-9_]{2,30}$
121 |
122 | # Regular expression which should only match correct variable names
123 | variable-rgx=[a-z_][a-z0-9_]{2,30}$
124 |
125 | # Regular expression which should only match correct attribute names in class
126 | # bodies
127 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
128 |
129 | # Regular expression which should only match correct list comprehension /
130 | # generator expression variable names
131 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
132 |
133 | # Good variable names which should always be accepted, separated by a comma
134 | good-names=i,j,k,ex,Run,_
135 |
136 | # Bad variable names which should always be refused, separated by a comma
137 | bad-names=foo,bar,baz,toto,tutu,tata
138 |
139 | # Regular expression which should only match function or class names that do
140 | # not require a docstring.
141 | no-docstring-rgx=__.*__
142 |
143 | # Minimum line length for functions/classes that require docstrings, shorter
144 | # ones are exempt.
145 | docstring-min-length=-1
146 |
147 |
148 | [VARIABLES]
149 |
150 | # Tells whether we should check for unused import in __init__ files.
151 | init-import=no
152 |
153 | # A regular expression matching the beginning of the name of dummy variables
154 | # (i.e. not used).
155 | dummy-variables-rgx=_$|dummy
156 |
157 | # List of additional names supposed to be defined in builtins. Remember that
158 | # you should avoid to define new builtins when possible.
159 | additional-builtins=
160 |
161 |
162 | [MISCELLANEOUS]
163 |
164 | # List of note tags to take in consideration, separated by a comma.
165 | notes=FIXME,XXX,TODO
166 |
167 |
168 | [FORMAT]
169 |
170 | # Maximum number of characters on a single line.
171 | max-line-length=80
172 |
173 | # Regexp for a line that is allowed to be longer than the limit.
174 | ignore-long-lines=^\s*(# )??$
175 |
176 | # Allow the body of an if to be on the same line as the test if there is no
177 | # else.
178 | single-line-if-stmt=no
179 |
180 | # List of optional constructs for which whitespace checking is disabled
181 | no-space-check=trailing-comma,dict-separator
182 |
183 | # Maximum number of lines in a module
184 | max-module-lines=1000
185 |
186 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
187 | # tab).
188 | indent-string=' '
189 |
190 |
191 | [TYPECHECK]
192 |
193 | # Tells whether missing members accessed in mixin class should be ignored. A
194 | # mixin class is detected if its name ends with "mixin" (case insensitive).
195 | ignore-mixin-members=yes
196 |
197 | # List of classes names for which member attributes should not be checked
198 | # (useful for classes with attributes dynamically set).
199 | ignored-classes=SQLObject
200 |
201 | # When zope mode is activated, add a predefined set of Zope acquired attributes
202 | # to generated-members.
203 | zope=no
204 |
205 | # List of members which are set dynamically and missed by pylint inference
206 | # system, and so shouldn't trigger E0201 when accessed. Python regular
207 | # expressions are accepted.
208 | generated-members=REQUEST,acl_users,aq_parent
209 |
210 |
211 | [DESIGN]
212 |
213 | # Maximum number of arguments for function / method
214 | max-args=5
215 |
216 | # Argument names that match this expression will be ignored. Default to name
217 | # with leading underscore
218 | ignored-argument-names=_.*
219 |
220 | # Maximum number of locals for function / method body
221 | max-locals=15
222 |
223 | # Maximum number of return / yield for function / method body
224 | max-returns=6
225 |
226 | # Maximum number of branch for function / method body
227 | max-branches=12
228 |
229 | # Maximum number of statements in function / method body
230 | max-statements=50
231 |
232 | # Maximum number of parents for a class (see R0901).
233 | max-parents=7
234 |
235 | # Maximum number of attributes for a class (see R0902).
236 | max-attributes=7
237 |
238 | # Minimum number of public methods for a class (see R0903).
239 | min-public-methods=2
240 |
241 | # Maximum number of public methods for a class (see R0904).
242 | max-public-methods=20
243 |
244 |
245 | [IMPORTS]
246 |
247 | # Deprecated modules which should not be used, separated by a comma
248 | deprecated-modules=regsub,TERMIOS,Bastion,rexec
249 |
250 | # Create a graph of every (i.e. internal and external) dependencies in the
251 | # given file (report RP0402 must not be disabled)
252 | import-graph=
253 |
254 | # Create a graph of external dependencies in the given file (report RP0402 must
255 | # not be disabled)
256 | ext-import-graph=
257 |
258 | # Create a graph of internal dependencies in the given file (report RP0402 must
259 | # not be disabled)
260 | int-import-graph=
261 |
262 |
263 | [CLASSES]
264 |
265 | # List of interface methods to ignore, separated by a comma. This is used for
266 | # instance to not check methods defines in Zope's Interface base class.
267 | ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
268 |
269 | # List of method names used to declare (i.e. assign) instance attributes.
270 | defining-attr-methods=__init__,__new__,setUp
271 |
272 | # List of valid names for the first argument in a class method.
273 | valid-classmethod-first-arg=cls
274 |
275 | # List of valid names for the first argument in a metaclass class method.
276 | valid-metaclass-classmethod-first-arg=mcs
277 |
278 |
279 | [EXCEPTIONS]
280 |
281 | # Exceptions that will emit a warning when being caught. Defaults to
282 | # "Exception"
283 | overgeneral-exceptions=Exception
284 |
--------------------------------------------------------------------------------
/pytrie.py:
--------------------------------------------------------------------------------
1 | """
2 | :mod:`pytrie` is a pure Python implementation of the
3 | `trie `_ (prefix tree) data structure.
4 |
5 | A *trie* is a tree data structure that is used to store a mapping where the keys
6 | are sequences, usually strings over an alphabet. In addition to implementing the
7 | mapping interface, tries facilitate finding the items for a given prefix, and
8 | vice versa, finding the items whose keys are prefixes of a given key ``K``. As a
9 | common special case, finding the longest-prefix item is also supported.
10 |
11 | Algorithmically, tries are more efficient than binary search trees (BSTs) both
12 | in lookup time and memory when they contain many keys sharing relatively few
13 | prefixes. Unlike hash tables, trie keys don't need to be hashable. In the
14 | current implementation, a key can be any finite iterable with hashable elements.
15 |
16 | Usage
17 | -----
18 | >>> from pytrie import SortedStringTrie as Trie
19 | >>> t = Trie(an=0, ant=1, all=2, allot=3, alloy=4, aloe=5, are=6, be=7)
20 | >>> t
21 | SortedStringTrie({'all': 2, 'allot': 3, 'alloy': 4, 'aloe': 5, 'an': 0, 'ant': 1, 'are': 6, 'be': 7})
22 | >>> t.keys(prefix='al')
23 | ['all', 'allot', 'alloy', 'aloe']
24 | >>> t.items(prefix='an')
25 | [('an', 0), ('ant', 1)]
26 | >>> t.longest_prefix('antonym')
27 | 'ant'
28 | >>> t.longest_prefix_item('allstar')
29 | ('all', 2)
30 | >>> t.longest_prefix_value('area', default='N/A')
31 | 6
32 | >>> t.longest_prefix('alsa')
33 | Traceback (most recent call last):
34 | ...
35 | KeyError
36 | >>> t.longest_prefix_value('alsa', default=-1)
37 | -1
38 | >>> list(t.iter_prefixes('allotment'))
39 | ['all', 'allot']
40 | >>> list(t.iter_prefix_items('antonym'))
41 | [('an', 0), ('ant', 1)]
42 | """
43 |
44 | __all__ = ['Trie', 'StringTrie', 'SortedTrie', 'SortedStringTrie', 'Node']
45 |
46 | import sys
47 | from copy import copy
48 | from collections.abc import MutableMapping
49 |
50 | import sortedcontainers
51 |
52 |
53 | # Singleton sentinel - works with pickling
54 | class NULL:
55 | pass
56 |
57 |
58 | class Node:
59 | """Trie node class.
60 |
61 | Subclasses may extend it to replace :attr:`ChildrenFactory` with a different
62 | mapping class (e.g. `sorteddict `_)
63 |
64 | :ivar value: The value of the key corresponding to this node or
65 | :const:`NULL` if there is no such key.
66 | :ivar children: A ``{key-part : child-node}`` mapping.
67 | """
68 |
69 | __slots__ = ('value', 'children')
70 |
71 | #: A callable for creating a new :attr:`children` mapping.
72 | ChildrenFactory = dict
73 |
74 | def __init__(self, value=NULL):
75 | self.value = value
76 | self.children = self.ChildrenFactory()
77 |
78 | def __len__(self):
79 | """Return the number of keys in the subtree rooted at this node."""
80 | return int(self.value is not NULL) + sum(map(len, self.children.values()))
81 |
82 | def __repr__(self):
83 | return '(%s, {%s})' % (
84 | self.value is NULL and 'NULL' or repr(self.value),
85 | ', '.join('%r: %r' % t for t in self.children.items()))
86 |
87 | def __copy__(self):
88 | clone = self.__class__(self.value)
89 | clone_children = clone.children
90 | for key, child in self.children.items():
91 | clone_children[key] = child.__copy__()
92 | return clone
93 |
94 | def __getstate__(self):
95 | return self.value, self.children
96 |
97 | def __setstate__(self, state):
98 | self.value, self.children = state
99 |
100 |
101 | class Trie(MutableMapping):
102 | """Base trie class.
103 |
104 | As with regular dicts, keys are not necessarily returned sorted. Use
105 | :class:`SortedTrie` if sorting is required.
106 | """
107 |
108 | #: Callable for forming a key from its parts.
109 | KeyFactory = tuple
110 |
111 | #: Callable for creating new trie nodes.
112 | NodeFactory = Node
113 |
114 | def __init__(self, *args, **kwargs):
115 | """Create a new trie.
116 |
117 | Parameters are the same with ``dict()``.
118 | """
119 | self._root = self.NodeFactory()
120 | self.update(*args, **kwargs)
121 |
122 | @classmethod
123 | def fromkeys(cls, iterable, value=None):
124 | """
125 | Create a new trie with keys from ``iterable`` and values set to
126 | ``value``.
127 |
128 | Parameters are the same with ``dict.fromkeys()``.
129 | """
130 | trie = cls()
131 | for key in iterable:
132 | trie[key] = value
133 | return trie
134 |
135 | #----- trie-specific methods -----------------------------------------------
136 |
137 | def longest_prefix(self, key, default=NULL):
138 | """Return the longest key in this trie that is a prefix of ``key``.
139 |
140 | If the trie doesn't contain any prefix of ``key``:
141 | - if ``default`` is given, return it
142 | - otherwise raise ``KeyError``
143 | """
144 | try:
145 | return self.longest_prefix_item(key)[0]
146 | except KeyError:
147 | if default is not NULL:
148 | return default
149 | raise
150 |
151 | def longest_prefix_value(self, key, default=NULL):
152 | """Return the value associated with the longest key in this trie that is
153 | a prefix of ``key``.
154 |
155 | If the trie doesn't contain any prefix of ``key``:
156 | - if ``default`` is given, return it
157 | - otherwise raise ``KeyError``
158 | """
159 | node = self._root
160 | longest_prefix_value = node.value
161 | for part in key:
162 | node = node.children.get(part)
163 | if node is None:
164 | break
165 | value = node.value
166 | if value is not NULL:
167 | longest_prefix_value = value
168 | if longest_prefix_value is not NULL:
169 | return longest_prefix_value
170 | elif default is not NULL:
171 | return default
172 | else:
173 | raise KeyError
174 |
175 | def longest_prefix_item(self, key, default=NULL):
176 | """Return the item (``(key,value)`` tuple) associated with the longest
177 | key in this trie that is a prefix of ``key``.
178 |
179 | If the trie doesn't contain any prefix of ``key``:
180 | - if ``default`` is given, return it
181 | - otherwise raise ``KeyError``
182 | """
183 | prefix = []
184 | append = prefix.append
185 | node = self._root
186 | longest_prefix_value = node.value
187 | max_non_null_index = -1
188 | for i, part in enumerate(key):
189 | node = node.children.get(part)
190 | if node is None:
191 | break
192 | append(part)
193 | value = node.value
194 | if value is not NULL:
195 | longest_prefix_value = value
196 | max_non_null_index = i
197 | if longest_prefix_value is not NULL:
198 | del prefix[max_non_null_index+1:]
199 | return self.KeyFactory(prefix), longest_prefix_value
200 | elif default is not NULL:
201 | return default
202 | else:
203 | raise KeyError
204 |
205 | def iter_prefixes(self, key):
206 | """
207 | Return an iterator over the keys of this trie that are prefixes of
208 | ``key``.
209 | """
210 | key_factory = self.KeyFactory
211 | prefix = []
212 | append = prefix.append
213 | node = self._root
214 | if node.value is not NULL:
215 | yield key_factory(prefix)
216 | for part in key:
217 | node = node.children.get(part)
218 | if node is None:
219 | break
220 | append(part)
221 | if node.value is not NULL:
222 | yield key_factory(prefix)
223 |
224 | def iter_prefix_values(self, key):
225 | """Return an iterator over the values of this trie that are associated
226 | with keys that are prefixes of ``key``.
227 | """
228 | node = self._root
229 | if node.value is not NULL:
230 | yield node.value
231 | for part in key:
232 | node = node.children.get(part)
233 | if node is None:
234 | break
235 | if node.value is not NULL:
236 | yield node.value
237 |
238 | def iter_prefix_items(self, key):
239 | """Return an iterator over the items (``(key,value)`` tuples) of this
240 | trie that are associated with keys that are prefixes of ``key``.
241 | """
242 | key_factory = self.KeyFactory
243 | prefix = []
244 | append = prefix.append
245 | node = self._root
246 | if node.value is not NULL:
247 | yield (key_factory(prefix), node.value)
248 | for part in key:
249 | node = node.children.get(part)
250 | if node is None:
251 | break
252 | append(part)
253 | if node.value is not NULL:
254 | yield (key_factory(prefix), node.value)
255 |
256 | #----- extended mapping API methods ----------------------------------------
257 |
258 | # pylint: disable=arguments-differ
259 |
260 | def keys(self, prefix=None):
261 | """Return a list of this trie's keys.
262 |
263 | :param prefix: If not None, return only the keys prefixed by ``prefix``.
264 | """
265 | return list(self.iterkeys(prefix))
266 |
267 | def values(self, prefix=None):
268 | """Return a list of this trie's values.
269 |
270 | :param prefix: If not None, return only the values associated with keys
271 | prefixed by ``prefix``.
272 | """
273 | return list(self.itervalues(prefix))
274 |
275 | def items(self, prefix=None):
276 | """Return a list of this trie's items (``(key,value)`` tuples).
277 |
278 | :param prefix: If not None, return only the items associated with keys
279 | prefixed by ``prefix``.
280 | """
281 | return list(self.iteritems(prefix))
282 |
283 | def iterkeys(self, prefix=None):
284 | """Return an iterator over this trie's keys.
285 |
286 | :param prefix: If not None, yield only the keys prefixed by ``prefix``.
287 | """
288 | return (key for key, value in self.iteritems(prefix))
289 |
290 | def itervalues(self, prefix=None):
291 | """Return an iterator over this trie's values.
292 |
293 | :param prefix: If not None, yield only the values associated with keys
294 | prefixed by ``prefix``.
295 | """
296 | def generator(node, null=NULL):
297 | if node.value is not null:
298 | yield node.value
299 | for child in node.children.values():
300 | for subresult in generator(child):
301 | yield subresult
302 | if prefix is None:
303 | root = self._root
304 | else:
305 | root = self._find(prefix)
306 | if root is None:
307 | root = self.NodeFactory()
308 | return generator(root)
309 |
310 | def iteritems(self, prefix=None):
311 | """Return an iterator over this trie's items (``(key,value)`` tuples).
312 |
313 | :param prefix: If not None, yield only the items associated with keys
314 | prefixed by ``prefix``.
315 | """
316 | parts = []
317 | append = parts.append
318 |
319 | # pylint: disable=dangerous-default-value
320 | def generator(node, key_factory=self.KeyFactory, parts=parts,
321 | append=append, null=NULL):
322 | if node.value is not null:
323 | yield (key_factory(parts), node.value)
324 | for part, child in node.children.items():
325 | append(part)
326 | for subresult in generator(child):
327 | yield subresult
328 | del parts[-1]
329 |
330 | root = self._root
331 | if prefix is not None:
332 | for part in prefix:
333 | append(part)
334 | root = root.children.get(part)
335 | if root is None:
336 | root = self.NodeFactory()
337 | break
338 |
339 | return generator(root)
340 |
341 | # pylint: enable=arguments-differ
342 |
343 | #----- original mapping API methods ----------------------------------------
344 |
345 | def __len__(self):
346 | return len(self._root)
347 |
348 | def __bool__(self):
349 | return self._root.value is not NULL or bool(self._root.children)
350 |
351 | def __iter__(self):
352 | return self.iterkeys()
353 |
354 | def __contains__(self, key):
355 | node = self._find(key)
356 | return node is not None and node.value is not NULL
357 |
358 | def __getitem__(self, key):
359 | node = self._find(key)
360 | if node is None or node.value is NULL:
361 | raise KeyError
362 | return node.value
363 |
364 | def __setitem__(self, key, value):
365 | node = self._root
366 | factory = self.NodeFactory
367 | for part in key:
368 | next_node = node.children.get(part)
369 | if next_node is None:
370 | node = node.children.setdefault(part, factory())
371 | else:
372 | node = next_node
373 | node.value = value
374 |
375 | def __delitem__(self, key):
376 | nodes_parts = []
377 | append = nodes_parts.append
378 | node = self._root
379 | for part in key:
380 | append((node, part))
381 | node = node.children.get(part)
382 | if node is None:
383 | break
384 | if node is None or node.value is NULL:
385 | raise KeyError
386 | node.value = NULL
387 | pop = nodes_parts.pop
388 | while node.value is NULL and not node.children and nodes_parts:
389 | node, part = pop()
390 | del node.children[part]
391 |
392 | def clear(self):
393 | self._root.children.clear()
394 |
395 | def copy(self):
396 | clone = copy(super(Trie, self))
397 | clone._root = copy(self._root) # pylint: disable=protected-access
398 | return clone
399 |
400 | def __repr__(self):
401 | return '%s({%s})' % (
402 | self.__class__.__name__,
403 | ', '.join('%r: %r' % t for t in self.iteritems()))
404 |
405 | def _find(self, key):
406 | node = self._root
407 | for part in key:
408 | node = node.children.get(part)
409 | if node is None:
410 | break
411 | return node
412 |
413 |
414 | class StringTrie(Trie):
415 | """A more appropriate for string keys :class:`Trie`."""
416 | KeyFactory = ''.join
417 |
418 |
419 | class _SortedNode(Node):
420 | ChildrenFactory = sortedcontainers.SortedDict
421 |
422 |
423 | class SortedTrie(Trie):
424 | """
425 | A :class:`Trie` that returns its keys (and associated values/items) sorted.
426 | """
427 | NodeFactory = _SortedNode
428 |
429 |
430 | # pylint: disable=too-many-ancestors
431 | class SortedStringTrie(SortedTrie, StringTrie):
432 | """
433 | A :class:`Trie` that is both a :class:`StringTrie` and a :class:`SortedTrie`
434 | """
435 |
436 |
437 | if __name__ == '__main__':
438 | import doctest
439 | doctest.testmod()
440 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from setuptools import setup
4 |
5 | setup(
6 | name='PyTrie',
7 | version='0.4.0',
8 | author='George Sakkis',
9 | author_email='george.sakkis@gmail.com',
10 | url='https://github.com/gsakkis/pytrie/',
11 | description='A pure Python implementation of the trie data structure.',
12 | long_description=open('README.md').read(),
13 | long_description_content_type='text/markdown',
14 | classifiers=[
15 | 'Development Status :: 4 - Beta',
16 | 'Intended Audience :: Developers',
17 | 'License :: OSI Approved :: BSD License',
18 | 'Operating System :: OS Independent',
19 | 'Programming Language :: Python :: 3',
20 | 'Topic :: Software Development :: Libraries :: Python Modules',
21 | ],
22 | py_modules=['pytrie'],
23 | install_requires=['sortedcontainers'],
24 | test_suite='tests',
25 | )
26 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsakkis/pytrie/38cc269bbc71a439f10d33c319facbbe8067d84f/tests/__init__.py
--------------------------------------------------------------------------------
/tests/test_mapping.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 | Mapping tests adapted from stdlib test.mapping_tests
4 |
5 | Essentially replaced non-iterable hardcoded keys with string keys,
6 | plus a few more extra tests.
7 | """
8 |
9 | try:
10 | from UserDict import UserDict
11 | except ImportError: # Python 3
12 | # pylint: disable=no-name-in-module
13 | from collections import UserDict
14 | from test import mapping_tests
15 |
16 | from pytrie import StringTrie
17 |
18 |
19 | # pylint: disable=invalid-name
20 |
21 | class BasicTestMappingTrie(mapping_tests.BasicTestMappingProtocol):
22 | # Functions that can be useful to override to adapt to dictionary
23 | # semantics
24 |
25 | # which class is being tested (overwrite in subclasses)
26 | type2test = StringTrie
27 |
28 | def _reference(self):
29 | """
30 | Return a dictionary of values which are invariant by storage in the
31 | object under test.
32 | """
33 | return {'key1': 'value1', 'key2': (1, 2, 3), 'key': None}
34 |
35 | def test_values(self):
36 | d = self._empty_mapping()
37 | self.assertEqual(d.values(), [])
38 |
39 | def test_items(self):
40 | d = self._empty_mapping()
41 | self.assertEqual(d.items(), [])
42 |
43 |
44 | class TestMappingTrie(BasicTestMappingTrie, mapping_tests.TestMappingProtocol):
45 |
46 | def test_values(self):
47 | super(TestMappingTrie, self).test_values()
48 | d = self._full_mapping({'1': 2})
49 | self.assertEqual(d.values(), [2])
50 |
51 | def test_items(self):
52 | super(TestMappingTrie, self).test_items()
53 | d = self._full_mapping({'1': 2})
54 | self.assertEqual(d.items(), [('1', 2)])
55 |
56 | def test_clear(self):
57 | d = self._full_mapping(self.reference)
58 | d.clear()
59 | self.assertEqual(d, {})
60 | self.assertRaises(TypeError, d.clear, None)
61 |
62 | def test_update(self):
63 | BasicTestMappingTrie.test_update(self)
64 | # mapping argument
65 | d = self._empty_mapping()
66 | d.update({'1': 100})
67 | d.update({'2': 20})
68 | d.update({'1': 1, '2': 2, '3': 3})
69 | self.assertEqual(d, {'1': 1, '2': 2, '3': 3})
70 |
71 | # no argument
72 | d.update()
73 | self.assertEqual(d, {'1': 1, '2': 2, '3': 3})
74 |
75 | # keyword arguments
76 | d = self._empty_mapping()
77 | d.update(x=100)
78 | d.update(y=20)
79 | d.update(x=1, y=2, z=3)
80 | self.assertEqual(d, {'x': 1, 'y': 2, 'z': 3})
81 |
82 | # item sequence
83 | d = self._empty_mapping()
84 | d.update([('x', 100), ('y', 20)])
85 | self.assertEqual(d, {'x': 100, 'y': 20})
86 |
87 | # Both item sequence and keyword arguments
88 | d = self._empty_mapping()
89 | d.update([('x', 100), ('y', 20)], x=1, y=2)
90 | self.assertEqual(d, {'x': 1, 'y': 2})
91 |
92 | # iterator
93 | d = self._full_mapping({'1': 3, '2': 4})
94 | d.update(self._full_mapping({'1': 2, '3': 4, '5': 6}).iteritems())
95 | self.assertEqual(d, {'1': 2, '2': 4, '3': 4, '5': 6})
96 |
97 | class SimpleUserDict: # pylint: disable=old-style-class
98 | def __init__(self):
99 | self.d = {'1': 1, '2': 2, '3': 3}
100 |
101 | def keys(self):
102 | return self.d.keys()
103 |
104 | def __getitem__(self, i):
105 | return self.d[i]
106 |
107 | d.clear()
108 | d.update(SimpleUserDict())
109 | self.assertEqual(d, {'1': 1, '2': 2, '3': 3})
110 |
111 | def test_fromkeys(self):
112 | self.assertEqual(self.type2test.fromkeys('abc'),
113 | {'a': None, 'b': None, 'c': None})
114 | d = self._empty_mapping()
115 | self.assertTrue(d.fromkeys('abc') is not d)
116 | self.assertEqual(d.fromkeys('abc'), {'a': None, 'b': None, 'c': None})
117 | self.assertEqual(d.fromkeys(('4', '5'), 0), {'4': 0, '5': 0})
118 | self.assertEqual(d.fromkeys([]), {})
119 |
120 | def g():
121 | yield '1'
122 |
123 | self.assertEqual(d.fromkeys(g()), {'1': None})
124 | self.assertRaises(TypeError, d.fromkeys, 3)
125 |
126 | class dictlike(self.type2test):
127 | pass
128 |
129 | self.assertEqual(dictlike.fromkeys('a'), {'a': None})
130 | self.assertEqual(dictlike().fromkeys('a'), {'a': None})
131 | self.assertTrue(dictlike.fromkeys('a').__class__ is dictlike)
132 | self.assertTrue(dictlike().fromkeys('a').__class__ is dictlike)
133 | self.assertTrue(type(dictlike.fromkeys('a')) is dictlike)
134 |
135 | class mydict(self.type2test):
136 | def __new__(cls):
137 | return UserDict()
138 |
139 | ud = mydict.fromkeys('ab')
140 | self.assertEqual(ud, {'a': None, 'b': None})
141 | self.assertTrue(isinstance(ud, UserDict))
142 | self.assertRaises(TypeError, dict.fromkeys)
143 |
144 | class Exc(Exception):
145 | pass
146 |
147 | class baddict1(self.type2test):
148 | def __init__(self): # pylint: disable=super-init-not-called
149 | raise Exc()
150 |
151 | self.assertRaises(Exc, baddict1.fromkeys, [1])
152 |
153 | class BadSeq(object):
154 |
155 | def __iter__(self):
156 | return self
157 |
158 | def next(self): # pylint: disable=no-self-use
159 | raise Exc()
160 |
161 | self.assertRaises(Exception, self.type2test.fromkeys, BadSeq())
162 |
163 | class baddict2(self.type2test):
164 | def __setitem__(self, key, value):
165 | raise Exc()
166 |
167 | self.assertRaises(Exc, baddict2.fromkeys, [1])
168 |
169 | def test_copy(self):
170 | d = self._full_mapping({'1': 1, '2': 2, '3': 3, '': []})
171 |
172 | d2 = d.copy()
173 | self.assertEqual(d2, d)
174 |
175 | d[''].append('x')
176 | self.assertEqual(d2[''], ['x'])
177 |
178 | d['4'] = 4
179 | self.assertNotEqual(d2, d)
180 |
181 | d2['4'] = 4
182 | self.assertEqual(d2, d)
183 |
184 | d2['5'] = 5
185 | self.assertNotEqual(d2, d)
186 |
187 | d = self._empty_mapping()
188 | self.assertEqual(d.copy(), d)
189 | self.assertTrue(isinstance(d.copy(), d.__class__))
190 | self.assertRaises(TypeError, d.copy, None)
191 |
192 | def test_pop(self):
193 | BasicTestMappingTrie.test_pop(self)
194 | # Tests for pop with specified key
195 | d = self._empty_mapping()
196 | k, v = 'abc', 'def'
197 | self.assertEqual(d.pop(k, v), v)
198 | d[k] = v
199 | self.assertEqual(d.pop(k, 1), v)
200 |
201 |
202 | class TestMappingTrieSubclass(TestMappingTrie):
203 |
204 | class type2test(StringTrie):
205 | pass
206 |
--------------------------------------------------------------------------------
/tests/test_trie.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from pytrie import SortedStringTrie
3 |
4 |
5 | class TestTrie(unittest.TestCase):
6 |
7 | def setUp(self):
8 | self.words = 'an ant all allot alloy aloe are ate be'.split()
9 | self.trie = SortedStringTrie(zip(self.words, range(len(self.words))))
10 |
11 | def test_longest_prefix(self):
12 | self.assertEqual(self.trie.longest_prefix('antonym'), 'ant')
13 | self.assertEqual(self.trie.longest_prefix('are'), 'are')
14 | self.assertEqual(self.trie.longest_prefix('alla'), 'all')
15 | self.assertEqual(self.trie.longest_prefix('allo'), 'all')
16 | self.assertRaises(KeyError, self.trie.longest_prefix_item, 'alumni')
17 | self.assertEqual(self.trie.longest_prefix('alumni', default=None), None)
18 | self.assertEqual(self.trie.longest_prefix('linux', default=-1), -1)
19 |
20 | def test_longest_prefix_value(self):
21 | self.assertEqual(self.trie.longest_prefix_value('antonym'), 1)
22 | self.assertEqual(self.trie.longest_prefix_value('are'), 6)
23 | self.assertEqual(self.trie.longest_prefix_value('alla'), 2)
24 | self.assertEqual(self.trie.longest_prefix_value('allo'), 2)
25 | self.assertRaises(KeyError, self.trie.longest_prefix_value, 'alumni')
26 | self.assertEqual(self.trie.longest_prefix_value('alumni', default=None),
27 | None)
28 | self.assertEqual(self.trie.longest_prefix_value('linux', default=-1),
29 | -1)
30 |
31 | def test_longest_prefix_item(self):
32 | self.assertEqual(self.trie.longest_prefix_item('antonym'), ('ant', 1))
33 | self.assertEqual(self.trie.longest_prefix_item('are'), ('are', 6))
34 | self.assertEqual(self.trie.longest_prefix_item('alla'), ('all', 2))
35 | self.assertEqual(self.trie.longest_prefix_item('allo'), ('all', 2))
36 | self.assertRaises(KeyError, self.trie.longest_prefix_item, 'alumni')
37 | self.assertEqual(self.trie.longest_prefix_item('alumni', default=None),
38 | None)
39 | self.assertEqual(self.trie.longest_prefix_item('linux', default=-1), -1)
40 |
41 | def test_iter_prefixes(self):
42 | self.assertEqual(list(self.trie.iter_prefixes('antonym')),
43 | ['an', 'ant'])
44 | self.assertEqual(list(self.trie.iter_prefixes('are')), ['are'])
45 | self.assertEqual(list(self.trie.iter_prefixes('alumni')), [])
46 |
47 | def test_iter_prefix_values(self):
48 | self.assertEqual(list(self.trie.iter_prefix_values('antonym')), [0, 1])
49 | self.assertEqual(list(self.trie.iter_prefix_values('are')), [6])
50 | self.assertEqual(list(self.trie.iter_prefix_values('alumni')), [])
51 |
52 | def test_iter_prefix_items(self):
53 | self.assertEqual(list(self.trie.iter_prefix_items('antonym')),
54 | [('an', 0), ('ant', 1)])
55 | self.assertEqual(list(self.trie.iter_prefix_items('are')), [('are', 6)])
56 | self.assertEqual(list(self.trie.iter_prefix_items('alumni')), [])
57 |
58 | def test_keys_wprefix(self):
59 | self.assertEqual(self.trie.keys('al'),
60 | ['all', 'allot', 'alloy', 'aloe'])
61 | self.assertEqual(self.trie.keys('are'), ['are'])
62 | self.assertEqual(self.trie.keys('ann'), [])
63 |
64 | def test_values_wprefix(self):
65 | self.assertEqual(self.trie.values('al'), [2, 3, 4, 5])
66 | self.assertEqual(self.trie.values('are'), [6])
67 | self.assertEqual(self.trie.values('ann'), [])
68 |
69 | def test_items_wprefix(self):
70 | self.assertEqual(self.trie.items('al'),
71 | [('all', 2), ('allot', 3), ('alloy', 4), ('aloe', 5)])
72 | self.assertEqual(self.trie.items('are'), [('are', 6)])
73 | self.assertEqual(self.trie.items('ann'), [])
74 |
75 | def test_consistency_wprefix(self):
76 | trie = self.trie
77 | for prefix in 'al', 'are', 'ann':
78 | self.assertEqual(
79 | trie.items(prefix),
80 | list(zip(trie.keys(prefix), trie.values(prefix)))
81 | )
82 |
83 | def test_empty_string(self):
84 | self.trie[''] = '!'
85 |
86 | self.assertEqual(self.trie.keys(''),
87 | ['', 'all', 'allot', 'alloy', 'aloe', 'an', 'ant',
88 | 'are', 'ate', 'be'])
89 | self.assertEqual(self.trie.values(''),
90 | ['!', 2, 3, 4, 5, 0, 1, 6, 7, 8])
91 | self.assertEqual(self.trie.items(''),
92 | [('', '!'), ('all', 2), ('allot', 3), ('alloy', 4),
93 | ('aloe', 5), ('an', 0), ('ant', 1), ('are', 6),
94 | ('ate', 7), ('be', 8)])
95 |
96 | self.assertEqual(list(self.trie.iter_prefixes('foo')), [''])
97 | self.assertEqual(list(self.trie.iter_prefix_values('foo')), ['!'])
98 | self.assertEqual(list(self.trie.iter_prefix_items('foo')), [('', '!')])
99 |
100 | self.assertEqual(self.trie.longest_prefix('foo'), '')
101 | self.assertEqual(self.trie.longest_prefix_value('foo'), '!')
102 | self.assertEqual(self.trie.longest_prefix_item('foo'), ('', '!'))
103 |
104 | def test_pickle(self):
105 | from pickle import dumps, loads, HIGHEST_PROTOCOL
106 | for proto in range(HIGHEST_PROTOCOL):
107 | unpickled = loads(dumps(self.trie, proto))
108 | self.assertEqual(self.trie, unpickled)
109 | self.assertTrue(type(self.trie) is type(unpickled))
110 | self.assertTrue(self.trie is not unpickled)
111 |
112 | def test_repr(self):
113 | evaled = eval(repr(self.trie))
114 | self.assertEqual(evaled, self.trie)
115 | self.assertEqual(evaled.__class__, self.trie.__class__)
116 |
--------------------------------------------------------------------------------
\ 689 | Sort by:\ 690 | best rated\ 691 | newest\ 692 | oldest\ 693 |
\ 694 |\ 698 |
Add a comment\ 700 | (markup):
\ 701 |``code``
, \ 704 | code blocks:::
and an indented block after blank line