Skip to main content

High-performance dictionary engine based on FST

Project description

fstd

A dictionary engine powered by Finite State Transducers, a data structure that enables us to search in dictionaries with many ways, including regex, suggesting based on edit distance, other than just prefix search powered by trie data structure used by traditional dictionaries. Fstd dictionary provides two format file: fstdx and fstdd , which is similar to the popular dictionary format: mdx and mdd. A fstdtools that can convert mdx/mdd to fstdx/fstdd.

Features

  • Multiple threads are supported to offer high-performance search and dictionary compilation.
  • Regex search.
  • Fuzzy search: suggest candidates sorted by the similarity calculated by edit distance to input keyword.
  • Prefix distance search: provide candidates sorted by the distance calculated by common prefix and prior suffix. By providing prior suffix, it can top the candidates that has a longer common prefix with input keyword and has a prior suffix. It's useful to help us find the simple form of an verb in a language whose verb has some constant suffix, such as Japanese ("する", "う", "く", "ぐ", "す", "つ", "ぬ", "ぶ", "む", "る", "い") or Korean ("하다", "다"). However, it's not always effective in all cases.
  • Prefix search(predictive), a way as the same as traditional dictionaries can provide.
  • Esay to convert from mdx/mdd to fstdx/fstdd.
  • Data related to dictionaries is compressed to reduce disk usage.
  • Low memory usage and high-performance search, as the FST made by compiling entry words of a dictionary is loaded into memory to support high-performance search. FST is a data structure providing a better compression rate than trie, because it can not only compress common prefix but also common suffix.
  • Python support by import fstd

Install

It has been tested on Macos and Linux platform now. On Windows platform, there might be a bug while launching a thread pool. It's not convenient to fix it because I don't have a windows machine. Pull a request to me if you can fix it.

Python

pip install fstd

It's recommanded to install a python command line tool fstdtools as it offers a safer and more friendly usage than the CLI compiled from c plus plus.

pip install fstdtools
fstdtools --version

Install from source code

  1. Install dependence
brew install cmake googletest indicators spdlog fmt zstd pcre2 nlohmann-json cli11
  1. Compile and install
git clone https://github.com/MouJieQin/fstd.git
cd fstd
mkdir build && cd build
cmake ..
make install -j8
fstd -h
  1. Run test
make check

Usage

Python

To run the demo.py, you should have a directory named dictionaries with a structure like this, fstdx files are required.

dictionaries
├── dict1
│   ├── dict1.css
│   ├── dict1.fstdd
│   ├── dict1.fstdx
│   ├── dict1.js
│   └── dict1.png
├── dict2
│   ├── dict2.css
│   ├── dict2.fstdd
│   ├── dict2.fstdx
│   ├── dict2.js
│   └── dict2.png
└── dict3
    ├── dict1.css
    ├── dict1.fstdd
    ├── dict1.fstdx
    ├── dict1.js
    └── dict1.png
# demo.py
import os
import sys
from pathlib import Path
import fstd


