geneplus-tools-test 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,133 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .nox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ target/
74
+
75
+ # Jupyter Notebook
76
+ .ipynb_checkpoints
77
+
78
+ # IPython
79
+ profile_default/
80
+ ipython_config.py
81
+
82
+ # pyenv
83
+ .python-version
84
+
85
+ # pipenv
86
+ Pipfile.lock
87
+
88
+ # PEP 582
89
+ __pypackages__/
90
+
91
+ # Celery stuff
92
+ celerybeat-schedule
93
+ celerybeat.pid
94
+
95
+ # SageMath parsed files
96
+ *.sage.py
97
+
98
+ # Environments
99
+ .env
100
+ .venv
101
+ env/
102
+ venv/
103
+ ENV/
104
+ env.bak/
105
+ venv.bak/
106
+
107
+ # Spyder project settings
108
+ .spyderproject
109
+ .spyproject
110
+
111
+ # Rope project settings
112
+ .ropeproject
113
+
114
+ # mkdocs documentation
115
+ /site
116
+
117
+ # mypy
118
+ .mypy_cache/
119
+ .dmypy.json
120
+ dmypy.json
121
+
122
+ # Pyre type checker
123
+ .pyre/
124
+
125
+ # IDE
126
+ .vscode/
127
+ .idea/
128
+ *.swp
129
+ *.swo
130
+ *~
131
+
132
+ # macOS
133
+ .DS_Store
@@ -0,0 +1,3 @@
1
+ [pypi]
2
+ username = __token__
3
+ password = pypi-替换为您的API-Token
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.4
2
+ Name: geneplus-tools-test
3
+ Version: 0.1.0
4
+ Summary: GenePlus Python Client - A simple HTTP client for GenePlus API
5
+ Project-URL: Homepage, https://github.com/geneplus/geneplus-tools-test
6
+ Project-URL: Documentation, https://github.com/geneplus/geneplus-tools-test#readme
7
+ Project-URL: Repository, https://github.com/geneplus/geneplus-tools-test.git
8
+ Project-URL: Issues, https://github.com/geneplus/geneplus-tools-test/issues
9
+ Author: GenePlus Team
10
+ License: MIT
11
+ Keywords: api,client,geneplus,http
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: >=3.8
23
+ Requires-Dist: requests>=2.25.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: build; extra == 'dev'
26
+ Requires-Dist: pytest; extra == 'dev'
27
+ Requires-Dist: twine; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # GenePlus Tools Test
31
+
32
+ GenePlus Python Client - A simple HTTP client for GenePlus API.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install geneplus-tools-test
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ from geneplus_tools_test import GenePlusClient
44
+
45
+ # Create client (token will be loaded from config or environment variable)
46
+ client = GenePlusClient()
47
+
48
+ # Test connectivity
49
+ result = client.ping()
50
+ print(result) # 'pong'
51
+
52
+ # Get user info
53
+ info = client.get_info("张三", "13512341234")
54
+ print(info) # '张三 - 13512341234,喜欢探索新事物'
55
+ ```
56
+
57
+ ## Configuration
58
+
59
+ The client can be configured in three ways (in order of priority):
60
+
61
+ ### 1. Direct Token
62
+
63
+ ```python
64
+ client = GenePlusClient(token="your-token-here")
65
+ ```
66
+
67
+ ### 2. Environment Variable
68
+
69
+ ```bash
70
+ export GENEPLUS_TOKEN="your-token-here"
71
+ ```
72
+
73
+ ```python
74
+ client = GenePlusClient() # Will use GENEPLUS_TOKEN
75
+ ```
76
+
77
+ ### 3. Config File
78
+
79
+ Create `~/.config/geneplus/token.json`:
80
+
81
+ ```json
82
+ {
83
+ "gp-tools-token": "your-token-here"
84
+ }
85
+ ```
86
+
87
+ ```python
88
+ client = GenePlusClient() # Will read from config file
89
+ ```
90
+
91
+ ## CLI Usage
92
+
93
+ After installation, you can use the `gp-tool` command:
94
+
95
+ ### Test connectivity
96
+
97
+ ```bash
98
+ gp-tool ping
99
+ ```
100
+
101
+ ### Get user information
102
+
103
+ ```bash
104
+ gp-tool get-info --name "张三" --phone "13512341234"
105
+ ```
106
+
107
+ ### Help
108
+
109
+ ```bash
110
+ gp-tool --help
111
+ gp-tool get-info --help
112
+ ```
113
+
114
+ ## API Reference
115
+
116
+ ### GenePlusClient
117
+
118
+ #### `__init__(token=None, base_url=None)`
119
+
120
+ Initialize the client.
121
+
122
+ - `token`: Optional API token
123
+ - `base_url`: Optional base URL (default: http://jdh.test.geneplus.org.cn)
124
+
125
+ #### `ping() -> str`
126
+
127
+ Test network connectivity to the server.
128
+
129
+ Returns response text from the server.
130
+
131
+ Raises `GenePlusConnectionError` if connection fails.
132
+
133
+ #### `get_info(name: str, phone: str) -> str`
134
+
135
+ Get user information from the server.
136
+
137
+ - `name`: User name
138
+ - `phone`: User phone number (11 digits, starts with 1)
139
+
140
+ Returns user information string.
141
+
142
+ Raises:
143
+ - `ValueError`: If phone number format is invalid
144
+ - `GenePlusAuthError`: If token is invalid
145
+ - `GenePlusAPIError`: If API returns other errors
146
+ - `GenePlusConnectionError`: If network connection fails
147
+
148
+ ## Exceptions
149
+
150
+ - `GenePlusError`: Base exception
151
+ - `GenePlusConnectionError`: Network connection error
152
+ - `GenePlusAuthError`: Authentication error (invalid token)
153
+ - `GenePlusAPIError`: API error
154
+ - `GenePlusConfigError`: Configuration error (missing token)
155
+
156
+ ## Development
157
+
158
+ ### Setup
159
+
160
+ ```bash
161
+ git clone https://github.com/geneplus/geneplus-tools-test.git
162
+ cd geneplus-tools-test
163
+ pip install -e ".[dev]"
164
+ ```
165
+
166
+ ### Build
167
+
168
+ ```bash
169
+ python -m build
170
+ ```
171
+
172
+ ### Publish to PyPI
173
+
174
+ ```bash
175
+ twine upload dist/*
176
+ ```
177
+
178
+ ## License
179
+
180
+ MIT
@@ -0,0 +1,151 @@
1
+ # GenePlus Tools Test
2
+
3
+ GenePlus Python Client - A simple HTTP client for GenePlus API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install geneplus-tools-test
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from geneplus_tools_test import GenePlusClient
15
+
16
+ # Create client (token will be loaded from config or environment variable)
17
+ client = GenePlusClient()
18
+
19
+ # Test connectivity
20
+ result = client.ping()
21
+ print(result) # 'pong'
22
+
23
+ # Get user info
24
+ info = client.get_info("张三", "13512341234")
25
+ print(info) # '张三 - 13512341234,喜欢探索新事物'
26
+ ```
27
+
28
+ ## Configuration
29
+
30
+ The client can be configured in three ways (in order of priority):
31
+
32
+ ### 1. Direct Token
33
+
34
+ ```python
35
+ client = GenePlusClient(token="your-token-here")
36
+ ```
37
+
38
+ ### 2. Environment Variable
39
+
40
+ ```bash
41
+ export GENEPLUS_TOKEN="your-token-here"
42
+ ```
43
+
44
+ ```python
45
+ client = GenePlusClient() # Will use GENEPLUS_TOKEN
46
+ ```
47
+
48
+ ### 3. Config File
49
+
50
+ Create `~/.config/geneplus/token.json`:
51
+
52
+ ```json
53
+ {
54
+ "gp-tools-token": "your-token-here"
55
+ }
56
+ ```
57
+
58
+ ```python
59
+ client = GenePlusClient() # Will read from config file
60
+ ```
61
+
62
+ ## CLI Usage
63
+
64
+ After installation, you can use the `gp-tool` command:
65
+
66
+ ### Test connectivity
67
+
68
+ ```bash
69
+ gp-tool ping
70
+ ```
71
+
72
+ ### Get user information
73
+
74
+ ```bash
75
+ gp-tool get-info --name "张三" --phone "13512341234"
76
+ ```
77
+
78
+ ### Help
79
+
80
+ ```bash
81
+ gp-tool --help
82
+ gp-tool get-info --help
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### GenePlusClient
88
+
89
+ #### `__init__(token=None, base_url=None)`
90
+
91
+ Initialize the client.
92
+
93
+ - `token`: Optional API token
94
+ - `base_url`: Optional base URL (default: http://jdh.test.geneplus.org.cn)
95
+
96
+ #### `ping() -> str`
97
+
98
+ Test network connectivity to the server.
99
+
100
+ Returns response text from the server.
101
+
102
+ Raises `GenePlusConnectionError` if connection fails.
103
+
104
+ #### `get_info(name: str, phone: str) -> str`
105
+
106
+ Get user information from the server.
107
+
108
+ - `name`: User name
109
+ - `phone`: User phone number (11 digits, starts with 1)
110
+
111
+ Returns user information string.
112
+
113
+ Raises:
114
+ - `ValueError`: If phone number format is invalid
115
+ - `GenePlusAuthError`: If token is invalid
116
+ - `GenePlusAPIError`: If API returns other errors
117
+ - `GenePlusConnectionError`: If network connection fails
118
+
119
+ ## Exceptions
120
+
121
+ - `GenePlusError`: Base exception
122
+ - `GenePlusConnectionError`: Network connection error
123
+ - `GenePlusAuthError`: Authentication error (invalid token)
124
+ - `GenePlusAPIError`: API error
125
+ - `GenePlusConfigError`: Configuration error (missing token)
126
+
127
+ ## Development
128
+
129
+ ### Setup
130
+
131
+ ```bash
132
+ git clone https://github.com/geneplus/geneplus-tools-test.git
133
+ cd geneplus-tools-test
134
+ pip install -e ".[dev]"
135
+ ```
136
+
137
+ ### Build
138
+
139
+ ```bash
140
+ python -m build
141
+ ```
142
+
143
+ ### Publish to PyPI
144
+
145
+ ```bash
146
+ twine upload dist/*
147
+ ```
148
+
149
+ ## License
150
+
151
+ MIT
@@ -0,0 +1,230 @@
1
+ """GenePlus Python Client - A simple HTTP client for GenePlus API."""
2
+
3
+ import json
4
+ import os
5
+ import re
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import requests
10
+
11
+
12
+ # Custom Exceptions
13
+ class GenePlusError(Exception):
14
+ """Base exception for GenePlus client."""
15
+ pass
16
+
17
+
18
+ class GenePlusConnectionError(GenePlusError):
19
+ """Raised when network connection fails."""
20
+ pass
21
+
22
+
23
+ class GenePlusAuthError(GenePlusError):
24
+ """Raised when authentication fails (invalid token)."""
25
+ pass
26
+
27
+
28
+ class GenePlusAPIError(GenePlusError):
29
+ """Raised when API returns an error."""
30
+ pass
31
+
32
+
33
+ class GenePlusConfigError(GenePlusError):
34
+ """Raised when configuration is missing or invalid."""
35
+ pass
36
+
37
+
38
+ class GenePlusClient:
39
+ """Client for GenePlus API.
40
+
41
+ Provides methods to interact with GenePlus test server:
42
+ - ping(): Test network connectivity
43
+ - get_info(name, phone): Get user information
44
+
45
+ Token can be provided directly, via environment variable GENEPLUS_TOKEN,
46
+ or read from ~/.config/geneplus/token.json file.
47
+
48
+ Args:
49
+ token: Optional API token. If not provided, will try to load from
50
+ environment variable or config file.
51
+ base_url: Optional base URL for the API. Defaults to
52
+ http://jdh.test.geneplus.org.cn
53
+
54
+ Raises:
55
+ GenePlusConfigError: If no token is found
56
+
57
+ Example:
58
+ >>> client = GenePlusClient()
59
+ >>> client.ping()
60
+ 'pong'
61
+ >>> client.get_info("张三", "13512341234")
62
+ '张三 - 13512341234,喜欢探索新事物'
63
+ """
64
+
65
+ DEFAULT_BASE_URL = "http://jdh.test.geneplus.org.cn"
66
+ CONFIG_PATH = Path.home() / ".config" / "geneplus" / "token.json"
67
+
68
+ def __init__(self, token: Optional[str] = None, base_url: Optional[str] = None):
69
+ """Initialize the client."""
70
+ self.base_url = base_url or self.DEFAULT_BASE_URL
71
+
72
+ if token:
73
+ self.token = token
74
+ else:
75
+ self.token = self._load_token()
76
+
77
+ if not self.token:
78
+ raise GenePlusConfigError(
79
+ "无法读取访问令牌。请提供 token 参数,"
80
+ "设置 GENEPLUS_TOKEN 环境变量,"
81
+ "或配置 ~/.config/geneplus/token.json 文件"
82
+ )
83
+
84
+ def _load_token(self) -> Optional[str]:
85
+ """Load token from environment variable or config file.
86
+
87
+ Returns:
88
+ The token string if found, None otherwise
89
+ """
90
+ # Try environment variable first
91
+ env_token = os.environ.get("GENEPLUS_TOKEN")
92
+ if env_token:
93
+ return env_token
94
+
95
+ # Try config file
96
+ if self.CONFIG_PATH.exists():
97
+ try:
98
+ with open(self.CONFIG_PATH, 'r', encoding='utf-8') as f:
99
+ config = json.load(f)
100
+ return config.get("gp-tools-token")
101
+ except (json.JSONDecodeError, IOError):
102
+ pass
103
+
104
+ return None
105
+
106
+ def _validate_phone(self, phone: str) -> None:
107
+ """Validate phone number format.
108
+
109
+ Args:
110
+ phone: Phone number to validate
111
+
112
+ Raises:
113
+ ValueError: If phone number format is invalid
114
+ """
115
+ if not re.match(r'^1[3-9]\d{9}$', phone):
116
+ raise ValueError(
117
+ "手机号码格式错误,请输入正确的11位中国大陆手机号码(如13812345678)"
118
+ )
119
+
120
+ def ping(self) -> str:
121
+ """Test network connectivity to the server.
122
+
123
+ Sends a GET request to the /ping endpoint.
124
+
125
+ Returns:
126
+ Response text from the server
127
+
128
+ Raises:
129
+ GenePlusConnectionError: If network connection fails
130
+ """
131
+ url = f"{self.base_url}/ping"
132
+
133
+ try:
134
+ response = requests.get(url, timeout=10)
135
+ response.raise_for_status()
136
+ return response.text
137
+ except requests.exceptions.ConnectionError as e:
138
+ raise GenePlusConnectionError(f"无法连接到服务器: {e}")
139
+ except requests.exceptions.Timeout:
140
+ raise GenePlusConnectionError("请求超时,请稍后重试")
141
+ except requests.exceptions.RequestException as e:
142
+ raise GenePlusConnectionError(f"网络请求错误: {e}")
143
+
144
+ def get_info(self, name: str, phone: str) -> str:
145
+ """Get user information from the server.
146
+
147
+ Sends a POST request to the /get_info endpoint with token,
148
+ name, and phone number.
149
+
150
+ Args:
151
+ name: User name
152
+ phone: User phone number (11 digits, starts with 1)
153
+
154
+ Returns:
155
+ User information string from the server
156
+
157
+ Raises:
158
+ ValueError: If phone number format is invalid
159
+ GenePlusAuthError: If token is invalid (401)
160
+ GenePlusAPIError: If API returns other errors
161
+ GenePlusConnectionError: If network connection fails
162
+ """
163
+ # Validate phone number
164
+ self._validate_phone(phone)
165
+
166
+ url = f"{self.base_url}/get_info"
167
+ payload = {
168
+ "token": self.token,
169
+ "name": name,
170
+ "phone": phone
171
+ }
172
+
173
+ try:
174
+ response = requests.post(
175
+ url,
176
+ json=payload,
177
+ headers={"Content-Type": "application/json"},
178
+ timeout=10
179
+ )
180
+
181
+ # Handle different status codes
182
+ if response.status_code == 401:
183
+ data = response.json()
184
+ raise GenePlusAuthError(data.get("message", "token无效"))
185
+
186
+ if response.status_code == 400:
187
+ data = response.json()
188
+ raise GenePlusAPIError(data.get("message", "请求参数错误"))
189
+
190
+ response.raise_for_status()
191
+ data = response.json()
192
+
193
+ if data.get("code") == 200:
194
+ return data.get("message", "")
195
+ else:
196
+ raise GenePlusAPIError(data.get("message", "未知错误"))
197
+
198
+ except requests.exceptions.ConnectionError as e:
199
+ raise GenePlusConnectionError(f"无法连接到服务器: {e}")
200
+ except requests.exceptions.Timeout:
201
+ raise GenePlusConnectionError("请求超时,请稍后重试")
202
+ except requests.exceptions.RequestException as e:
203
+ raise GenePlusConnectionError(f"网络请求错误: {e}")
204
+
205
+
206
+ # Convenience function for quick usage
207
+ def get_client(token: Optional[str] = None, base_url: Optional[str] = None) -> GenePlusClient:
208
+ """Create a new GenePlusClient instance.
209
+
210
+ This is a convenience function that creates and returns a client.
211
+
212
+ Args:
213
+ token: Optional API token
214
+ base_url: Optional base URL
215
+
216
+ Returns:
217
+ A new GenePlusClient instance
218
+ """
219
+ return GenePlusClient(token=token, base_url=base_url)
220
+
221
+
222
+ __all__ = [
223
+ "GenePlusClient",
224
+ "GenePlusError",
225
+ "GenePlusConnectionError",
226
+ "GenePlusAuthError",
227
+ "GenePlusAPIError",
228
+ "GenePlusConfigError",
229
+ "get_client",
230
+ ]
@@ -0,0 +1,66 @@
1
+ """GenePlus CLI - Command line interface for GenePlus API."""
2
+
3
+ import argparse
4
+ import sys
5
+
6
+ from geneplus_tools_test import GenePlusClient, GenePlusError
7
+
8
+
9
+ def main():
10
+ """Main entry point for CLI."""
11
+ parser = argparse.ArgumentParser(
12
+ prog="gp-tool",
13
+ description="GenePlus CLI tool - interact with GenePlus API"
14
+ )
15
+
16
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
17
+
18
+ # ping command
19
+ ping_parser = subparsers.add_parser(
20
+ "ping",
21
+ help="Test network connectivity to the server"
22
+ )
23
+
24
+ # get-info command
25
+ get_info_parser = subparsers.add_parser(
26
+ "get-info",
27
+ help="Get user information from the server"
28
+ )
29
+ get_info_parser.add_argument(
30
+ "--name",
31
+ required=True,
32
+ help="User name"
33
+ )
34
+ get_info_parser.add_argument(
35
+ "--phone",
36
+ required=True,
37
+ help="User phone number (11 digits)"
38
+ )
39
+
40
+ args = parser.parse_args()
41
+
42
+ if not args.command:
43
+ parser.print_help()
44
+ sys.exit(1)
45
+
46
+ try:
47
+ client = GenePlusClient()
48
+
49
+ if args.command == "ping":
50
+ result = client.ping()
51
+ print(result)
52
+
53
+ elif args.command == "get-info":
54
+ result = client.get_info(args.name, args.phone)
55
+ print(result)
56
+
57
+ except GenePlusError as e:
58
+ print(f"Error: {e}", file=sys.stderr)
59
+ sys.exit(1)
60
+ except KeyboardInterrupt:
61
+ print("\nOperation cancelled", file=sys.stderr)
62
+ sys.exit(130)
63
+
64
+
65
+ if __name__ == "__main__":
66
+ main()
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "geneplus-tools-test"
7
+ version = "0.1.0"
8
+ description = "GenePlus Python Client - A simple HTTP client for GenePlus API"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ {name = "GenePlus Team"},
14
+ ]
15
+ keywords = ["geneplus", "api", "client", "http"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ ]
28
+ dependencies = [
29
+ "requests>=2.25.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "build",
35
+ "twine",
36
+ "pytest",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/geneplus/geneplus-tools-test"
41
+ Documentation = "https://github.com/geneplus/geneplus-tools-test#readme"
42
+ Repository = "https://github.com/geneplus/geneplus-tools-test.git"
43
+ Issues = "https://github.com/geneplus/geneplus-tools-test/issues"
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["geneplus_tools_test"]
47
+
48
+ [project.scripts]
49
+ gp-tool = "geneplus_tools_test.cli:main"