bioguider 0.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of bioguider might be problematic. Click here for more details.

Files changed (47) hide show
  1. bioguider/__init__.py +0 -0
  2. bioguider/agents/__init__.py +0 -0
  3. bioguider/agents/agent_task.py +88 -0
  4. bioguider/agents/agent_tools.py +147 -0
  5. bioguider/agents/agent_utils.py +357 -0
  6. bioguider/agents/collection_execute_step.py +180 -0
  7. bioguider/agents/collection_observe_step.py +113 -0
  8. bioguider/agents/collection_plan_step.py +154 -0
  9. bioguider/agents/collection_task.py +179 -0
  10. bioguider/agents/collection_task_utils.py +109 -0
  11. bioguider/agents/common_agent.py +159 -0
  12. bioguider/agents/common_agent_2step.py +126 -0
  13. bioguider/agents/common_step.py +85 -0
  14. bioguider/agents/dockergeneration_execute_step.py +186 -0
  15. bioguider/agents/dockergeneration_observe_step.py +153 -0
  16. bioguider/agents/dockergeneration_plan_step.py +158 -0
  17. bioguider/agents/dockergeneration_task.py +158 -0
  18. bioguider/agents/dockergeneration_task_utils.py +220 -0
  19. bioguider/agents/evaluation_task.py +269 -0
  20. bioguider/agents/identification_execute_step.py +179 -0
  21. bioguider/agents/identification_observe_step.py +92 -0
  22. bioguider/agents/identification_plan_step.py +135 -0
  23. bioguider/agents/identification_task.py +220 -0
  24. bioguider/agents/identification_task_utils.py +18 -0
  25. bioguider/agents/peo_common_step.py +64 -0
  26. bioguider/agents/prompt_utils.py +190 -0
  27. bioguider/agents/python_ast_repl_tool.py +69 -0
  28. bioguider/agents/rag_collection_task.py +130 -0
  29. bioguider/conversation.py +67 -0
  30. bioguider/database/summarized_file_db.py +140 -0
  31. bioguider/managers/evaluation_manager.py +108 -0
  32. bioguider/rag/__init__.py +0 -0
  33. bioguider/rag/config.py +117 -0
  34. bioguider/rag/data_pipeline.py +648 -0
  35. bioguider/rag/embedder.py +24 -0
  36. bioguider/rag/rag.py +134 -0
  37. bioguider/settings.py +103 -0
  38. bioguider/utils/constants.py +40 -0
  39. bioguider/utils/default.gitignore +140 -0
  40. bioguider/utils/file_utils.py +126 -0
  41. bioguider/utils/gitignore_checker.py +175 -0
  42. bioguider/utils/pyphen_utils.py +73 -0
  43. bioguider/utils/utils.py +27 -0
  44. bioguider-0.2.3.dist-info/LICENSE +21 -0
  45. bioguider-0.2.3.dist-info/METADATA +44 -0
  46. bioguider-0.2.3.dist-info/RECORD +47 -0
  47. bioguider-0.2.3.dist-info/WHEEL +4 -0