class FstdSearcher:
    def __init__(self, dicts_path: str):
        fstd.set_log_level(4)
        self._all_dict_names: list[str] = []
        self._fstd_searcher: fstd.FstdxSearcher = fstd.FstdxSearcher()
        self._prior_suf = ["する", "う", "く", "ぐ", "す", "つ", "ぬ", "ぶ", "む", "る", "い", "하다", "다"]
        self._fstd_searcher.insert_prior_suffix(self._prior_suf)
        self._load_dicts(dicts_path)

    def _load_dicts(self, dicts_path: str) -> None:
        """
        Load the dictionaries from the path.
        :param dicts_path: the path to the dictionaries
        """
        for dict_path in os.listdir(dicts_path):
            if os.path.isdir(os.path.join(dicts_path, dict_path)):
                for file in os.listdir(os.path.join(dicts_path, dict_path)):
                    if file.endswith(".fstdx"):
                        dict_name = Path(dict_path).name
                        self._all_dict_names.append(dict_name)
                        self._fstd_searcher.insert_if_not_exists(dict_name, os.path.join(dicts_path, dict_path, file))
                        print(f"Load dictionary {dict_name} from {os.path.join(dicts_path, dict_path, file)}")

    def lookup(
        self,
        keyword: str,
        dict_names: list[str],
    ) -> dict[str, list[str]]:
        """
        Lookup the keyword in the dictionaries.
        :param keyword: the keyword to lookup
        :param dict_names: the dictionaries to lookup
        :return: the results of the lookup,a dictionary of dict_name -> result
        """
        results = {}
        dict_names = dict_names or self._all_dict_names
        for dict_name in dict_names:
            res = self._fstd_searcher.exact_match_search(keyword, dict_name)
            if res:
                result = []
                self._hand_link_word(result, res, dict_name, [keyword])
                results[dict_name] = result
        return results

    def _hand_link_word(
        self,
        result: list[str],
        cur_result: list[str],
        dict_name: str,
        words_show: list[str],
    ):
        """
        Process the redirect words in the result.
        :param result: the result to append the words
        :param cur_result: the current result to process
        :param dict_name: the dictionary name to process
        :param words_show: the words to show
        """
        for i in range(len(cur_result)):
            item = cur_result[i]
            if "@@@LINK=" not in item:
                result.append(item)
            else:
                redirect_word = item.split("@@@LINK=")[1].strip()
                if redirect_word not in words_show:
                    words_show.append(redirect_word)
                    res_redirect = self._fstd_searcher.exact_match_search(redirect_word, dict_name)
                    if res_redirect:
                        self._hand_link_word(
                            result, res_redirect, dict_name, words_show
                        )

    def keyword_options_search(
        self,
        keyword: str,
        search_method: str,
        dict_names: list[str]
    ):
        """
        Search the keyword in the dictionaries using the search method.
        :param keyword: the keyword to search
        :param search_method: the search method to use
        :param dict_names: the dictionaries to search
        :return: the results of the search,a dictionary of dict_name -> result
        """
        use_dicts = dict_names or self._all_dict_names
        if search_method == "prefix_search":
            return self._fstd_searcher.predictive_search(keyword, use_dicts)

        elif search_method == "suggest":
            return self._fstd_searcher.suggest(keyword, use_dicts)

        elif search_method == "regex_search":
            return self._fstd_searcher.regex_search(keyword, use_dicts)

        elif search_method == "prefix_distance_search":
            return self._fstd_searcher.prefix_distance_search(keyword, use_dicts, 3)

        else:
            print(f"Invalid search method: {search_method}", file=sys.stderr)
            return []


def print_options_result(method: str, results: list[str]) -> None:
    """
    Print the results of the options search.
    :param results: the results of the options search
    """
    print(f"\nResults of {method}: ----------")
    for result in results:
        print(result)


def main():
    fstd_searcher = FstdSearcher("./dictionaries")
    print("start search....")
    results = fstd_searcher.keyword_options_search("suggst", "suggest", ["dict1","dict2"])
    print_options_result("suggest", results)
    results = fstd_searcher.keyword_options_search("振り返ってるのは", "prefix_distance_search", [])
    print_options_result("prefix_distance_search", results)
    results = fstd_searcher.keyword_options_search("dict.*n.*y$", "regex_search", [])
    if results[1]:
        print(f"Regex error: {results[1]}")
    else:
        print_options_result("regex_search", results[0])

    results = fstd_searcher.lookup("do", [])
    print("\nlookup:-------")
    for dict_name, result in results.items():
        print(f"{dict_name}: --------")
        for item in result:
            print("---------")
            print(item)


if __name__ == "__main__":
    main()

API Reference

class FstdxSearcher:
    """
    Multi-dictionary search manager, load multiple fstdx and batch search
    """

    @overload
    def __init__(self, worker_num: int = 0) -> None:
        """
        Initialize the searcher with worker_num.
        :param worker_num: the number of threads to use for search
        :default worker_num is 0, automatically use all the current threads
        """
        ...

    @overload
    def __init__(self, meta_json_path: str, worker_num: int = 0) -> None:
        """
        Initialize the searcher with meta_json_path and worker_num.
        :param meta_json_path: the path to the meta json file
        :param worker_num: the number of threads to use for search
        :default worker_num is 0, automatically use all the current threads
        """
        ...

    def compile_fstdx(*args, **kwargs) -> None:
        ...

    def __bool__(self) -> bool:
        """Check if the searcher is valid."""
        ...

    def is_valid(self) -> bool:
        """
        Check if the searcher is valid.
        :return: True if the searcher is valid, False otherwise
        """
        ...

    def extract(self, name: str, file_path: str, dst_dir: str = "") -> bool:
        """
        Extract file_path from the fstdd files found in the same directory as the fstdx file.
        :param name: the name of the dictionary
        :param file_path: the path(key) to the file to extract
        :param dst_dir: the destination directory to extract the files, if empty, will extract to the default directory
        :return: True if the extraction is successful, False otherwise
        """
        ...

    def contains(self, word: str, names: Sequence[str]) -> bool:
        """
        Check if the word is in the dictionaries.
        :param word: the word to check
        :param names: the names of dictionaries to check
        :return: True if the word is in the dictionaries, False otherwise
        """
        ...

    @overload
    def exact_match_search(self, word: str, name: str) -> List[str]:
        """
        Search the word in the dictionary with name.
        :param word: the word to search
        :param name: the name of the dictionary to search
        :return: the results of the search
        """
        ...

    @overload
    def exact_match_search(self, word: str, names: Sequence[str]) -> dict[str, list[str]]:
        """
        Search the word in the dictionaries with names.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :return: the results of the search
        """
        ...

    def exact_match_search(*args, **kwargs) -> List[str]:
        ...

    def common_prefix_search(self, word: str, names: Sequence[str]) -> List[str]:
        """
        Search the longest common prefix of the word in the dictionaries.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :return: the length of the longest common prefix in the dictionaries.
        """
        ...

    def longest_prefix_len(self, word: str, names: Sequence[str]) -> int:
        """
        Search the longest common prefix of the word in the dictionaries.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :return: the results of the search
        """
        ...

    def edit_distance_search(self, word: str, names: Sequence[str], edit_distance: int = 1) -> List[str]:
        """
        Search the word in the dictionaries with edit distance.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :param edit_distance: the maximum edit distance
        :return: the results of the search
        """
        ...

    def predictive_search(self, word: str, names: Sequence[str]) -> List[str]:
        """
        Perform predictive search for the word in the dictionaries.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :return: the results of the search
        """
        ...

    def suggest(self, word: str, names: Sequence[str]) -> List[str]:
        """
        Provide suggestions for the word in the dictionaries.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :return: the suggested words
        """
        ...

    def prefix_distance_search(self, word: str, names: Sequence[str], max_distance: int = 1) -> List[str]:
        """
        Search the word in the dictionaries with prefix distance.
        :param word: the word to search
        :param names: the names of dictionaries to search
        :param max_distance: the maximum prefix distance
        :return: the results of the search
        """
        ...

    def regex_search(self, pattern: str, names: Sequence[str]) -> Tuple[List[str], str]:
        """
        Search the word in the dictionaries with regex.
        :param pattern: the regex pattern to search
        :param names: the names of dictionaries to search
        :return: the words that match the regex pattern in the dictionary in tuple[0], the error message if any in tuple[1]
        """
        ...

    def insert_prior_suffix(self, sufs: Sequence[str]) -> None:
        """
        Insert prior suffixes for the dictionaries.
        :param sufs: the prior suffixes to insert
        """
        ...

    def insert_if_not_exists(self, name: str, fstdx_path: str) -> None:
        """
        Insert the fstdx file if it does not exist.
        :param name: the name of the dictionary
        :param fstdx_path: the path to the fstdx file
        :return: True if the insertion is successful, False otherwise
        """
        ...

    def insert(self, name: str, fstdx_path: str) -> bool:
        """
        Insert the fstdx file.
        :param name: the name of the dictionary
        :param fstdx_path: the path to the fstdx file
        :return: True if the insertion is successful, False otherwise
        """
        ...

    def save_to_disk(self, meta_json_path: str) -> bool:
        """
        Save the meta json to disk.
        :param meta_json_path: the path to save the meta json
        :return: True if the save is successful, False otherwise
        """
        ...