@@ -0,0 +1,175 @@
1
+ import fnmatch
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Callable
5
+
6
+ class GitignoreChecker:
7
+ def __init__(
8
+ self,
9
+ directory: str,
10
+ gitignore_path: str,
11
+ exclude_dir_patterns: list[str] | None = None,
12
+ exclude_file_patterns: list[str] | None = None
13
+ ):
14
+ """
15
+ Initialize the GitignoreChecker with a specific directory and the path to a .gitignore file.
16
+
17
+ Args:
18
+ directory (str): The directory to be checked.
19
+ gitignore_path (str): The path to the .gitignore file.
20
+ """
21
+ self.directory = directory
22
+ self.gitignore_path = gitignore_path
23
+ self.folder_patterns, self.file_patterns = self._load_gitignore_patterns()
24
+ self.exclude_dir_patterns = exclude_dir_patterns
25
+ self.exclude_file_patterns = exclude_file_patterns
26
+
27
+ def _load_gitignore_patterns(self) -> tuple:
28
+ """
29
+ Load and parse the .gitignore file, then split the patterns into folder and file patterns.
30
+
31
+ If the specified .gitignore file is not found, fall back to the default path.
32
+
33
+ Returns:
34
+ tuple: A tuple containing two lists - one for folder patterns and one for file patterns.
35
+ """
36
+ try:
37
+ with open(self.gitignore_path, "r", encoding="utf-8") as file:
38
+ gitignore_content = file.read()
39
+ except FileNotFoundError:
40
+ # Fallback to the default .gitignore path if the specified file is not found
41
+ default_path = os.path.join(
42
+ os.path.dirname(__file__), "default.gitignore"
43
+ )
44
+ with open(default_path, "r", encoding="utf-8") as file:
45
+ gitignore_content = file.read()
46
+
47
+ patterns = self._parse_gitignore(gitignore_content)
48
+ return self._split_gitignore_patterns(patterns)
49
+
50
+ @staticmethod
51
+ def _parse_gitignore(gitignore_content: str) -> list:
52
+ """
53
+ Parse the .gitignore content and return patterns as a list.
54
+
55
+ Args:
56
+ gitignore_content (str): The content of the .gitignore file.
57
+
58
+ Returns:
59
+ list: A list of patterns extracted from the .gitignore content.
60
+ """
61
+ patterns = []
62
+ for line in gitignore_content.splitlines():
63
+ line = line.strip()
64
+ if line and not line.startswith("#"):
65
+ patterns.append(line)
66
+ return patterns
67
+
68
+ @staticmethod
69
+ def _split_gitignore_patterns(gitignore_patterns: list) -> tuple:
70
+ """
71
+ Split the .gitignore patterns into folder patterns and file patterns.
72
+
73
+ Args:
74
+ gitignore_patterns (list): A list of patterns from the .gitignore file.
75
+
76
+ Returns:
77
+ tuple: Two lists, one for folder patterns and one for file patterns.
78
+ """
79
+ folder_patterns = []
80
+ file_patterns = []
81
+ for pattern in gitignore_patterns:
82
+ if pattern.endswith("/"):
83
+ folder_patterns.append(pattern.rstrip("/"))
84
+ else:
85
+ file_patterns.append(pattern)
86
+ return folder_patterns, file_patterns
87
+
88
+ @staticmethod
89
+ def _is_ignored(path: str, patterns: list, is_dir: bool = False) -> bool:
90
+ """
91
+ Check if the given path matches any of the patterns.
92
+
93
+ Args:
94
+ path (str): The path to check.
95
+ patterns (list): A list of patterns to check against.
96
+ is_dir (bool): True if the path is a directory, False otherwise.
97
+
98
+ Returns:
99
+ bool: True if the path matches any pattern, False otherwise.
100
+ """
101
+ for pattern in patterns:
102
+ if fnmatch.fnmatch(path, pattern):
103
+ return True
104
+ if is_dir and pattern.endswith("/") and fnmatch.fnmatch(path, pattern[:-1]):
105
+ return True
106
+ return False
107
+
108
+ @staticmethod
109
+ def _is_ignored_by_default(path: str, is_dir: bool=False) -> bool:
110
+ return is_dir and path.startswith(".") # path == ".git"
111
+
112
+
113
+ def _is_ignored_by_exclude_file_patterns(self, f: str):
114
+ if self.exclude_file_patterns is None:
115
+ return False
116
+ return True if self._is_ignored(f, self.exclude_file_patterns) else False
117
+
118
+
119
+ def check_files_and_folders(
120
+ self,
121
+ level=-1,
122
+ check_file_cb: Callable[[str, str], bool] | None = None
123
+ ) -> list:
124
+ """
125
+ Check all files and folders in the given directory against the split gitignore patterns.
126
+ Return a list of files that are not ignored.
127
+ The returned file paths are relative to the self.directory.
128
+
129
+ Returns:
130
+ list: A list of paths to files that are not ignored.
131
+ """
132
+ not_ignored_files = []
133
+ root_path = Path(self.directory)
134
+ for root, dirs, files in os.walk(self.directory):
135
+ current_root_path = Path(root)
136
+ current_levels = len(current_root_path.relative_to(root_path).parts)
137
+ if level >= 0 and current_levels > level:
138
+ continue
139
+ dirs[:] = [
140
+ d
141
+ for d in dirs
142
+ if not self._is_ignored(d, self.folder_patterns, is_dir=True) \
143
+ and not self._is_ignored_by_default(d, True)
144
+ ]
145
+ if self.exclude_dir_patterns:
146
+ dirs[:] = [
147
+ d
148
+ for d in dirs
149
+ if not self._is_ignored(d, self.exclude_dir_patterns, is_dir=True)
150
+ ]
151
+
152
+ for file in files:
153
+ file_path = os.path.join(root, file)
154
+ relative_path = os.path.relpath(file_path, self.directory)
155
+ if not self._is_ignored(
156
+ file, self.file_patterns
157
+ ) and not self._is_ignored_by_exclude_file_patterns(file):
158
+ if check_file_cb is None:
159
+ not_ignored_files.append(relative_path)
160
+ else:
161
+ if check_file_cb(self.directory, relative_path):
162
+ not_ignored_files.append(relative_path)
163
+
164
+ if level >= 0 and current_levels == level:
165
+ not_ignored_files = \
166
+ not_ignored_files + \
167
+ [os.path.relpath(os.path.join(root, d), self.directory) for d in dirs]
168
+
169
+ return not_ignored_files
170
+
171
+
172
+ # Example usage:
173
+ # gitignore_checker = GitignoreChecker('path_to_directory', 'path_to_gitignore_file')
174
+ # not_ignored_files = gitignore_checker.check_files_and_folders()
175
+ # print(not_ignored_files)
@@ -0,0 +1,73 @@
1
+
2
+ import os
3
+ import re
4
+ import pyphen
5
+ import math
6
+
7
+ class PyphenReadability:
8
+ def __init__(self, lang='en'):
9
+ self.dic = pyphen.Pyphen(lang=lang)
10
+
11
+ def count_syllables(self, word):
12
+ return self.dic.inserted(word).count('-') + 1 if word.isalpha() else 0
13
+
14
+ def extract_urls(self, text):
15
+ """Find all URLs in the text."""
16
+ url_pattern = r'https?://\S+|www\.\S+'
17
+ return re.findall(url_pattern, text)
18
+
19
+ def remove_urls(self, text):
20
+ """Remove URLs from text for clean sentence splitting."""
21
+ url_pattern = r'https?://\S+|www\.\S+'
22
+ return re.sub(url_pattern, '', text)
23
+
24
+ def split_sentences(self, text):
25
+ """Split into sentences using punctuation."""
26
+ return re.split(r'[.!?]+', text)
27
+
28
+ def split_words(self, text):
29
+ """Extract words."""
30
+ return re.findall(r'\b\w+\b', text)
31
+
32
+ def is_polysyllabic(self, word):
33
+ return self.count_syllables(word) >= 3
34
+
35
+ def is_complex(self, word):
36
+ return self.is_polysyllabic(word)
37
+
38
+ def readability_metrics(self, text):
39
+ # Extract and remove URLs
40
+ urls = self.extract_urls(text)
41
+ url_count = len(urls)
42
+ text_without_urls = self.remove_urls(text)
43
+
44
+ # Split and count
45
+ sentences = [s for s in self.split_sentences(text_without_urls) if s.strip()]
46
+ sentence_count = len(sentences) + url_count
47
+
48
+ words = self.split_words(text) # split_words(text_without_urls)
49
+ word_count = len(words)
50
+
51
+ syllable_count = sum(self.count_syllables(w) for w in words)
52
+ polysyllables = sum(1 for w in words if self.is_polysyllabic(w))
53
+ complex_words = sum(1 for w in words if self.is_complex(w))
54
+
55
+ # Avoid division by zero
56
+ words_per_sentence = word_count / sentence_count if sentence_count > 0 else 0
57
+ syllables_per_word = syllable_count / word_count if word_count > 0 else 0
58
+ complex_per_word = complex_words / word_count if word_count > 0 else 0
59
+
60
+ # Readability formulas
61
+ flesch_reading_ease = 206.835 - 1.015 * words_per_sentence - 84.6 * syllables_per_word
62
+ flesch_kincaid_grade = 0.39 * words_per_sentence + 11.8 * syllables_per_word - 15.59
63
+ gunning_fog_index = 0.4 * (words_per_sentence + 100 * complex_per_word)
64
+ smog_index = (
65
+ 1.043 * math.sqrt(polysyllables * (30 / sentence_count)) + 3.1291
66
+ if sentence_count >= 1 else 0
67
+ )
68
+
69
+ return flesch_reading_ease, flesch_kincaid_grade, gunning_fog_index, smog_index,\
70
+ sentence_count, word_count, syllable_count, polysyllables, complex_words
71
+
72
+
73
+
@@ -0,0 +1,27 @@
1
+ import logging
2
+ import tiktoken
3
+ logger = logging.getLogger(__name__)
4
+
5
+ def count_tokens(text: str, local_ollama: bool = False) -> int:
6
+ """
7
+ Count the number of tokens in a text string using tiktoken.
8
+
9
+ Args:
10
+ text (str): The text to count tokens for.
11
+ local_ollama (bool, optional): Whether using local Ollama embeddings. Default is False.
12
+
13
+ Returns:
14
+ int: The number of tokens in the text.
15
+ """
16
+ try:
17
+ if local_ollama:
18
+ encoding = tiktoken.get_encoding("cl100k_base")
19
+ else:
20
+ encoding = tiktoken.encoding_for_model("text-embedding-3-small")
21
+
22
+ return len(encoding.encode(text))
23
+ except Exception as e:
24
+ # Fallback to a simple approximation if tiktoken fails
25
+ logger.warning(f"Error counting tokens with tiktoken: {e}")
26
+ # Rough approximation: 4 characters per token
27
+ return len(text) // 4
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OSU_BMBL
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.3
2
+ Name: bioguider
3
+ Version: 0.2.3
4
+ Summary: An AI-Powered package to help biomedical developers to generate clear documentation
5
+ License: MIT
6
+ Author: Cankun Wang
7
+ Author-email: Cankun.Wang@osumc.edu
8
+ Requires-Python: >=3.11,<4.0
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Natural Language :: English
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Requires-Dist: adalflow (>=1.0.4,<2.0.0)
21
+ Requires-Dist: binaryornot (>=0.4.4,<0.5.0)
22
+ Requires-Dist: faiss-cpu (>=1.11.0,<2.0.0)
23
+ Requires-Dist: grandalf (>=0.8,<0.9)
24
+ Requires-Dist: langchain (>=0.3.20,<0.4.0)
25
+ Requires-Dist: langchain-anthropic (>=0.3.10,<0.4.0)
26
+ Requires-Dist: langchain-deepseek (>=0.1.2,<0.2.0)
27
+ Requires-Dist: langchain-experimental (>=0.3.4,<0.4.0)
28
+ Requires-Dist: langchain-google-genai (>=2.1.4,<3.0.0)
29
+ Requires-Dist: langchain-openai (>=0.3.8,<0.4.0)
30
+ Requires-Dist: langgraph (>=0.3.11,<0.4.0)
31
+ Requires-Dist: nanoid (>=2.0.0,<3.0.0)
32
+ Requires-Dist: pydantic (>=2.10.6,<3.0.0)
33
+ Requires-Dist: pydantic-settings (>=2.8.1,<3.0.0)
34
+ Requires-Dist: pyphen (>=0.17.2,<0.18.0)
35
+ Requires-Dist: pytest (>=8.3.5,<9.0.0)
36
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
37
+ Requires-Dist: python-iso639 (>=2025.2.18,<2026.0.0)
38
+ Requires-Dist: tenacity (>=9.1.2,<10.0.0)
39
+ Requires-Dist: textstat (>=0.7.6,<0.8.0)
40
+ Requires-Dist: tiktoken (>=0.9.0,<0.10.0)
41
+ Requires-Dist: tqdm (>=4.67.1,<5.0.0)
42
+ Description-Content-Type: text/markdown
43
+
44
+ # bioguider
@@ -0,0 +1,47 @@
1
+ bioguider/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ bioguider/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ bioguider/agents/agent_task.py,sha256=SX4iLdGqQttT39qvr-RtXiSpQEzm7Z3ECVw8IGQzpDc,2828
4
+ bioguider/agents/agent_tools.py,sha256=Q7yciRjMwW4J6V4TGZx_smaBYiV_ZtmKkjBb1ofVgM0,5898
5
+ bioguider/agents/agent_utils.py,sha256=qngmkCiTz46PJebzWmdZLo5XWtyUDZddCQv06PDKBrw,12450
6
+ bioguider/agents/collection_execute_step.py,sha256=6hCCP9LG5goC-EbS6Ye3wKS4vPy7p9NndMYo48Qt3RA,5515
7
+ bioguider/agents/collection_observe_step.py,sha256=iNeV6f16Emk1LMStSR4FXBPZ6Sc0eTjwxEfmoeegV-U,4554
8
+ bioguider/agents/collection_plan_step.py,sha256=mx-_5Y3pqKDPBaMMyFElKlpq1GWN7g03ZplnlTr9ppE,5699
9
+ bioguider/agents/collection_task.py,sha256=9jqasC5PVZvnPzQtLGAJiYvO1M2RGWH7tqWO6KbEnl8,6663
10
+ bioguider/agents/collection_task_utils.py,sha256=WRzzpMV6r8aY0FlX_zroHbLDXyrmvS48OSiBr_fIq2Q,3677
11
+ bioguider/agents/common_agent.py,sha256=eGs8m8bjO0dmW6lDIen7DQNdWdHD7j8Udf3XhL1k6vI,5242
12
+ bioguider/agents/common_agent_2step.py,sha256=wIg9m9-8tq0AYrG2quuI1ZYg82Q54MHtTQLG4pqN8y4,4596
13
+ bioguider/agents/common_step.py,sha256=GdOCbmj1pwh4etg-futVFYVDQuoUG89DnIrw-B6QbzM,2594
14
+ bioguider/agents/dockergeneration_execute_step.py,sha256=F92jDlkc6KjAvTkX7q1FsCYP8J15SCaNgmwh3YPqfDo,6500
15
+ bioguider/agents/dockergeneration_observe_step.py,sha256=gVCsr0EiKCgYMRQvev_LWBf78yHzLxIltPVIgRmdS3o,6062
16
+ bioguider/agents/dockergeneration_plan_step.py,sha256=v0X95Lzj5kjfqcOch6IOMcuOfsRBkgJjsYDlxMpblLI,7204
17
+ bioguider/agents/dockergeneration_task.py,sha256=ezsweVHJsFpOyOI6rYMt1DZ3PE19dcq4J3Lm-d0IA8M,6220
18
+ bioguider/agents/dockergeneration_task_utils.py,sha256=v7emqrJlVW-A5ZdLmPSdiaMSKCR8uzy9UYzx_1cgzyo,9041
19
+ bioguider/agents/evaluation_task.py,sha256=iEa47N1iL-MgLKNZfMzRjjMcg2rEqSis4FeXaEGYLJQ,10928
20
+ bioguider/agents/identification_execute_step.py,sha256=_9x_KITVtNJjQlgjfq-LazoUl46Tctaj_W_AVxz5q-w,5488
21
+ bioguider/agents/identification_observe_step.py,sha256=B5E61luYteyKOaMZsgjxI-xuNijPfAjNpNBWL5DyTHc,3636
22
+ bioguider/agents/identification_plan_step.py,sha256=p-a3vc0qhifJCM0cerFVAtYuYSvqImzqCsQofFaQRrs,5193
23
+ bioguider/agents/identification_task.py,sha256=-4bnw39OSkhu8RkDVQPRpmu0g8K79dji3HXTybch5As,8329
24
+ bioguider/agents/identification_task_utils.py,sha256=5gevknha9hJiiQN5L7Yp9-pyhAlbR_j31aGRK5j0D_w,522
25
+ bioguider/agents/peo_common_step.py,sha256=iw2c1h7X11WJzSE2tSRg0UAoXH0QOlQDxW9CCzSVMOY,2677
26
+ bioguider/agents/prompt_utils.py,sha256=KBNWsUJMjZAczD_y7nFMnjfJv4dVBPI3cAlQDMbFHec,12379
27
+ bioguider/agents/python_ast_repl_tool.py,sha256=o7-4P1h8jS8ikhGSA4CI_OWQ2a0Eg5tEdmuAp_qrO-0,2519
28
+ bioguider/agents/rag_collection_task.py,sha256=r_jPAMjQcC7dIydKxX77UuMqjJ3MiVKswNZ-yNw7yx8,5199
29
+ bioguider/conversation.py,sha256=DIvk_d7pz_guuORByK1eaaF09FAK-8shcNTrbSUHz9Y,1779
30
+ bioguider/database/summarized_file_db.py,sha256=9Iyin5BChlFjDJlFamTwmzkYZvO3BzFu7M8AbikyPXw,4441
31
+ bioguider/managers/evaluation_manager.py,sha256=EtVSTP75mtlvXDcXKMedsqlwUZEkxaD9MBwHJQfpmr4,3920
32
+ bioguider/rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ bioguider/rag/config.py,sha256=5g4IqTzgyfZfax9Af9CTkXShgItPOt4_9TEMSekCPik,4602
34
+ bioguider/rag/data_pipeline.py,sha256=rG3iSxWlIZzQ5ml3E2Zo7UJEnlVeeneAm_kSCsngUhw,27126
35
+ bioguider/rag/embedder.py,sha256=jofR8hOj3Aj2IyBQ9y6FeAc84tgq5agbIfCGyFxYpJ8,650
36
+ bioguider/rag/rag.py,sha256=2G2b7JIDsjrR74lnkIFyEuMPF14kn6B-WhphZkUxd3c,4481
37
+ bioguider/settings.py,sha256=BD_iz9aYarxmWUl0XaKl4-D4oTXMhFzljsXLNn2phis,3143
38
+ bioguider/utils/constants.py,sha256=_xMAhwE3py2RR0pIimnb2qfucXdnTj4ZNeKGACouh2w,932
39
+ bioguider/utils/default.gitignore,sha256=XjPdyO2KV8z8iyuqluaNR_70tBQftMpyKL8HboVNyeI,1605
40
+ bioguider/utils/file_utils.py,sha256=R68ayY1flc2Mbl7yMkp_39AUzw5_8iPF5Ow3YVQaZdY,3610
41
+ bioguider/utils/gitignore_checker.py,sha256=pOYUwsS9D5014LxcZb0cj3s2CAYaD2uF_pYJpaNKcho,6532
42
+ bioguider/utils/pyphen_utils.py,sha256=cdZc3qphkvMDeL5NiZ8Xou13M_uVNP7ifJ-FwxO-0BE,2680
43
+ bioguider/utils/utils.py,sha256=YP3HXgU_rvYDWkEcTzWGiYZw-mlfVrqGhUGSc0_4Pms,900
44
+ bioguider-0.2.3.dist-info/LICENSE,sha256=qzkvZcKwwA5DuSuhXMOm2LcO6BdEr4V7jwFZVL2-jL4,1065
45
+ bioguider-0.2.3.dist-info/METADATA,sha256=_Vaa_hK-a2Y9bI07jzhC8UW16TLjMlwLjqXVfwOSJzQ,1823
46
+ bioguider-0.2.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
47
+ bioguider-0.2.3.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.3
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any