C plus plus

  1. Compile fstdx/fstdd
# go to the project directory
cd fstd
# use default configure to compile a fstdx
fstd write -f tests/dict/dict.txt -o dict.fstdx
# use default configure to compile a fstdd. Note: fstdd normally include resource data, such as pictures and audios, but we use the project lib directory for test.
fstd write -f lib -o dict.fstdd

The raw content of tests/dict/dict.txt :

  1. The first entry requires no preceding delimiter: write the entry word (key) directly, followed by its corresponding definition (value). Definitions can span multiple lines, but entry words must stay on a single line.
  2. Starting from the second entry, each entry word (key) must be preceded by the delimiter </>. Entry words must still be written on one line, while definitions can span multiple lines.
  3. The end of each complete entry (entry word + corresponding definition) must be marked with the delimiter </> as a closing tag.
Ab
The definition of Ab
</>
Ababdeh
The definition of Ababdeh
</>
Abby
The definition of Abby
</>
...
  1. Search in a fstdx
# show meta data
> fstd search -m dict.fstdx
{
   "Compressionlevel": 5,
   "Creationdate": "2026-06-28",
   "Description": "",
   "Encoding": "UTF-8",
   "Format": "Html",
   "Keycasesensitive": false,
   "Left2Right": true,
   "Record": 23603,
   "Stripkey": true,
   "Stylesheet": "",
   "Title": "",
   "Version": "0.1.0"
}

# exact match search
> fstd search 'Ababdeh'  dict.fstdx
------------------------------
The definition of Ababdeh
------------------------------

# regex search
> fstd search -r 'di.*na.*y' dict.fstdx
dictionary
disciplinability
disproportionality
disproportionably

# suggest search
> fstd search -g 'dicioa' dict.fstdx
dictionary -> 0.544
dilo -> 0.438889
diol -> 0.438889
radicicola -> 0.42
decoat -> 0.4
disc -> 0.303704
io -> 0.185185
coca -> 0.175926

# fuzzy search
> fstd search -e 5 'dicionary' dict.fstdx
congiary
dictionary
donary
missionary
ordinary

# enumerate all entry words in a dictionary
> fstd search -u dict.fstdx
Ab
Aberia
Abelite
Abietineae
Ababdeh
Abby
Acanthodidae
Acarus
...
  1. Search in multiple fstdx

It's just an example of showing how to search in multiple fstdx dictionaries. The project does not provide the following fstdx files.

# Prefix distance search in multiple fstdx dicionaries
>  fstd search -P 2 振り返ってみます -f lj.fstdx -f dcq.fstdx -f hgy.fstdx
振り返る
振り
振り乱す
振り仰ぐ
振り出す
振り切る
振り合う
...

> fstd search -P 2 알아보겠습 -f lj.fstdx -f dcq.fstdx -f hgy.fstdx
알아보다
알아보
알아보-
알아내다
알아듣다
알아먹다
알아주다
알아채다
알다
...
  1. Extract a file from a fstdd
# list all keys of a fstdd
> fstd search -u dict.fstdd
include/fstd/common.h
include/fstd/fstdd_compressor.h
include/fstd/fstdd_reader.h
include/fstd/fstdd_writer.h
...

# extract include/fstd/common.h from the fstdd to the data directory
> fstd extract -k include/fstd/common.h -o data dict.fstdd

API reference

namespace fstd {

class FstdxSearcher {

public:
   FstdxSearcher(size_t worker_num = 0);

   FstdxSearcher(const std::string &meta_json_path, size_t worker_num = 0);

   operator bool() const;

   bool extract(const std::string &name, const std::string &file_path,
               const std::string &dst_dir) const;

   bool extract(const std::string &name, const std::string &file_path) const;

   bool contains(std::string_view word,
                  const std::vector<std::string> &names) const;

   std::vector<std::string> search(std::string_view word,
                                    const std::string &name) const;

   std::unordered_map<std::string, std::vector<std::string>>
   search(std::string_view word, const std::vector<std::string> &names) const;

   std::vector<std::string>
   common_prefix_search(std::string_view word,
                        const std::vector<std::string> &names) const;

   size_t
   longest_prefix_len(std::string_view word,
                                 const std::vector<std::string> &names) const;

   std::vector<std::string>
   edit_distance_search(std::string_view word,
                        const std::vector<std::string> &names,
                        size_t edit_distance = 1) const;

   std::vector<std::string>
   predictive_search(std::string_view word,
                     const std::vector<std::string> &names) const;

   std::vector<std::string> suggest(std::string_view word,
                                    const std::vector<std::string> &names) const;

   std::vector<std::string>
   prefix_distance_search(std::string_view word,
                           const std::vector<std::string> &names,
                           size_t max_distance) const;

   std::pair<std::vector<std::string>, std::string>
   regex_search(std::string_view pattern,
               const std::vector<std::string> &names) const;

   void insert_prior_suffix(const std::vector<std::string> &sufs);

   void insert_if_not_exists(const std::string &name,
                              const std::string &fstdx_path);

   bool insert(const std::string &name, const std::string &fstdx_path);

   bool save_to_disk(const std::string &meta_json_path);
}
}

Reference

Based on cpp-fstlib by yhirose.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

fstd-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

fstd-0.1.7-cp312-cp312-macosx_11_0_x86_64.whl (985.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ x86-64

fstd-0.1.7-cp312-cp312-macosx_11_0_arm64.whl (856.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

fstd-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

fstd-0.1.7-cp311-cp311-macosx_11_0_x86_64.whl (983.4 kB view details)

Uploaded CPython 3.11macOS 11.0+ x86-64

fstd-0.1.7-cp311-cp311-macosx_11_0_arm64.whl (855.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

fstd-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

fstd-0.1.7-cp310-cp310-macosx_11_0_x86_64.whl (982.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ x86-64

fstd-0.1.7-cp310-cp310-macosx_11_0_arm64.whl (854.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

fstd-0.1.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

fstd-0.1.7-cp39-cp39-macosx_11_0_x86_64.whl (982.3 kB view details)

Uploaded CPython 3.9macOS 11.0+ x86-64

fstd-0.1.7-cp39-cp39-macosx_11_0_arm64.whl (854.5 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file fstd-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5f42771efbe566b2a3ed432c15d27ec9ae58a74308a3eeeb4196f4beb9ced3d2
MD5 ceb9489c18f2ca4a73769822ef495f23
BLAKE2b-256 739a84991b2ace8606471b266f7bb30e522d71e1435cade008cbf4cc793b0c5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp312-cp312-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp312-cp312-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 d918a76890f010f490c0b6a624aacc713e65a330b83d2c52913a0f654725f45f
MD5 9a2c316af7347af1c2616f53bd6ef792
BLAKE2b-256 717ec8b0a6b4a622072c3f03fe9b561e2237f3b43405c34d8f2c814db07e7e3c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp312-cp312-macosx_11_0_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a7bcd2e3fa224f187cab6a960072c24bdfec1a550dd40ac27bba7350da44a61f
MD5 7570540ad124a79e77c6e97da82f5e81
BLAKE2b-256 48384a0f11feed2d12c8a2af12803ad9955d5de2d9a4fc1ca6501f4cbd5e0f4b

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5ff4d98675d4881cfacd276d81488957d538a0283ae4b602a54543388c580aa7
MD5 54665416512ecb8bf42c545c17a54b61
BLAKE2b-256 c0cdf11ebef81b2b8b6e3e86bb4589b6a73003a886184fad714b3d62ed213bd7

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp311-cp311-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp311-cp311-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 93129e7615aff2210a737239913bf7c24228fdd07f3d01e626c3b0540510e062
MD5 e9f7fe9404b77fc32af5b177c42b0d79
BLAKE2b-256 fd1e578be49e307f3e75269beecbfd0eab42bcc7041cc78ed3d78edebff1f8d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp311-cp311-macosx_11_0_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bc3cffeeff8e1c0282998d4206699ed768251d937455e31a51e3521558e9b1a7
MD5 47700fe8ad7a1466686af4b24d02f50f
BLAKE2b-256 bb6661d69eadc3229dfdadc592741697915886acdab102b096a2f53d7fd6f97d

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 80c35a2d3e70c8140bab98a31a644a2a901986e5632ddf61fd242cb962e28c69
MD5 e8b5743878e7c56c1b2a308c830f9b12
BLAKE2b-256 faaa456b9f35bcf6bbadfe2a3c794d08340c3eac074343998239cb0253f0aceb

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp310-cp310-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp310-cp310-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 f60aab0da0cac9b26df8a6be41ed128db1370d40d416a90813070a3fb65b48ad
MD5 9fcb27f1f601ac25918d77804ad3af88
BLAKE2b-256 9dffb50389d24faac34afccca30b79bdbb0163b3e31be0f44c37d828e7ab770e

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp310-cp310-macosx_11_0_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f5eae936e230f298405887c826a8765b52357f53be7c0b376bc6213e359d004f
MD5 849e3326c715a06b9a7cf9c48f67b265
BLAKE2b-256 4a985a06af57f0f497a381403cf2aec019973a077e01f9475e06f5c2928e0821

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fstd-0.1.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 84b75bed862a1810372a9d259c8dbdb78dc43e1c6a81e0d1b50117b39d4d9784
MD5 349f71759869b2d337fdc9b46f0d1243
BLAKE2b-256 5ee1101fb1ddc8cd523a8abbaf67358fcf3d5a2bc6e4e32ce8916e7a54b68c81

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp39-cp39-macosx_11_0_x86_64.whl.

File metadata

  • Download URL: fstd-0.1.7-cp39-cp39-macosx_11_0_x86_64.whl
  • Upload date:
  • Size: 982.3 kB
  • Tags: CPython 3.9, macOS 11.0+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fstd-0.1.7-cp39-cp39-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 edaf48042ae1a1b0901536a2d0fbcaa4a604100da26fdad9efab6406ae192442
MD5 18d6a6d08432b96b0178bc7873c4c86a
BLAKE2b-256 524afbb2f6cfdff23f5fa0418512f9b1c9514ede8ecd51d3dccea61264a28d9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp39-cp39-macosx_11_0_x86_64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fstd-0.1.7-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

  • Download URL: fstd-0.1.7-cp39-cp39-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 854.5 kB
  • Tags: CPython 3.9, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fstd-0.1.7-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4c445fa5e982743795d4278c400c6090be7d4483ddf37328c758f0cad44213d8
MD5 740d37fdb94001940de49818af3461ce
BLAKE2b-256 da4a81de18a9b9052e56ab52ab320c5ac933719012b63215fe3461d2e2ea1ee4

See more details on using hashes here.

Provenance

The following attestation bundles were made for fstd-0.1.7-cp39-cp39-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MouJieQin/fstd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page